@unotest/web 0.10.0 → 0.12.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.
@@ -306,9 +306,11 @@ What's **not allowed** (parser / runtime will reject): `import` /
306
306
  `export` / `require`, top-level `await`, `class`, JSX, `while` /
307
307
  `do…while` / `continue` / `++`. Bounded `for (i = 0; i < N; i = i + 1)`
308
308
  loops ARE supported, and `break` is legal inside a loop body — poll with
309
- `for` + `if (…) { break; }` + `pause(ms) // reason: …`. Index access
309
+ `for` + `if (…) { break; }` + `pause(ms) // lint-ok: …`. Index access
310
310
  reads data (`docs[0].count`, bare variable only, never a Locator);
311
- `arr[i] = v` stays rejected.
311
+ `obj.prop[i]` does not parse — assign the member first:
312
+ `m = state.matches; last = m[m.length - 1];`. `arr[i] = v` stays
313
+ rejected.
312
314
 
313
315
  Navigation:
314
316
  - `goto(url, opts?)`, `reload(opts?)`, `getUrl()`, `goBack()`, `goForward()`.
@@ -377,7 +379,7 @@ Disambiguate with `.filter({hasText: '…'})` or `.filter({has: …})` —
377
379
  Waits:
378
380
  - `waitFor(loc, opts?)`, `waitForText(text, opts?)`,
379
381
  `waitForCount(loc, n, opts?)`, `waitForUrl(pattern)`, `pause(ms)` —
380
- `pause` requires `// reason: <why>` comment immediately above (linter
382
+ `pause` requires a trailing `// lint-ok: <why>` comment on the same line (linter
381
383
  flags `lint:pause-explicit` otherwise).
382
384
  - `waitForText` waits for ≥1 VISIBLE occurrence (repeated text in a feed
383
385
  is fine); substring by default — `{exact: true}` or a regex
@@ -395,20 +397,22 @@ State reads:
395
397
  `getInputValue(loc)`.
396
398
 
397
399
  Sandbox primitives:
398
- - `shell("cmd", "arg", )` — `execFile` style, no shell interpretation.
400
+ - `shell("cmd", "arg", …, options?)` — `execFile` style, no shell interpretation. Non-zero exit fails the step; pass `{allowNonZero: true}` to inspect `res.code` yourself. Wall-clock budget `{timeoutMs}` (default 120s).
401
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it exists / matches; use it to await output of background processes started via `shell()`.
399
402
  - `dbQuery(sql, …params)`, `dbExec(sql, …params)` — parameterized.
400
403
  - `apiCall(method, path, body?, headers?, opts?)` — path-only against
401
404
  `sandbox.apiBaseUrl`; another host via `{base: 'API_BASE_X'}` — the
402
405
  NAME of a `unotest/.env` variable, never a URL. Multipart upload:
403
- body of the exact shape `{file: 'fixtures/doc.pdf', field?, fields?}`
406
+ pass `upload('fixtures/doc.pdf', {field?, fields?})` as the body
404
407
  (relative path inside the project / `sandbox.uploadDir`; don't set
405
- Content-Type yourself).
408
+ Content-Type yourself). A JSON body with a `file` key posts as plain
409
+ JSON — there is no key-name magic.
406
410
 
407
411
  Escape hatch:
408
412
  - `evaluate(\`js body\`, …args)` — raw backticks, no `${}`. Linter
409
413
  warns `lint:evaluate-discouraged`. Use only when nothing above fits.
410
414
 
411
- Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`.
415
+ Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`. Marker helper: `randomWord(len)` — random lowercase letters, digit-free.
412
416
 
413
417
  ## Helpers convention
414
418
 
@@ -437,9 +437,11 @@ What's **not allowed** (parser / runtime will reject): `import` /
437
437
  `export` / `require`, top-level `await`, `class`, JSX, `while` /
438
438
  `do…while` / `continue` / `++`. Bounded `for (i = 0; i < N; i = i + 1)`
439
439
  loops ARE supported, and `break` is legal inside a loop body — poll with
440
- `for` + `if (…) { break; }` + `pause(ms) // reason: …`. Index access
440
+ `for` + `if (…) { break; }` + `pause(ms) // lint-ok: …`. Index access
441
441
  reads data (`docs[0].count`, bare variable only, never a Locator);
442
- `arr[i] = v` stays rejected.
442
+ `obj.prop[i]` does not parse — assign the member first:
443
+ `m = state.matches; last = m[m.length - 1];`. `arr[i] = v` stays
444
+ rejected.
443
445
 
444
446
  Navigation:
445
447
  - `goto(url, opts?)`, `reload(opts?)`, `getUrl()`, `goBack()`, `goForward()`.
@@ -508,7 +510,7 @@ Disambiguate with `.filter({hasText: '…'})` or `.filter({has: …})` —
508
510
  Waits:
509
511
  - `waitFor(loc, opts?)`, `waitForText(text, opts?)`,
510
512
  `waitForCount(loc, n, opts?)`, `waitForUrl(pattern)`, `pause(ms)` —
511
- `pause` requires `// reason: <why>` comment immediately above (linter
513
+ `pause` requires a trailing `// lint-ok: <why>` comment on the same line (linter
512
514
  flags `lint:pause-explicit` otherwise).
513
515
  - `waitForText` waits for ≥1 VISIBLE occurrence (repeated text in a feed
514
516
  is fine); substring by default — `{exact: true}` or a regex
@@ -526,20 +528,22 @@ State reads:
526
528
  `getInputValue(loc)`.
527
529
 
528
530
  Sandbox primitives:
529
- - `shell("cmd", "arg", )` — `execFile` style, no shell interpretation.
531
+ - `shell("cmd", "arg", …, options?)` — `execFile` style, no shell interpretation. Non-zero exit fails the step; pass `{allowNonZero: true}` to inspect `res.code` yourself. Wall-clock budget `{timeoutMs}` (default 120s).
532
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it exists / matches; use it to await output of background processes started via `shell()`.
530
533
  - `dbQuery(sql, …params)`, `dbExec(sql, …params)` — parameterized.
531
534
  - `apiCall(method, path, body?, headers?, opts?)` — path-only against
532
535
  `sandbox.apiBaseUrl`; another host via `{base: 'API_BASE_X'}` — the
533
536
  NAME of a `unotest/.env` variable, never a URL. Multipart upload:
534
- body of the exact shape `{file: 'fixtures/doc.pdf', field?, fields?}`
537
+ pass `upload('fixtures/doc.pdf', {field?, fields?})` as the body
535
538
  (relative path inside the project / `sandbox.uploadDir`; don't set
536
- Content-Type yourself).
539
+ Content-Type yourself). A JSON body with a `file` key posts as plain
540
+ JSON — there is no key-name magic.
537
541
 
538
542
  Escape hatch:
539
543
  - `evaluate(\`js body\`, …args)` — raw backticks, no `${}`. Linter
540
544
  warns `lint:evaluate-discouraged`. Use only when nothing above fits.
541
545
 
542
- Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`.
546
+ Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`. Marker helper: `randomWord(len)` — random lowercase letters, digit-free.
543
547
 
544
548
  ## Helpers convention
545
549
 
package/CHANGELOG.md CHANGED
@@ -5,6 +5,204 @@ All notable changes to `@unotest/web` are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.12.0] - 2026-08-14
9
+
10
+ ### Minor Changes
11
+
12
+ - 479aa25: The active variable environment is now agent-visible instead of
13
+ docs-only. `explore_start` and `run_test` replies carry an
14
+ `environment` field: the active env name (`UNOTEST_ENV`, `null` = base)
15
+ plus every `.env` / `.secrets` layer file with an `exists` flag. A
16
+ missing external variable error now also lists the searched layers
17
+ (`Looked in environment "dev" (UNOTEST_ENV): unotest/.env,
18
+ unotest/.env.dev (no such file)`). Tool descriptions for `run_test` /
19
+ `explore_start` explain the env mechanism — MCP sessions inherit
20
+ `UNOTEST_ENV` from the server process (set it in the client's `env`
21
+ block); CLI runs take `--env <name>`. The shipped agent guide gains a
22
+ "Variable environments" section.
23
+ - 479aa25: Feedback batch from a real-world integration (bot-service): shell()
24
+ safety, run diagnostics, boolean-attribute probes, linter ergonomics.
25
+
26
+ **BREAKING — `shell()` fails the step on a non-zero exit code.**
27
+ Previously a non-zero exit resolved silently and a forgotten `res.code`
28
+ check produced false-green tests. Migration: calls where non-zero is
29
+ expected (probes, `grep -q`) pass `{allowNonZero: true}` as the last
30
+ argument and keep checking `res.code`; calls that asserted
31
+ `assertTrue(out.code == 0, ...)` can drop the assert. More shell()
32
+ hardening: a missing binary is a distinct "failed to start" error (was a
33
+ fake `code: 1`), output over 10 MiB fails loudly (was silent
34
+ truncation), and every call has a wall-clock budget
35
+ (`sandbox.shellTimeoutMs`, default 120 s, or per-call `{timeoutMs}`) —
36
+ a detached grandchild holding the stdio pipes no longer hangs the
37
+ scenario forever; the timeout error explains the detach recipe.
38
+
39
+ New capabilities:
40
+
41
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it
42
+ exists / contains a substring or regex; the file-side `waitForText`
43
+ for background processes. Returns the content.
44
+ - `sandbox.exportSecrets: [names]` — explicit allowlist of `.secrets*`
45
+ variables exported into `shell()` subprocess env (still masked in
46
+ logs). Secrets stay out of `process.env` otherwise.
47
+ - `isDisabled(loc)` / `isEnabled(loc)` — honest disabled probe (native
48
+ `:disabled` incl. fieldset inheritance, or `aria-disabled`);
49
+ `hasAttribute(loc, name)` — presence probe for boolean attributes
50
+ (`getAttribute` reads `""` for present and absent alike).
51
+ - Generators: `randomWord(len)` (letters only — digit-free markers),
52
+ `nowMs()`, `today()`, `daysFromNow(n)` (previously documented in the
53
+ skills but not implemented).
54
+ - Failed runs report the enclosing step: `✗ test: … in step "…"` in the
55
+ console, `stepLabel` in the failure bundle and `inspect_runtime`.
56
+ - Every CLI run prints a one-line header: active environment, layer
57
+ files (missing ones flagged) and effective `baseUrl`; `run_test` /
58
+ `explore_start` replies echo `baseUrl` next to `environment`.
59
+ - `run_test` accepts per-call `env` — the spawned runner child gets
60
+ `UNOTEST_ENV=<env>` for that run only.
61
+ - Linter: `// lint-ok: <reason>` silences warning/info diagnostics on
62
+ its line (reason required; errors never suppressible); new
63
+ `lint:echo-assert` warns when `waitForText`/`assertText` overlaps a
64
+ value the scenario itself filled (chat echo trap);
65
+ `lint:goto-concat` / `lint:regex-invalid` are now configurable in
66
+ `linter.rules` (they were emitted but missing from the config schema).
67
+ - A `_helpers` file that fails to parse is reported as the root cause in
68
+ `unotest-web lint` (and explore replies list `unparsableHelperFiles`)
69
+ instead of silently cascading into "Unknown function" at every call
70
+ site. The viewer logs the same condition (patch).
71
+
72
+ ### Patch Changes
73
+
74
+ - Updated dependencies [40300d3]
75
+ - Updated dependencies [479aa25]
76
+ - Updated dependencies [5dd59af]
77
+ - Updated dependencies [7069d24]
78
+ - @unotest/dsl@0.12.0
79
+ - @unotest/viewer@0.12.0
80
+ - @unotest/core@0.12.0
81
+ - @unotest/grounder-client@0.12.0
82
+ - @unotest/protocol@0.12.0
83
+
84
+ ## [0.11.0] - 2026-08-13
85
+
86
+ ### Minor Changes
87
+
88
+ - eb568a6: `e2e` CLI argument diagnostics: extra positional arguments are rejected
89
+ instead of silently ignored (with a "did you mean: unotest-web e2e <name>"
90
+ hint for a duplicated subcommand); an argument that resolves to a
91
+ directory gets its own message instead of the misleading ".js extension"
92
+ error; unknown scenario names now suggest close matches from
93
+ `unotest/e2e/**` (new `suggestClosest` / `levenshteinDistance` utilities
94
+ in `@unotest/core`). The `collection` command also rejects extra
95
+ positionals.
96
+ - a195713: Failure artifacts are always on, and steps can carry screenshots.
97
+
98
+ - On any scenario failure the runner writes `screenshot.png` +
99
+ `page.html` (runtime DOM, open shadow roots included, secrets
100
+ redacted) to `unotest/.runs/<runId>/failure/` — no `UNOTEST_DEBUG`
101
+ needed. The `.unotest/failures/` bundle gains the same `page.html`;
102
+ its screenshot keeps honouring `failureBundle.tier2`.
103
+ - New env flag `UNOTEST_STEP_SCREENSHOTS=1` captures a PNG after every
104
+ executed step into `unotest/.runs/<runId>/screenshot/`.
105
+ - Protocol: `screenshot` events may carry the step's `file`/`line`/`col`.
106
+ - Viewer: a step row with a captured screenshot shows a camera icon and
107
+ toggles an inline preview on click (both `screenshot()` DSL captures
108
+ and per-step ones).
109
+
110
+ - d0ae620: Parse errors now carry an exact position and a caret code frame.
111
+
112
+ - Every lexer failure is a `ParseError` with `line`/`column` (previously
113
+ bare `Error` with no position).
114
+ - New `formatCodeFrame(source, line, column)` / `formatParseError`
115
+ exports in `@unotest/dsl`.
116
+ - The web runner's "parse error in <file>" message now includes
117
+ `<file>:<line>:<col>` plus the code frame — no more hunting for an
118
+ "unexpected LBRACKET" by eye.
119
+ - Token columns are now uniformly 1-based at the token start.
120
+ Previously identifier/number/string tokens were 0-based while
121
+ operators were 1-based, so carets and editor squiggles missed by one.
122
+ Migration note: `line:col` breakpoint keys stored in
123
+ `.debugger[-suffix].json` against word-initial statements shift by
124
+ +1 — re-set those breakpoints once.
125
+
126
+ - 98b0736: BREAKING: multipart uploads in `apiCall` are now opted into explicitly
127
+ with the new `upload(path, {field?, fields?})` DSL function — the
128
+ `{file, field?, fields?}` body-shape magic is removed.
129
+
130
+ A JSON body containing a `file` key now always posts as JSON (the old
131
+ key-name detection broke JSON APIs with a legitimate `file` field —
132
+ `{file: 'x.jsonl'}` tried to read a file from disk and died with
133
+ ENOENT).
134
+
135
+ Migration:
136
+
137
+ ```js
138
+ // before
139
+ apiCall("POST", "/documents", {
140
+ file: "fixtures/doc.pdf",
141
+ fields: { source: "e2e" },
142
+ });
143
+ // after
144
+ apiCall(
145
+ "POST",
146
+ "/documents",
147
+ upload("fixtures/doc.pdf", { fields: { source: "e2e" } })
148
+ );
149
+ ```
150
+
151
+ `upload()` must be the body itself (a nested `{doc: upload(...)}` is
152
+ rejected with a pointer to the correct usage). Path containment in
153
+ `sandbox.uploadDir` and the Content-Type rules are unchanged.
154
+
155
+ ### Patch Changes
156
+
157
+ - ce25926: Fixes and DX follow-ups from the real-time-polls field check:
158
+
159
+ - **Fix: `unotest/.runs/<runId>/failure/` was never written.** The
160
+ runner derived the run dir from its internal runtime id (`r-N…`)
161
+ while the on-disk dir is named by `makeRunId(scenario)`, so the
162
+ always-on failure artifacts silently skipped. The CLI now passes its
163
+ run dir into the runner (`RunJsScenarioOptions.runDir`), and the
164
+ failure screenshot + page.html land where documented.
165
+ - **`init` re-syncs tool-owned skill copies.** `.claude/skills/*` and
166
+ `.claude/hooks/*` shipped by the package are overwritten on a plain
167
+ `init` re-run when they diverge from the installed version (status
168
+ `updated`) — stale skills after a package upgrade no longer require
169
+ `--force`. User-scaffolded files keep the skip-unless-`--force`
170
+ behaviour.
171
+ - The MCP `agent-test-author` prompt caught up with the runtime:
172
+ multipart via `upload(...)` and the `obj.prop[i]` workaround are now
173
+ documented there too, and both facts are enforced by
174
+ `check-skill-prompt-sync`.
175
+
176
+ - 7ac23d5: Screenshots are no longer saved as blank white PNGs. `goto()` resolves
177
+ on the `load` event, which on any client-rendered app fires before the
178
+ first frame carries content — so a per-step capture
179
+ (`UNOTEST_STEP_SCREENSHOTS=1`) of a step that ended on `goto()`, or a
180
+ `screenshot()` call placed right after one, froze the pre-render frame.
181
+ Both paths now settle first: wait for the network to go quiet, then for
182
+ a painted frame, capped at 2s total. A page that never goes quiet
183
+ (polling, live feeds) spends the cap once per capture and is then shot
184
+ as-is; the wait never fails a run. The failure screenshot deliberately
185
+ skips the settle — it must show the page as it was at the failure.
186
+
187
+ Adds `DriverPage.waitForLoadState(state, opts?)` — diagnostics-only,
188
+ backing the settle. It is not exposed to the DSL: a test that waits on
189
+ "the network went quiet" instead of on visible app state is the flaky
190
+ pattern the linter rejects.
191
+
192
+ - Updated dependencies [eb568a6]
193
+ - Updated dependencies [a195713]
194
+ - Updated dependencies [ce25926]
195
+ - Updated dependencies [5a8e92b]
196
+ - Updated dependencies [d0ae620]
197
+ - Updated dependencies [2a68997]
198
+ - Updated dependencies [c01b72f]
199
+ - Updated dependencies [dea90e9]
200
+ - @unotest/core@0.11.0
201
+ - @unotest/protocol@0.11.0
202
+ - @unotest/viewer@0.11.0
203
+ - @unotest/dsl@0.11.0
204
+ - @unotest/grounder-client@0.11.0
205
+
8
206
  ## [0.10.0] - 2026-08-06
9
207
 
10
208
  ### Minor Changes
@@ -90,19 +90,19 @@ declare const FailureBundleConfigSchema: z.ZodObject<{
90
90
  type FailureBundleConfig = z.infer<typeof FailureBundleConfigSchema>;
91
91
  declare const DialogPolicySchema: z.ZodEnum<["accept", "dismiss", "manual"]>;
92
92
  type DialogPolicy = z.infer<typeof DialogPolicySchema>;
93
- declare const LinterRuleIdSchema: z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>;
93
+ declare const LinterRuleIdSchema: z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "lint:goto-concat", "lint:regex-invalid", "lint:echo-assert", "lint:lint-ok-missing-reason", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>;
94
94
  type LinterRuleId = z.infer<typeof LinterRuleIdSchema>;
95
95
  declare const LinterSeveritySchema: z.ZodEnum<["off", "warn", "error"]>;
96
96
  type LinterSeverity = z.infer<typeof LinterSeveritySchema>;
97
97
  declare const LinterConfigSchema: z.ZodObject<{
98
98
  enabled: z.ZodBoolean;
99
- rules: z.ZodRecord<z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>, z.ZodEnum<["off", "warn", "error"]>>;
99
+ rules: z.ZodRecord<z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "lint:goto-concat", "lint:regex-invalid", "lint:echo-assert", "lint:lint-ok-missing-reason", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>, z.ZodEnum<["off", "warn", "error"]>>;
100
100
  }, "strip", z.ZodTypeAny, {
101
101
  enabled: boolean;
102
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
102
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
103
103
  }, {
104
104
  enabled: boolean;
105
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
105
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
106
106
  }>;
107
107
  type LinterConfig = z.infer<typeof LinterConfigSchema>;
108
108
  declare const McpConfigSchema: z.ZodObject<{
@@ -116,6 +116,17 @@ type McpConfig = z.infer<typeof McpConfigSchema>;
116
116
  declare const SandboxConfigSchema: z.ZodObject<{
117
117
  /** Default cwd for `shell(cmd, ...args)`. Defaults to `process.cwd()`. */
118
118
  shellCwd: z.ZodOptional<z.ZodString>;
119
+ /** Wall-clock budget for one `shell()` call, ms. Default 120 000. A call
120
+ * that exceeds it fails the step (the child gets SIGTERM, then SIGKILL) —
121
+ * without this, a grandchild process inheriting stdio pipes hangs the
122
+ * scenario forever. Per-call override: `shell(..., {timeoutMs})`. */
123
+ shellTimeoutMs: z.ZodOptional<z.ZodNumber>;
124
+ /** Names of `.secrets*` variables exported into `shell()` subprocess env.
125
+ * Secrets are deliberately kept OUT of process.env (see
126
+ * scenario-variables.ts) — this is the explicit opt-in for the listener /
127
+ * seeder subprocess that genuinely needs a token. Values are still
128
+ * masked in logs by the SecretRegistry. */
129
+ exportSecrets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
119
130
  /** Database connection string consumed by `dbQuery` / `dbExec`. URL form
120
131
  * picks the dialect: `postgres://`, `mysql://`, `sqlite:`. */
121
132
  database: z.ZodOptional<z.ZodString>;
@@ -124,17 +135,21 @@ declare const SandboxConfigSchema: z.ZodObject<{
124
135
  * URLs are rejected at runtime. Additional bases come from env
125
136
  * variables via `apiCall(..., {base: "API_BASE_X"})`. */
126
137
  apiBaseUrl: z.ZodOptional<z.ZodString>;
127
- /** Root for `apiCall` multipart `{file}` fixtures. Relative upload
128
- * paths resolve against it and may not escape it. Defaults to the
129
- * project root (the runner's cwd). */
138
+ /** Root for `upload()` fixtures. Relative upload paths resolve
139
+ * against it and may not escape it. Defaults to the project root
140
+ * (the runner's cwd). */
130
141
  uploadDir: z.ZodOptional<z.ZodString>;
131
142
  }, "strip", z.ZodTypeAny, {
132
143
  shellCwd?: string | undefined;
144
+ shellTimeoutMs?: number | undefined;
145
+ exportSecrets?: string[] | undefined;
133
146
  database?: string | undefined;
134
147
  apiBaseUrl?: string | undefined;
135
148
  uploadDir?: string | undefined;
136
149
  }, {
137
150
  shellCwd?: string | undefined;
151
+ shellTimeoutMs?: number | undefined;
152
+ exportSecrets?: string[] | undefined;
138
153
  database?: string | undefined;
139
154
  apiBaseUrl?: string | undefined;
140
155
  uploadDir?: string | undefined;
@@ -158,14 +173,14 @@ declare const WebServerConfigSchema: z.ZodObject<{
158
173
  timeoutMs: z.ZodDefault<z.ZodNumber>;
159
174
  }, "strip", z.ZodTypeAny, {
160
175
  url: string;
176
+ timeoutMs: number;
161
177
  command: string;
162
178
  reuseExistingServer: boolean;
163
- timeoutMs: number;
164
179
  }, {
165
180
  url: string;
166
181
  command: string;
167
- reuseExistingServer?: boolean | undefined;
168
182
  timeoutMs?: number | undefined;
183
+ reuseExistingServer?: boolean | undefined;
169
184
  }>;
170
185
  type WebServerConfig = z.infer<typeof WebServerConfigSchema>;
171
186
  declare const UnotestConfigSchema: z.ZodObject<{
@@ -192,14 +207,14 @@ declare const UnotestConfigSchema: z.ZodObject<{
192
207
  timeoutMs: z.ZodDefault<z.ZodNumber>;
193
208
  }, "strip", z.ZodTypeAny, {
194
209
  url: string;
210
+ timeoutMs: number;
195
211
  command: string;
196
212
  reuseExistingServer: boolean;
197
- timeoutMs: number;
198
213
  }, {
199
214
  url: string;
200
215
  command: string;
201
- reuseExistingServer?: boolean | undefined;
202
216
  timeoutMs?: number | undefined;
217
+ reuseExistingServer?: boolean | undefined;
203
218
  }>>;
204
219
  browsers: z.ZodArray<z.ZodEnum<["chromium", "firefox", "webkit"]>, "many">;
205
220
  channel: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"chrome">, z.ZodLiteral<"msedge">, z.ZodLiteral<"chrome-beta">, z.ZodNull]>>;
@@ -297,13 +312,13 @@ declare const UnotestConfigSchema: z.ZodObject<{
297
312
  defaultNavigationTimeoutMs: z.ZodNumber;
298
313
  linter: z.ZodObject<{
299
314
  enabled: z.ZodBoolean;
300
- rules: z.ZodRecord<z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>, z.ZodEnum<["off", "warn", "error"]>>;
315
+ rules: z.ZodRecord<z.ZodEnum<["lint:deep-css", "lint:xpath", "lint:obfuscated-class", "lint:pause-explicit", "lint:disambig-by-index", "lint:evaluate-discouraged", "lint:scenario-in-root", "lint:mustache-in-dsl", "lint:goto-concat", "lint:regex-invalid", "lint:echo-assert", "lint:lint-ok-missing-reason", "validator:unknown-function", "validator:arity", "validator:arg-kind", "validator:step-coverage", "validator:step-shape", "validator:meta-shape", "validator:function-shape", "validator:for-shape", "validator:if-shape", "validator:var-shape", "validator:unsupported-statement", "validator:unsupported-expression", "validator:string-concat", "validator:semantic-loss", "validator:list-arg", "validator:wrapped-format"]>, z.ZodEnum<["off", "warn", "error"]>>;
301
316
  }, "strip", z.ZodTypeAny, {
302
317
  enabled: boolean;
303
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
318
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
304
319
  }, {
305
320
  enabled: boolean;
306
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
321
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
307
322
  }>;
308
323
  mcp: z.ZodObject<{
309
324
  transport: z.ZodLiteral<"stdio">;
@@ -315,6 +330,17 @@ declare const UnotestConfigSchema: z.ZodObject<{
315
330
  sandbox: z.ZodObject<{
316
331
  /** Default cwd for `shell(cmd, ...args)`. Defaults to `process.cwd()`. */
317
332
  shellCwd: z.ZodOptional<z.ZodString>;
333
+ /** Wall-clock budget for one `shell()` call, ms. Default 120 000. A call
334
+ * that exceeds it fails the step (the child gets SIGTERM, then SIGKILL) —
335
+ * without this, a grandchild process inheriting stdio pipes hangs the
336
+ * scenario forever. Per-call override: `shell(..., {timeoutMs})`. */
337
+ shellTimeoutMs: z.ZodOptional<z.ZodNumber>;
338
+ /** Names of `.secrets*` variables exported into `shell()` subprocess env.
339
+ * Secrets are deliberately kept OUT of process.env (see
340
+ * scenario-variables.ts) — this is the explicit opt-in for the listener /
341
+ * seeder subprocess that genuinely needs a token. Values are still
342
+ * masked in logs by the SecretRegistry. */
343
+ exportSecrets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
318
344
  /** Database connection string consumed by `dbQuery` / `dbExec`. URL form
319
345
  * picks the dialect: `postgres://`, `mysql://`, `sqlite:`. */
320
346
  database: z.ZodOptional<z.ZodString>;
@@ -323,17 +349,21 @@ declare const UnotestConfigSchema: z.ZodObject<{
323
349
  * URLs are rejected at runtime. Additional bases come from env
324
350
  * variables via `apiCall(..., {base: "API_BASE_X"})`. */
325
351
  apiBaseUrl: z.ZodOptional<z.ZodString>;
326
- /** Root for `apiCall` multipart `{file}` fixtures. Relative upload
327
- * paths resolve against it and may not escape it. Defaults to the
328
- * project root (the runner's cwd). */
352
+ /** Root for `upload()` fixtures. Relative upload paths resolve
353
+ * against it and may not escape it. Defaults to the project root
354
+ * (the runner's cwd). */
329
355
  uploadDir: z.ZodOptional<z.ZodString>;
330
356
  }, "strip", z.ZodTypeAny, {
331
357
  shellCwd?: string | undefined;
358
+ shellTimeoutMs?: number | undefined;
359
+ exportSecrets?: string[] | undefined;
332
360
  database?: string | undefined;
333
361
  apiBaseUrl?: string | undefined;
334
362
  uploadDir?: string | undefined;
335
363
  }, {
336
364
  shellCwd?: string | undefined;
365
+ shellTimeoutMs?: number | undefined;
366
+ exportSecrets?: string[] | undefined;
337
367
  database?: string | undefined;
338
368
  apiBaseUrl?: string | undefined;
339
369
  uploadDir?: string | undefined;
@@ -368,13 +398,15 @@ declare const UnotestConfigSchema: z.ZodObject<{
368
398
  defaultNavigationTimeoutMs: number;
369
399
  linter: {
370
400
  enabled: boolean;
371
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
401
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
372
402
  };
373
403
  mcp: {
374
404
  transport: "stdio";
375
405
  };
376
406
  sandbox: {
377
407
  shellCwd?: string | undefined;
408
+ shellTimeoutMs?: number | undefined;
409
+ exportSecrets?: string[] | undefined;
378
410
  database?: string | undefined;
379
411
  apiBaseUrl?: string | undefined;
380
412
  uploadDir?: string | undefined;
@@ -382,9 +414,9 @@ declare const UnotestConfigSchema: z.ZodObject<{
382
414
  baseUrl?: string | undefined;
383
415
  webServer?: {
384
416
  url: string;
417
+ timeoutMs: number;
385
418
  command: string;
386
419
  reuseExistingServer: boolean;
387
- timeoutMs: number;
388
420
  } | undefined;
389
421
  channel?: "chrome" | "msedge" | "chrome-beta" | null | undefined;
390
422
  storageState?: string | undefined;
@@ -418,13 +450,15 @@ declare const UnotestConfigSchema: z.ZodObject<{
418
450
  defaultNavigationTimeoutMs: number;
419
451
  linter: {
420
452
  enabled: boolean;
421
- rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
453
+ rules: Partial<Record<"lint:deep-css" | "lint:xpath" | "lint:obfuscated-class" | "lint:pause-explicit" | "lint:disambig-by-index" | "lint:evaluate-discouraged" | "lint:scenario-in-root" | "lint:mustache-in-dsl" | "lint:goto-concat" | "lint:regex-invalid" | "lint:echo-assert" | "lint:lint-ok-missing-reason" | "validator:unknown-function" | "validator:arity" | "validator:arg-kind" | "validator:step-coverage" | "validator:step-shape" | "validator:meta-shape" | "validator:function-shape" | "validator:for-shape" | "validator:if-shape" | "validator:var-shape" | "validator:unsupported-statement" | "validator:unsupported-expression" | "validator:string-concat" | "validator:semantic-loss" | "validator:list-arg" | "validator:wrapped-format", "off" | "warn" | "error">>;
422
454
  };
423
455
  mcp: {
424
456
  transport: "stdio";
425
457
  };
426
458
  sandbox: {
427
459
  shellCwd?: string | undefined;
460
+ shellTimeoutMs?: number | undefined;
461
+ exportSecrets?: string[] | undefined;
428
462
  database?: string | undefined;
429
463
  apiBaseUrl?: string | undefined;
430
464
  uploadDir?: string | undefined;
@@ -433,8 +467,8 @@ declare const UnotestConfigSchema: z.ZodObject<{
433
467
  webServer?: {
434
468
  url: string;
435
469
  command: string;
436
- reuseExistingServer?: boolean | undefined;
437
470
  timeoutMs?: number | undefined;
471
+ reuseExistingServer?: boolean | undefined;
438
472
  } | undefined;
439
473
  channel?: "chrome" | "msedge" | "chrome-beta" | null | undefined;
440
474
  storageState?: string | undefined;
@@ -1 +1 @@
1
- var _0x2e344b=_0x8977;(function(_0x274a7d,_0xfc8b9d){var _0x244ac2={_0x4ac5bb:0xdd,_0x4ff88e:0xe4,_0x286156:0xe0,_0x4f3327:0xe8,_0x58371b:0xe1},_0x41182f=_0x8977,_0x5b93a8=_0x274a7d();while(!![]){try{var _0x1d56a7=-parseInt(_0x41182f(0xdf))/0x1*(-parseInt(_0x41182f(_0x244ac2._0x4ac5bb))/0x2)+-parseInt(_0x41182f(_0x244ac2._0x4ff88e))/0x3*(-parseInt(_0x41182f(0xc7))/0x4)+parseInt(_0x41182f(0xea))/0x5+parseInt(_0x41182f(_0x244ac2._0x286156))/0x6+-parseInt(_0x41182f(0xcc))/0x7+parseInt(_0x41182f(_0x244ac2._0x4f3327))/0x8*(parseInt(_0x41182f(0xfc))/0x9)+-parseInt(_0x41182f(_0x244ac2._0x58371b))/0xa;if(_0x1d56a7===_0xfc8b9d)break;else _0x5b93a8['push'](_0x5b93a8['shift']());}catch(_0x35c23d){_0x5b93a8['push'](_0x5b93a8['shift']());}}}(_0x19a6,0x37d44));import{z}from'zod';var BrowserSchema=z[_0x2e344b(0xfa)]([_0x2e344b(0xe3),_0x2e344b(0xcf),_0x2e344b(0xf9)]),BrowserChannelSchema=z[_0x2e344b(0xf3)]([z['literal'](_0x2e344b(0xca)),z[_0x2e344b(0xc6)](_0x2e344b(0xc9)),z[_0x2e344b(0xc6)](_0x2e344b(0xf5)),z[_0x2e344b(0xe9)]()])[_0x2e344b(0xec)](),ViewportSchema=z[_0x2e344b(0xd7)]({'width':z['number']()[_0x2e344b(0xee)]()[_0x2e344b(0xcb)](),'height':z[_0x2e344b(0xd1)]()[_0x2e344b(0xee)]()[_0x2e344b(0xcb)]()}),RetryReasonSchema=z[_0x2e344b(0xfa)](['transient',_0x2e344b(0xd6),_0x2e344b(0xef)]),RetryConfigSchema=z[_0x2e344b(0xd7)]({'count':z[_0x2e344b(0xd1)]()[_0x2e344b(0xee)]()[_0x2e344b(0x103)](0x0)['max'](0xa),'on':z[_0x2e344b(0xed)](RetryReasonSchema)}),FailureBundleConfigSchema=z[_0x2e344b(0xd7)]({'tier1':z[_0x2e344b(0xc6)](!![])[_0x2e344b(0xc5)](!![]),'tier2':z[_0x2e344b(0xdc)](),'tier3':z[_0x2e344b(0xd7)]({'network':z[_0x2e344b(0xdc)](),'video':z[_0x2e344b(0xdc)]()}),'retention':z['object']({'runs':z[_0x2e344b(0xd1)]()['int']()[_0x2e344b(0xcb)](),'days':z['number']()[_0x2e344b(0xee)]()['positive']()}),'storageDir':z[_0x2e344b(0x104)]()[_0x2e344b(0x103)](0x1)}),DialogPolicySchema=z[_0x2e344b(0xfa)]([_0x2e344b(0xd0),_0x2e344b(0xf1),_0x2e344b(0xde)]),LinterRuleIdSchema=z[_0x2e344b(0xfa)]([_0x2e344b(0xd5),'lint:xpath',_0x2e344b(0xf6),_0x2e344b(0xff),_0x2e344b(0xeb),_0x2e344b(0xfd),_0x2e344b(0xfb),_0x2e344b(0xe5),_0x2e344b(0xd4),_0x2e344b(0xf2),_0x2e344b(0xd2),_0x2e344b(0xe2),_0x2e344b(0xd3),'validator:meta-shape',_0x2e344b(0xc8),_0x2e344b(0xf0),_0x2e344b(0x100),_0x2e344b(0x101),_0x2e344b(0x102),_0x2e344b(0xcd),'validator:string-concat',_0x2e344b(0xc4),_0x2e344b(0xf7),'validator:wrapped-format']),LinterSeveritySchema=z[_0x2e344b(0xfa)]([_0x2e344b(0xe6),'warn','error']),LinterConfigSchema=z[_0x2e344b(0xd7)]({'enabled':z[_0x2e344b(0xdc)](),'rules':z[_0x2e344b(0xf4)](LinterRuleIdSchema,LinterSeveritySchema)}),McpConfigSchema=z[_0x2e344b(0xd7)]({'transport':z[_0x2e344b(0xc6)](_0x2e344b(0xce))}),SandboxConfigSchema=z[_0x2e344b(0xd7)]({'shellCwd':z[_0x2e344b(0x104)]()[_0x2e344b(0xec)](),'database':z['string']()['optional'](),'apiBaseUrl':z[_0x2e344b(0x104)]()[_0x2e344b(0xda)]()[_0x2e344b(0xec)](),'uploadDir':z['string']()[_0x2e344b(0xec)]()}),WebServerConfigSchema=z[_0x2e344b(0xd7)]({'command':z[_0x2e344b(0x104)]()[_0x2e344b(0x103)](0x1),'url':z[_0x2e344b(0x104)]()['url'](),'reuseExistingServer':z[_0x2e344b(0xdc)]()[_0x2e344b(0xc5)](!![]),'timeoutMs':z[_0x2e344b(0xd1)]()[_0x2e344b(0xee)]()[_0x2e344b(0xcb)]()[_0x2e344b(0xc5)](0xea60)}),UnotestConfigSchema=z['object']({'baseUrl':z[_0x2e344b(0x104)]()['url']()[_0x2e344b(0xec)](),'webServer':WebServerConfigSchema[_0x2e344b(0xec)](),'browsers':z[_0x2e344b(0xed)](BrowserSchema)[_0x2e344b(0x103)](0x1),'channel':BrowserChannelSchema,'viewport':ViewportSchema,'retry':RetryConfigSchema,'failureBundle':FailureBundleConfigSchema,'dialogPolicy':DialogPolicySchema,'storageState':z[_0x2e344b(0x104)]()[_0x2e344b(0xec)](),'testDir':z[_0x2e344b(0x104)]()['min'](0x1),'helpersDir':z['string']()[_0x2e344b(0x103)](0x1),'defaultTimeoutMs':z[_0x2e344b(0xd1)]()[_0x2e344b(0xee)]()['positive'](),'defaultNavigationTimeoutMs':z['number']()[_0x2e344b(0xee)]()[_0x2e344b(0xcb)](),'linter':LinterConfigSchema,'mcp':McpConfigSchema,'sandbox':SandboxConfigSchema}),DEFAULT_CONFIG={'browsers':['chromium'],'viewport':{'width':0x500,'height':0x2d0},'retry':{'count':0x0,'on':[_0x2e344b(0xdb)]},'failureBundle':{'tier1':!![],'tier2':!![],'tier3':{'network':![],'video':![]},'retention':{'runs':0x14,'days':0x7},'storageDir':_0x2e344b(0xd9)},'dialogPolicy':'accept','testDir':_0x2e344b(0xe7),'helpersDir':_0x2e344b(0xf8),'defaultTimeoutMs':0xbb8,'defaultNavigationTimeoutMs':0x7530,'linter':{'enabled':!![],'rules':{'lint:deep-css':_0x2e344b(0xd8),'lint:xpath':'warn','lint:obfuscated-class':_0x2e344b(0xd8),'lint:pause-explicit':'warn','lint:disambig-by-index':_0x2e344b(0xe6),'lint:evaluate-discouraged':_0x2e344b(0xd8),'lint:scenario-in-root':_0x2e344b(0xfe),'lint:mustache-in-dsl':_0x2e344b(0xfe),'validator:unknown-function':_0x2e344b(0xfe)}},'mcp':{'transport':_0x2e344b(0xce)},'sandbox':{}};function _0x8977(_0x3a774f,_0x1b39aa){_0x3a774f=_0x3a774f-0xc4;var _0x19a653=_0x19a6();var _0x89776=_0x19a653[_0x3a774f];if(_0x8977['fRpWih']===undefined){var _0x38d7ef=function(_0x26bdbc){var _0x3caffa='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0xda4aa0='',_0x563661='';for(var _0x305f13=0x0,_0x3d29c0,_0x481c1e,_0x19b0ec=0x0;_0x481c1e=_0x26bdbc['charAt'](_0x19b0ec++);~_0x481c1e&&(_0x3d29c0=_0x305f13%0x4?_0x3d29c0*0x40+_0x481c1e:_0x481c1e,_0x305f13++%0x4)?_0xda4aa0+=String['fromCharCode'](0xff&_0x3d29c0>>(-0x2*_0x305f13&0x6)):0x0){_0x481c1e=_0x3caffa['indexOf'](_0x481c1e);}for(var _0x4792b1=0x0,_0x49dbb6=_0xda4aa0['length'];_0x4792b1<_0x49dbb6;_0x4792b1++){_0x563661+='%'+('00'+_0xda4aa0['charCodeAt'](_0x4792b1)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x563661);};_0x8977['wyEdtR']=_0x38d7ef,_0x8977['cHKdQs']={},_0x8977['fRpWih']=!![];}var _0x1354e5=_0x19a653[0x0],_0x16a4bb=_0x3a774f+_0x1354e5,_0x9c7c53=_0x8977['cHKdQs'][_0x16a4bb];return!_0x9c7c53?(_0x89776=_0x8977['wyEdtR'](_0x89776),_0x8977['cHKdQs'][_0x16a4bb]=_0x89776):_0x89776=_0x9c7c53,_0x89776;}export{BrowserChannelSchema,BrowserSchema,DEFAULT_CONFIG,DialogPolicySchema,FailureBundleConfigSchema,LinterConfigSchema,LinterRuleIdSchema,LinterSeveritySchema,McpConfigSchema,RetryConfigSchema,RetryReasonSchema,SandboxConfigSchema,UnotestConfigSchema,ViewportSchema,WebServerConfigSchema};function _0x19a6(){var _0x1434f7=['DMfSAwrHDg9YoMXPC3qTyxjN','Dw5VDgvZDc9LmMuVx2HLBhbLCNm','D2vIA2L0','zw51Bq','BgLUDdPZy2vUyxjPBY1PBI1YB290','mtG3nduYCKHJsuHS','BgLUDdPLDMfSDwf0zs1KAxnJB3vYywDLza','zxjYB3i','BgLUDdPWyxvZzs1LEhbSAwnPDa','DMfSAwrHDg9YoMLMlxnOyxbL','DMfSAwrHDg9YoNzHCI1ZAgfWzq','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlxn0yxrLBwvUDa','BwLU','C3rYAw5N','DMfSAwrHDg9YoNnLBwfUDgLJlwXVC3m','zgvMyxvSDa','BgL0zxjHBa','mJyYmdrzrev4q0K','DMfSAwrHDg9YoMz1BMn0Aw9UlxnOyxbL','BxnLzgDL','y2HYB21L','Cg9ZAxrPDMu','mtq3nZa0mLfMrgnerW','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlwv4ChjLC3nPB24','C3rKAw8','zMLYzwzVEa','ywnJzxb0','BNvTyMvY','DMfSAwrHDg9YoMfYzY1RAw5K','DMfSAwrHDg9YoNn0zxaTC2HHCgu','DMfSAwrHDg9YoNvUA25VD24TzNvUy3rPB24','BgLUDdPKzwvWlwnZCW','BMv0D29YAW','B2jQzwn0','D2fYBG','lNvUB3rLC3qVzMfPBhvYzxm','DxjS','DhjHBNnPzw50','yM9VBgvHBG','mLPiC0XWDq','BwfUDwfS','mZy5ntm1tgPYrKfu','mtqWntu0offSrgvtBG','nti5mdiZmgLwwwnRDG','DMfSAwrHDg9YoNn0zxaTy292zxjHz2u','y2HYB21PDw0','m1LeDg1LzG','BgLUDdPTDxn0ywnOzs1PBI1KC2W','B2zM','Dw5VDgvZDc9LmMu','odHXD3bdzNq','BNvSBa','nJq2mJy1seL0CvP3','BgLUDdPKAxnHBwjPzY1IEs1PBMrLEa','B3b0Aw9UywW','yxjYyxK','Aw50','y3jHC2G','DMfSAwrHDg9YoMzVCI1ZAgfWzq','zgLZBwLZCW','DMfSAwrHDg9YoMfYAxr5','Dw5PB24','CMvJB3jK','y2HYB21LlwjLDge','BgLUDdPVyMz1C2nHDgvKlwnSyxnZ'];_0x19a6=function(){return _0x1434f7;};return _0x19a6();}
1
+ var _0x24740a=_0x202c;(function(_0x2e7bfe,_0x17cbeb){var _0x5d30b8={_0x2648ae:0x193,_0x5ea1b9:0x19f,_0x1fb823:0x19d,_0x2f0413:0x1a8,_0x2e20ee:0x192},_0x482484=_0x202c,_0x3038a0=_0x2e7bfe();while(!![]){try{var _0x3f2fa8=-parseInt(_0x482484(0x189))/0x1+-parseInt(_0x482484(_0x5d30b8._0x2648ae))/0x2+-parseInt(_0x482484(_0x5d30b8._0x5ea1b9))/0x3*(-parseInt(_0x482484(0x1b3))/0x4)+-parseInt(_0x482484(_0x5d30b8._0x1fb823))/0x5+parseInt(_0x482484(_0x5d30b8._0x2f0413))/0x6+-parseInt(_0x482484(_0x5d30b8._0x2e20ee))/0x7+parseInt(_0x482484(0x1a5))/0x8;if(_0x3f2fa8===_0x17cbeb)break;else _0x3038a0['push'](_0x3038a0['shift']());}catch(_0x3f5318){_0x3038a0['push'](_0x3038a0['shift']());}}}(_0x4907,0x97be5));function _0x4907(){var _0x351a15=['B2jQzwn0','otK0otG5Ewr1EeHv','BgLUDdPYzwDLEc1PBNzHBgLK','Dw5VDgvZDc9LmMuVx2HLBhbLCNm','Dw5PB24','lNvUB3rLC3qVzMfPBhvYzxm','y3jHC2G','BgLUDdPKAxnHBwjPzY1IEs1PBMrLEa','DMfSAwrHDg9YoMXPC3qTyxjN','BgLUDdPLDMfSDwf0zs1KAxnJB3vYywDLza','mJyZmdGYnfLUr2HSuG','mJe4mZq0nKPorhLkuG','DxjS','DMfSAwrHDg9YoNvUA25VD24TzNvUy3rPB24','BNvSBa','DMfSAwrHDg9YoNnLBwfUDgLJlwXVC3m','DMfSAwrHDg9YoMLMlxnOyxbL','D2vIA2L0','BwfUDwfS','CMvJB3jK','DMfSAwrHDg9YoNn0CMLUzY1JB25Jyxq','mJe0odCWmgnHCwXHCa','BgL0zxjHBa','ntKXDfrWzhPP','BgLUDdPNB3rVlwnVBMnHDa','DMfSAwrHDg9YoNn0zxaTC2HHCgu','y2HYB21L','zxjYB3i','yxjYyxK','mtmWodC3mJHItgfuB3m','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlwv4ChjLC3nPB24','zw51Bq','nJa5ntKWnhnNDvbezG','C3rKAw8','BMv0D29YAW','DMfSAwrHDg9YoMfYzY1RAw5K','BgLUDdP4Cgf0Aa','BNvTyMvY','DhjHBNnPzw50','B3b0Aw9UywW','DMfSAwrHDg9YoMzVCI1ZAgfWzq','BgLUDdPLy2HVlwfZC2vYDa','BgLUDdPTDxn0ywnOzs1PBI1KC2W','mtC1mdbcD3zWrLm','BgLUDdPSAw50lw9Rlw1PC3nPBMCTCMvHC29U','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlxn0yxrLBwvUDa','Cg9ZAxrPDMu','yM9VBgvHBG','BxnLzgDL','Aw50','zgvMyxvSDa','zMLYzwzVEa','BwLU','DMfSAwrHDg9YoNzHCI1ZAgfWzq','Dw5VDgvZDc9LmMu','DMfSAwrHDg9YoM1LDgeTC2HHCgu','DMfSAwrHDg9YoMfYAxr5','y2HYB21LlwjLDge','C3rYAw5N','D2fYBG','y2HYB21PDw0','BgLUDdPKzwvWlwnZCW','zgLZBwLZCW'];_0x4907=function(){return _0x351a15;};return _0x4907();}import{z}from'zod';var BrowserSchema=z[_0x24740a(0x1a7)](['chromium',_0x24740a(0x17c),_0x24740a(0x199)]),BrowserChannelSchema=z[_0x24740a(0x18c)]([z[_0x24740a(0x19e)](_0x24740a(0x1a2)),z[_0x24740a(0x19e)](_0x24740a(0x1b8)),z[_0x24740a(0x19e)](_0x24740a(0x182)),z[_0x24740a(0x196)]()])[_0x24740a(0x1af)](),ViewportSchema=z[_0x24740a(0x188)]({'width':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()[_0x24740a(0x1b6)](),'height':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()[_0x24740a(0x1b6)]()}),RetryReasonSchema=z[_0x24740a(0x1a7)]([_0x24740a(0x1ae),_0x24740a(0x1aa),_0x24740a(0x18e)]),RetryConfigSchema=z[_0x24740a(0x188)]({'count':z[_0x24740a(0x1ad)]()['int']()['min'](0x0)['max'](0xa),'on':z[_0x24740a(0x1a4)](RetryReasonSchema)}),FailureBundleConfigSchema=z['object']({'tier1':z['literal'](!![])['default'](!![]),'tier2':z[_0x24740a(0x1b7)](),'tier3':z[_0x24740a(0x188)]({'network':z[_0x24740a(0x1b7)](),'video':z['boolean']()}),'retention':z['object']({'runs':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()[_0x24740a(0x1b6)](),'days':z[_0x24740a(0x1ad)]()['int']()[_0x24740a(0x1b6)]()}),'storageDir':z[_0x24740a(0x183)]()[_0x24740a(0x17d)](0x1)}),DialogPolicySchema=z['enum'](['accept',_0x24740a(0x187),_0x24740a(0x19a)]),LinterRuleIdSchema=z[_0x24740a(0x1a7)]([_0x24740a(0x186),_0x24740a(0x1ac),'lint:obfuscated-class','lint:pause-explicit',_0x24740a(0x18f),_0x24740a(0x191),'lint:scenario-in-root',_0x24740a(0x1b2),_0x24740a(0x1a0),_0x24740a(0x18a),_0x24740a(0x1b1),_0x24740a(0x1b4),_0x24740a(0x195),_0x24740a(0x181),_0x24740a(0x1ab),'validator:step-coverage',_0x24740a(0x1a1),_0x24740a(0x180),'validator:function-shape',_0x24740a(0x1b0),_0x24740a(0x198),_0x24740a(0x17e),_0x24740a(0x1b5),_0x24740a(0x1a6),_0x24740a(0x19c),_0x24740a(0x197),_0x24740a(0x190),'validator:wrapped-format']),LinterSeveritySchema=z[_0x24740a(0x1a7)](['off',_0x24740a(0x184),'error']),LinterConfigSchema=z[_0x24740a(0x188)]({'enabled':z[_0x24740a(0x1b7)](),'rules':z[_0x24740a(0x19b)](LinterRuleIdSchema,LinterSeveritySchema)}),McpConfigSchema=z['object']({'transport':z[_0x24740a(0x19e)](_0x24740a(0x1a9))}),SandboxConfigSchema=z[_0x24740a(0x188)]({'shellCwd':z['string']()['optional'](),'shellTimeoutMs':z[_0x24740a(0x1ad)]()['int']()[_0x24740a(0x1b6)]()[_0x24740a(0x1af)](),'exportSecrets':z['array'](z['string']())[_0x24740a(0x1af)](),'database':z[_0x24740a(0x183)]()['optional'](),'apiBaseUrl':z[_0x24740a(0x183)]()[_0x24740a(0x194)]()[_0x24740a(0x1af)](),'uploadDir':z[_0x24740a(0x183)]()['optional']()}),WebServerConfigSchema=z[_0x24740a(0x188)]({'command':z[_0x24740a(0x183)]()[_0x24740a(0x17d)](0x1),'url':z[_0x24740a(0x183)]()[_0x24740a(0x194)](),'reuseExistingServer':z[_0x24740a(0x1b7)]()['default'](!![]),'timeoutMs':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()['positive']()[_0x24740a(0x1ba)](0xea60)}),UnotestConfigSchema=z[_0x24740a(0x188)]({'baseUrl':z[_0x24740a(0x183)]()[_0x24740a(0x194)]()[_0x24740a(0x1af)](),'webServer':WebServerConfigSchema[_0x24740a(0x1af)](),'browsers':z[_0x24740a(0x1a4)](BrowserSchema)[_0x24740a(0x17d)](0x1),'channel':BrowserChannelSchema,'viewport':ViewportSchema,'retry':RetryConfigSchema,'failureBundle':FailureBundleConfigSchema,'dialogPolicy':DialogPolicySchema,'storageState':z['string']()[_0x24740a(0x1af)](),'testDir':z[_0x24740a(0x183)]()[_0x24740a(0x17d)](0x1),'helpersDir':z[_0x24740a(0x183)]()[_0x24740a(0x17d)](0x1),'defaultTimeoutMs':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()[_0x24740a(0x1b6)](),'defaultNavigationTimeoutMs':z[_0x24740a(0x1ad)]()[_0x24740a(0x1b9)]()[_0x24740a(0x1b6)](),'linter':LinterConfigSchema,'mcp':McpConfigSchema,'sandbox':SandboxConfigSchema}),DEFAULT_CONFIG={'browsers':[_0x24740a(0x185)],'viewport':{'width':0x500,'height':0x2d0},'retry':{'count':0x0,'on':['transient']},'failureBundle':{'tier1':!![],'tier2':!![],'tier3':{'network':![],'video':![]},'retention':{'runs':0x14,'days':0x7},'storageDir':_0x24740a(0x18d)},'dialogPolicy':'accept','testDir':_0x24740a(0x17f),'helpersDir':_0x24740a(0x18b),'defaultTimeoutMs':0xbb8,'defaultNavigationTimeoutMs':0x7530,'linter':{'enabled':!![],'rules':{'lint:deep-css':'warn','lint:xpath':_0x24740a(0x184),'lint:obfuscated-class':_0x24740a(0x184),'lint:pause-explicit':_0x24740a(0x184),'lint:disambig-by-index':'off','lint:evaluate-discouraged':'warn','lint:scenario-in-root':_0x24740a(0x1a3),'lint:mustache-in-dsl':'error','lint:goto-concat':_0x24740a(0x184),'lint:regex-invalid':_0x24740a(0x1a3),'lint:echo-assert':_0x24740a(0x184),'lint:lint-ok-missing-reason':_0x24740a(0x184),'validator:unknown-function':_0x24740a(0x1a3)}},'mcp':{'transport':_0x24740a(0x1a9)},'sandbox':{}};function _0x202c(_0x5b55f0,_0x1e1548){_0x5b55f0=_0x5b55f0-0x17c;var _0x49075b=_0x4907();var _0x202c4b=_0x49075b[_0x5b55f0];if(_0x202c['tyZDFh']===undefined){var _0xe49ede=function(_0x401a06){var _0x337267='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x3744b8='',_0x98677e='';for(var _0x5d0a3c=0x0,_0x50befd,_0x1f34a4,_0x56a82f=0x0;_0x1f34a4=_0x401a06['charAt'](_0x56a82f++);~_0x1f34a4&&(_0x50befd=_0x5d0a3c%0x4?_0x50befd*0x40+_0x1f34a4:_0x1f34a4,_0x5d0a3c++%0x4)?_0x3744b8+=String['fromCharCode'](0xff&_0x50befd>>(-0x2*_0x5d0a3c&0x6)):0x0){_0x1f34a4=_0x337267['indexOf'](_0x1f34a4);}for(var _0x2145f6=0x0,_0xfee7e3=_0x3744b8['length'];_0x2145f6<_0xfee7e3;_0x2145f6++){_0x98677e+='%'+('00'+_0x3744b8['charCodeAt'](_0x2145f6)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x98677e);};_0x202c['pPVuVN']=_0xe49ede,_0x202c['TGtDoY']={},_0x202c['tyZDFh']=!![];}var _0x95650d=_0x49075b[0x0],_0x58923e=_0x5b55f0+_0x95650d,_0x39365d=_0x202c['TGtDoY'][_0x58923e];return!_0x39365d?(_0x202c4b=_0x202c['pPVuVN'](_0x202c4b),_0x202c['TGtDoY'][_0x58923e]=_0x202c4b):_0x202c4b=_0x39365d,_0x202c4b;}export{BrowserChannelSchema,BrowserSchema,DEFAULT_CONFIG,DialogPolicySchema,FailureBundleConfigSchema,LinterConfigSchema,LinterRuleIdSchema,LinterSeveritySchema,McpConfigSchema,RetryConfigSchema,RetryReasonSchema,SandboxConfigSchema,UnotestConfigSchema,ViewportSchema,WebServerConfigSchema};
@@ -1,5 +1,5 @@
1
- import { E as ElementHint, N as NetworkEntry, W as WebDriver, L as LaunchOptions, C as ContextOptions, D as DriverContext } from '../interfaces-BxviHxnr.js';
2
- export { A as ActionTimeout, a as CheckOptions, b as ClickOptions, c as CookieOptions, d as DriverPage, F as FillOptions, G as GotoOptions, H as HoverOptions, e as NavigationOptions, P as PressOptions, R as ReloadOptions, S as ScreenshotOptions, f as SelectOptions, V as Viewport, g as WaitOptions, h as WaitState } from '../interfaces-BxviHxnr.js';
1
+ import { E as ElementHint, N as NetworkEntry, W as WebDriver, L as LaunchOptions, C as ContextOptions, D as DriverContext } from '../interfaces-XvuefHHC.js';
2
+ export { A as ActionTimeout, a as CheckOptions, b as ClickOptions, c as CookieOptions, d as DriverPage, F as FillOptions, G as GotoOptions, H as HoverOptions, e as NavigationOptions, P as PressOptions, R as ReloadOptions, S as ScreenshotOptions, f as SelectOptions, V as Viewport, g as WaitOptions, h as WaitState } from '../interfaces-XvuefHHC.js';
3
3
  import '@unotest/protocol';
4
4
  import '../config/schema.js';
5
5
  import 'zod';
@@ -27,6 +27,8 @@ interface FakeBehavior {
27
27
  inputValueByDefault?: string;
28
28
  /** Default isVisible() response. Default: true. */
29
29
  isVisibleByDefault?: boolean;
30
+ /** Default isDisabled() response. Default: false. */
31
+ isDisabledByDefault?: boolean;
30
32
  /** Default checkedState() response — null = "not a checkable element",
31
33
  * the shape a plain <input type=text> reports. Default: null. */
32
34
  checkedStateByDefault?: boolean | null;