@unotest/web 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/write-e2e-test/SKILL.md +136 -44
- package/.claude/skills/write-e2e-test-ground/SKILL.md +784 -0
- package/CHANGELOG.md +210 -0
- package/dist/config/schema.d.ts +104 -14
- package/dist/config/schema.js +1 -1
- package/dist/driver/index.d.ts +5 -2
- package/dist/driver/index.js +1 -1
- package/dist/dsl/index.d.ts +36 -106
- package/dist/dsl/index.js +1 -1
- package/dist/dsl/web-dsl-language-service.js +1 -1
- package/dist/inspection/page-inject.d.ts +11 -35
- package/dist/inspection/page-inject.js +173 -1032
- package/dist/{interfaces-dbZG10RS.d.ts → interfaces-BxviHxnr.d.ts} +42 -3
- package/dist/mcp/server.js +1 -1
- package/dist/runner/cli.d.ts +1 -13
- package/dist/runner/cli.js +1 -1
- package/dist/runner/init/chrome-probe.js +1 -1
- package/dist/runner/init.js +1 -1
- package/dist/runner/install-chromium.js +1 -1
- package/dist/runner/prepare-fix.js +1 -1
- package/dist/runner/scaffold-workspace.js +1 -1
- package/dist/runner/serve-fixture.js +1 -1
- package/dist/runner/web-runner-adapter.js +1 -1
- package/examples/fixtures/break-fix-app/serve.mjs +6 -2
- package/guides/agent-integration.md +103 -2
- package/guides/dsl-reference.md +139 -13
- package/package.json +18 -8
- package/src/mcp/prompts/agent-test-author.md +75 -4
|
@@ -69,6 +69,65 @@ Disambiguate multi-matches with `.filter({hasText: '…'})` or
|
|
|
69
69
|
`.nth(N)`. The linter flags index-based picking
|
|
70
70
|
(`lint:disambig-by-index`) because element order is brittle.
|
|
71
71
|
|
|
72
|
+
## Discovery: snapshot mode vs ground mode
|
|
73
|
+
|
|
74
|
+
Which discovery tool exists depends on the server's mode — check the
|
|
75
|
+
tool list once. `get_page_snapshot` present — snapshot mode. Absent
|
|
76
|
+
(the server runs with `UNOTEST_SNAPSHOT=0`, ground mode) — it does not
|
|
77
|
+
exist, do NOT search or retry for it. In ground mode you normally need
|
|
78
|
+
no discovery call at all — act directly with an **intent locator**;
|
|
79
|
+
the runner grounds it inside the same call:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
locator: {kind:"locator", steps:[{kind:"intent",
|
|
83
|
+
intent:"<the element in the user's words>",
|
|
84
|
+
ordinal?: "first" | "last" | N}]}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Positions go in `ordinal` (typed), never in the intent text. Name the
|
|
88
|
+
target itself, not its page region. Lookups for when you must look
|
|
89
|
+
before acting: `ground_element {intent, ordinal?}` (element line +
|
|
90
|
+
top-20 candidates) and `find_element {role, name, near?}` (exact ARIA
|
|
91
|
+
query). Any "re-`get_page_snapshot`" advice below reads as "retry the
|
|
92
|
+
intent step / re-ground via `ground_element`" in ground mode.
|
|
93
|
+
|
|
94
|
+
## Batching: `explore_steps`
|
|
95
|
+
|
|
96
|
+
When the next several steps are known in advance, send ONE
|
|
97
|
+
`explore_steps {explorationId?, steps:[…]}` call — up to 25 steps, each
|
|
98
|
+
with the same shape as `explore_step`. Sequential; stops at the first
|
|
99
|
+
failure; the reply carries per-step status + `firstError`; only the
|
|
100
|
+
steps that executed are recorded.
|
|
101
|
+
|
|
102
|
+
Every step whose locator was an intent replies with `groundedTo` — the
|
|
103
|
+
element line the intent resolved to. Check the target there rather than
|
|
104
|
+
pre-probing with `ground_element`. A step that CHANGED the address also
|
|
105
|
+
replies with `url`: the last one in the batch is where you ended up, so
|
|
106
|
+
`get_active_context` / `get_url` afterwards re-reads what you have.
|
|
107
|
+
|
|
108
|
+
Record checks as assert steps — `assert_text {locator, text, options?:
|
|
109
|
+
{exact}}`, `assert_visible {locator}`, `assert_hidden {locator}`,
|
|
110
|
+
`assert_value {locator, value}`, `assert_count {locator, count}`,
|
|
111
|
+
`assert_url {pattern}`. When the brief names no check, verify with the
|
|
112
|
+
text it DID give you — the last thing you were told to click is on the
|
|
113
|
+
page you land on, so assert that name inside the same batch, quoting
|
|
114
|
+
the text alone (`"<name>"`, not `heading "<name>"` — the words often
|
|
115
|
+
live in a row or a link, and a role word then grounds to nothing);
|
|
116
|
+
don't spend calls hunting for something assertable.
|
|
117
|
+
`assert_url` is for briefs that name the destination URL. On a checkbox
|
|
118
|
+
/ radio / switch `assert_value`
|
|
119
|
+
takes `"true"` / `"false"` and asserts the checked state — no CSS
|
|
120
|
+
`:checked` selector. They execute live, so a recorded assert has
|
|
121
|
+
already passed against the real page; never hand-edit assertions into
|
|
122
|
+
the generated file. The final batch of a scenario can pass `autoRun:
|
|
123
|
+
true`: when every step succeeds, a verification step is recorded and
|
|
124
|
+
the draft has no blocking warnings (FRAGILE_LOCATOR passes and is
|
|
125
|
+
reported in the reply; DYNAMIC_TEXT / NO_DSL_PRIMITIVE block), the same
|
|
126
|
+
call saves the scenario, resets the context and runs it
|
|
127
|
+
(`autoRun.run.next.outcome === "completed"` is the pass signal);
|
|
128
|
+
otherwise `autoRun.status: "skipped"` + reason and the manual
|
|
129
|
+
generate → save → run flow applies.
|
|
130
|
+
|
|
72
131
|
## Recording: name the `section` like a test-plan line
|
|
73
132
|
|
|
74
133
|
Each `explore_step`/`explore_record` carries a `section` that becomes a
|
|
@@ -99,24 +158,36 @@ completion signal).
|
|
|
99
158
|
## When a scenario fails
|
|
100
159
|
|
|
101
160
|
The MCP server keeps a paused-failure runtime alive (default
|
|
102
|
-
`pauseOnFailure: true`)
|
|
161
|
+
`pauseOnFailure: true`) and `run_test` auto-attaches you to that live
|
|
162
|
+
page — your `get_page_snapshot` / `find_element` / `check_locator`
|
|
163
|
+
already target the page being debugged (no manual
|
|
164
|
+
`attach_debug_session`). Use that:
|
|
103
165
|
|
|
104
166
|
1. **`inspect_runtime {runtimeId}`** — shows `lastFailure` (error +
|
|
105
167
|
line/col + AST node) and `vars` (every assignment up to the pause).
|
|
106
168
|
This tells you what was observed vs expected, and what intermediate
|
|
107
169
|
state the scenario built up.
|
|
108
|
-
2. **`
|
|
170
|
+
2. **`check_locator {locator}`** — paste the EXACT locator from the
|
|
171
|
+
failing line (e.g. `getByRole('row').filter({hasText: 'Uma Quinn'}).first()`).
|
|
172
|
+
It parses that string with the same DSL parser the runner uses and
|
|
173
|
+
evaluates it against the live paused page: `count` of matches, and —
|
|
174
|
+
when the chain ends in `.first()`/`.last()`/`.nth()` — `pinned.ofCount`,
|
|
175
|
+
how many elements that index op silently collapsed (a `.first()`
|
|
176
|
+
hiding 16 identical rows is the classic break), plus per-match
|
|
177
|
+
role/name/text/testId so you see WHERE it points. Verify the selector
|
|
178
|
+
at runtime instead of guessing or re-running the whole test.
|
|
179
|
+
3. **`get_page_snapshot`** — compact outline of the active page in
|
|
109
180
|
its failed state: regions grouped by kind (navigation / form /
|
|
110
181
|
main / dialog / cmp / overlay / …), interactive actions per
|
|
111
182
|
region, off-screen actions partitioned by side (top / bottom /
|
|
112
183
|
left / right). Look for whether the locator is reachable, or
|
|
113
184
|
whether the page navigated somewhere unexpected. The `_meta`
|
|
114
185
|
section carries viewport + totals.
|
|
115
|
-
|
|
186
|
+
4. **`list_failures` + `get_failure_*`** — read from the failure bundle
|
|
116
187
|
(failure.json, console.json, snapshot.json, screenshot.png).
|
|
117
188
|
`get_failure_console` is often the giveaway when the failure is
|
|
118
189
|
actually a runtime error in the app.
|
|
119
|
-
|
|
190
|
+
5. **`agent_fix {runId}`** — composes a structured prompt with the
|
|
120
191
|
failure, the relevant scenario excerpt, and a classifier
|
|
121
192
|
suggestion (`edit-locator` / `edit-assertion` / `edit-wait` /
|
|
122
193
|
`edit-flow` / `investigate-app`). Use it as a starting hypothesis.
|