@unotest/web 0.47.0 → 0.48.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.
@@ -465,8 +465,9 @@ Escape hatch:
465
465
  this: none → nothing, exactly one → the value itself, **with two or
466
466
  more extra arguments the body receives ONE array** — destructure it:
467
467
  `evaluate('function(n){ return n * 2 }', 21)` and
468
- `evaluate('([a, b]) => a + b', a, b)`. The linter's warning says so
469
- when it sees two or more.
468
+ `evaluate('([a, b]) => a + b', a, b)`. One argument is `(n) =>`,
469
+ never `([n]) =>` — that fails with `2 is not iterable`. The linter's
470
+ warning states the rule whenever it sees one or more.
470
471
  - Native dialogs (`confirm()` / `alert()` / `prompt()`) are accepted by
471
472
  the runner itself (`dialogPolicy: "accept"` by default) — a "Remove"
472
473
  that asks first needs no special step.
@@ -596,8 +596,9 @@ Escape hatch:
596
596
  this: none → nothing, exactly one → the value itself, **with two or
597
597
  more extra arguments the body receives ONE array** — destructure it:
598
598
  `evaluate('function(n){ return n * 2 }', 21)` and
599
- `evaluate('([a, b]) => a + b', a, b)`. The linter's warning says so
600
- when it sees two or more.
599
+ `evaluate('([a, b]) => a + b', a, b)`. One argument is `(n) =>`,
600
+ never `([n]) =>` — that fails with `2 is not iterable`. The linter's
601
+ warning states the rule whenever it sees one or more.
601
602
  - Native dialogs (`confirm()` / `alert()` / `prompt()`) are accepted by
602
603
  the runner itself (`dialogPolicy: "accept"` by default) — a "Remove"
603
604
  that asks first needs no special step.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.48.0] - 2026-10-08
4
+
5
+ ### Minor Changes
6
+
7
+ - 2c63fd2: The viewer's status bar on a box now labels both versions — `suite 0.47.0 · box 0.48.0` — instead of a bare `v0.47.0` that read as the box's version while it was the suite's `@unotest/web`. When the suite runs an `@unotest/web` older than the lowest version the box runs suites on, the bar shows a yellow "suite too old" mark; hovering it says which version to raise in `unotest/package.json` before pushing the suite again. A viewer outside a box shows its version as before.
8
+
9
+ The box publishes its own version and that lowest supported `@unotest/web` to each environment's viewer. A box older than this change publishes neither, and the bar then labels the suite's version alone.
10
+
11
+ - f4e2a0c: New command `bundle rm <bundle-id>`: the project token that pushes a bundle can now take it back — one pushed with the wrong project's token, or one nobody wants. The box looks for the bundle in the token's project only and answers "not found in project …" the same way whether another project holds it or none does, so a token learns nothing about other projects.
12
+
13
+ A bundle in use stays: one an environment runs, or one a waiting or running ticket needs (a queued run, or a switch on its way to it), is refused with the environments named. `--switch-to <bundle-id>` first switches the environments that run it to another bundle of the same project, the way the viewer does; the box answers as the switches start, and the same `bundle rm` removes the bundle once they have landed. An environment that follows its branch cannot be switched by hand: push a newer bundle to that branch first.
14
+
15
+ A box older than bundle removal refuses and removes nothing: update the box, then retry. `unotest-web --help` now also says that `env push` merges into the box's values and lists `--prune`.
16
+
17
+ - 57beda5: `env push` now merges an environment's values into the box instead of replacing them. Every name your files carry is set; a name the box holds that your files do not carry stays there and is listed as kept, so a value put on the box with `env set` or on the admin page survives a push. A name that moved between your `.env*` and `.secrets*` files moves on the box too and is printed as `NAME: variable → secret`. `--dry-run` says that it cannot know which names the box holds.
18
+
19
+ New flag `--prune`: also remove what the box holds and your files do not, the target override included, and list it. `UNOTEST_*` names on the box are never pruned, because a push never sends them.
20
+
21
+ A box too old to merge refuses the push with "only replaces an environment's values" and changes nothing: update the box, then retry. The CLI never falls back to a replace.
22
+
23
+ **Migration:** this changes what a published command does. A push used to remove every name its files did not carry; it now keeps them. To get the old behaviour, add `--prune`: `npx @unotest/web env push <env> --prune`. With `--json`, the answer's `status` is now `"merged"`, and it carries `set`, `kept`, `removed` and `moved`.
24
+
25
+ - 0368c9c: `bundle push --run --follow` now prints what each run printed while it goes, so a CI log says why a suite failed, not only that it did: every scenario's start and end, each failed step with where it is and its error, and the run's `log` and `note` lines. With several collections each line starts with `[collection]`; with `--json` the lines go to stderr and stdout stays the one JSON document. Each line is printed once, also when the box did not answer for a moment. Exit codes are unchanged.
26
+
27
+ The box reads the lines off the run's own journal and gives them only to the token that ordered the run, the same rule as the run's state. Before they leave the box it masks the environment's secrets again (`‹secret:NAME›`), including a value the run itself did not know to mask: a CI log of a public repository is read by everybody.
28
+
29
+ A box too old to give lines says so once — "this box does not stream run lines; the verdict and link follow" — and the follow ends as before.
30
+
31
+ - 5c9b1f1: Scenarios can negate with `!x` and append to an array with `arr.push(x)`.
32
+
33
+ `!x` works as in JavaScript: it returns `true` or `false`, treats `0`, `""`, `null` and `false` as falsy, the same values `if` treats as false, and binds tighter than `&&` and `||`. Negations no longer need `x == false`.
34
+
35
+ `arr.push(x, …)` appends to the array in place and returns its new length, so a loop can collect values in one array. A variable holds the array itself, not a copy: after `b = a; a.push(1)`, `b` sees the new element, and a helper that pushes onto an array it was given changes the caller's array. Calling `push` on a value that is not an array fails the step with the value's type in the message, and the linter flags `push` on a string. Other array methods are still not available, and the "arrays are literals" hint for `push` is gone.
36
+
37
+ - c54285f: `setViewport(null)` runs a test on the real browser window, as Playwright's `viewport: null` does, without a separate run on its own config. It must come before the test does anything in its browser: the first navigation, `mockRoute`, a cookie or storage value, the page clock, `emulateMedia`, a second page or context. The browser context is opened again with the same options, so locale, storage state and the rest stay as configured. After any of those calls it is refused with that rule, because the new context would lose them. On a browser profile (`launch.userDataDir`, `launch.profile`) it is always refused; `viewport: null` in the config remains the way to run a whole suite on the real window.
38
+
39
+ ### Patch Changes
40
+
41
+ - db5c5a5: `assertCount`, `assertVisible`, `assertHidden` and `assertValue` accept their options object in a scenario: `assertCount(loc, 3, {timeout: 8000})` (or `timeoutMs`) now passes `lint` and the `run_test` check. The runner already honoured the option, but the validator refused the extra argument. A misspelled key is still refused with the list of supported ones.
42
+ - a160836: A box operator can now add an environment to a project without editing the box configuration and without restarting the daemon, from a shell on the box: `docker compose exec boxd node /boxd.mjs environment add <project> <name> --target <url>`, with optional `--default-branch`, `--no-switch`, `--concurrency` and `--by`. `environment list` (the same way) shows every environment and where it came from (the configuration, added on the box, or a pull request's preview), and `environment remove` takes back one added this way — never one from the configuration, and not while a run waits or runs in it; its run history and values stay on disk. The box serves an added environment on its next sweep, or as soon as a push names it — but the box looks for new environments on a push at most once every 10 seconds, so a push refused for a missing environment in the last 10 seconds is refused again until they are up. A name the configuration also declares is refused, and if the configuration declares it later, the configuration wins.
43
+
44
+ When `env push` or `bundle push --run` names an environment the box does not have, the box now says which environments the token's project has, and the CLI lists them with the command a box operator runs to add the missing one.
45
+
46
+ - 1384e6f: The note `bundle push` prints when the box has no value for a name now lists only the names the suite actually reads — in its scenarios and in `_helpers/` — instead of every name declared in `unotest/.env.example`. A name read as a bare identifier or as an `apiCall` base is said to stop a run at the first step that reads it; a name read with `env()` is said to give `null` there. A suite that computes a name at run time (`env(someVariable)`) still gets the full declared list with the conditional wording, since its reads cannot be known before it runs. When the suite reads none of the missing names, there is no note.
47
+ - 88f7b2f: The `evaluate` warning now also states how a single extra argument arrives: as the value itself, so the body is written `(x) => …`, not `([x]) => …` (which fails with "is not iterable"). The DSL reference states the whole rule for `evaluate`, `evaluateOnLocator` and `evaluateInServiceWorker`: no extra argument gives `undefined`, one gives the value itself, two or more give one array. Behaviour is unchanged.
48
+ - 4c4af51: The lint that runs before a scenario now honours `linter.rules` from your config, the same as `unotest-web lint`. A rule set to `off` (`lint:disambig-by-index` is off by default) no longer prints on `e2e` or `run_test`, and a rule set to `warn` or `error` is reported at that level. `run_test` refuses to start on a rule your config raises to `error`. `e2e` prints it as an error and still runs the scenario.
49
+ - 07d39d3: The `lint:one-test-per-file` warning now shows the replacement: each former test becomes a `step.soft(...)` of one `test_*`, or moves to a file of its own. It also links the new guide "Port a @playwright/test spec" (https://docs.unotest.com/guides/port-a-spec/), which ports a spec with several tests and runs one test over cases from a table or a JSONL file.
50
+ - 2d35731: `unotest-web` now warns when it is not the copy your suite installed. Run as `npx @unotest/web lint` from the project root, where no package sits, it used to take whatever version npx had cached without a word. It now prints one line with both versions and their paths, plus the command to run it from the suite instead (`cd unotest && npx unotest-web …`). When nothing is installed for the suite, the line asks you to run `npm i` in `unotest/`. The run goes on in both cases. From inside `unotest/`, wherever the suite resolves to this same copy, or when the copy that runs is the same version the suite installed, nothing is printed.
51
+ - f9100af: `wait(ms)` and `waitForTimeout(ms)` in a scenario are now answered with `use pause(ms) for a fixed delay, or a waitFor* for a state`, as `sleep` already was. The hint now appears on the run too, not only in `lint`: a scenario that reaches the runner with an unknown function name fails with `Unknown DSL function "wait" at 3:5 — use pause(ms) …` when the name is a known habit, and with the bare error otherwise.
52
+ - Updated dependencies [2c63fd2]
53
+ - Updated dependencies [a160836]
54
+ - Updated dependencies [f4e2a0c]
55
+ - Updated dependencies [57beda5]
56
+ - Updated dependencies [0368c9c]
57
+ - Updated dependencies [5c9b1f1]
58
+ - Updated dependencies [f9100af]
59
+ - @unotest/viewer@0.48.0
60
+ - @unotest/protocol@0.48.0
61
+ - @unotest/dsl@0.48.0
62
+ - @unotest/core@0.48.0
63
+ - @unotest/grounder-client@0.48.0
64
+
3
65
  ## [0.47.0] - 2026-10-07
4
66
 
5
67
  ### Minor Changes
@@ -1570,7 +1632,7 @@ picker on` fetches this project's own access and writes the three grounder
1570
1632
 
1571
1633
  That screen named one command:
1572
1634
 
1573
- npx @unotest/web bundle push --run --env ENVIRONMENT
1635
+ npx @unotest/web bundle push --run --env ENVIRONMENT
1574
1636
 
1575
1637
  In a project that has just been created, the command refuses with `no box
1576
1638
  address` before it does anything: the project holds neither the box's address
@@ -1579,8 +1641,8 @@ address` before it does anything: the project holds neither the box's address
1579
1641
 
1580
1642
  The screen now names both steps, in the order they have to happen:
1581
1643
 
1582
- npx @unotest/web box access larch
1583
- npx @unotest/web bundle push --run --env ENVIRONMENT
1644
+ npx @unotest/web box access larch
1645
+ npx @unotest/web bundle push --run --env ENVIRONMENT
1584
1646
 
1585
1647
  The box's own name is filled in when its licence carries one. `box access`
1586
1648
  with no name refuses, and its refusal offers to create a box — to somebody who
@@ -2953,6 +3015,8 @@ KEY | CREDENTIAL` is sent empty and flagged `secret`, and `GET /api/targets`
2953
3015
  outcome. The run journal gains `step-block:started` / `step-block:finished`
2954
3016
  envelopes per block (label, tag, soft, outcome, whole-block duration).
2955
3017
  Editor typings declare the new forms.
3018
+ A worked example — cases from a table and from a JSONL file, each a
3019
+ tagged soft step: [Port a @playwright/test spec](https://docs.unotest.com/guides/port-a-spec/).
2956
3020
  - ad7c918: The run journal records every loop pass (`loop:iteration`, with the loop
2957
3021
  statement's position and the pass index), which the viewer's new Trace
2958
3022
  view uses to show a loop as one group per iteration. Also: when an error
@@ -42,10 +42,10 @@ declare const RetryConfigSchema: z.ZodObject<{
42
42
  on: z.ZodArray<z.ZodEnum<["transient", "network", "crash"]>, "many">;
43
43
  }, "strict", z.ZodTypeAny, {
44
44
  count: number;
45
- on: ("network" | "transient" | "crash")[];
45
+ on: ("transient" | "network" | "crash")[];
46
46
  }, {
47
47
  count: number;
48
- on: ("network" | "transient" | "crash")[];
48
+ on: ("transient" | "network" | "crash")[];
49
49
  }>;
50
50
  type RetryConfig = z.infer<typeof RetryConfigSchema>;
51
51
  declare const FailureBundleConfigSchema: z.ZodObject<{
@@ -241,15 +241,15 @@ declare const WebServerConfigSchema: z.ZodObject<{
241
241
  /** How long to wait for the URL to come up after spawning. */
242
242
  timeoutMs: z.ZodDefault<z.ZodNumber>;
243
243
  }, "strict", z.ZodTypeAny, {
244
- url: string;
245
- timeoutMs: number;
246
244
  command: string;
245
+ url: string;
247
246
  reuseExistingServer: boolean;
247
+ timeoutMs: number;
248
248
  }, {
249
- url: string;
250
249
  command: string;
251
- timeoutMs?: number | undefined;
250
+ url: string;
252
251
  reuseExistingServer?: boolean | undefined;
252
+ timeoutMs?: number | undefined;
253
253
  }>;
254
254
  type WebServerConfig = z.infer<typeof WebServerConfigSchema>;
255
255
  /** `webServer`: one server, or several (a front and its fake backends),
@@ -273,15 +273,15 @@ declare const WebServersConfigSchema: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.Zo
273
273
  /** How long to wait for the URL to come up after spawning. */
274
274
  timeoutMs: z.ZodDefault<z.ZodNumber>;
275
275
  }, "strict", z.ZodTypeAny, {
276
- url: string;
277
- timeoutMs: number;
278
276
  command: string;
277
+ url: string;
279
278
  reuseExistingServer: boolean;
279
+ timeoutMs: number;
280
280
  }, {
281
- url: string;
282
281
  command: string;
283
- timeoutMs?: number | undefined;
282
+ url: string;
284
283
  reuseExistingServer?: boolean | undefined;
284
+ timeoutMs?: number | undefined;
285
285
  }>, z.ZodArray<z.ZodObject<{
286
286
  /** Shell command that starts the app under test (`npm run dev`,
287
287
  * `python manage.py runserver`, …). Runs in the user's shell from the
@@ -299,45 +299,45 @@ declare const WebServersConfigSchema: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.Zo
299
299
  /** How long to wait for the URL to come up after spawning. */
300
300
  timeoutMs: z.ZodDefault<z.ZodNumber>;
301
301
  }, "strict", z.ZodTypeAny, {
302
- url: string;
303
- timeoutMs: number;
304
302
  command: string;
303
+ url: string;
305
304
  reuseExistingServer: boolean;
305
+ timeoutMs: number;
306
306
  }, {
307
- url: string;
308
307
  command: string;
309
- timeoutMs?: number | undefined;
308
+ url: string;
310
309
  reuseExistingServer?: boolean | undefined;
310
+ timeoutMs?: number | undefined;
311
311
  }>, "many">]>, {
312
- url: string;
313
- timeoutMs: number;
314
312
  command: string;
313
+ url: string;
315
314
  reuseExistingServer: boolean;
315
+ timeoutMs: number;
316
316
  }[], {
317
- url: string;
318
317
  command: string;
319
- timeoutMs?: number | undefined;
318
+ url: string;
320
319
  reuseExistingServer?: boolean | undefined;
320
+ timeoutMs?: number | undefined;
321
321
  } | {
322
- url: string;
323
322
  command: string;
324
- timeoutMs?: number | undefined;
323
+ url: string;
325
324
  reuseExistingServer?: boolean | undefined;
325
+ timeoutMs?: number | undefined;
326
326
  }[]>, {
327
- url: string;
328
- timeoutMs: number;
329
327
  command: string;
328
+ url: string;
330
329
  reuseExistingServer: boolean;
330
+ timeoutMs: number;
331
331
  }[], {
332
- url: string;
333
332
  command: string;
334
- timeoutMs?: number | undefined;
333
+ url: string;
335
334
  reuseExistingServer?: boolean | undefined;
335
+ timeoutMs?: number | undefined;
336
336
  } | {
337
- url: string;
338
337
  command: string;
339
- timeoutMs?: number | undefined;
338
+ url: string;
340
339
  reuseExistingServer?: boolean | undefined;
340
+ timeoutMs?: number | undefined;
341
341
  }[]>;
342
342
  declare const EnvConfigSchema: z.ZodObject<{
343
343
  /** Variable names whose base `.env` value is deliberately shared by
@@ -373,15 +373,15 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
373
373
  /** How long to wait for the URL to come up after spawning. */
374
374
  timeoutMs: z.ZodDefault<z.ZodNumber>;
375
375
  }, "strict", z.ZodTypeAny, {
376
- url: string;
377
- timeoutMs: number;
378
376
  command: string;
377
+ url: string;
379
378
  reuseExistingServer: boolean;
379
+ timeoutMs: number;
380
380
  }, {
381
- url: string;
382
381
  command: string;
383
- timeoutMs?: number | undefined;
382
+ url: string;
384
383
  reuseExistingServer?: boolean | undefined;
384
+ timeoutMs?: number | undefined;
385
385
  }>, z.ZodArray<z.ZodObject<{
386
386
  /** Shell command that starts the app under test (`npm run dev`,
387
387
  * `python manage.py runserver`, …). Runs in the user's shell from the
@@ -399,45 +399,45 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
399
399
  /** How long to wait for the URL to come up after spawning. */
400
400
  timeoutMs: z.ZodDefault<z.ZodNumber>;
401
401
  }, "strict", z.ZodTypeAny, {
402
- url: string;
403
- timeoutMs: number;
404
402
  command: string;
403
+ url: string;
405
404
  reuseExistingServer: boolean;
405
+ timeoutMs: number;
406
406
  }, {
407
- url: string;
408
407
  command: string;
409
- timeoutMs?: number | undefined;
408
+ url: string;
410
409
  reuseExistingServer?: boolean | undefined;
410
+ timeoutMs?: number | undefined;
411
411
  }>, "many">]>, {
412
- url: string;
413
- timeoutMs: number;
414
412
  command: string;
413
+ url: string;
415
414
  reuseExistingServer: boolean;
415
+ timeoutMs: number;
416
416
  }[], {
417
- url: string;
418
417
  command: string;
419
- timeoutMs?: number | undefined;
418
+ url: string;
420
419
  reuseExistingServer?: boolean | undefined;
420
+ timeoutMs?: number | undefined;
421
421
  } | {
422
- url: string;
423
422
  command: string;
424
- timeoutMs?: number | undefined;
423
+ url: string;
425
424
  reuseExistingServer?: boolean | undefined;
425
+ timeoutMs?: number | undefined;
426
426
  }[]>, {
427
- url: string;
428
- timeoutMs: number;
429
427
  command: string;
428
+ url: string;
430
429
  reuseExistingServer: boolean;
430
+ timeoutMs: number;
431
431
  }[], {
432
- url: string;
433
432
  command: string;
434
- timeoutMs?: number | undefined;
433
+ url: string;
435
434
  reuseExistingServer?: boolean | undefined;
435
+ timeoutMs?: number | undefined;
436
436
  } | {
437
- url: string;
438
437
  command: string;
439
- timeoutMs?: number | undefined;
438
+ url: string;
440
439
  reuseExistingServer?: boolean | undefined;
440
+ timeoutMs?: number | undefined;
441
441
  }[]>>;
442
442
  browsers: z.ZodArray<z.ZodEnum<["chromium", "firefox", "webkit"]>, "many">;
443
443
  channel: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["chrome", "msedge", "chrome-beta", "chromium"]>, z.ZodEffects<z.ZodLiteral<"bundled">, null, "bundled">, z.ZodNull]>>;
@@ -482,23 +482,23 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
482
482
  profile: z.ZodOptional<z.ZodLiteral<"per-test">>;
483
483
  args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
484
484
  }, "strict", z.ZodTypeAny, {
485
- args?: string[] | undefined;
486
485
  userDataDir?: string | undefined;
487
486
  profile?: "per-test" | undefined;
488
- }, {
489
487
  args?: string[] | undefined;
488
+ }, {
490
489
  userDataDir?: string | undefined;
491
490
  profile?: "per-test" | undefined;
491
+ args?: string[] | undefined;
492
492
  }>>;
493
493
  retry: z.ZodObject<{
494
494
  count: z.ZodNumber;
495
495
  on: z.ZodArray<z.ZodEnum<["transient", "network", "crash"]>, "many">;
496
496
  }, "strict", z.ZodTypeAny, {
497
497
  count: number;
498
- on: ("network" | "transient" | "crash")[];
498
+ on: ("transient" | "network" | "crash")[];
499
499
  }, {
500
500
  count: number;
501
- on: ("network" | "transient" | "crash")[];
501
+ on: ("transient" | "network" | "crash")[];
502
502
  }>;
503
503
  failureBundle: z.ZodObject<{
504
504
  /** Tier 1 is always on by D-16. Schema lock — not user-toggleable. */
@@ -709,12 +709,13 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
709
709
  readRoots?: string[] | undefined;
710
710
  }>;
711
711
  }, "strict", z.ZodTypeAny, {
712
- defaultTimeoutMs: number;
713
- defaultNavigationTimeoutMs: number;
712
+ env: {
713
+ shared: string[];
714
+ };
714
715
  browsers: ("chromium" | "firefox" | "webkit")[];
715
716
  retry: {
716
717
  count: number;
717
- on: ("network" | "transient" | "crash")[];
718
+ on: ("transient" | "network" | "crash")[];
718
719
  };
719
720
  failureBundle: {
720
721
  tier1: true;
@@ -733,9 +734,8 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
733
734
  dialogPolicy: "accept" | "dismiss" | "manual";
734
735
  testDir: string;
735
736
  helpersDir: string;
736
- env: {
737
- shared: string[];
738
- };
737
+ defaultTimeoutMs: number;
738
+ defaultNavigationTimeoutMs: number;
739
739
  linter: {
740
740
  enabled: boolean;
741
741
  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:api-call-file-body" | "lint:lint-ok-missing-reason" | "lint:flow-returns-value" | "lint:legacy-layout" | "lint:external-variable-undeclared" | "lint:env-host-from-base" | "lint:one-test-per-file" | "lint:shadows-dsl-function" | "lint:skip-outside-test" | "lint:set-test-timeout-outside-test" | "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">>;
@@ -762,38 +762,39 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
762
762
  uploadDir?: string | undefined;
763
763
  readRoots?: string[] | undefined;
764
764
  };
765
- locale?: string | undefined;
766
- timezone?: string | undefined;
767
- testTimeoutMs?: number | undefined;
768
765
  baseUrl?: string | undefined;
769
766
  webServer?: {
770
- url: string;
771
- timeoutMs: number;
772
767
  command: string;
768
+ url: string;
773
769
  reuseExistingServer: boolean;
770
+ timeoutMs: number;
774
771
  }[] | undefined;
775
- channel?: "chrome" | "msedge" | "chrome-beta" | "chromium" | null | undefined;
772
+ channel?: "chromium" | "chrome" | "msedge" | "chrome-beta" | null | undefined;
776
773
  viewport?: {
777
774
  width?: number | undefined;
778
775
  height?: number | undefined;
779
776
  deviceScaleFactor?: number | undefined;
780
777
  } | null | undefined;
781
778
  device?: string | undefined;
779
+ timezone?: string | undefined;
780
+ locale?: string | undefined;
782
781
  maxContexts?: number | undefined;
783
782
  launch?: {
784
- args?: string[] | undefined;
785
783
  userDataDir?: string | undefined;
786
784
  profile?: "per-test" | undefined;
785
+ args?: string[] | undefined;
787
786
  } | undefined;
788
787
  storageState?: string | undefined;
789
788
  teardownTimeoutMs?: number | undefined;
789
+ testTimeoutMs?: number | undefined;
790
790
  }, {
791
- defaultTimeoutMs: number;
792
- defaultNavigationTimeoutMs: number;
791
+ env: {
792
+ shared?: string[] | undefined;
793
+ };
793
794
  browsers: ("chromium" | "firefox" | "webkit")[];
794
795
  retry: {
795
796
  count: number;
796
- on: ("network" | "transient" | "crash")[];
797
+ on: ("transient" | "network" | "crash")[];
797
798
  };
798
799
  failureBundle: {
799
800
  tier2: boolean;
@@ -812,9 +813,8 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
812
813
  dialogPolicy: "accept" | "dismiss" | "manual";
813
814
  testDir: string;
814
815
  helpersDir: string;
815
- env: {
816
- shared?: string[] | undefined;
817
- };
816
+ defaultTimeoutMs: number;
817
+ defaultNavigationTimeoutMs: number;
818
818
  linter: {
819
819
  enabled: boolean;
820
820
  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:api-call-file-body" | "lint:lint-ok-missing-reason" | "lint:flow-returns-value" | "lint:legacy-layout" | "lint:external-variable-undeclared" | "lint:env-host-from-base" | "lint:one-test-per-file" | "lint:shadows-dsl-function" | "lint:skip-outside-test" | "lint:set-test-timeout-outside-test" | "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">>;
@@ -835,36 +835,36 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
835
835
  uploadDir?: string | undefined;
836
836
  readRoots?: string[] | undefined;
837
837
  };
838
- locale?: string | undefined;
839
- timezone?: string | undefined;
840
- testTimeoutMs?: number | undefined;
841
838
  baseUrl?: string | undefined;
842
839
  webServer?: {
843
- url: string;
844
840
  command: string;
845
- timeoutMs?: number | undefined;
841
+ url: string;
846
842
  reuseExistingServer?: boolean | undefined;
843
+ timeoutMs?: number | undefined;
847
844
  } | {
848
- url: string;
849
845
  command: string;
850
- timeoutMs?: number | undefined;
846
+ url: string;
851
847
  reuseExistingServer?: boolean | undefined;
848
+ timeoutMs?: number | undefined;
852
849
  }[] | undefined;
853
- channel?: "chrome" | "msedge" | "chrome-beta" | "chromium" | "bundled" | null | undefined;
850
+ channel?: "chromium" | "chrome" | "msedge" | "chrome-beta" | "bundled" | null | undefined;
854
851
  viewport?: {
855
852
  width?: number | undefined;
856
853
  height?: number | undefined;
857
854
  deviceScaleFactor?: number | undefined;
858
855
  } | null | undefined;
859
856
  device?: string | undefined;
857
+ timezone?: string | undefined;
858
+ locale?: string | undefined;
860
859
  maxContexts?: number | undefined;
861
860
  launch?: {
862
- args?: string[] | undefined;
863
861
  userDataDir?: string | undefined;
864
862
  profile?: "per-test" | undefined;
863
+ args?: string[] | undefined;
865
864
  } | undefined;
866
865
  storageState?: string | undefined;
867
866
  teardownTimeoutMs?: number | undefined;
867
+ testTimeoutMs?: number | undefined;
868
868
  schedules?: {
869
869
  collection: string;
870
870
  cron: string;
@@ -872,12 +872,13 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
872
872
  prepare?: string | undefined;
873
873
  }[] | undefined;
874
874
  }>, {
875
- defaultTimeoutMs: number;
876
- defaultNavigationTimeoutMs: number;
875
+ env: {
876
+ shared: string[];
877
+ };
877
878
  browsers: ("chromium" | "firefox" | "webkit")[];
878
879
  retry: {
879
880
  count: number;
880
- on: ("network" | "transient" | "crash")[];
881
+ on: ("transient" | "network" | "crash")[];
881
882
  };
882
883
  failureBundle: {
883
884
  tier1: true;
@@ -896,9 +897,8 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
896
897
  dialogPolicy: "accept" | "dismiss" | "manual";
897
898
  testDir: string;
898
899
  helpersDir: string;
899
- env: {
900
- shared: string[];
901
- };
900
+ defaultTimeoutMs: number;
901
+ defaultNavigationTimeoutMs: number;
902
902
  linter: {
903
903
  enabled: boolean;
904
904
  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:api-call-file-body" | "lint:lint-ok-missing-reason" | "lint:flow-returns-value" | "lint:legacy-layout" | "lint:external-variable-undeclared" | "lint:env-host-from-base" | "lint:one-test-per-file" | "lint:shadows-dsl-function" | "lint:skip-outside-test" | "lint:set-test-timeout-outside-test" | "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">>;
@@ -925,38 +925,39 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
925
925
  uploadDir?: string | undefined;
926
926
  readRoots?: string[] | undefined;
927
927
  };
928
- locale?: string | undefined;
929
- timezone?: string | undefined;
930
- testTimeoutMs?: number | undefined;
931
928
  baseUrl?: string | undefined;
932
929
  webServer?: {
933
- url: string;
934
- timeoutMs: number;
935
930
  command: string;
931
+ url: string;
936
932
  reuseExistingServer: boolean;
933
+ timeoutMs: number;
937
934
  }[] | undefined;
938
- channel?: "chrome" | "msedge" | "chrome-beta" | "chromium" | null | undefined;
935
+ channel?: "chromium" | "chrome" | "msedge" | "chrome-beta" | null | undefined;
939
936
  viewport?: {
940
937
  width?: number | undefined;
941
938
  height?: number | undefined;
942
939
  deviceScaleFactor?: number | undefined;
943
940
  } | null | undefined;
944
941
  device?: string | undefined;
942
+ timezone?: string | undefined;
943
+ locale?: string | undefined;
945
944
  maxContexts?: number | undefined;
946
945
  launch?: {
947
- args?: string[] | undefined;
948
946
  userDataDir?: string | undefined;
949
947
  profile?: "per-test" | undefined;
948
+ args?: string[] | undefined;
950
949
  } | undefined;
951
950
  storageState?: string | undefined;
952
951
  teardownTimeoutMs?: number | undefined;
952
+ testTimeoutMs?: number | undefined;
953
953
  }, {
954
- defaultTimeoutMs: number;
955
- defaultNavigationTimeoutMs: number;
954
+ env: {
955
+ shared?: string[] | undefined;
956
+ };
956
957
  browsers: ("chromium" | "firefox" | "webkit")[];
957
958
  retry: {
958
959
  count: number;
959
- on: ("network" | "transient" | "crash")[];
960
+ on: ("transient" | "network" | "crash")[];
960
961
  };
961
962
  failureBundle: {
962
963
  tier2: boolean;
@@ -975,9 +976,8 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
975
976
  dialogPolicy: "accept" | "dismiss" | "manual";
976
977
  testDir: string;
977
978
  helpersDir: string;
978
- env: {
979
- shared?: string[] | undefined;
980
- };
979
+ defaultTimeoutMs: number;
980
+ defaultNavigationTimeoutMs: number;
981
981
  linter: {
982
982
  enabled: boolean;
983
983
  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:api-call-file-body" | "lint:lint-ok-missing-reason" | "lint:flow-returns-value" | "lint:legacy-layout" | "lint:external-variable-undeclared" | "lint:env-host-from-base" | "lint:one-test-per-file" | "lint:shadows-dsl-function" | "lint:skip-outside-test" | "lint:set-test-timeout-outside-test" | "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">>;
@@ -998,36 +998,36 @@ declare const UnotestConfigSchema: z.ZodEffects<z.ZodObject<{
998
998
  uploadDir?: string | undefined;
999
999
  readRoots?: string[] | undefined;
1000
1000
  };
1001
- locale?: string | undefined;
1002
- timezone?: string | undefined;
1003
- testTimeoutMs?: number | undefined;
1004
1001
  baseUrl?: string | undefined;
1005
1002
  webServer?: {
1006
- url: string;
1007
1003
  command: string;
1008
- timeoutMs?: number | undefined;
1004
+ url: string;
1009
1005
  reuseExistingServer?: boolean | undefined;
1006
+ timeoutMs?: number | undefined;
1010
1007
  } | {
1011
- url: string;
1012
1008
  command: string;
1013
- timeoutMs?: number | undefined;
1009
+ url: string;
1014
1010
  reuseExistingServer?: boolean | undefined;
1011
+ timeoutMs?: number | undefined;
1015
1012
  }[] | undefined;
1016
- channel?: "chrome" | "msedge" | "chrome-beta" | "chromium" | "bundled" | null | undefined;
1013
+ channel?: "chromium" | "chrome" | "msedge" | "chrome-beta" | "bundled" | null | undefined;
1017
1014
  viewport?: {
1018
1015
  width?: number | undefined;
1019
1016
  height?: number | undefined;
1020
1017
  deviceScaleFactor?: number | undefined;
1021
1018
  } | null | undefined;
1022
1019
  device?: string | undefined;
1020
+ timezone?: string | undefined;
1021
+ locale?: string | undefined;
1023
1022
  maxContexts?: number | undefined;
1024
1023
  launch?: {
1025
- args?: string[] | undefined;
1026
1024
  userDataDir?: string | undefined;
1027
1025
  profile?: "per-test" | undefined;
1026
+ args?: string[] | undefined;
1028
1027
  } | undefined;
1029
1028
  storageState?: string | undefined;
1030
1029
  teardownTimeoutMs?: number | undefined;
1030
+ testTimeoutMs?: number | undefined;
1031
1031
  schedules?: {
1032
1032
  collection: string;
1033
1033
  cron: string;