@unotest/web 0.9.1 → 0.11.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 +118 -38
- package/.claude/skills/write-e2e-test-ground/SKILL.md +787 -0
- package/CHANGELOG.md +297 -0
- package/dist/config/schema.d.ts +29 -10
- 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 +19 -3
- 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-MxHi1Air.d.ts} +50 -3
- package/dist/mcp/server.js +1 -1
- package/dist/runner/cli.d.ts +11 -1
- 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/guides/agent-integration.md +103 -2
- package/guides/dsl-reference.md +150 -13
- package/package.json +10 -38
- package/src/mcp/prompts/agent-test-author.md +71 -3
|
@@ -45,11 +45,17 @@ type LocatorStep = {
|
|
|
45
45
|
} | {
|
|
46
46
|
kind: 'nth';
|
|
47
47
|
index: number;
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'randomNth';
|
|
48
50
|
} | {
|
|
49
51
|
kind: 'contentFrame';
|
|
50
52
|
} | {
|
|
51
53
|
kind: 'ref';
|
|
52
54
|
ref: string;
|
|
55
|
+
} | {
|
|
56
|
+
kind: 'intent';
|
|
57
|
+
intent: string;
|
|
58
|
+
ordinal?: 'first' | 'last' | number;
|
|
53
59
|
};
|
|
54
60
|
interface LocatorValue {
|
|
55
61
|
readonly kind: 'locator';
|
|
@@ -163,6 +169,18 @@ type WaitState = "attached" | "detached" | "visible" | "hidden";
|
|
|
163
169
|
interface WaitOptions extends ActionTimeout {
|
|
164
170
|
state?: WaitState;
|
|
165
171
|
}
|
|
172
|
+
interface WaitForTextOptions extends WaitOptions {
|
|
173
|
+
/** @deprecated No-op: "first visible occurrence" is the default now.
|
|
174
|
+
* Chat feeds and repeated labels made the old whole-list strict-mode
|
|
175
|
+
* wait a footgun — ≥1 visible match is what "the text is on screen"
|
|
176
|
+
* means. Kept so recorded scenarios with {first: true} stay valid. */
|
|
177
|
+
first?: boolean;
|
|
178
|
+
/** Match the full text exactly (Playwright getByText semantics).
|
|
179
|
+
* Default: substring, which also matches INSIDE a word ("hi" hits
|
|
180
|
+
* "anything") — pass a regex with \b anchors via the DSL for
|
|
181
|
+
* word-boundary matching. */
|
|
182
|
+
exact?: boolean;
|
|
183
|
+
}
|
|
166
184
|
interface NavigationOptions extends ActionTimeout {
|
|
167
185
|
/**
|
|
168
186
|
* When to consider navigation done. Default: 'load'.
|
|
@@ -328,20 +346,39 @@ interface DriverPage {
|
|
|
328
346
|
scrollIntoView(loc: LocatorValue): Promise<void>;
|
|
329
347
|
/** Drag the source element onto the target. */
|
|
330
348
|
dragAndDrop(from: LocatorValue, to: LocatorValue, opts?: ClickOptions): Promise<void>;
|
|
331
|
-
/** Set the input element's selected files. Accepts
|
|
332
|
-
uploadFile(loc: LocatorValue, files: string | ReadonlyArray<string>
|
|
349
|
+
/** Set the input element's selected files. Accepts a path, path[], or an in-memory file buffer. */
|
|
350
|
+
uploadFile(loc: LocatorValue, files: string | ReadonlyArray<string> | {
|
|
351
|
+
name: string;
|
|
352
|
+
mimeType: string;
|
|
353
|
+
buffer: Buffer;
|
|
354
|
+
}): Promise<void>;
|
|
333
355
|
/** Focus the locator then dispatch a paste-like input with `text`. */
|
|
334
356
|
clipboardPaste(loc: LocatorValue, text: string): Promise<void>;
|
|
335
357
|
count(loc: LocatorValue): Promise<number>;
|
|
336
358
|
textContent(loc: LocatorValue): Promise<string | null>;
|
|
337
359
|
inputValue(loc: LocatorValue): Promise<string>;
|
|
360
|
+
/** Checked state of a checkbox / radio / switch, `null` when the element
|
|
361
|
+
* is none of those. Separate from `inputValue` on purpose: a checkbox's
|
|
362
|
+
* `value` is the submitted payload ("on" by default), never its state. */
|
|
363
|
+
checkedState(loc: LocatorValue): Promise<boolean | null>;
|
|
338
364
|
isVisible(loc: LocatorValue): Promise<boolean>;
|
|
339
365
|
/** Read a DOM attribute on the matched element. Returns null if absent. */
|
|
340
366
|
getAttribute(loc: LocatorValue, name: string): Promise<string | null>;
|
|
341
367
|
waitFor(loc: LocatorValue, opts?: WaitOptions): Promise<void>;
|
|
342
368
|
waitForUrl(pattern: string | RegExp, opts?: NavigationOptions): Promise<void>;
|
|
343
|
-
|
|
369
|
+
/** Wait until ≥1 VISIBLE occurrence of `text` matches (or none, with
|
|
370
|
+
* `state: 'hidden' | 'detached'`). Accepts a regex matcher in the
|
|
371
|
+
* JSON-safe `Matcher` shape. */
|
|
372
|
+
waitForText(text: Matcher, opts?: WaitForTextOptions): Promise<void>;
|
|
344
373
|
waitForNavigation(opts?: NavigationOptions): Promise<void>;
|
|
374
|
+
/** Wait for a page-level lifecycle state on the CURRENT document (no
|
|
375
|
+
* navigation required). Diagnostics-only — it backs the pre-capture
|
|
376
|
+
* settle for screenshots, never a DSL action: a test that waits on
|
|
377
|
+
* "the network went quiet" instead of on visible app state is exactly
|
|
378
|
+
* the flaky pattern the linter rejects. */
|
|
379
|
+
waitForLoadState(state: "load" | "domcontentloaded" | "networkidle", opts?: {
|
|
380
|
+
timeout?: number;
|
|
381
|
+
}): Promise<void>;
|
|
345
382
|
goto(url: string, opts?: GotoOptions): Promise<void>;
|
|
346
383
|
reload(opts?: ReloadOptions): Promise<void>;
|
|
347
384
|
goBack(opts?: NavigationOptions): Promise<void>;
|
|
@@ -392,6 +429,16 @@ interface ElementHint {
|
|
|
392
429
|
/** textContent (trimmed, clipped). Last-resort semantic fallback
|
|
393
430
|
* before the CSS escape hatch. */
|
|
394
431
|
text?: string;
|
|
432
|
+
/** Descendant text of a STRUCTURAL container (record row / card /
|
|
433
|
+
* tree-item / `<li>` / `<tr>`) that carries no accessible name of its
|
|
434
|
+
* own — its identifying text lives in children, so it has no `name`/
|
|
435
|
+
* `text` signal. Captured ONLY when short enough to name a single
|
|
436
|
+
* record (not a whole table/section). The resolver turns it into
|
|
437
|
+
* `getByRole(role).filter({hasText})` — the sole semantic handle on
|
|
438
|
+
* containers materialised from unit-grounded asserts (assert_visible on
|
|
439
|
+
* a record). Kept separate from `text` so ARIA name semantics (a
|
|
440
|
+
* container takes its name only from aria-label/labelledby) hold. */
|
|
441
|
+
containerText?: string;
|
|
395
442
|
/** href attribute for `<a>` elements lacking any of the above.
|
|
396
443
|
* Resolver emits `locator('a[href="..."]')`. */
|
|
397
444
|
href?: string;
|