Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
d27aa95
feat(core,backend): emit console/stdout/stderr events into trace.zip …
vishnuv688 Jul 2, 2026
9eb326c
feat(app): trace-player layout parity — full workbench with top-docke…
vishnuv688 Jul 2, 2026
d4df0ac
feat(app): reference-style timeline strip with inline playback controls
vishnuv688 Jul 3, 2026
56af656
refactor(shared,backend,core): derive LogLevel from runtime LOG_LEVEL…
vishnuv688 Jul 3, 2026
fe19038
fix(backend): skip tracing-group markers when reconstructing player c…
vishnuv688 Jul 3, 2026
c7f94b4
feat(shared,backend,app): nested action tree with failure rollup in t…
vishnuv688 Jul 3, 2026
e5ba562
feat(shared,core): trace retention policy foundations
vishnuv688 Jul 7, 2026
adc167b
feat(core,backend): carry network response bodies through the trace
vishnuv688 Jul 7, 2026
53aebcf
feat(shared,core,backend,adapters): assertions as first-class trace a…
vishnuv688 Jul 7, 2026
a93fe17
refactor(core,adapters): consolidate trace-export orchestration into …
vishnuv688 Jul 7, 2026
c634da2
feat(core,backend): carry command result through the trace
vishnuv688 Jul 8, 2026
f81f8c4
feat(core,adapters): wire tracePolicy so retain-on-failure gates trac…
vishnuv688 Jul 8, 2026
e76b8c1
feat(core,service): surface expect/step failures on the triggering ac…
vishnuv688 Jul 8, 2026
f35b59c
feat(app): Errors tab in the workbench with jump-to-source
vishnuv688 Jul 8, 2026
dd4bc5b
fix(service,nightwatch): distinct rerun-stable uids for Cucumber step…
vishnuv688 Jul 8, 2026
3da30fa
fix(core,service): collapse same-timestamp snapshots so blank frames …
vishnuv688 Jul 8, 2026
2a26451
chore: Added more actions to the action mapping to appear in the time…
vishnuv688 Jul 8, 2026
9fe36d0
chore(examples): split wdio example into cucumber/ and mocha/ with sh…
vishnuv688 Jul 8, 2026
62d3a32
chore: Update path in readme and update pnpm-lock.yaml
vishnuv688 Jul 8, 2026
fabd782
fix(core): drop dependency-internal assertions from the trace
vishnuv688 Jul 8, 2026
c7f3ca4
fix(service): give Cucumber scenario-outline rows distinct trace groups
vishnuv688 Jul 8, 2026
8d1f98a
fix(service): show waits as actions and suppress their internal polling
vishnuv688 Jul 8, 2026
40d9208
feat(core,adapters): capture per-test retry attempts for retry-aware …
vishnuv688 Jul 9, 2026
ce5c673
feat(service,core): render expect-webdriverio matchers as trace actions
vishnuv688 Jul 9, 2026
7c87033
test(backend): remove skip-forever foreign-zip tests
vishnuv688 Jul 9, 2026
d6bcd38
chore(examples): add WDIO retry harness for retry-aware trace policies
vishnuv688 Jul 9, 2026
015fb75
docs: correct node:assert note; record retain-on-first-failure limita…
vishnuv688 Jul 9, 2026
56e92ff
refactor(shared,adapters): consolidate adapter types into shared
vishnuv688 Jul 9, 2026
3e5203b
test(service): cover expect-webdriverio matcher capture
vishnuv688 Jul 9, 2026
4d1c569
feat(core): per-test trace granularity foundation
vishnuv688 Jul 9, 2026
2626631
feat(trace): per-test granularity, output folders, and test-results/ …
vishnuv688 Jul 10, 2026
41db0aa
feat(service): capture expect-webdriverio matchers as assertion actions
vishnuv688 Jul 10, 2026
6b068e2
feat(nightwatch): capture native browser.assert/verify as assertion a…
vishnuv688 Jul 10, 2026
084bdb9
fix(core): rate-limit repeated terminal lines and fix failLastAction
vishnuv688 Jul 10, 2026
7009296
fix(app): real per-action duration and span-based active highlight
vishnuv688 Jul 10, 2026
f2a4534
fix(app): sidebar icon alignment and resizable-pane drag
vishnuv688 Jul 10, 2026
3a8092b
chore(examples): assertion + retry harnesses, chromedriver bump
vishnuv688 Jul 10, 2026
19d046a
docs: test-results/ layout, traceGranularity:'test', tracePolicy, and…
vishnuv688 Jul 10, 2026
98db922
fix(core): bound the pending-snapshot settle in trace finalize
vishnuv688 Jul 13, 2026
e7ddba8
fix(core): order trace actions chronologically, not by insertion
vishnuv688 Jul 13, 2026
10afcf8
fix(core): capture strict-mode node:assert and label asserts from args
vishnuv688 Jul 13, 2026
181b6d5
fix(nightwatch): emit native asserts at test-end with real outcomes
vishnuv688 Jul 13, 2026
80916f6
fix(service): keep expect matchers to a single row
vishnuv688 Jul 13, 2026
26e79a2
fix(app): render assertions consistently across frameworks
vishnuv688 Jul 13, 2026
6d066d5
fix(backend): escape test names in grep-style rerun filters
vishnuv688 Jul 13, 2026
918c830
fix(selenium): read snapshot state via unpatched driver; forward trac…
vishnuv688 Jul 13, 2026
7da55c0
chore(selenium): bump chromedriver to ^150 for Chrome 150
vishnuv688 Jul 13, 2026
b4522a7
chore(examples): live/trace config-ladder harnesses + retry scripts
vishnuv688 Jul 13, 2026
47aa59e
docs: record Nightwatch BDD per-test and WDIO assert-capture debt
vishnuv688 Jul 13, 2026
83345d2
refactor: dedupe assert-result type into shared; drop unused trace de…
vishnuv688 Jul 13, 2026
42a6d88
refactor(core): one findFlushableRange for the three adapters' slice …
vishnuv688 Jul 13, 2026
ac211b2
refactor(service): rebuild expect-matcher capture around before/after…
vishnuv688 Jul 13, 2026
1cf0bcc
fix(service): exclude the devtools bundle from user-frame detection
vishnuv688 Jul 13, 2026
03f5f77
fix(nightwatch): record negated native asserts (assert.not.* / verify…
vishnuv688 Jul 14, 2026
8781afb
refactor(service): extract assertion capture into AssertionTracker
vishnuv688 Jul 14, 2026
b5d6ade
docs: sync WDIO assert-capture debt to the fold model; drop fixed ent…
vishnuv688 Jul 14, 2026
35ec983
feat(core): per-attempt outcome ledger + group-by-test retention
vishnuv688 Jul 14, 2026
80b32f9
fix(service): feed the retention ledger for correct retry-aware policies
vishnuv688 Jul 14, 2026
6a70ca3
fix(core): fall back to metadata when a scoped retention ledger view …
vishnuv688 Jul 14, 2026
305c6ea
fix(core): infer the failed attempt from a retry in the outcome ledge…
vishnuv688 Jul 14, 2026
1e8bf17
fix(nightwatch): feed the retention ledger for correct retry-aware po…
vishnuv688 Jul 14, 2026
8542175
fix(selenium): feed the retention ledger for correct retry-aware poli…
vishnuv688 Jul 14, 2026
941ab02
docs: retry-aware retention scope + assert-capture debt sync
vishnuv688 Jul 14, 2026
7c18690
feat(core): artifacts manifest + WDIO Allure trace/video attach
vishnuv688 Jul 14, 2026
cb555e2
feat: per-test screenshot + video options with inline Allure attach
vishnuv688 Jul 15, 2026
28982ce
fix(core): replace polynomial-ReDoS edge-trims with a linear trimChar
vishnuv688 Jul 15, 2026
8e96fd0
fix: scope screenshot/video options to the WDIO ServiceOptions
vishnuv688 Jul 15, 2026
7cc96f6
fix(app): de-duplicate live-mode Errors tab (command + reworded test …
vishnuv688 Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ packages/nightwatch-devtools/nightwatch-video-*.webm
trace-*.zip
examples/**/trace-*/

# test results
examples/**/test-results/

# vitest --coverage output
coverage/

# pnpm state, cache, logs, and debug files
/packages/**/*.mjs

.claude
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ The execution environment is the browser, not Node, so this package cannot impor

Per-framework demo projects used for manual verification.

- `examples/wdio/` — WebdriverIO with Mocha (default). Run via `pnpm demo:wdio`.
- `examples/wdio/` — WebdriverIO, split into `cucumber/` and `mocha/` (shared page objects in `pageobjects/`). Run via `pnpm demo:wdio` (Cucumber) or `pnpm demo:wdio:mocha`.
- `examples/nightwatch/` — Nightwatch (both vanilla and Cucumber). Run via `pnpm demo:nightwatch`.
- `examples/selenium/` — Selenium with subdirs for `mocha-test/`, `jest-test/`, `cucumber-test/`, `jasmine-test/`, `vitest-test/`. `pnpm demo:selenium` runs mocha; `pnpm --filter @wdio/selenium-devtools example:<runner>` runs the others.

Expand Down
15 changes: 13 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,23 @@ Documented divergences from the conventions above. They exist today as debt to b
### Architecture

- `replaceCommand` has two semantics — Selenium mutates in place (preserves `_id`/`id` for chained calls); Nightwatch splices and reissues. Both call the same `core/suite-helpers` factories; the storage strategy stays adapter-specific because runner integrations differ. Could be unified by parameterizing the policy if the divergence ever causes a real problem.
- `patchNodeAssert` is wired only in `selenium-devtools`. The shared helper lives in `core/assert-patcher`; Service and Nightwatch can opt in via a one-line call when ready. Not auto-enabled — both communities lean on chai/expect.
- `patchNodeAssert` (via `core/assert-patcher`) is now wired in all three adapters, default-on behind each adapter's `captureAssertions` option (opt out with `captureAssertions: false`). Framework matcher libraries differ: Service taps expect-webdriverio's `beforeAssertion`/`afterAssertion` hooks so passing+failing matchers render as `expect.*` actions (mechanism in the assert-capture entry below); Nightwatch native `assert`/`verify` and Selenium's `node:assert` also surface passing+failing rows via their reconcile/patch paths. The remaining gap is Selenium's jest-style `expect()` (and chai): jest/vitest expose no pass+fail assertion hook, so only failing matchers surface there.
- BiDi is auto-attached in Service and Selenium; Nightwatch is opt-in via `bidi: true` and requires `webSocketUrl: true` in capabilities.
- Retry-aware trace policies share one mechanism: adapters feed a per-attempt **outcome ledger** (`core/attempt-tracker.ts` `TestAttemptTracker.recordStart(uid, specFile)` + `recordOutcome(uid, state, attempt)`) keyed by the **retry-stable** uid, and the finalizer reads the scoped views (`all`/`forSpec`/`forTest`) so `trace-retention.ts` evaluates **group-by-test** — `retain-on-failure` keys on each test's *final* attempt (no over-retaining a fail-then-pass), `retain-on-first-failure` on *attempt 0*. `recordStart` on a second attempt stamps the prior attempt `failed` (a retry only follows a failure), which corrects runners that swallow the intermediate failure — e.g. Mocha via a `--require` plugin never surfaces the retried attempt's failure, so the ledger would otherwise see `[passed, passed]`. An empty scoped view falls back to `testMetadata` (never fail-open-retains).
- **WDIO + Selenium: verified end-to-end** (manual fail-then-pass runs: retained under `retain-on-first-failure`, dropped under `retain-on-failure`).
- **Nightwatch: `retain-on-failure` works; the other retry-aware policies degrade.** Its `--retries` re-runs the testcase *internally* without re-firing the plugin's per-test hooks, and the per-testcase results carry no attempt/retry field (retries live only in undocumented, version-varying Nightwatch internals — `suiteRetries.testRetriesCount` / `reporter.testResults.retryTest`), so the ledger sees only the final attempt for the `describe/it` and exports-object interfaces. Cucumber scenarios expose per-scenario hooks, so the feed captures their attempts. Not cleanly fixable without depending on those internals.
- WDIO `specFileRetries` spawns a fresh worker per retry, so cross-process attempts aren't in the (process-scoped) ledger.
- Eager per-test trace slice (Nightwatch + Selenium) can drop an action snapshot whose fire-and-forget capture hasn't resolved by `afterEach` / scenario end — the slice is written from whatever snapshots exist at flush time. The WDIO service is immune because it awaits each snapshot inline before flushing.
- The per-test `screenshot` and `video` options live on the **WDIO `ServiceOptions` only** — not `BaseDevToolsOptions` — because only the service implements them (an option belongs on an adapter until a second adapter consumes it, mirroring the core-helper rule; putting them on the shared base made them appear available in Selenium/Nightwatch and broke those adapters' `Required<>` option types). The policy *types* (`TraceScreenshotPolicy`/`TraceVideoPolicy`) and the capture/slice/encode logic (`core/screenshot-artifact.ts`, `core/video-slice.ts`) are framework-agnostic, so Selenium/Nightwatch adoption is wiring-only (capture the base64 + feed `captureAndAttach*`) plus adding the option to their own options type; pending. Both are gated to `traceGranularity:'test'` (per-test inline Allure); coarser granularities keep artifacts in the manifest. Video records the screencast continuously and slices per-test by wall-time — the frame buffer is unbounded for the session (a decimation cap is a noted follow-up), and on non-Chrome the polling recorder issues many `takeScreenshot`s that flood `@wdio/allure-reporter` (pair with `disableWebdriverStepsReporting`).
- Nightwatch native asserts are buffered at call time and emitted in one batch at test-end (Nightwatch exposes no per-assertion execution/outcome hook reachable from the plugin — `client.queue.tree` / `client.reporter` aren't on `browser`). Streaming mid-run would flash every assert green before its outcome is known, so rows are held and reconciled against `results.testcases[*].assertions` at `afterEach` (the flat `results.assertions` only reflects the last testcase). The exporter re-sorts commands by timestamp (`buildActionEvents`) so the batched rows land at their real timeline positions rather than clustering at flush time. `actual` is parsed from the failure message (`but got: …`, failures only) into a collapsed `{passed, expected, actual}` result; `expected` is the assertion arg — the label still mirrors the call args, not the derived values.
- Nightwatch's BDD `describe/it` interface fires the plugin's global `beforeEach`/`afterEach` **once per module** (with an empty `currentTest.name`), not per `it` — Nightwatch runs the individual `it`s internally with no per-testcase hook or event reachable from the plugin (the lib emits only transport-level events). So `traceGranularity:'test'` records a single slice boundary (the first test) and collapses to one session-scoped slice; retry-aware/per-test retention (`tracePolicy`) degrades to session scope for this interface. Per-test slicing works for adapters/styles that expose per-test hooks (WDIO mocha/cucumber, Selenium mocha; likely Nightwatch's exports-object style, unverified). Session-granularity trace is unaffected.
- Service renders expect-webdriverio matchers as single `expect.<matcher>` rows by **folding**, not stack/depth suppression (the old `#assertionDepth`/`#matcherStarted`/self-heal machinery is gone). The matcher's value-read (`toHaveText`→`getText`, `toExist`→`isExisting`, …) is captured as a normal command; `afterAssertion` then coalesces the synthesized `expect.*` row into that read in place — inheriting its callSource, screenshot, and timeline position — and the fold replaces **by timestamp, never a public `id`**: `id` is the per-worker `commandCounter`, which resets per spec, so stamping one lets the app's id-first `replaceCommand` swap a same-id row from another spec (duplicate rows + a fold from another spec vanishing, in multi-spec live mode). `beforeAssertion` arms the pending matcher (depth-counted so aliases like `toBeChecked`→`toBeSelected` fold once); a matcher that **hard-throws** — element never resolves, so expect-webdriverio's `waitUntil` rethrows and `afterAssertion` never fires — is synthesized at `afterTest`/`afterStep` from the throwing read, so a failing assertion renders as `expect.<matcher>` whether or not the element existed. Two limits: its error is then the read's (`Can't call getText on … element wasn't found`), not an assertion-phrased message; and `MATCHER_READ_COMMANDS` is a hand-maintained allowlist, so a matcher whose read isn't listed leaves its raw read visible alongside the `expect.*` row. Plain-value jest matchers (`expect(x).toBe(y)`) don't fire the ewdio hooks, so they aren't captured as rows.

### File-size (raw line counts; soft cap is 500 logic lines)

None of the entries below trigger the `max-lines` lint rule after `skipBlankLines`/`skipComments`. They're documented because their raw line count is over 500, and the next substantive change to any of them should still look for an extraction opportunity.
Most entries below don't trigger the `max-lines` lint rule after `skipBlankLines`/`skipComments`; they're documented because their raw line count is over 500, and the next substantive change to any of them should still look for an extraction opportunity. The service plugin is the exception — it's now over the *logic*-line cap.

- `packages/service/src/index.ts` — over the 500-**logic**-line soft cap and ~620 raw (the WDIO plugin god-file: session/screencast/command/assertion/trace-slice wiring in one class). The assertion-capture block (`beforeAssertion`/`afterAssertion`/`#handleAssertionOutcome`/`#finalizePendingAssertion`, plus the `#assertionDepth`/`#pendingAssertion` state) is now the largest self-contained seam and the prime extraction candidate; trace-slice and screencast are the next two.

- `packages/nightwatch-devtools/src/index.ts` (~536 raw). Cucumber/test/run-lifecycle, session-init, event-hub modules already extracted; remainder is the `PluginInternals` accessor bag plus per-method delegators plus the factory. Accept-as-is.
- `packages/selenium-devtools/src/index.ts` (~560 raw). Session/test-lifecycle extracted; remainder is the `PluginInternals` accessor bag plus onCommand/onDriverCreated wiring. Same situation as nightwatch.
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ When BiDi is active in Selenium or Nightwatch, the per-command Chrome performanc

### 📦 Trace mode (trace.zip)

Headless capture path — no DevTools UI window opens. At session end the adapter writes a trace artifact next to the user's output directory, suitable for offline replay, AI-agent diffing, or any consumer that prefers a portable artifact over a live UI.
Headless capture path — no DevTools UI window opens. At session end the adapter writes trace artifacts into a `test-results/` folder (created next to the resolved spec/config directory), suitable for offline replay, AI-agent diffing, or any consumer that prefers a portable artifact over a live UI.

| Adapter | How to enable |
|---|---|
Expand All @@ -79,7 +79,7 @@ Headless capture path — no DevTools UI window opens. At session end the adapte
| **Nightwatch** | `globals: nightwatchDevtools({ mode: 'trace' })` |

The trace artifact contains:
- `trace.trace` — NDJSON `context-options` + `before`/`after` action events. When test hooks are available (Mocha's `it()` / Cucumber's `Scenario()`), each test becomes a [`Tracing.tracingGroup`](https://github.com/VibiumDev/vibium/blob/main/docs/explanation/recording-format.md#action-groups-user-defined) span — an open/close `before`/`after` pair with `method: "tracingGroup"` and `params.name` set to the test title. Child actions inside the group carry `parentId` pointing back to the group's `callId`, so timeline viewers render tests as labelled spans wrapping their commands.
- `trace.trace` — NDJSON `context-options` + `before`/`after` action events. When test hooks are available (Mocha's `it()` / Cucumber's `Scenario()`), each test becomes a `Tracing.tracingGroup` span — an open/close `before`/`after` pair with `method: "tracingGroup"` and `params.name` set to the test title. Child actions inside the group carry `parentId` pointing back to the group's `callId`, so timeline viewers render tests as labelled spans wrapping their commands.
- `trace.network` — HAR-style network entries derived from the existing capture
- `resources/page@<id>-<ts>.jpeg` — screenshot per user-facing action
- `resources/elements-page@<id>-<ts>.json` — flat interactable element list extracted by the page-injected scripts in `@wdio/devtools-core/element-scripts`
Expand All @@ -103,15 +103,17 @@ npx show-trace path/to/trace.zip # in a project that installs an adapter

The `show-trace` bin is exposed by each 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.

**Other viewers.** Because the format is unchanged, the same `.zip` also drops into [player.vibium.dev](https://player.vibium.dev) or `npx playwright show-trace <path>`. The format follows the [Vibium recording format](https://github.com/VibiumDev/vibium/blob/main/docs/explanation/recording-format.md) spec — a Playwright-compatible NDJSON schema that the ecosystem already renders. This is the same format [`@wdio/mcp`](https://webdriver.io/docs/mcp) uses for AI-driven session recording.
**Other viewers.** The trace uses a portable NDJSON schema, so the same `.zip` also opens in other compatible trace viewers that read the format. This is the same format [`@wdio/mcp`](https://webdriver.io/docs/mcp) uses for AI-driven session recording.

#### Options

| Option | Values | Default | Description |
|--------|--------|---------|-------------|
| `mode` | `'live'` \| `'trace'` | `'live'` | `'live'` launches the DevTools UI; `'trace'` writes an offline artifact. |
| `traceFormat` | `'zip'` \| `'ndjson-directory'` | `'zip'` | Output layout. `'zip'` writes a single archive; `'ndjson-directory'` unpacks into `trace-<id>/`. |
| `traceGranularity` | `'session'` \| `'spec'` | `'session'` | `'session'` writes one trace per worker; `'spec'` writes one trace per spec file — smaller artifacts, easier to navigate. |
| `traceGranularity` | `'session'` \| `'spec'` \| `'test'` | `'session'` | `'session'` writes one trace per worker; `'spec'` one per spec file; `'test'` one per test into its own `<spec>-<title>-<browser>[-retryN]/trace.zip` folder — the smallest, most navigable artifacts, and the best pairing for a retention policy. |
| `tracePolicy` | `'on'` \| `'retain-on-failure'` \| `'retain-on-first-failure'` \| `'on-first-retry'` \| `'on-all-retries'` \| `'retain-on-failure-and-retries'` | `'on'` | Which traces to keep. `'on'` keeps every trace; the rest keep only failing/retried tests — pairs well with `traceGranularity: 'test'`. |
| `captureAssertions` | `boolean` | `true` | Capture assertions as action rows: `node:assert` (all adapters), WebdriverIO `expect(...)` matchers, and Nightwatch `browser.assert`/`verify`. Set `false` to opt out. |

WDIO config example:

Expand All @@ -129,7 +131,7 @@ services: [[DevToolsHookService, {

Adapters detect mobile sessions via `platformName: 'android' | 'ios'` (case-insensitive) and adjust the per-action snapshot to extract elements from the mobile XML tree instead of the DOM. The trace's `context-options` records `title: 'android' — <deviceName>` / `'ios' — <deviceName>` so the viewer labels frames correctly.

A reference WDIO config is at [examples/wdio/wdio.mobile.conf.ts](examples/wdio/wdio.mobile.conf.ts). Prereqs to run it end-to-end with a local emulator:
A reference WDIO config is at [examples/wdio/cucumber/wdio.mobile.conf.ts](examples/wdio/cucumber/wdio.mobile.conf.ts). Prereqs to run it end-to-end with a local emulator:

1. **Java JDK** — `brew install --cask temurin`
2. **Android SDK** — `brew install --cask android-commandlinetools` then `yes | sdkmanager --licenses && sdkmanager "platform-tools" "emulator" "system-images;android-34;google_apis_playstore;arm64-v8a"`. The brew cask installs sdkmanager under `/opt/homebrew/share/android-commandlinetools/`, and sdkmanager downloads other SDK pieces alongside it — set `ANDROID_HOME` to that path (not `~/Library/Android/sdk/`).
Expand Down
24 changes: 16 additions & 8 deletions examples/nightwatch/nightwatch.conf.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,24 @@ module.exports = {
},
'goog:loggingPrefs': { performance: 'ALL' }
},
// Simple configuration - just call the function to get globals.
// - screencast: polling-mode .webm written to cwd as
// nightwatch-video-<sessionId>.webm.
// - bidi: opt-in WebDriver BiDi capture for console + network. When
// attached, the per-command Chrome perf-log network path is gated
// off to avoid duplicate entries.
// bidi: opt-in WebDriver BiDi capture for console + network. When
// attached, the per-command Chrome perf-log network path is gated off to
// avoid duplicate entries.
globals: nightwatchDevtools({
port: 3000,
mode: 'live',
screencast: { enabled: true, pollIntervalMs: 200 },
// ── Config ladder — change ONLY this block per rung ───────────────
// 1 live: mode: 'live'
// 2 trace: mode: 'trace'
// 3 per-test: mode: 'trace', traceGranularity: 'test'
// 4 fail: mode: 'trace', traceGranularity: 'test', tracePolicy: 'retain-on-failure'
// 5 retry: mode: 'trace', traceGranularity: 'test', tracePolicy: 'on-first-retry'
// (rung 5 needs retries → run `pnpm demo:nightwatch:retry`)
// NOTE: the BDD describe/it interface fires the plugin's beforeEach once
// per module (no per-`it` hook), so traceGranularity:'test' collapses to
// a single session-scoped slice here. See CLAUDE.md § Known debt.
mode: 'trace',
traceGranularity: 'session',
tracePolicy: 'retain-on-first-failure',
bidi: true
})
}
Expand Down
47 changes: 0 additions & 47 deletions examples/nightwatch/tests/login.js

This file was deleted.

Loading
Loading