@unotest/web 0.6.2 → 0.9.1
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 +37 -22
- package/CHANGELOG.md +63 -0
- package/README.md +12 -12
- package/dist/config/schema.d.ts +81 -10
- package/dist/config/schema.js +1 -1
- package/dist/driver/index.d.ts +7 -2
- package/dist/driver/index.js +1 -1
- package/dist/dsl/index.d.ts +33 -107
- package/dist/dsl/index.js +1 -1
- package/dist/dsl/web-dsl-language-service.d.ts +18 -0
- package/dist/dsl/web-dsl-language-service.js +1 -0
- package/dist/inspection/page-inject.d.ts +45 -1
- package/dist/inspection/page-inject.js +253 -4
- package/dist/{interfaces-iTfjd1zT.d.ts → interfaces-dbZG10RS.d.ts} +40 -1
- package/dist/{linter-DzAzJpab.d.ts → linter-CM2CpIyW.d.ts} +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/runner/cli.d.ts +8 -14
- package/dist/runner/cli.js +1 -1
- package/dist/runner/init/chrome-probe.d.ts +15 -0
- package/dist/runner/init/chrome-probe.js +1 -0
- 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.d.ts +24 -0
- package/dist/runner/scaffold-workspace.js +1 -0
- package/dist/runner/serve-fixture.js +1 -1
- package/dist/runner/web-runner-adapter.d.ts +1 -1
- package/dist/runner/web-runner-adapter.js +1 -1
- package/examples/fixtures/break-fix-app/serve.mjs +6 -2
- package/guides/dsl-reference.md +7 -7
- package/package.json +21 -4
- package/src/mcp/prompts/agent-test-author.md +17 -5
package/dist/dsl/index.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { i as LocatorValue, W as WebDriver, D as DriverContext, d as DriverPage } from '../interfaces-dbZG10RS.js';
|
|
2
|
+
export { j as LocatorStep, k as appendStep, l as describeLocator, m as isLocatorValue, r as rootedAt } from '../interfaces-dbZG10RS.js';
|
|
3
3
|
import { Matcher, RegexLiteral } from '@unotest/protocol';
|
|
4
|
-
import {
|
|
4
|
+
import { ExecutionWalker, ExecutionEvent, RunResult, RunOptions } from '@unotest/dsl/executor';
|
|
5
|
+
export { ExecutionError, ExecutionEvent, RunOptions, RunResult } from '@unotest/dsl/executor';
|
|
5
6
|
import { SandboxConfig } from '../config/schema.js';
|
|
6
|
-
|
|
7
|
+
import { RuntimeExecState } from '@unotest/core';
|
|
8
|
+
export { L as LintDiagnostic, b as LintOptions, a as LintSeverity, l as lintAst } from '../linter-CM2CpIyW.js';
|
|
7
9
|
import 'zod';
|
|
10
|
+
import '@unotest/dsl';
|
|
8
11
|
|
|
9
12
|
/** Test/codegen convenience: build a RegexLiteral inline. The DSL
|
|
10
13
|
* parser produces these for `/pattern/flags` literals at runtime;
|
|
@@ -65,83 +68,6 @@ declare function chainGetByTitle(loc: LocatorValue, text: Matcher, options?: {
|
|
|
65
68
|
exact?: boolean;
|
|
66
69
|
}): LocatorValue;
|
|
67
70
|
|
|
68
|
-
interface ExecutionError {
|
|
69
|
-
message: string;
|
|
70
|
-
/** Error class name (e.g. "AssertionError", "LocatorError"). Lets consumers
|
|
71
|
-
* classify failure vs. infra error without parsing the message. */
|
|
72
|
-
name?: string;
|
|
73
|
-
stack?: string;
|
|
74
|
-
/** Path to a screenshot saved on failure (driver-side). */
|
|
75
|
-
screenshotPath?: string;
|
|
76
|
-
/** Path to the a11y / semantic-dom snapshot saved on failure. */
|
|
77
|
-
snapshotPath?: string;
|
|
78
|
-
/** Optional rich detail (top-3 NearMisses, etc.). Free-form for the explainer. */
|
|
79
|
-
details?: unknown;
|
|
80
|
-
}
|
|
81
|
-
type ExecutionEvent = {
|
|
82
|
-
kind: 'step-start';
|
|
83
|
-
node: Statement;
|
|
84
|
-
file: string;
|
|
85
|
-
line: number;
|
|
86
|
-
col: number;
|
|
87
|
-
callStack?: readonly string[];
|
|
88
|
-
} | {
|
|
89
|
-
kind: 'step-end';
|
|
90
|
-
node: Statement;
|
|
91
|
-
file: string;
|
|
92
|
-
line: number;
|
|
93
|
-
col: number;
|
|
94
|
-
ok: true;
|
|
95
|
-
callStack?: readonly string[];
|
|
96
|
-
} | {
|
|
97
|
-
kind: 'step-end';
|
|
98
|
-
node: Statement;
|
|
99
|
-
file: string;
|
|
100
|
-
line: number;
|
|
101
|
-
col: number;
|
|
102
|
-
ok: false;
|
|
103
|
-
error: ExecutionError;
|
|
104
|
-
callStack?: readonly string[];
|
|
105
|
-
} | {
|
|
106
|
-
kind: 'paused';
|
|
107
|
-
reason: 'step' | 'failure' | 'breakpoint';
|
|
108
|
-
file: string;
|
|
109
|
-
line: number;
|
|
110
|
-
col: number;
|
|
111
|
-
};
|
|
112
|
-
interface RunOptions {
|
|
113
|
-
/** "auto" = run until completion / failure. "step" = pause after each statement. */
|
|
114
|
-
mode: 'auto' | 'step';
|
|
115
|
-
/** When true, on uncaught error we emit `paused: 'failure'` instead of throwing. */
|
|
116
|
-
pauseOnFailure: boolean;
|
|
117
|
-
/** Safety budget — abort with synthetic failure if exceeded. */
|
|
118
|
-
maxSteps?: number;
|
|
119
|
-
/** Wall-clock budget — same semantics. */
|
|
120
|
-
maxDurationMs?: number;
|
|
121
|
-
/** Maximum user-function nesting depth. Default 32. Guards against runaway
|
|
122
|
-
* recursion that wouldn't trip `maxSteps` (deep expression-tree calls). */
|
|
123
|
-
maxCallDepth?: number;
|
|
124
|
-
/** Mutable set of "line:col" keys. Executor checks membership before each
|
|
125
|
-
* statement; on hit, emits `paused: 'breakpoint'`. set-bp/clear-bp commands
|
|
126
|
-
* from the debug-commands-watcher mutate this set in place — same instance
|
|
127
|
-
* reference is shared with the watcher. */
|
|
128
|
-
breakpoints?: Set<string>;
|
|
129
|
-
/** Ref-object atomic flag for "pause on next statement". The pause-command
|
|
130
|
-
* watcher sets `value = true`; the executor reads it at every step-start,
|
|
131
|
-
* yields `paused: 'step'` if set, and resets to false. Ref-object (not raw
|
|
132
|
-
* boolean) so the watcher's mutation is visible to the executor without
|
|
133
|
-
* re-passing options. */
|
|
134
|
-
pauseRequested?: {
|
|
135
|
-
value: boolean;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
interface RunResult {
|
|
139
|
-
outcome: 'completed' | 'failed' | 'aborted';
|
|
140
|
-
stepsExecuted: number;
|
|
141
|
-
durationMs: number;
|
|
142
|
-
error?: ExecutionError;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
71
|
/** Read-only lookup over external scenario variables. */
|
|
146
72
|
interface VariableStore {
|
|
147
73
|
has(name: string): boolean;
|
|
@@ -175,6 +101,10 @@ interface TestRuntimeDeps {
|
|
|
175
101
|
/** External variable store (`unotest/.env` + `.secrets`). Resolves bare
|
|
176
102
|
* UPPER_SNAKE identifiers. Defaults to an empty store when omitted. */
|
|
177
103
|
readonly variables?: VariableStore;
|
|
104
|
+
/** Resolved base URL (`config.baseUrl`, auto-wired from APP_BASE_URL). Used
|
|
105
|
+
* to fail a relative `goto('/path')` with a clear message when no base is
|
|
106
|
+
* configured, instead of an opaque Playwright "invalid URL". */
|
|
107
|
+
readonly baseUrl?: string;
|
|
178
108
|
/** Injectable clock — defaults to Date.now. Tests pass a fake. */
|
|
179
109
|
readonly nowFn?: () => number;
|
|
180
110
|
}
|
|
@@ -184,6 +114,7 @@ declare class TestRuntime {
|
|
|
184
114
|
readonly context: DriverContext;
|
|
185
115
|
readonly logger: Logger;
|
|
186
116
|
readonly sandbox: SandboxConfig;
|
|
117
|
+
readonly baseUrl?: string;
|
|
187
118
|
private readonly variables;
|
|
188
119
|
private readonly nowFn;
|
|
189
120
|
private readonly scope;
|
|
@@ -232,34 +163,11 @@ declare class FunctionRegistry {
|
|
|
232
163
|
names(): string[];
|
|
233
164
|
}
|
|
234
165
|
|
|
235
|
-
declare class AstExecutor {
|
|
236
|
-
private readonly registry;
|
|
166
|
+
declare class AstExecutor extends ExecutionWalker<TestRuntime> {
|
|
237
167
|
constructor(registry: FunctionRegistry);
|
|
238
|
-
private entryFile;
|
|
239
|
-
private fnFile;
|
|
240
|
-
/** Project-root-relative posix file the current step lives in: origin of
|
|
241
|
-
* the innermost user-function frame, else the entry file. `callStack`
|
|
242
|
-
* only ever holds user-function names (pushed in callUserFunction), so
|
|
243
|
-
* every frame has a `fnFile` entry; the `?? entryFile` is a defensive
|
|
244
|
-
* fallback, not a normal path. */
|
|
245
|
-
private fileForStack;
|
|
246
|
-
run(program: BlockStatement, testName: string, runtime: TestRuntime, opts: RunOptions, helpers?: BlockStatement[], entryFile?: string, fnFile?: ReadonlyMap<string, string>): AsyncGenerator<ExecutionEvent, RunResult>;
|
|
247
|
-
private runBlock;
|
|
248
|
-
private runStatement;
|
|
249
|
-
private execStatement;
|
|
250
|
-
private evalExpression;
|
|
251
|
-
private callUserFunction;
|
|
252
|
-
private runLoop;
|
|
253
|
-
/** Run one loop-body pass. Returns `true` if a `break` fired (caller stops
|
|
254
|
-
* the loop), `false` for normal completion or `continue` (both end this
|
|
255
|
-
* iteration the same way). Each pass counts as a step so an empty-bodied
|
|
256
|
-
* infinite loop still trips `maxSteps`; `checkBudgets` enforces wall-clock. */
|
|
257
|
-
private runLoopIteration;
|
|
258
|
-
private applyIncrement;
|
|
259
|
-
private checkBudgets;
|
|
260
168
|
}
|
|
261
169
|
|
|
262
|
-
type RuntimeState =
|
|
170
|
+
type RuntimeState = RuntimeExecState;
|
|
263
171
|
interface ActiveRuntime {
|
|
264
172
|
id: string;
|
|
265
173
|
scenarioName: string;
|
|
@@ -317,6 +225,14 @@ interface TestRuntimeManagerDeps {
|
|
|
317
225
|
declare class TestRuntimeManager {
|
|
318
226
|
private readonly deps;
|
|
319
227
|
private readonly runtimes;
|
|
228
|
+
/** Final snapshot of recently-aborted runtimes. `abort()` removes the live
|
|
229
|
+
* runtime from `runtimes`, so a trailing `inspect()` (the runtime-state
|
|
230
|
+
* writer's final flush, or the agent reading after `abort_runtime`) would
|
|
231
|
+
* otherwise miss the terminal `aborted` state and report the stale pre-abort
|
|
232
|
+
* `paused-*`. We keep the captured terminal snapshot here so inspect reflects
|
|
233
|
+
* `aborted`. Bounded — only the last few matter (a writer flushes once). */
|
|
234
|
+
private readonly terminalTombstones;
|
|
235
|
+
private static readonly MAX_TOMBSTONES;
|
|
320
236
|
private nextId;
|
|
321
237
|
constructor(deps: TestRuntimeManagerDeps);
|
|
322
238
|
register(opts: {
|
|
@@ -330,7 +246,17 @@ declare class TestRuntimeManager {
|
|
|
330
246
|
step(id: string): Promise<ExecutionEvent | RunResult>;
|
|
331
247
|
resume(id: string): Promise<ExecutionEvent | RunResult>;
|
|
332
248
|
abort(id: string): Promise<void>;
|
|
249
|
+
/** Snapshot a just-aborted (still-live) runtime into the tombstone map so a
|
|
250
|
+
* later inspect() reflects `aborted`. Bounded LRU; best-effort. */
|
|
251
|
+
private rememberTombstone;
|
|
333
252
|
inspect(id: string): RuntimeSnapshot;
|
|
253
|
+
/** The live active page of a runtime — used by the locator picker to
|
|
254
|
+
* attach its overlay to the page held open during a debug pause.
|
|
255
|
+
* Returns null when the runtime is gone or has no page yet. */
|
|
256
|
+
currentPage(id: string): DriverPage | null;
|
|
257
|
+
/** The runtime's driver context (for capture artifacts — console/network).
|
|
258
|
+
* Null when the runtime isn't registered. */
|
|
259
|
+
currentContext(id: string): DriverContext | null;
|
|
334
260
|
list(): RuntimeSummary[];
|
|
335
261
|
private armTtl;
|
|
336
262
|
private clearTtl;
|
|
@@ -340,4 +266,4 @@ declare class TestRuntimeManager {
|
|
|
340
266
|
/** Build a fully-populated FunctionRegistry. */
|
|
341
267
|
declare function buildDefaultRegistry(): FunctionRegistry;
|
|
342
268
|
|
|
343
|
-
export { AstExecutor, type DslArg, type DslArray, type DslFunction, type DslObject, type DslValue,
|
|
269
|
+
export { AstExecutor, type DslArg, type DslArray, type DslFunction, type DslObject, type DslValue, FunctionRegistry, LocatorValue, TestRuntime, TestRuntimeManager, buildDefaultRegistry, chainGetByAltText, chainGetByLabel, chainGetByPlaceholder, chainGetByRole, chainGetByTestId, chainGetByText, chainGetByTitle, contentFrame, filter, first, getByAltText, getByLabel, getByPlaceholder, getByRole, getByTestId, getByText, getByTitle, last, locator, nth, re };
|