Skip to content

Open several trace zips or a whole run in the player - #523

Merged
vishnuv688 merged 2 commits into
mainfrom
feat/501-open-whole-run
Nov 2, 2026
Merged

vishnuv688 merged 2 commits into
mainfrom
feat/501-open-whole-run

Conversation

@vishnuv688

Copy link
Copy Markdown
Member

What & why

Closes #501. Part of #494. Stacked on #522.

With traceGranularity: 'test' every test writes its own zip, so a failed CI run is a folder of zips that had to be opened one at a time. The player, hosted and show-trace alike, now opens several zips or a whole folder at once, lists them with each test's outcome (failures first), and plays the one picked without reloading. Opening a single zip behaves exactly as before, with no list.

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Polish (an improvement to an existing feature)
  • Breaking change (existing behavior changes for users)
  • Documentation
  • Internal (build, CI, dependencies, tooling)

Packages touched

  • shared (types and contracts)
  • core (framework-agnostic capture/reporting)
  • elements (published element/snapshot API — @wdio/elements)
  • service (WebdriverIO adapter)
  • nightwatch-devtools (Nightwatch adapter)
  • selenium-devtools (Selenium adapter)
  • selenium-devtools-py (Selenium Python adapter)
  • backend (server)
  • app (UI)
  • script (page-injected runtime)
  • trace (Trace mode)

Capability matrix

  • packages/conformance/src/features.ts updated, and tables regenerated with pnpm docs:capabilities, if this adds or changes user-facing behaviour

Not updated: the player opens traces from every adapter the same way, so this is not a per-adapter capability. Say if the trace-mode row should mention it.

Notes for reviewers

What it does

  • Hosted player: "Select files" (multiple) and "Select folder" on the landing screen and in the header; drop several zips, a folder, or both. Folders are walked recursively and non-zip files in them skipped; a file picked or dropped directly is always tried, so a wrong file still gets the reader's error.
  • show-trace <zip | folder>...: exactly one zip behaves as today. Several are listed at TRACE_API.run, and each zip's bytes are served at TRACE_API.zip by its position in the list fixed at startup: the request carries only a number (^\d+$), never a path. That route has its own rate limit sized to the list, since the backend's global 100/min would block a large run (a test with 120 zips fails without it). The contract (TraceRunListing, traceZipUrl) is in shared/trace-player.ts.
  • The list sits where a live run's test tree sits, with the same resize handle: a status icon (the sidebar's, now shared as state-icon.ts), the test name and its path; a zip that could not be opened is its own row with the reason; a header line counts traces, failures and unopenable zips, and shows progress while loading. Rows are buttons: Tab, Up/Down, Enter or Space (Space is kept from toggling playback).

Design notes

  • Outcome is derived, because a zip does not record its test's result: failed when an action or step failed (a poll a passing wait retried past does not count), passed when it has actions and none failed, unknown when it has none. A jest expect or chai failure records no row, so that test reads as passed; the README says so.
  • Every zip is read up front, one at a time, because the outcome the list exists to show needs a full read; each result is kept for when its row is picked. There is no separate cache: the list holds the reader's own output, so Trace reader: read zip entries on demand instead of up front #498's on-demand reading shrinks it with no change here. Memory grows with the number of traces opened.
  • Order: failed, could not open, unknown, passed, each in run order; rows keep their found order while loading so they do not move under the pointer, then sort once and open the top row unless one was already picked. A newer open cancels a run still loading.
  • To stay within the file-size caps, the boot-time trace probe moved out of DataManager.ts to controller/trace-serve.ts, the localStorage cache to controller/trace-cache.ts, and the backend's trace routes to trace-routes.ts.
  • Privacy unchanged: the hosted build fetches nothing new and writes nothing to browser storage.

Testing

  • pnpm install --frozen-lockfile, pnpm build, pnpm test (3484 passed, twice) and pnpm lint are green after rebasing onto Move duplicated adapter code into core #522; one import conflict in the backend resolved.
  • New tests: outcome derivation, file collection from inputs, drops and folders, list ordering, per-row error isolation, cancelling a superseded run, and the backend listing, index-only file serving and rate limit.

Needs checking by eye

  1. A folder of per-test zips: DEVTOOLS_MODE=trace DEVTOOLS_TRACE_GRANULARITY=test pnpm demo:wdio (make one assertion fail for a failed row; drop a junk .zip in for a could-not-open row).
  2. pnpm show-trace <that folder>, two zip paths, and one zip (unchanged).
  3. pnpm player:hosted: pick several files, pick a folder, drop a folder, drop one zip (unchanged), and use the header's folder button while a list is shown. Check row layout in both themes, focus ring, Up/Down, and that switching rows clears the previous trace's selection.

Not in this PR

  • In show-trace the zips are parsed on the page's main thread (the live build has no worker), so a large folder can stutter while loading; the hosted build uses the worker.
  • One row per zip: a session- or spec-level zip holding several tests is one row.
  • The docs-site mirror, with the other docs-site changes once trace.webdriver.io is live.

Screenshots / recordings

To be added: the list with failed, passed and could-not-open rows, in both themes.

🤖 Generated with Claude Code

vishnuv688 and others added 2 commits October 30, 2026 15:31
With traceGranularity 'test' every test writes its own zip, so a failed CI
run is a folder of zips that had to be opened one at a time. The player,
hosted and show-trace alike, now opens several zips or a folder at once and
lists them with each test's outcome, failures first, playing the one picked
without reloading. Opening a single zip behaves as before, with no list.

A zip does not record its test's result, so the outcome is derived: failed
when an action or step failed (a poll a passing wait retried past does not
count), passed when it has actions and none failed, unknown otherwise. A
jest expect or chai failure records no row and so reads as passed. Each zip
is read once, one at a time; a zip that cannot be opened is its own row and
does not stop the rest.

show-trace takes several zips or folders; the backend lists them at
TRACE_API.run and serves each by its position in the list, never by a path
from the request.

Closes #501

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A browser's file dialog picks files or folders, never both, so the landing
screen and the header each offered two pickers. They now offer one: "Open
traces" picks one or several zips, and a folder opens by dropping it
anywhere on the page, which already walked folders. The header's tooltip
says so, since its folder button is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vishnuv688
vishnuv688 force-pushed the refactor/adapter-duplicates-to-core branch from 2b01d71 to f00bd8d Compare October 30, 2026 10:13
@vishnuv688
vishnuv688 force-pushed the feat/501-open-whole-run branch from 9aae1d4 to 0ca62df Compare October 30, 2026 10:13
@vishnuv688
vishnuv688 changed the base branch from refactor/adapter-duplicates-to-core to main November 2, 2026 10:20
@vishnuv688
vishnuv688 merged commit ae77e80 into main Nov 2, 2026
10 checks passed
@vishnuv688
vishnuv688 deleted the feat/501-open-whole-run branch November 2, 2026 10:24
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.

Player: open several traces or a whole run at once

1 participant