Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
429c544
test: add cross-adapter capture-parity harness (Layer A)
vishnuv688 Jul 27, 2026
009928b
test: add cross-adapter verification harness (Layer A + Layer B)
vishnuv688 Jul 27, 2026
f6797e7
test(visual): enforce WebDriver Classic to avoid flaky BiDi shadow-DO…
vishnuv688 Jul 27, 2026
4e2dff5
fix(nightwatch): generate cucumber traces (build the hooks + capture …
vishnuv688 Jul 27, 2026
f193aac
feat(nightwatch): capture native asserts in cucumber traces
vishnuv688 Jul 27, 2026
2766e27
test(visual): pin device-scale-factor so HEADED matches headless base…
vishnuv688 Jul 27, 2026
252c889
test(harness): add live-mode parity layer + record-live recorder
vishnuv688 Jul 28, 2026
6aa9b7c
test(harness): finalize Layer B — re-mint visual baselines + live-das…
vishnuv688 Jul 28, 2026
fcf2b0b
fix(capture): recover DOM capture on documents that miss script injec…
vishnuv688 Jul 28, 2026
e4a6507
test(app): add WDIO component tests for the Lit dashboard
vishnuv688 Jul 29, 2026
52ac526
test(harness): drop the fixture-driven verification layers
vishnuv688 Jul 29, 2026
e1a1275
refactor(shared): make the trace.zip layout one definition
vishnuv688 Jul 29, 2026
c603d31
test(core): table the traceGranularity × tracePolicy grid
vishnuv688 Jul 29, 2026
8a5687b
test(core): assert the artifacts manifest per trace config
vishnuv688 Jul 29, 2026
4ab67ca
test(app): use path aliases and the real demo URLs in component specs
vishnuv688 Jul 29, 2026
59d3125
test(app): cover Tier 1 components with rendering specs
vishnuv688 Jul 29, 2026
ace6f85
test(app): cover Tier 2 components with rendering specs
vishnuv688 Jul 29, 2026
56422d3
fix(app): stop the Errors tab mangling assertion failures
vishnuv688 Jul 30, 2026
914d94b
test(app): cover the compare panel
vishnuv688 Jul 30, 2026
88035a2
test(app): derive sidebar row state instead of asserting it
vishnuv688 Jul 30, 2026
d5ec4ca
test(app): harden panel and player specs, unit-test their helpers
vishnuv688 Jul 30, 2026
1ed0d96
test(app): add an attachable mode to the component-test runner
vishnuv688 Jul 30, 2026
aeaa536
fix(backend,core,service): keep run state across a run's worker sockets
vishnuv688 Jul 30, 2026
d72eca0
fix(backend): match the runner's own full-title form in rerun filters
vishnuv688 Jul 30, 2026
c5450b6
fix(app): window the compare panel to a preserved test's own uid
vishnuv688 Jul 31, 2026
51bd224
fix(ci): commit the vitest config the root gitignore was swallowing
vishnuv688 Jul 31, 2026
9dcbcbb
chore(elements): Added @wdio/elements package context
vishnuv688 Jul 31, 2026
0488dcc
fix(app): derive test outcome one way instead of four
vishnuv688 Jul 31, 2026
29fbed6
fix(app): resolve one failure site per step, strip the ESC byte
vishnuv688 Jul 31, 2026
6793d3d
fix(app): show the Compare tab only for the selected test
vishnuv688 Jul 31, 2026
656050a
fix(app): head each Errors row with what failed
vishnuv688 Jul 31, 2026
9f7f882
fix(app): render the empty-state copy the panels pass
vishnuv688 Jul 31, 2026
8b7b5c0
fix(app): tear down the player's listeners, show the viewport
vishnuv688 Jul 31, 2026
0314345
fix(app): honour the theme per instance, send elapsedTime, nest legally
vishnuv688 Jul 31, 2026
5d0f475
fix(app): stop two event details resolving to any
vishnuv688 Jul 31, 2026
09f5a04
ci: run the component suite, cap workers at two
vishnuv688 Jul 31, 2026
c5136e4
test(app): cover the sidebar shell, shortcuts and DataManager
vishnuv688 Jul 31, 2026
1da6655
docs: correct claims the code no longer supports
vishnuv688 Jul 31, 2026
6b272c1
build: make tsc a gate that actually runs
vishnuv688 Jul 31, 2026
a6bd883
ci: run typecheck and the coverage floor
vishnuv688 Jul 31, 2026
f22ec1d
test: pin the coverage denominator to the source tree
vishnuv688 Jul 31, 2026
908e871
fix(tests): clear the 28 errors the dead type gate had accumulated
vishnuv688 Jul 31, 2026
61acd2e
fix(app): give a suite no verdict until a child settles
vishnuv688 Jul 31, 2026
038f934
refactor(app): drop CollectedError.command and the comments that over…
vishnuv688 Jul 31, 2026
81c40cc
refactor(app): one elapsed-time rule, one theme source
vishnuv688 Jul 31, 2026
fd7a23c
fix(app): explain the empty panels instead of drawing a skeleton forever
vishnuv688 Jul 31, 2026
20e1136
fix: point two ambient globals at the canonical shared types
vishnuv688 Jul 31, 2026
2941dcc
fix(app): keep the window a step's remaining bound gives you
vishnuv688 Jul 31, 2026
b4aed39
fix(app): let a running test be stopped, and offer the control the tr…
vishnuv688 Jul 31, 2026
3fbd334
fix(app): wire the sidebar selection into the selected-test context
vishnuv688 Jul 31, 2026
ddfa2d0
fix: capture and replay text-only DOM changes
vishnuv688 Jul 31, 2026
aa4dcb7
fix: recognise the native a11y header instead of parsing it as a node
vishnuv688 Jul 31, 2026
881fc27
fix: one request-type vocabulary across capture, wire and UI
vishnuv688 Jul 31, 2026
89760bb
docs: correct the component-testing inventory
vishnuv688 Jul 31, 2026
53a85b4
test(app): pin that an Errors row is not a control
vishnuv688 Jul 31, 2026
18f9c6e
fix: update pnpm-lock.yaml
vishnuv688 Jul 31, 2026
f86aa0d
revert(test): pin the coverage denominator to the source tree
vishnuv688 Aug 2, 2026
c8ca562
test(app): make the player specs able to fail, and cover what was cla…
vishnuv688 Aug 2, 2026
5dc7751
test(app): make the panel specs able to fail
vishnuv688 Aug 2, 2026
bec50af
test(app): make the sidebar, shell and workbench specs able to fail
vishnuv688 Aug 2, 2026
8d7ef50
docs: correct the component-testing inventory against the code
vishnuv688 Aug 2, 2026
8b6a6da
fix(app): replay boolean attributes by presence, not by value
vishnuv688 Aug 2, 2026
ed23bc3
fix(app): make show-command the logs panel's only input, and tear it …
vishnuv688 Aug 2, 2026
1dc84aa
fix(app): time a console entry captured at zero like any other
vishnuv688 Aug 2, 2026
c718b52
fix(app): judge a run-all against canRunAll, and say why it is refused
vishnuv688 Aug 2, 2026
7db1e59
fix(app): keep a multi-line failure inside its own bullet
vishnuv688 Aug 2, 2026
41f5a8e
fix(core): keep a test's step titles in its own trace slice
vishnuv688 Aug 3, 2026
437f6b4
fix(app): colour a trace's resource dots by sniffing its response type
vishnuv688 Aug 3, 2026
daa54c3
fix(app): read a failed request's status as ERR in the list and the card
vishnuv688 Aug 3, 2026
0f43317
fix(app): keep the compare toolbar on one line
vishnuv688 Aug 3, 2026
eb54e1d
fix(script): put an attribute removal on the wire as a removal
vishnuv688 Aug 3, 2026
3d45ec9
refactor: give RUN_ALL_UID and the transcript builder one home each
vishnuv688 Aug 3, 2026
5034767
fix(app): replay a non-boolean attribute removal as a removal
vishnuv688 Aug 3, 2026
33efd44
fix(app): keep a boolean attribute the page set to false
vishnuv688 Aug 3, 2026
d56ce57
fix(app): empty a replayed field whose value attribute the page removed
vishnuv688 Aug 3, 2026
4419175
Merge pull request #266 from webdriverio/vv/fix-pinned-defects
vishnuv688 Aug 3, 2026
acc22dc
chore: add changeset for the UI-test correctness pass
vishnuv688 Aug 3, 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
21 changes: 21 additions & 0 deletions .changeset/ui-test-pass-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@wdio/nightwatch-devtools": minor
"@wdio/devtools-app": patch
"@wdio/devtools-backend": patch
"@wdio/devtools-script": patch
"@wdio/selenium-devtools": patch
"@wdio/devtools-service": patch
---

Correctness pass over the dashboard and trace player, driven by a new component-test suite that ran the UI in a real browser for the first time.

- **DOM replay** now reproduces what the page actually did: a boolean attribute is replayed by presence rather than by value (`checked="false"` no longer replays as checked, and a `disabled="false"` the page set stays disabled), an attribute the page removed replays as removed instead of being recreated empty, a removed `value` empties a field that was never typed into while keeping text that was, and a text-only DOM change is captured and replayed at all.
- **Trace slices keep their step names**: a per-test slice dropped the metadata its step titles lived under, so every Gherkin step rendered as `stable-…:step:1` instead of its own text.
- **Network panel**: resource-type dots are coloured for a reconstructed trace, whose HAR reports no MIME type; a request that failed at the transport level reads `ERR` in both the list and the detail card rather than the dash that means "still in flight"; capture, wire and UI now share one request-type vocabulary.
- **Errors panel** no longer mangles assertion failures — each row is headed by what failed, a multi-line failure stays inside its own bullet, and one failure site is resolved per step.
- **Compare tab** appears only for the selected test, is windowed to that test's own uid, and keeps its toolbar on one line.
- **Run state survives a run's worker sockets**, so Preserve & Rerun no longer 409s on every spec but the last, and a dashboard opened mid-run replays the whole run instead of the current spec. Rerun filters also match the runner's own full-title form, so a rerun no longer reports the test as skipped.
- **Sidebar**: a running test can be stopped, a suite carries no verdict until one of its children settles, a Run All refusal is judged against `canRunAll` and says why, and the selection feeds the selected-test context.
- **Player**: listeners are torn down on disconnect, the viewport is shown, and the theme is honoured per instance.
- **Capture**: DOM capture recovers on a document that missed script injection, and Nightwatch cucumber runs now produce traces with native assertions captured.
- **Empty panels** explain why they are empty instead of drawing a loading skeleton forever.
4 changes: 3 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ body:
- WebdriverIO (@wdio/devtools-service)
- Nightwatch (@wdio/nightwatch-devtools)
- Selenium WebDriver (@wdio/selenium-devtools)
- None — @wdio/elements used standalone
validations:
required: true

Expand All @@ -40,7 +41,7 @@ body:
id: devtools-version
attributes:
label: DevTools package version
description: The version of the adapter package above (check your package.json or lockfile).
description: The version of the package you selected above (check your package.json or lockfile).
placeholder: e.g. 0.4.2
validations:
required: true
Expand Down Expand Up @@ -72,6 +73,7 @@ body:
options:
- Dashboard UI (rendering, controls, rerun/stop)
- Captured data (network, console, screencast, trace)
- Element snapshot / locators (getSnapshot, getElements, accessibility tree)
- Backend / server (connection, websocket, crashes)
- Test launch / lifecycle (hooks, session, capabilities)
- Not sure
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ body:
options:
- Dashboard UI
- Capture / reporting core
- Element snapshot / locator API (@wdio/elements)
- WebdriverIO adapter
- Nightwatch adapter
- Selenium adapter
Expand Down
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

- [ ] `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)
Expand Down
44 changes: 42 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:
- v[0-9]+.[0-9]+.[0-9]+*
pull_request:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -23,9 +26,9 @@ jobs:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-
${{ runner.os }}-build-${{ env.cache-name }}-
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 10.26.1
Expand All @@ -36,5 +39,42 @@ jobs:
run: pnpm lint
- name: 📦 Bundle
run: pnpm -r --workspace-concurrency=1 build
# Four tsc programs — see the `typecheck` script. Runs before the tests
# because it is fast and its failures are cheaper to read.
- name: 🔎 Typecheck
run: pnpm typecheck
- name: 🧪 Run Tests
run: pnpm test

# Separate job because these are the only tests that need a real browser, and
# they parallelise with `build` instead of extending it. No bundle step: the
# specs and packages/app/src reach @wdio/devtools-shared through its source
# exports, so Vite compiles everything from source. Chrome comes preinstalled
# on the runner image; wdio fetches the matching driver itself.
component-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: .nvmrc
- name: Cache pnpm modules
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 10.26.1
run_install: false
- name: Install dependencies
run: pnpm install --frozen-lockfile
# Two workers, not the runner default: each carries a Vite server plus a
# Chrome, and past 2 the heaviest specs time out under that contention.
- name: 🧩 Component Tests
run: pnpm test:ui --maxInstances 2
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ dist-ssr
*.njsproj
*.sln
*.sw?
# Scratch scripts and dumps dropped at the repo root. Real root-level config
# has to be un-ignored by name: a new one is otherwise silently never added,
# and CI then runs with different settings than everyone's checkout.
/*.ts
/*.json
!/vitest.config.ts
!/tsconfig.dts.json
*.tgz
examples/wdio/wdio-*.json
examples/wdio/wdio-*.webm
Expand Down Expand Up @@ -55,6 +60,5 @@ examples/**/allure-results*/
examples/**/allure-report*/
packages/**/allure-results*/
packages/**/allure-report*/
examples/playwright-allure/
examples/wdio/cucumber/wdio.allure.conf.ts

6 changes: 4 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ The execution environment is the browser, not Node, so this package cannot impor

### `packages/elements`

Element-detection scripts (`@wdio/elements`). Produces the per-action data that feeds the snapshot pipeline: `getSnapshot`, the depth-indented accessibility-tree serializer, and the interactable-element list, plus locator generation.
The WDIO-typed element-detection API (`@wdio/elements`): `getSnapshot`, `getElements`, the accessibility-tree and interactable-element readers. Unlike `shared` and `core` this package **is** published, so its exported names are public API.

Consumed by `core` (the element-snapshot builder) and by the adapters' per-action capture (`captureActionSnapshot`). The DOM-walking scripts run in the page via `browser.execute`, so — like `script` — they avoid Node-only APIs.
Imports from: `core`. The script bodies, serializers, types, and locator generation all live in `core` (`element-scripts.ts`, `element-snapshot.ts`, `element-types.ts`, `locators/`) because they're framework-agnostic; this package holds only the wrappers that take a `WebdriverIO.Browser` — which `core` can't type against. The arrow never reverses: `core` does not import `elements`, and the adapters' per-action capture (`captureActionSnapshot`) calls core's script bodies directly rather than going through this package. `elements/snapshot.ts` and `elements/locators/index.ts` are re-export shims kept for API stability.

The DOM-walking scripts run in the page via `browser.execute`, so — like `script` — they avoid Node-only APIs.

### `examples/`

Expand Down
Loading
Loading