Skip to content

Commit 0ca62df

Browse files
vishnuv688claude
andcommitted
Open traces through one button, with folders dropped
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>
1 parent 0ae4f43 commit 0ca62df

4 files changed

Lines changed: 12 additions & 52 deletions

File tree

‎.changeset/open-whole-run.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
'@wdio/devtools-backend': minor
44
---
55

6-
The trace player opens several traces at once. `show-trace` accepts several zips or a folder (`npx show-trace test-results/`), and the hosted player accepts several zips or a folder, picked or dropped. The player then lists every trace beside the timeline, one row per test with its outcome, failures first and then in run order, and plays the one picked without reloading. With `traceGranularity: 'test'` a run is a folder of per-test zips, so the whole run opens in one go. A zip records no test state, so the outcome is read from the trace: failed when an action or step failed, passed when it holds actions and none failed, unknown when it holds none. Files in the folder that are not zips are skipped, and a zip that cannot be opened is listed with the reason without stopping the rest. Opening a single zip works exactly as before.
6+
The trace player opens several traces at once. `show-trace` accepts several zips or a folder (`npx show-trace test-results/`), and the hosted player takes several zips through its Open button, or zips and folders dropped on the page. The player then lists every trace beside the timeline, one row per test with its outcome, failures first and then in run order, and plays the one picked without reloading. With `traceGranularity: 'test'` a run is a folder of per-test zips, so the whole run opens in one go. A zip records no test state, so the outcome is read from the trace: failed when an action or step failed, passed when it holds actions and none failed, unknown when it holds none. Files in the folder that are not zips are skipped, and a zip that cannot be opened is listed with the reason without stopping the rest. Opening a single zip works exactly as before.

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ The player exposes everything captured in the archive:
262262

263263
The `show-trace` bin is exposed by each JavaScript adapter (`@wdio/devtools-service`, `@wdio/nightwatch-devtools`, `@wdio/selenium-devtools`), so `pnpm show-trace <zip>` / `npx show-trace <zip>` work in any project that installs one — no extra dependency.
264264

265-
**A whole run at once.** With `traceGranularity: 'test'` every test writes its own `trace.zip`, so a run is a folder of them. Give `show-trace` the folder, or several zips, and the player lists every trace beside the timeline, one row per test with its outcome, failures first and then in the order they ran; picking a row plays that trace without reloading (`↑`/`↓` move between rows, `Enter` opens one). The hosted player does the same for several zips, or a folder, picked or dropped on the page.
265+
**A whole run at once.** With `traceGranularity: 'test'` every test writes its own `trace.zip`, so a run is a folder of them. Give `show-trace` the folder, or several zips, and the player lists every trace beside the timeline, one row per test with its outcome, failures first and then in the order they ran; picking a row plays that trace without reloading (`↑`/`↓` move between rows, `Enter` opens one). The hosted player does the same for several zips picked with its one Open button, or for a folder dropped on the page (a browser's file dialog picks files or folders, never both).
266266

267267
```sh
268268
pnpm show-trace test-results/ # every zip under the folder
@@ -271,7 +271,7 @@ pnpm show-trace a/trace.zip b/trace.zip # several zips
271271

272272
Each zip is read once, as the list fills in, and kept for when it is picked. Anything in the folder that is not a `.zip` (screenshots, videos, the artifacts manifest) is skipped; a zip that cannot be opened stays in the list with the reason, and the rest open normally. A zip records no test state, so the outcome is read from the trace itself: **failed** when an action or step in it failed, **passed** when it holds actions and none failed, **unknown** when it holds none. An assertion library that records no row (a jest `expect`, chai) can fail a test whose trace still reads as passed. One zip opens exactly as before, with no list.
273273

274-
**Hosted player: [trace.webdriver.io](https://trace.webdriver.io).** The same player as a web page, for opening a trace without installing anything: drop a `.zip` on the page or pick one, or several, or a folder of them. The archive is parsed in the browser tab and never uploaded, which matters because a trace records everything the run showed or typed. Run controls are absent, as in `show-trace`. A replayed page still loads its own stylesheets and images from the site under test, as it does in `show-trace`; from an `https` page the browser blocks the `http` ones, so a trace of an `http` site can render unstyled there and fully in `show-trace`. To try the hosted build locally:
274+
**Hosted player: [trace.webdriver.io](https://trace.webdriver.io).** The same player as a web page, for opening a trace without installing anything: pick one or several `.zip` files, or drop them or a folder of them on the page. The archive is parsed in the browser tab and never uploaded, which matters because a trace records everything the run showed or typed. Run controls are absent, as in `show-trace`. A replayed page still loads its own stylesheets and images from the site under test, as it does in `show-trace`; from an `https` page the browser blocks the `http` ones, so a trace of an `http` site can render unstyled there and fully in `show-trace`. To try the hosted build locally:
275275

276276
```sh
277277
pnpm player:hosted # builds it and serves it at http://localhost:4173 under the production headers

‎packages/app/src/components/header.ts‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import '~icons/custom/logo.svg'
66
import '~icons/mdi/white-balance-sunny.js'
77
import '~icons/mdi/moon-waning-crescent.js'
88
import '~icons/mdi/upload.js'
9-
import '~icons/mdi/folder-open.js'
109

1110
import {
1211
applyDarkMode,
@@ -110,42 +109,25 @@ export class DevtoolsHeader extends Element {
110109
`
111110
}
112111

113-
@query('input[data-pick="files"]') traceInput?: HTMLInputElement
114-
@query('input[data-pick="folder"]') folderInput?: HTMLInputElement
112+
@query('input[type="file"]') traceInput?: HTMLInputElement
115113

116114
#openTraceButton() {
117115
return html`
118116
<button
119117
class="p-2"
120-
title="Open other trace .zip files"
121-
aria-label="Open other trace .zip files"
118+
title="Open trace .zip files, or drop a folder of them on the page"
119+
aria-label="Open trace .zip files"
122120
@click="${() => this.traceInput?.click()}"
123121
>
124122
<icon-mdi-upload></icon-mdi-upload>
125123
</button>
126-
<button
127-
class="p-2"
128-
title="Open a folder of traces"
129-
aria-label="Open a folder of traces"
130-
@click="${() => this.folderInput?.click()}"
131-
>
132-
<icon-mdi-folder-open></icon-mdi-folder-open>
133-
</button>
134124
<input
135-
data-pick="files"
136125
type="file"
137126
accept="${TRACE_FILE_ACCEPT}"
138127
multiple
139128
hidden
140129
@change="${() => this.#onTracePicked(this.traceInput)}"
141130
/>
142-
<input
143-
data-pick="folder"
144-
type="file"
145-
webkitdirectory
146-
hidden
147-
@change="${() => this.#onTracePicked(this.folderInput)}"
148-
/>
149131
`
150132
}
151133

‎packages/app/src/components/onboarding/open-trace.ts‎

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ export class DevtoolsOpenTrace extends Element {
2222

2323
@state() dragging = false
2424

25-
@query('input[data-pick="files"]') input?: HTMLInputElement
26-
@query('input[data-pick="folder"]') folderInput?: HTMLInputElement
25+
@query('input[type="file"]') input?: HTMLInputElement
2726

2827
static styles = [
2928
...Element.styles,
@@ -46,14 +45,8 @@ export class DevtoolsOpenTrace extends Element {
4645
border-color: var(--accent);
4746
}
4847
49-
.actions {
50-
display: flex;
51-
justify-content: center;
52-
gap: 8px;
53-
margin-top: 16px;
54-
}
55-
5648
button {
49+
margin-top: 16px;
5750
padding: 8px 18px;
5851
border-radius: 6px;
5952
background: var(--accent);
@@ -156,34 +149,19 @@ export class DevtoolsOpenTrace extends Element {
156149
return this.phase ? TRACE_OPEN_PHASE_LABEL[this.phase] : 'Opening trace…'
157150
}
158151

152+
// A picker takes files or folders, never both, so folders come in by drop.
159153
#pickers() {
160154
return html`
161-
<div class="actions">
162-
<button ?disabled="${this.busy}" @click="${() => this.input?.click()}">
163-
Select files
164-
</button>
165-
<button
166-
?disabled="${this.busy}"
167-
@click="${() => this.folderInput?.click()}"
168-
>
169-
Select folder
170-
</button>
171-
</div>
155+
<button ?disabled="${this.busy}" @click="${() => this.input?.click()}">
156+
Open traces
157+
</button>
172158
<input
173-
data-pick="files"
174159
type="file"
175160
accept="${TRACE_FILE_ACCEPT}"
176161
multiple
177162
hidden
178163
@change="${() => this.#onPick(this.input)}"
179164
/>
180-
<input
181-
data-pick="folder"
182-
type="file"
183-
webkitdirectory
184-
hidden
185-
@change="${() => this.#onPick(this.folderInput)}"
186-
/>
187165
`
188166
}
189167

0 commit comments

Comments
 (0)