Skip to content

feat: add Playwright-compatible trace recorder (tauri mode)#5

Open
srsholmes wants to merge 2 commits into
mainfrom
feat/trace-recorder
Open

feat: add Playwright-compatible trace recorder (tauri mode)#5
srsholmes wants to merge 2 commits into
mainfrom
feat/trace-recorder

Conversation

@srsholmes

Copy link
Copy Markdown
Owner

Summary

Ports the TraceRecorder pattern from electrobun-playwright and wires it into createTauriTest() for tauri-mode tests. Each test now produces a trace.zip attached to the Playwright HTML report, viewable with `npx playwright show-trace`.

  • Auto-wired in tauri mode; `browser`/`cdp` modes are unchanged (Playwright's native tracing already covers them)
  • Additive — does not remove or change the existing `startRecording`/`stopRecording` MP4 pipeline
  • Adds one dependency: fflate (~20KB, zero transitive deps)

Architectural note

The electrobun version runs tracing in the Bun bridge (server-side). Tauri's runner is Rust, so this port puts the recorder on the JS test-client side and intercepts every non-internal command via a `PluginClient` subclass (`TracingPluginClient`). Frames come from the existing `native_screenshot` Rust command — no Rust-side changes.

Trade-off: one extra `native_screenshot` round-trip before and after each action command (~20-50ms on macOS via CoreGraphics). Acceptable — MP4 recording keeps running in parallel.

New files

File Role
`packages/test/src/trace/recorder.ts` Writes NDJSON events + PNG frames into a Playwright trace zip
`packages/test/src/trace/writer.ts` `fflate.zipSync` writer (Bun/Node safe — synchronous API avoids fflate's WebWorker path)
`packages/test/src/trace/tracing-plugin-client.ts` `PluginClient` subclass that captures before/after frames and calls `recordAction`
`packages/test/src/trace/recorder.test.ts` Vitest covering start/recordAction/stop, zip contents, edge cases

Modified files

  • `packages/test/src/fixture.ts` — constructs `TracingPluginClient` instead of `PluginClient`, calls `tracer.start()` before `use()`, attaches the zip via `testInfo.attach()` after. All trace failures are non-fatal (test result unaffected)
  • `packages/test/src/index.ts` — exports `TraceRecorder`, `CaptureFrame`, `TracingPluginClient`
  • `packages/test/package.json` — adds `fflate` to `dependencies`
  • `.changeset/add-trace-recorder.md` — `minor` bump

Test plan

  • `pnpm test` — 135/135 pass (8 new vitest cases for the recorder)
  • `pnpm lint` — clean
  • `pnpm build` — tsup emits `dist/index.js` (66.6KB) + `dist/index.d.ts` (36.9KB)
  • End-to-end: `cd examples/hello-world && cargo tauri dev --features e2e-testing`, then `npx playwright test --project=tauri` — confirm `test-results//trace-dir/trace.zip` exists and opens cleanly in `npx playwright show-trace`

Known non-blocking

`pnpm --filter @srsholmes/tauri-playwright typecheck` surfaces a pre-existing `ITEMS is not defined` error in `ipc-mock.test.ts:84` (present on `main` before this branch). Not touched by this PR.

🤖 Generated with Claude Code

srsholmes and others added 2 commits April 21, 2026 16:46
Ports the TraceRecorder pattern from electrobun-playwright and wires it into
createTauriTest() for tauri-mode tests. Each test now produces a
Playwright-compatible trace.zip attached to the HTML report, viewable with
`npx playwright show-trace`.

- `packages/test/src/trace/recorder.ts` — writes NDJSON events + PNG frames
  (adapted from electrobun's bridge-side recorder; uses a captureFrame
  callback so the test client can source frames from the existing
  native_screenshot Rust command)
- `packages/test/src/trace/writer.ts` — fflate zipSync writer (verbatim
  port; sync API works under Bun/Node without the WebWorker surprise)
- `packages/test/src/trace/tracing-plugin-client.ts` — PluginClient
  subclass that intercepts every non-internal command with before/after
  native_screenshot calls, routes native_screenshot itself through
  super.send() to avoid recursion
- Fixture starts/stops tracing around `await use()` and attaches the zip
  via testInfo.attach, mirroring electrobun's non-fatal error handling
- Existing MP4 recording pipeline is untouched — trace is additive

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Emit `stepId` on every `before` event so the v8 trace viewer's test
  list panel renders correctly without relying on the v7→v8 modernizer
  fallback.
- Detect `@playwright/test` version at runtime via `createRequire` so
  the trace header matches whatever version the user has installed,
  instead of a hardcoded "1.58.0" that goes stale on every bump.
- Map `listWindows`/`waitForWindow` to `class: 'BrowserContext'` in
  trace events; everything else stays `Page`. The viewer renders this
  as "<class>.<method>" so context-shaped commands now read correctly.
- Rename the `sha1` local in `captureFrame` to `resourceName` and add
  a comment clarifying that the field name is schema-mandated but we
  don't actually hash (so identical frames don't dedup).
- Document show-trace compat in the class-level JSDoc: action list +
  per-action screenshots work, DOM/Network tabs will be empty for a
  Tauri webview.

136 unit tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant