@unotest/web 0.11.0 → 0.13.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.
@@ -60,6 +60,10 @@ explore_start { scenario_name: "<feature>/<name>" } → { explorationId }
60
60
 
61
61
  Keep the `explorationId` — every recorded step needs it.
62
62
 
63
+ Optional `env: "<name>"` records THIS session against the
64
+ `.env.<name>` / `.secrets.<name>` overlays (variables, secrets,
65
+ APP_BASE_URL) — same idea as run_test's per-call `env`.
66
+
63
67
  `explore_start` opens the browser itself. Do NOT call `new_context`
64
68
  first — it's for RESETTING the browser (Phase 5), not for starting.
65
69
 
@@ -306,7 +310,7 @@ What's **not allowed** (parser / runtime will reject): `import` /
306
310
  `export` / `require`, top-level `await`, `class`, JSX, `while` /
307
311
  `do…while` / `continue` / `++`. Bounded `for (i = 0; i < N; i = i + 1)`
308
312
  loops ARE supported, and `break` is legal inside a loop body — poll with
309
- `for` + `if (…) { break; }` + `pause(ms) // reason: …`. Index access
313
+ `for` + `if (…) { break; }` + `pause(ms) // lint-ok: …`. Index access
310
314
  reads data (`docs[0].count`, bare variable only, never a Locator);
311
315
  `obj.prop[i]` does not parse — assign the member first:
312
316
  `m = state.matches; last = m[m.length - 1];`. `arr[i] = v` stays
@@ -379,7 +383,7 @@ Disambiguate with `.filter({hasText: '…'})` or `.filter({has: …})` —
379
383
  Waits:
380
384
  - `waitFor(loc, opts?)`, `waitForText(text, opts?)`,
381
385
  `waitForCount(loc, n, opts?)`, `waitForUrl(pattern)`, `pause(ms)` —
382
- `pause` requires `// reason: <why>` comment immediately above (linter
386
+ `pause` requires a trailing `// lint-ok: <why>` comment on the same line (linter
383
387
  flags `lint:pause-explicit` otherwise).
384
388
  - `waitForText` waits for ≥1 VISIBLE occurrence (repeated text in a feed
385
389
  is fine); substring by default — `{exact: true}` or a regex
@@ -397,7 +401,8 @@ State reads:
397
401
  `getInputValue(loc)`.
398
402
 
399
403
  Sandbox primitives:
400
- - `shell("cmd", "arg", )` — `execFile` style, no shell interpretation.
404
+ - `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).
405
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it exists / matches; use it to await output of background processes started via `shell()`.
401
406
  - `dbQuery(sql, …params)`, `dbExec(sql, …params)` — parameterized.
402
407
  - `apiCall(method, path, body?, headers?, opts?)` — path-only against
403
408
  `sandbox.apiBaseUrl`; another host via `{base: 'API_BASE_X'}` — the
@@ -411,7 +416,7 @@ Escape hatch:
411
416
  - `evaluate(\`js body\`, …args)` — raw backticks, no `${}`. Linter
412
417
  warns `lint:evaluate-discouraged`. Use only when nothing above fits.
413
418
 
414
- Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`.
419
+ Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`. Marker helper: `randomWord(len)` — random lowercase letters, digit-free.
415
420
 
416
421
  ## Helpers convention
417
422
 
@@ -85,6 +85,10 @@ explore_start { scenario_name: "<feature>/<name>" } → { explorationId }
85
85
 
86
86
  Keep the `explorationId` — every recorded step needs it.
87
87
 
88
+ Optional `env: "<name>"` records THIS session against the
89
+ `.env.<name>` / `.secrets.<name>` overlays (variables, secrets,
90
+ APP_BASE_URL) — same idea as run_test's per-call `env`.
91
+
88
92
  `explore_start` opens the browser itself. Do NOT call `new_context`
89
93
  first — it's for RESETTING the browser (Phase 5), not for starting.
90
94
 
@@ -437,7 +441,7 @@ What's **not allowed** (parser / runtime will reject): `import` /
437
441
  `export` / `require`, top-level `await`, `class`, JSX, `while` /
438
442
  `do…while` / `continue` / `++`. Bounded `for (i = 0; i < N; i = i + 1)`
439
443
  loops ARE supported, and `break` is legal inside a loop body — poll with
440
- `for` + `if (…) { break; }` + `pause(ms) // reason: …`. Index access
444
+ `for` + `if (…) { break; }` + `pause(ms) // lint-ok: …`. Index access
441
445
  reads data (`docs[0].count`, bare variable only, never a Locator);
442
446
  `obj.prop[i]` does not parse — assign the member first:
443
447
  `m = state.matches; last = m[m.length - 1];`. `arr[i] = v` stays
@@ -510,7 +514,7 @@ Disambiguate with `.filter({hasText: '…'})` or `.filter({has: …})` —
510
514
  Waits:
511
515
  - `waitFor(loc, opts?)`, `waitForText(text, opts?)`,
512
516
  `waitForCount(loc, n, opts?)`, `waitForUrl(pattern)`, `pause(ms)` —
513
- `pause` requires `// reason: <why>` comment immediately above (linter
517
+ `pause` requires a trailing `// lint-ok: <why>` comment on the same line (linter
514
518
  flags `lint:pause-explicit` otherwise).
515
519
  - `waitForText` waits for ≥1 VISIBLE occurrence (repeated text in a feed
516
520
  is fine); substring by default — `{exact: true}` or a regex
@@ -528,7 +532,8 @@ State reads:
528
532
  `getInputValue(loc)`.
529
533
 
530
534
  Sandbox primitives:
531
- - `shell("cmd", "arg", )` — `execFile` style, no shell interpretation.
535
+ - `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).
536
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it exists / matches; use it to await output of background processes started via `shell()`.
532
537
  - `dbQuery(sql, …params)`, `dbExec(sql, …params)` — parameterized.
533
538
  - `apiCall(method, path, body?, headers?, opts?)` — path-only against
534
539
  `sandbox.apiBaseUrl`; another host via `{base: 'API_BASE_X'}` — the
@@ -542,7 +547,7 @@ Escape hatch:
542
547
  - `evaluate(\`js body\`, …args)` — raw backticks, no `${}`. Linter
543
548
  warns `lint:evaluate-discouraged`. Use only when nothing above fits.
544
549
 
545
- Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`.
550
+ Time helpers: `nowMs()`, `today()`, `daysFromNow(n)`. Marker helper: `randomWord(len)` — random lowercase letters, digit-free.
546
551
 
547
552
  ## Helpers convention
548
553
 
package/CHANGELOG.md CHANGED
@@ -1,10 +1,125 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.0] - 2026-08-15
4
+
5
+ ### Minor Changes
6
+
7
+ - 189c0e9: Per-call environments for explore sessions + init guidance
8
+ (bot-service feedback, round 2):
9
+
10
+ - `explore_start` accepts `env`: that session's variables, secrets and
11
+ `APP_BASE_URL` resolve against the `.env.<env>` / `.secrets.<env>`
12
+ overlays, without touching the server's own environment or other
13
+ sessions. Overlay secrets are also masked in all log sinks. The
14
+ `explore_steps` autoRun finale runs the saved test with the same
15
+ `env`. Symmetric with `run_test`'s per-call `env`.
16
+ - `init` "Next steps" now says to restart an already-open agent session
17
+ (MCP clients load `.mcp.json` servers at session start — no
18
+ hot-connect in the protocol); same recipe added to the
19
+ troubleshooting manual.
20
+
21
+ - 4b3c9fd: New DSL function `textJoin(parts) → string` — concatenates an array of
22
+ parts (numbers coerced). The validator has always rejected `+` on
23
+ strings with a hint pointing at `textJoin([...])`, but the function did
24
+ not exist in the web registry, leaving scenarios with no legal way to
25
+ build a dynamic string. Found by the dogfood suite on its first lint.
26
+
27
+ ### Patch Changes
28
+
29
+ - `waitForText` now respects the active `enterFrame` stack — it used to
30
+ build its locator from the top document, so inside a frame it waited on
31
+ text the frame content could never satisfy. Found by the dogfood suite
32
+ (nested-iframes scenario).
33
+ - Updated dependencies [39ca34f]
34
+ - Updated dependencies [a4f0a62]
35
+ - Updated dependencies [8d70df6]
36
+ - @unotest/dsl@0.13.0
37
+ - @unotest/core@0.13.0
38
+ - @unotest/viewer@0.13.0
39
+ - @unotest/grounder-client@0.13.0
40
+ - @unotest/protocol@0.13.0
41
+
3
42
  All notable changes to `@unotest/web` are documented in this file.
4
43
 
5
44
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
45
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
46
 
47
+ ## [0.12.0] - 2026-08-14
48
+
49
+ ### Minor Changes
50
+
51
+ - 479aa25: The active variable environment is now agent-visible instead of
52
+ docs-only. `explore_start` and `run_test` replies carry an
53
+ `environment` field: the active env name (`UNOTEST_ENV`, `null` = base)
54
+ plus every `.env` / `.secrets` layer file with an `exists` flag. A
55
+ missing external variable error now also lists the searched layers
56
+ (`Looked in environment "dev" (UNOTEST_ENV): unotest/.env,
57
+ unotest/.env.dev (no such file)`). Tool descriptions for `run_test` /
58
+ `explore_start` explain the env mechanism — MCP sessions inherit
59
+ `UNOTEST_ENV` from the server process (set it in the client's `env`
60
+ block); CLI runs take `--env <name>`. The shipped agent guide gains a
61
+ "Variable environments" section.
62
+ - 479aa25: Feedback batch from a real-world integration (bot-service): shell()
63
+ safety, run diagnostics, boolean-attribute probes, linter ergonomics.
64
+
65
+ **BREAKING — `shell()` fails the step on a non-zero exit code.**
66
+ Previously a non-zero exit resolved silently and a forgotten `res.code`
67
+ check produced false-green tests. Migration: calls where non-zero is
68
+ expected (probes, `grep -q`) pass `{allowNonZero: true}` as the last
69
+ argument and keep checking `res.code`; calls that asserted
70
+ `assertTrue(out.code == 0, ...)` can drop the assert. More shell()
71
+ hardening: a missing binary is a distinct "failed to start" error (was a
72
+ fake `code: 1`), output over 10 MiB fails loudly (was silent
73
+ truncation), and every call has a wall-clock budget
74
+ (`sandbox.shellTimeoutMs`, default 120 s, or per-call `{timeoutMs}`) —
75
+ a detached grandchild holding the stdio pipes no longer hangs the
76
+ scenario forever; the timeout error explains the detach recipe.
77
+
78
+ New capabilities:
79
+
80
+ - `waitForFile(path, pattern?, {timeoutMs})` — poll a file until it
81
+ exists / contains a substring or regex; the file-side `waitForText`
82
+ for background processes. Returns the content.
83
+ - `sandbox.exportSecrets: [names]` — explicit allowlist of `.secrets*`
84
+ variables exported into `shell()` subprocess env (still masked in
85
+ logs). Secrets stay out of `process.env` otherwise.
86
+ - `isDisabled(loc)` / `isEnabled(loc)` — honest disabled probe (native
87
+ `:disabled` incl. fieldset inheritance, or `aria-disabled`);
88
+ `hasAttribute(loc, name)` — presence probe for boolean attributes
89
+ (`getAttribute` reads `""` for present and absent alike).
90
+ - Generators: `randomWord(len)` (letters only — digit-free markers),
91
+ `nowMs()`, `today()`, `daysFromNow(n)` (previously documented in the
92
+ skills but not implemented).
93
+ - Failed runs report the enclosing step: `✗ test: … in step "…"` in the
94
+ console, `stepLabel` in the failure bundle and `inspect_runtime`.
95
+ - Every CLI run prints a one-line header: active environment, layer
96
+ files (missing ones flagged) and effective `baseUrl`; `run_test` /
97
+ `explore_start` replies echo `baseUrl` next to `environment`.
98
+ - `run_test` accepts per-call `env` — the spawned runner child gets
99
+ `UNOTEST_ENV=<env>` for that run only.
100
+ - Linter: `// lint-ok: <reason>` silences warning/info diagnostics on
101
+ its line (reason required; errors never suppressible); new
102
+ `lint:echo-assert` warns when `waitForText`/`assertText` overlaps a
103
+ value the scenario itself filled (chat echo trap);
104
+ `lint:goto-concat` / `lint:regex-invalid` are now configurable in
105
+ `linter.rules` (they were emitted but missing from the config schema).
106
+ - A `_helpers` file that fails to parse is reported as the root cause in
107
+ `unotest-web lint` (and explore replies list `unparsableHelperFiles`)
108
+ instead of silently cascading into "Unknown function" at every call
109
+ site. The viewer logs the same condition (patch).
110
+
111
+ ### Patch Changes
112
+
113
+ - Updated dependencies [40300d3]
114
+ - Updated dependencies [479aa25]
115
+ - Updated dependencies [5dd59af]
116
+ - Updated dependencies [7069d24]
117
+ - @unotest/dsl@0.12.0
118
+ - @unotest/viewer@0.12.0
119
+ - @unotest/core@0.12.0
120
+ - @unotest/grounder-client@0.12.0
121
+ - @unotest/protocol@0.12.0
122
+
8
123
  ## [0.11.0] - 2026-08-13
9
124
 
10
125
  ### 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>;
@@ -130,11 +141,15 @@ declare const SandboxConfigSchema: z.ZodObject<{
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>;
@@ -329,11 +355,15 @@ declare const UnotestConfigSchema: z.ZodObject<{
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
- function _0xbf3c(){var _0x5a10e4=['zgvMyxvSDa','nZaZnZDkrwX3y0S','DMfSAwrHDg9YoNn0zxaTy292zxjHz2u','mtaXnZiXm1riAMTSDG','mZnyzhzhvg4','zMLYzwzVEa','DMfSAwrHDg9YoNn0CMLUzY1JB25Jyxq','mtK1mZqYthPkwhPg','ohjqwxfcBa','lNvUB3rLC3qVzMfPBhvYzxm','D2fYBG','BxnLzgDL','BgLUDdPVyMz1C2nHDgvKlwnSyxnZ','DMfSAwrHDg9YoM1LDgeTC2HHCgu','Cg9ZAxrPDMu','B3b0Aw9UywW','DMfSAwrHDg9YoNzHCI1ZAgfWzq','BNvSBa','B2jQzwn0','mJu1nZu2mffKrevZEq','BwfUDwfS','y2HYB21PDw0','yxjYyxK','DMfSAwrHDg9YoNDYyxbWzwqTzM9YBwf0','BgLUDdPZy2vUyxjPBY1PBI1YB290','Bwf4','C3rYAw5N','nvrIEKz2uq','mJrfCe1AEee','BNvTyMvY','yM9VBgvHBG','DMfSAwrHDg9YoNvUA25VD24TzNvUy3rPB24','mtqZwK5wBKPy','BgLUDdPTDxn0ywnOzs1PBI1KC2W','Aw50','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlxn0yxrLBwvUDa','DMfSAwrHDg9YoMXPC3qTyxjN','DMfSAwrHDg9YoMzVCI1ZAgfWzq','ywnJzxb0','BgLUDdPKAxnHBwjPzY1IEs1PBMrLEa','C3rKAw8','B2zM','BgLUDdPWyxvZzs1LEhbSAwnPDa','ntuZzhrbsufk','DxjS','zxjYB3i','y2HYB21L','y2HYB21LlwjLDge','mtqXndq1ogLKz3rmtW','CMvJB3jK','mteWotG2ohDLv3LyBa','zw51Bq','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlwv4ChjLC3nPB24','nJu0nJrpt2TzrgO','y3jHC2G','BwLU','Dw5VDgvZDc9LmMu','Dw5VDgvZDc9LmMuVx2HLBhbLCNm','BgLUDdPLDMfSDwf0zs1KAxnJB3vYywDLza','BgL0zxjHBa','DMfSAwrHDg9YoNn0zxaTC2HHCgu'];_0xbf3c=function(){return _0x5a10e4;};return _0xbf3c();}var _0x5b7026=_0x4a4e;(function(_0x2f37c3,_0xd597d6){var _0x574d49={_0x201899:0x172,_0xd15309:0x171,_0x5646ca:0x158,_0x1341cf:0x15d,_0x1122e5:0x17d},_0x412659=_0x4a4e,_0x24087b=_0x2f37c3();while(!![]){try{var _0x157f85=-parseInt(_0x412659(0x16b))/0x1*(-parseInt(_0x412659(0x149))/0x2)+parseInt(_0x412659(0x16d))/0x3*(parseInt(_0x412659(_0x574d49._0x201899))/0x4)+parseInt(_0x412659(0x185))/0x5*(-parseInt(_0x412659(_0x574d49._0xd15309))/0x6)+parseInt(_0x412659(_0x574d49._0x5646ca))/0x7*(-parseInt(_0x412659(0x162))/0x8)+-parseInt(_0x412659(_0x574d49._0x1341cf))/0x9+parseInt(_0x412659(_0x574d49._0x1122e5))/0xa*(parseInt(_0x412659(0x16e))/0xb)+parseInt(_0x412659(0x15f))/0xc*(-parseInt(_0x412659(0x14d))/0xd);if(_0x157f85===_0xd597d6)break;else _0x24087b['push'](_0x24087b['shift']());}catch(_0x5c5156){_0x24087b['push'](_0x24087b['shift']());}}}(_0xbf3c,0x6a89b));import{z}from'zod';var BrowserSchema=z[_0x5b7026(0x160)](['chromium',_0x5b7026(0x16f),'webkit']),BrowserChannelSchema=z['union']([z['literal'](_0x5b7026(0x15b)),z[_0x5b7026(0x168)](_0x5b7026(0x175)),z[_0x5b7026(0x168)](_0x5b7026(0x15c)),z[_0x5b7026(0x17b)]()])[_0x5b7026(0x179)](),ViewportSchema=z[_0x5b7026(0x17c)]({'width':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x178)](),'height':z[_0x5b7026(0x14a)]()['int']()[_0x5b7026(0x178)]()}),RetryReasonSchema=z[_0x5b7026(0x160)](['transient','network',_0x5b7026(0x163)]),RetryConfigSchema=z[_0x5b7026(0x17c)]({'count':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x164)](0x0)[_0x5b7026(0x183)](0xa),'on':z[_0x5b7026(0x180)](RetryReasonSchema)}),FailureBundleConfigSchema=z[_0x5b7026(0x17c)]({'tier1':z[_0x5b7026(0x168)](!![])[_0x5b7026(0x16a)](!![]),'tier2':z['boolean'](),'tier3':z[_0x5b7026(0x17c)]({'network':z[_0x5b7026(0x14b)](),'video':z[_0x5b7026(0x14b)]()}),'retention':z[_0x5b7026(0x17c)]({'runs':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x178)](),'days':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x178)]()}),'storageDir':z[_0x5b7026(0x184)]()['min'](0x1)}),DialogPolicySchema=z[_0x5b7026(0x160)]([_0x5b7026(0x153),'dismiss',_0x5b7026(0x17e)]),LinterRuleIdSchema=z[_0x5b7026(0x160)](['lint:deep-css','lint:xpath',_0x5b7026(0x176),_0x5b7026(0x157),_0x5b7026(0x154),_0x5b7026(0x167),_0x5b7026(0x182),_0x5b7026(0x14e),_0x5b7026(0x14c),'validator:arity','validator:arg-kind',_0x5b7026(0x16c),_0x5b7026(0x169),_0x5b7026(0x177),'validator:function-shape',_0x5b7026(0x152),'validator:if-shape',_0x5b7026(0x17a),_0x5b7026(0x150),_0x5b7026(0x161),_0x5b7026(0x170),'validator:semantic-loss',_0x5b7026(0x151),_0x5b7026(0x181)]),LinterSeveritySchema=z[_0x5b7026(0x160)]([_0x5b7026(0x156),_0x5b7026(0x174),_0x5b7026(0x15a)]),LinterConfigSchema=z[_0x5b7026(0x17c)]({'enabled':z[_0x5b7026(0x14b)](),'rules':z[_0x5b7026(0x15e)](LinterRuleIdSchema,LinterSeveritySchema)}),McpConfigSchema=z[_0x5b7026(0x17c)]({'transport':z['literal'](_0x5b7026(0x155))}),SandboxConfigSchema=z[_0x5b7026(0x17c)]({'shellCwd':z['string']()['optional'](),'database':z[_0x5b7026(0x184)]()[_0x5b7026(0x179)](),'apiBaseUrl':z[_0x5b7026(0x184)]()['url']()[_0x5b7026(0x179)](),'uploadDir':z[_0x5b7026(0x184)]()['optional']()}),WebServerConfigSchema=z[_0x5b7026(0x17c)]({'command':z[_0x5b7026(0x184)]()[_0x5b7026(0x164)](0x1),'url':z['string']()[_0x5b7026(0x159)](),'reuseExistingServer':z[_0x5b7026(0x14b)]()[_0x5b7026(0x16a)](!![]),'timeoutMs':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()['positive']()[_0x5b7026(0x16a)](0xea60)}),UnotestConfigSchema=z['object']({'baseUrl':z[_0x5b7026(0x184)]()['url']()[_0x5b7026(0x179)](),'webServer':WebServerConfigSchema[_0x5b7026(0x179)](),'browsers':z[_0x5b7026(0x180)](BrowserSchema)[_0x5b7026(0x164)](0x1),'channel':BrowserChannelSchema,'viewport':ViewportSchema,'retry':RetryConfigSchema,'failureBundle':FailureBundleConfigSchema,'dialogPolicy':DialogPolicySchema,'storageState':z[_0x5b7026(0x184)]()[_0x5b7026(0x179)](),'testDir':z['string']()['min'](0x1),'helpersDir':z[_0x5b7026(0x184)]()['min'](0x1),'defaultTimeoutMs':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x178)](),'defaultNavigationTimeoutMs':z[_0x5b7026(0x14a)]()[_0x5b7026(0x14f)]()[_0x5b7026(0x178)](),'linter':LinterConfigSchema,'mcp':McpConfigSchema,'sandbox':SandboxConfigSchema}),DEFAULT_CONFIG={'browsers':[_0x5b7026(0x17f)],'viewport':{'width':0x500,'height':0x2d0},'retry':{'count':0x0,'on':['transient']},'failureBundle':{'tier1':!![],'tier2':!![],'tier3':{'network':![],'video':![]},'retention':{'runs':0x14,'days':0x7},'storageDir':_0x5b7026(0x173)},'dialogPolicy':_0x5b7026(0x153),'testDir':_0x5b7026(0x165),'helpersDir':_0x5b7026(0x166),'defaultTimeoutMs':0xbb8,'defaultNavigationTimeoutMs':0x7530,'linter':{'enabled':!![],'rules':{'lint:deep-css':_0x5b7026(0x174),'lint:xpath':_0x5b7026(0x174),'lint:obfuscated-class':'warn','lint:pause-explicit':_0x5b7026(0x174),'lint:disambig-by-index':_0x5b7026(0x156),'lint:evaluate-discouraged':'warn','lint:scenario-in-root':_0x5b7026(0x15a),'lint:mustache-in-dsl':_0x5b7026(0x15a),'validator:unknown-function':_0x5b7026(0x15a)}},'mcp':{'transport':_0x5b7026(0x155)},'sandbox':{}};function _0x4a4e(_0x5a0c8d,_0x24a94e){_0x5a0c8d=_0x5a0c8d-0x149;var _0xbf3c28=_0xbf3c();var _0x4a4e14=_0xbf3c28[_0x5a0c8d];if(_0x4a4e['ZZiVPP']===undefined){var _0x3cbfd6=function(_0x5b8e52){var _0x1d90b9='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x23a664='',_0x5dd330='';for(var _0x54bc48=0x0,_0x2de8ed,_0xc5f58c,_0x271a4b=0x0;_0xc5f58c=_0x5b8e52['charAt'](_0x271a4b++);~_0xc5f58c&&(_0x2de8ed=_0x54bc48%0x4?_0x2de8ed*0x40+_0xc5f58c:_0xc5f58c,_0x54bc48++%0x4)?_0x23a664+=String['fromCharCode'](0xff&_0x2de8ed>>(-0x2*_0x54bc48&0x6)):0x0){_0xc5f58c=_0x1d90b9['indexOf'](_0xc5f58c);}for(var _0x599abd=0x0,_0x439dac=_0x23a664['length'];_0x599abd<_0x439dac;_0x599abd++){_0x5dd330+='%'+('00'+_0x23a664['charCodeAt'](_0x599abd)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5dd330);};_0x4a4e['BLwFta']=_0x3cbfd6,_0x4a4e['JKObLm']={},_0x4a4e['ZZiVPP']=!![];}var _0x25b54b=_0xbf3c28[0x0],_0x2f5e17=_0x5a0c8d+_0x25b54b,_0x298485=_0x4a4e['JKObLm'][_0x2f5e17];return!_0x298485?(_0x4a4e14=_0x4a4e['BLwFta'](_0x4a4e14),_0x4a4e['JKObLm'][_0x2f5e17]=_0x4a4e14):_0x4a4e14=_0x298485,_0x4a4e14;}export{BrowserChannelSchema,BrowserSchema,DEFAULT_CONFIG,DialogPolicySchema,FailureBundleConfigSchema,LinterConfigSchema,LinterRuleIdSchema,LinterSeveritySchema,McpConfigSchema,RetryConfigSchema,RetryReasonSchema,SandboxConfigSchema,UnotestConfigSchema,ViewportSchema,WebServerConfigSchema};
1
+ function _0x5620(_0x3bdb70,_0x5c2c92){_0x3bdb70=_0x3bdb70-0xc0;var _0x303e6a=_0x303e();var _0x56208b=_0x303e6a[_0x3bdb70];if(_0x5620['DtMoAC']===undefined){var _0x48d5d3=function(_0x4ca8e1){var _0x42faca='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x3761cf='',_0x3f19ee='';for(var _0xf3835c=0x0,_0x491d91,_0xbe24b9,_0x307333=0x0;_0xbe24b9=_0x4ca8e1['charAt'](_0x307333++);~_0xbe24b9&&(_0x491d91=_0xf3835c%0x4?_0x491d91*0x40+_0xbe24b9:_0xbe24b9,_0xf3835c++%0x4)?_0x3761cf+=String['fromCharCode'](0xff&_0x491d91>>(-0x2*_0xf3835c&0x6)):0x0){_0xbe24b9=_0x42faca['indexOf'](_0xbe24b9);}for(var _0x458ccb=0x0,_0x1ec763=_0x3761cf['length'];_0x458ccb<_0x1ec763;_0x458ccb++){_0x3f19ee+='%'+('00'+_0x3761cf['charCodeAt'](_0x458ccb)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3f19ee);};_0x5620['fiJJKr']=_0x48d5d3,_0x5620['jgqfJj']={},_0x5620['DtMoAC']=!![];}var _0x201d93=_0x303e6a[0x0],_0x46ecb6=_0x3bdb70+_0x201d93,_0x182087=_0x5620['jgqfJj'][_0x46ecb6];return!_0x182087?(_0x56208b=_0x5620['fiJJKr'](_0x56208b),_0x5620['jgqfJj'][_0x46ecb6]=_0x56208b):_0x56208b=_0x182087,_0x56208b;}var _0x454e0b=_0x5620;(function(_0xd31fc5,_0x3cc398){var _0x45e4c3={_0x28c5d9:0xdd,_0x584a8b:0xe7,_0x446d8b:0xce,_0x1f4b62:0xc8},_0xed309a=_0x5620,_0xa855fe=_0xd31fc5();while(!![]){try{var _0x131090=parseInt(_0xed309a(0xf9))/0x1+-parseInt(_0xed309a(0xc6))/0x2+parseInt(_0xed309a(_0x45e4c3._0x28c5d9))/0x3+-parseInt(_0xed309a(_0x45e4c3._0x584a8b))/0x4+parseInt(_0xed309a(_0x45e4c3._0x446d8b))/0x5*(parseInt(_0xed309a(_0x45e4c3._0x1f4b62))/0x6)+-parseInt(_0xed309a(0xfa))/0x7*(-parseInt(_0xed309a(0xc1))/0x8)+-parseInt(_0xed309a(0xd7))/0x9*(-parseInt(_0xed309a(0xe1))/0xa);if(_0x131090===_0x3cc398)break;else _0xa855fe['push'](_0xa855fe['shift']());}catch(_0x3ac620){_0xa855fe['push'](_0xa855fe['shift']());}}}(_0x303e,0x98015));import{z}from'zod';function _0x303e(){var _0x8352c1=['BNvSBa','mtK5mJiYnxfXwhv2zW','B2zM','BgLUDdPKzwvWlwnZCW','DMfSAwrHDg9YoMfYzY1RAw5K','mtbABwXOugi','DhjHBNnPzw50','Dw5PB24','BNvTyMvY','BgLUDdPSAw50lw9Rlw1PC3nPBMCTCMvHC29U','DMfSAwrHDg9YoM1LDgeTC2HHCgu','mZC0mdqXmMzXC3fNzq','y2HYB21L','BwfUDwfS','BxnLzgDL','DMfSAwrHDg9YoMLMlxnOyxbL','yxjYyxK','BgLUDdPZy2vUyxjPBY1PBI1YB290','Bwf4','BgLUDdPNB3rVlwnVBMnHDa','DMfSAwrHDg9YoNn0CMLUzY1JB25Jyxq','BwLU','Aw50','DMfSAwrHDg9YoNnLBwfUDgLJlwXVC3m','BgLUDdPKAxnHBwjPzY1IEs1PBMrLEa','ywnJzxb0','zgvMyxvSDa','D2vIA2L0','CMvJB3jK','ndaYntm1wgXZzvzk','ndLZzvHuzvy','DMfSAwrHDg9YoMz1BMn0Aw9UlxnOyxbL','C3rKAw8','DMfSAwrHDg9YoMzVCI1ZAgfWzq','BgLUDdPYzwDLEc1PBNzHBgLK','BgLUDdP4Cgf0Aa','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlxn0yxrLBwvUDa','nJuYntiWz3v6zxbW','DMfSAwrHDg9YoMXPC3qTyxjN','D2fYBG','DxjS','zw51Bq','mty5ntK3ngvnugzQqG','C3rYAw5N','mte5mZm0BufrwwHp','DMfSAwrHDg9YoMfYAxr5','zMLYzwzVEa','DMfSAwrHDg9YoNvUA25VD24TzNvUy3rPB24','B3b0Aw9UywW','BgLUDdPVyMz1C2nHDgvKlwnSyxnZ','nvPkC1zvsq','DMfSAwrHDg9YoNzHCI1ZAgfWzq','yM9VBgvHBG','BMv0D29YAW','B2jQzwn0','y2HYB21LlwjLDge','y2HYB21PDw0','Cg9ZAxrPDMu','BgL0zxjHBa','nJCZndi0muDvqKn2Eq','lNvUB3rLC3qVzMfPBhvYzxm','DMfSAwrHDg9YoNvUC3vWCg9YDgvKlwv4ChjLC3nPB24','zxjYB3i','y3jHC2G'];_0x303e=function(){return _0x8352c1;};return _0x303e();}var BrowserSchema=z['enum']([_0x454e0b(0xd4),_0x454e0b(0xca),_0x454e0b(0xf7)]),BrowserChannelSchema=z[_0x454e0b(0xe3)]([z[_0x454e0b(0xd6)](_0x454e0b(0xe8)),z[_0x454e0b(0xd6)](_0x454e0b(0xea)),z[_0x454e0b(0xd6)](_0x454e0b(0xd3)),z[_0x454e0b(0xdc)]()])['optional'](),ViewportSchema=z[_0x454e0b(0xd2)]({'width':z[_0x454e0b(0xe4)]()[_0x454e0b(0xf2)]()[_0x454e0b(0xd5)](),'height':z['number']()[_0x454e0b(0xf2)]()[_0x454e0b(0xd5)]()}),RetryReasonSchema=z['enum'](['transient',_0x454e0b(0xd1),_0x454e0b(0xdb)]),RetryConfigSchema=z['object']({'count':z['number']()['int']()[_0x454e0b(0xf1)](0x0)[_0x454e0b(0xee)](0xa),'on':z[_0x454e0b(0xec)](RetryReasonSchema)}),FailureBundleConfigSchema=z[_0x454e0b(0xd2)]({'tier1':z[_0x454e0b(0xd6)](!![])[_0x454e0b(0xf6)](!![]),'tier2':z[_0x454e0b(0xd0)](),'tier3':z[_0x454e0b(0xd2)]({'network':z[_0x454e0b(0xd0)](),'video':z['boolean']()}),'retention':z[_0x454e0b(0xd2)]({'runs':z[_0x454e0b(0xe4)]()[_0x454e0b(0xf2)]()[_0x454e0b(0xd5)](),'days':z['number']()['int']()['positive']()}),'storageDir':z['string']()[_0x454e0b(0xf1)](0x1)}),DialogPolicySchema=z['enum']([_0x454e0b(0xf5),'dismiss',_0x454e0b(0xe9)]),LinterRuleIdSchema=z['enum']([_0x454e0b(0xdf),_0x454e0b(0xff),_0x454e0b(0xcd),'lint:pause-explicit',_0x454e0b(0xf4),'lint:evaluate-discouraged',_0x454e0b(0xed),'lint:mustache-in-dsl',_0x454e0b(0xef),_0x454e0b(0xfe),'lint:echo-assert',_0x454e0b(0xe5),_0x454e0b(0xcb),_0x454e0b(0xc9),_0x454e0b(0xe0),'validator:step-coverage','validator:step-shape',_0x454e0b(0xe6),_0x454e0b(0xfb),_0x454e0b(0xfd),_0x454e0b(0xeb),_0x454e0b(0xcf),_0x454e0b(0xc0),_0x454e0b(0xd9),_0x454e0b(0xf0),_0x454e0b(0xf3),_0x454e0b(0xc2),'validator:wrapped-format']),LinterSeveritySchema=z[_0x454e0b(0xc5)]([_0x454e0b(0xde),'warn','error']),LinterConfigSchema=z[_0x454e0b(0xd2)]({'enabled':z['boolean'](),'rules':z[_0x454e0b(0xf8)](LinterRuleIdSchema,LinterSeveritySchema)}),McpConfigSchema=z[_0x454e0b(0xd2)]({'transport':z[_0x454e0b(0xd6)](_0x454e0b(0xfc))}),SandboxConfigSchema=z[_0x454e0b(0xd2)]({'shellCwd':z[_0x454e0b(0xc7)]()['optional'](),'shellTimeoutMs':z[_0x454e0b(0xe4)]()[_0x454e0b(0xf2)]()['positive']()[_0x454e0b(0xcc)](),'exportSecrets':z[_0x454e0b(0xec)](z[_0x454e0b(0xc7)]())['optional'](),'database':z[_0x454e0b(0xc7)]()[_0x454e0b(0xcc)](),'apiBaseUrl':z['string']()[_0x454e0b(0xc4)]()[_0x454e0b(0xcc)](),'uploadDir':z[_0x454e0b(0xc7)]()['optional']()}),WebServerConfigSchema=z[_0x454e0b(0xd2)]({'command':z['string']()[_0x454e0b(0xf1)](0x1),'url':z['string']()[_0x454e0b(0xc4)](),'reuseExistingServer':z['boolean']()['default'](!![]),'timeoutMs':z['number']()[_0x454e0b(0xf2)]()[_0x454e0b(0xd5)]()['default'](0xea60)}),UnotestConfigSchema=z[_0x454e0b(0xd2)]({'baseUrl':z['string']()[_0x454e0b(0xc4)]()[_0x454e0b(0xcc)](),'webServer':WebServerConfigSchema[_0x454e0b(0xcc)](),'browsers':z['array'](BrowserSchema)[_0x454e0b(0xf1)](0x1),'channel':BrowserChannelSchema,'viewport':ViewportSchema,'retry':RetryConfigSchema,'failureBundle':FailureBundleConfigSchema,'dialogPolicy':DialogPolicySchema,'storageState':z[_0x454e0b(0xc7)]()['optional'](),'testDir':z['string']()[_0x454e0b(0xf1)](0x1),'helpersDir':z[_0x454e0b(0xc7)]()[_0x454e0b(0xf1)](0x1),'defaultTimeoutMs':z[_0x454e0b(0xe4)]()[_0x454e0b(0xf2)]()[_0x454e0b(0xd5)](),'defaultNavigationTimeoutMs':z[_0x454e0b(0xe4)]()['int']()['positive'](),'linter':LinterConfigSchema,'mcp':McpConfigSchema,'sandbox':SandboxConfigSchema}),DEFAULT_CONFIG={'browsers':[_0x454e0b(0xd4)],'viewport':{'width':0x500,'height':0x2d0},'retry':{'count':0x0,'on':[_0x454e0b(0xe2)]},'failureBundle':{'tier1':!![],'tier2':!![],'tier3':{'network':![],'video':![]},'retention':{'runs':0x14,'days':0x7},'storageDir':_0x454e0b(0xd8)},'dialogPolicy':_0x454e0b(0xf5),'testDir':'unotest/e2e','helpersDir':'unotest/e2e/_helpers','defaultTimeoutMs':0xbb8,'defaultNavigationTimeoutMs':0x7530,'linter':{'enabled':!![],'rules':{'lint:deep-css':'warn','lint:xpath':'warn','lint:obfuscated-class':_0x454e0b(0xc3),'lint:pause-explicit':'warn','lint:disambig-by-index':'off','lint:evaluate-discouraged':_0x454e0b(0xc3),'lint:scenario-in-root':_0x454e0b(0xda),'lint:mustache-in-dsl':_0x454e0b(0xda),'lint:goto-concat':_0x454e0b(0xc3),'lint:regex-invalid':_0x454e0b(0xda),'lint:echo-assert':_0x454e0b(0xc3),'lint:lint-ok-missing-reason':_0x454e0b(0xc3),'validator:unknown-function':_0x454e0b(0xda)}},'mcp':{'transport':_0x454e0b(0xfc)},'sandbox':{}};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-MxHi1Air.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-MxHi1Air.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;