Skip to content

Built-in trace viewer with DOM snapshots for browser mode #9945

@hi-ogawa

Description

@hi-ogawa

Clear and concise description of the problem

Draft brainstorm with Claude

As a developer using Vitest browser mode, I want a built-in trace viewer — like Playwright's — that lets me step through my test and inspect the DOM at each action, directly in Vitest UI and the HTML reporter.

Currently, browser mode has a mark API and trace support, but it fully delegates to Playwright's trace system:

  • Produces .trace.zip files that must be opened in Playwright's separate trace viewer
  • Playwright-provider-only — gated behind if (provider.name === 'playwright'), so WebDriverIO and preview users get nothing
  • No integration with Vitest UI or HTML reporter — trace data exists but Vitest doesn't render it

The goal is for Vitest to have its own trace viewer with DOM snapshot support — provider-agnostic and built into the UI/reporter. Playwright trace output can remain as an optional secondary output.

Suggested solution

Build a built-in trace viewer by porting Playwright's DOM snapshot serialization and rendering into Vitest. The system captures a DOM snapshot at each mark point and renders it in Vitest's own UI.

What to port from Playwright (Apache 2.0, compatible with attribution):

  1. DOM serializer (snapshotterInjected.ts, ~650 lines) — injected into the browser page. Serializes the DOM into a compact array-based format capturing form state, scroll positions, shadow DOM, adopted stylesheets, and more.
  2. Snapshot renderer (snapshotRenderer.ts, ~300 lines) — converts the compact format back into viewable HTML, restoring all captured state.
  3. Type definitions (snapshot.ts) — NodeSnapshot, FrameSnapshot, ResourceOverride.

Integration with existing infrastructure:

  • Client side: At each mark() / expect.element() / locator action, run the DOM serializer and send snapshot data via the existing WebSocket RPC alongside the mark payload.
  • _markTrace handler: Remove the provider gate. Capture DOM snapshots for all providers. Optionally still delegate to Playwright trace.
  • Server: Add HTTP endpoints to serve rendered snapshots via the existing Vite dev server (e.g., /snapshot?id=... serving HTML in an iframe).
  • Trace viewer UI: New component in Vitest UI and HTML reporter — a timeline of marks with an inline DOM snapshot preview for the selected step, similar to Playwright's trace viewer.

What can be deferred:

  • Network HAR recording
  • Canvas content population
  • Cross-snapshot subtree deduplication
  • Video/screencast

Alternative

  • Embed Playwright's trace viewer directly. Downside: remains Playwright-only, heavy dependency, and doesn't integrate with Vitest's UI.
  • Use simple outerHTML instead of the compact format. Downside: misses form state, scroll positions, shadow DOM; much larger output; no deduplication.

Additional context

The DOM serializer runs as injected JS in the browser page (not through any provider API), making it naturally provider-agnostic. WebDriverIO and preview providers get DOM snapshot support for free.

The mark API already fires at all the right moments — this is about capturing DOM state at those existing hook points and rendering it in Vitest's own viewer:

  • page.mark(name) — explicit marks
  • locator.mark(name) — marks with element selector
  • expect.element() settlement — automatic marks after DOM assertions
  • runner.onAfterRetryTask — marks on test retry

Validations

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestp2-nice-to-haveNot breaking anything but nice to have (priority)

Projects

Status

Approved

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions