@specific.dev/spectest 0.68.0 → 0.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +1 -1
- package/dist/index.js +3 -3
- package/dist/locator-errors.js +1 -1
- package/dist/locator.d.ts +10 -5
- package/dist/locator.js +11 -6
- package/dist/terminal.js +4 -1
- package/package.json +1 -1
- package/src/browser.ts +1 -1
- package/src/index.ts +3 -3
- package/src/locator-errors.ts +1 -1
- package/src/locator.ts +12 -7
- package/src/terminal.ts +4 -1
package/dist/browser.js
CHANGED
|
@@ -1406,7 +1406,7 @@ function buildBackend(holder, recorder, buildOpts) {
|
|
|
1406
1406
|
}, { wrap: true });
|
|
1407
1407
|
},
|
|
1408
1408
|
async waitForFunction(description, fn, arg, options = {}) {
|
|
1409
|
-
const timeoutMs = options.timeout ??
|
|
1409
|
+
const timeoutMs = options.timeout ?? DEFAULT_ACTION_TIMEOUT_MS;
|
|
1410
1410
|
const intervalMs = options.polling ?? 100;
|
|
1411
1411
|
const src = typeof fn === "string" ? fn : fn.toString();
|
|
1412
1412
|
const t = truncateUtf8(src);
|
package/dist/index.js
CHANGED
|
@@ -713,7 +713,7 @@ function buildLocatorMatchers(loc, negated, message) {
|
|
|
713
713
|
// The last error a probe threw, kept for the failure message: a matcher
|
|
714
714
|
// whose read waits for the element (textContent, inputValue, isEnabled …)
|
|
715
715
|
// reports a missing element as a playwright timeout, and that — not
|
|
716
|
-
// "got <error: Timeout
|
|
716
|
+
// "got <error: Timeout 10000ms exceeded …>" — is the sentence to fail with.
|
|
717
717
|
let probeError;
|
|
718
718
|
for (;;) {
|
|
719
719
|
let satisfied;
|
|
@@ -753,8 +753,8 @@ function buildLocatorMatchers(loc, negated, message) {
|
|
|
753
753
|
}
|
|
754
754
|
if (Date.now() >= deadline) {
|
|
755
755
|
// The deadline, not the stopwatch: every one of these polled until it
|
|
756
|
-
// ran out, and "(waited
|
|
757
|
-
// number twice in a row — a measured
|
|
756
|
+
// ran out, and "(waited 10s)" is both what the author set and the same
|
|
757
|
+
// number twice in a row — a measured 9_987ms is neither.
|
|
758
758
|
const msg = (await elementFailure(probeError)) ??
|
|
759
759
|
`${describe(actual)} (waited ${formatWaited(budget)})`;
|
|
760
760
|
const sourceSeq = await probe.settle(matcher, Date.now() - started, msg, settleOpts);
|
package/dist/locator-errors.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Readable failures for locator steps.
|
|
2
2
|
//
|
|
3
3
|
// Playwright reports every unmet actionability wait the same way: a
|
|
4
|
-
// `TimeoutError` whose message is "Timeout
|
|
4
|
+
// `TimeoutError` whose message is "Timeout 10000ms exceeded." with the real
|
|
5
5
|
// story — did the element exist at all? was it disabled? did something cover
|
|
6
6
|
// it? — buried in a call log below it. A test that clicks a button that is not
|
|
7
7
|
// on the page therefore fails with a sentence about OUR deadline, which reads
|
package/dist/locator.d.ts
CHANGED
|
@@ -3,11 +3,16 @@ import type { RecordableFields } from "./browser.js";
|
|
|
3
3
|
import type { Wrapped } from "./inspect.js";
|
|
4
4
|
import { type HintTarget } from "./locator-hints.js";
|
|
5
5
|
/** Default deadline for a locator action/read's target to become actionable.
|
|
6
|
-
* Playwright's own default is 30s — far too slow-failing for tests
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
6
|
+
* Playwright's own default is 30s — far too slow-failing for tests. This was
|
|
7
|
+
* 5s (the pre-Playwright behavior) until 2026-09-03, and 5s turned out to be
|
|
8
|
+
* about one page load: a real app under a full VM fan-out took 1.8-2.0s for a
|
|
9
|
+
* full navigation plus its client data chain on a quiet box, and 4x that on
|
|
10
|
+
* the tail, so a step that was correct and merely late failed. 10s still
|
|
11
|
+
* fails fast enough to be useful and leaves room for the tail. A per-call
|
|
12
|
+
* `{ timeout }` overrides it; `undefined` falls through to the context
|
|
13
|
+
* default (also set to this in browser.ts's `newViewContext`). Navigations
|
|
14
|
+
* keep a longer deadline. */
|
|
15
|
+
export declare const DEFAULT_ACTION_TIMEOUT_MS = 10000;
|
|
11
16
|
export interface GetByTextOptions {
|
|
12
17
|
/** Whole-string, case-sensitive match instead of the default
|
|
13
18
|
* case-insensitive substring. Ignored when the query is a RegExp. */
|
package/dist/locator.js
CHANGED
|
@@ -27,11 +27,16 @@ import { formatHints, nearMissHints } from "./locator-hints.js";
|
|
|
27
27
|
import { resolveExistingProjectPath } from "./project-files.js";
|
|
28
28
|
import { truncateUtf8 } from "./recorder.js";
|
|
29
29
|
/** Default deadline for a locator action/read's target to become actionable.
|
|
30
|
-
* Playwright's own default is 30s — far too slow-failing for tests
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
30
|
+
* Playwright's own default is 30s — far too slow-failing for tests. This was
|
|
31
|
+
* 5s (the pre-Playwright behavior) until 2026-09-03, and 5s turned out to be
|
|
32
|
+
* about one page load: a real app under a full VM fan-out took 1.8-2.0s for a
|
|
33
|
+
* full navigation plus its client data chain on a quiet box, and 4x that on
|
|
34
|
+
* the tail, so a step that was correct and merely late failed. 10s still
|
|
35
|
+
* fails fast enough to be useful and leaves room for the tail. A per-call
|
|
36
|
+
* `{ timeout }` overrides it; `undefined` falls through to the context
|
|
37
|
+
* default (also set to this in browser.ts's `newViewContext`). Navigations
|
|
38
|
+
* keep a longer deadline. */
|
|
39
|
+
export const DEFAULT_ACTION_TIMEOUT_MS = 10_000;
|
|
35
40
|
// Brand + chain carrier. Both are `Symbol.for` keys so `JSON.stringify` drops
|
|
36
41
|
// them (locators are never serialized) while runtime code can still detect a
|
|
37
42
|
// locator and read a nested one's chain during lowering.
|
|
@@ -401,7 +406,7 @@ export function makeLocator(backend, strategy, chain) {
|
|
|
401
406
|
return formatHints(await nearMissHints(page, target));
|
|
402
407
|
};
|
|
403
408
|
// Every terminal op runs through this: playwright's actionability timeouts
|
|
404
|
-
// say "Timeout
|
|
409
|
+
// say "Timeout 10000ms exceeded" and hide what actually went wrong in a call
|
|
405
410
|
// log, so they are rewritten into a sentence naming the element and its
|
|
406
411
|
// state (see locator-errors.ts), and a failure that found NO element asks
|
|
407
412
|
// the page what it does hold. Applied INSIDE `pageOp`, so the recorded step
|
package/dist/terminal.js
CHANGED
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
import { Terminal as XtermHeadless } from "@xterm/headless";
|
|
29
29
|
import { recordTerminalStep, reserveEvent, truncateUtf8 } from "./recorder.js";
|
|
30
30
|
import { wrap } from "./inspect.js";
|
|
31
|
+
// One default deadline for "wait until the app shows it", whichever surface
|
|
32
|
+
// the author is watching — see the constant for why it is what it is.
|
|
33
|
+
import { DEFAULT_ACTION_TIMEOUT_MS } from "./locator.js";
|
|
31
34
|
// Cap on cumulative output we keep in memory. The asciicast frames
|
|
32
35
|
// grow separately (they live on the session record) and aren't bounded
|
|
33
36
|
// here. Matches `TERMINAL_OUTPUT_CAP_BYTES` in daemon.ts.
|
|
@@ -421,7 +424,7 @@ export async function openTerminal(args) {
|
|
|
421
424
|
return renderScreen();
|
|
422
425
|
},
|
|
423
426
|
async waitFor(description, matcher, waitOpts) {
|
|
424
|
-
const timeoutMs = waitOpts?.timeoutMs ??
|
|
427
|
+
const timeoutMs = waitOpts?.timeoutMs ?? DEFAULT_ACTION_TIMEOUT_MS;
|
|
425
428
|
const intervalMs = waitOpts?.intervalMs ?? 100;
|
|
426
429
|
const t = Date.now();
|
|
427
430
|
const resv = reserveEvent();
|
package/package.json
CHANGED
package/src/browser.ts
CHANGED
|
@@ -1943,7 +1943,7 @@ function buildBackend(
|
|
|
1943
1943
|
arg?: unknown,
|
|
1944
1944
|
options: { timeout?: number; polling?: number } = {},
|
|
1945
1945
|
): Promise<Wrapped<T>> {
|
|
1946
|
-
const timeoutMs = options.timeout ??
|
|
1946
|
+
const timeoutMs = options.timeout ?? DEFAULT_ACTION_TIMEOUT_MS;
|
|
1947
1947
|
const intervalMs = options.polling ?? 100;
|
|
1948
1948
|
const src = typeof fn === "string" ? fn : fn.toString();
|
|
1949
1949
|
const t = truncateUtf8(src);
|
package/src/index.ts
CHANGED
|
@@ -2900,7 +2900,7 @@ function buildLocatorMatchers(
|
|
|
2900
2900
|
// The last error a probe threw, kept for the failure message: a matcher
|
|
2901
2901
|
// whose read waits for the element (textContent, inputValue, isEnabled …)
|
|
2902
2902
|
// reports a missing element as a playwright timeout, and that — not
|
|
2903
|
-
// "got <error: Timeout
|
|
2903
|
+
// "got <error: Timeout 10000ms exceeded …>" — is the sentence to fail with.
|
|
2904
2904
|
let probeError: unknown;
|
|
2905
2905
|
for (;;) {
|
|
2906
2906
|
let satisfied: boolean;
|
|
@@ -2939,8 +2939,8 @@ function buildLocatorMatchers(
|
|
|
2939
2939
|
}
|
|
2940
2940
|
if (Date.now() >= deadline) {
|
|
2941
2941
|
// The deadline, not the stopwatch: every one of these polled until it
|
|
2942
|
-
// ran out, and "(waited
|
|
2943
|
-
// number twice in a row — a measured
|
|
2942
|
+
// ran out, and "(waited 10s)" is both what the author set and the same
|
|
2943
|
+
// number twice in a row — a measured 9_987ms is neither.
|
|
2944
2944
|
const msg = (await elementFailure(probeError)) ??
|
|
2945
2945
|
`${describe(actual)} (waited ${formatWaited(budget)})`;
|
|
2946
2946
|
const sourceSeq = await probe.settle(matcher, Date.now() - started, msg, settleOpts);
|
package/src/locator-errors.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Readable failures for locator steps.
|
|
2
2
|
//
|
|
3
3
|
// Playwright reports every unmet actionability wait the same way: a
|
|
4
|
-
// `TimeoutError` whose message is "Timeout
|
|
4
|
+
// `TimeoutError` whose message is "Timeout 10000ms exceeded." with the real
|
|
5
5
|
// story — did the element exist at all? was it disabled? did something cover
|
|
6
6
|
// it? — buried in a call log below it. A test that clicks a button that is not
|
|
7
7
|
// on the page therefore fails with a sentence about OUR deadline, which reads
|
package/src/locator.ts
CHANGED
|
@@ -32,11 +32,16 @@ import { resolveExistingProjectPath } from "./project-files.js";
|
|
|
32
32
|
import { truncateUtf8 } from "./recorder.js";
|
|
33
33
|
|
|
34
34
|
/** Default deadline for a locator action/read's target to become actionable.
|
|
35
|
-
* Playwright's own default is 30s — far too slow-failing for tests
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
35
|
+
* Playwright's own default is 30s — far too slow-failing for tests. This was
|
|
36
|
+
* 5s (the pre-Playwright behavior) until 2026-09-03, and 5s turned out to be
|
|
37
|
+
* about one page load: a real app under a full VM fan-out took 1.8-2.0s for a
|
|
38
|
+
* full navigation plus its client data chain on a quiet box, and 4x that on
|
|
39
|
+
* the tail, so a step that was correct and merely late failed. 10s still
|
|
40
|
+
* fails fast enough to be useful and leaves room for the tail. A per-call
|
|
41
|
+
* `{ timeout }` overrides it; `undefined` falls through to the context
|
|
42
|
+
* default (also set to this in browser.ts's `newViewContext`). Navigations
|
|
43
|
+
* keep a longer deadline. */
|
|
44
|
+
export const DEFAULT_ACTION_TIMEOUT_MS = 10_000;
|
|
40
45
|
|
|
41
46
|
// Brand + chain carrier. Both are `Symbol.for` keys so `JSON.stringify` drops
|
|
42
47
|
// them (locators are never serialized) while runtime code can still detect a
|
|
@@ -656,7 +661,7 @@ export interface Locator {
|
|
|
656
661
|
/** Explicit strict-mode opt-out: the i-th resolved element (0-based). */
|
|
657
662
|
nth(index: number): Locator;
|
|
658
663
|
|
|
659
|
-
// ── Actions (auto-wait; default
|
|
664
|
+
// ── Actions (auto-wait; default 10s, `{ timeout }` overrides) ─────────
|
|
660
665
|
click(opts?: ClickOptions): Promise<void>;
|
|
661
666
|
dblclick(opts?: ClickOptions): Promise<void>;
|
|
662
667
|
/** Touch-tap (mobile sessions only; throws on desktop). `duration`
|
|
@@ -761,7 +766,7 @@ export function makeLocator(
|
|
|
761
766
|
};
|
|
762
767
|
|
|
763
768
|
// Every terminal op runs through this: playwright's actionability timeouts
|
|
764
|
-
// say "Timeout
|
|
769
|
+
// say "Timeout 10000ms exceeded" and hide what actually went wrong in a call
|
|
765
770
|
// log, so they are rewritten into a sentence naming the element and its
|
|
766
771
|
// state (see locator-errors.ts), and a failure that found NO element asks
|
|
767
772
|
// the page what it does hold. Applied INSIDE `pageOp`, so the recorded step
|
package/src/terminal.ts
CHANGED
|
@@ -32,6 +32,9 @@ import { recordTerminalStep, reserveEvent, truncateUtf8 } from "./recorder.js";
|
|
|
32
32
|
import type { EventReservation } from "./recorder.js";
|
|
33
33
|
import type { TerminalStepAction } from "./recorder.js";
|
|
34
34
|
import { wrap } from "./inspect.js";
|
|
35
|
+
// One default deadline for "wait until the app shows it", whichever surface
|
|
36
|
+
// the author is watching — see the constant for why it is what it is.
|
|
37
|
+
import { DEFAULT_ACTION_TIMEOUT_MS } from "./locator.js";
|
|
35
38
|
import type { Wrapped } from "./inspect.js";
|
|
36
39
|
|
|
37
40
|
export interface TerminalOpts {
|
|
@@ -614,7 +617,7 @@ export async function openTerminal(args: OpenTerminalArgs): Promise<InternalTerm
|
|
|
614
617
|
matcher: string | RegExp | ((screen: string, output: string) => unknown),
|
|
615
618
|
waitOpts?: { timeoutMs?: number; intervalMs?: number },
|
|
616
619
|
) {
|
|
617
|
-
const timeoutMs = waitOpts?.timeoutMs ??
|
|
620
|
+
const timeoutMs = waitOpts?.timeoutMs ?? DEFAULT_ACTION_TIMEOUT_MS;
|
|
618
621
|
const intervalMs = waitOpts?.intervalMs ?? 100;
|
|
619
622
|
const t = Date.now();
|
|
620
623
|
const resv = reserveEvent();
|