@vosjs/render-core 0.8.0 → 0.10.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/record/index.d.ts +490 -196
- package/dist/record/index.js +916 -62
- package/dist/record/index.js.map +1 -1
- package/package.json +2 -2
package/dist/record/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { RecordingMeta, CursorEvent, RecordingSkip, RecordingOutput, Backdrop, RecordingArtifact, ProjectDoc, RecordingPageMedia } from '@vosjs/studio-core';
|
|
1
|
+
import { RecordingMeta, PeerStepSpan, CursorEvent, RecordingSkip, RecordingOutput, Backdrop, RecordingArtifact, ProjectDoc, RecordingPageMedia } from '@vosjs/studio-core';
|
|
2
|
+
export { PeerStepSpan } from '@vosjs/studio-core';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The recorder's driver: what it needs from a browser, as a STRUCTURAL
|
|
@@ -415,6 +416,156 @@ declare function deadWarns(r: DeadReport): boolean;
|
|
|
415
416
|
/** The dead time in words, naming the steps and what to cut. */
|
|
416
417
|
declare function deadLine(r: DeadReport): string;
|
|
417
418
|
|
|
419
|
+
/**
|
|
420
|
+
* `setup`: the steps that run BEFORE the camera rolls. A sign-in form, a
|
|
421
|
+
* cookie banner, the "choose your editor" modal, an onboarding tour: things
|
|
422
|
+
* a take must get past and must not show. They run after the first
|
|
423
|
+
* navigation and before `Page.startScreencast`, with no cursor synthesis,
|
|
424
|
+
* no pace accounting and nothing written to `meta.steps`. Then the recorder
|
|
425
|
+
* navigates to `url` again and the take begins where the setup left it.
|
|
426
|
+
*
|
|
427
|
+
* A `type` step's `text` may be `{ "env": "DEMO_PASSWORD" }`: resolved at run
|
|
428
|
+
* time from the `env` the caller hands in (the shell's for the CLI, the
|
|
429
|
+
* job's own map for a hosted take), never logged, never stored. The
|
|
430
|
+
* guarantee is narrow and real: the secret is never in a file that travels
|
|
431
|
+
* (`actions.json` is committed and pushed with the take; `meta.json` is read
|
|
432
|
+
* by the digest) and never in the footage.
|
|
433
|
+
*
|
|
434
|
+
* `teardown`: the same steps, run AFTER the take, off camera too: what the
|
|
435
|
+
* take created in the product (an API key, a project, an invite) removed
|
|
436
|
+
* again, so a rehearsal or a re-record leaves the account as it found it.
|
|
437
|
+
* They run once the screencast has stopped, on the take's own page and
|
|
438
|
+
* context (a session's cookies apply), and also when the take stops early
|
|
439
|
+
* or throws once its first step has run. A teardown that fails never fails
|
|
440
|
+
* the take: the footage is fine, and what is left behind is reported.
|
|
441
|
+
*/
|
|
442
|
+
|
|
443
|
+
type SetupText = string | {
|
|
444
|
+
env: string;
|
|
445
|
+
};
|
|
446
|
+
type SetupStep = ({
|
|
447
|
+
do: 'wait';
|
|
448
|
+
ms: number;
|
|
449
|
+
} | {
|
|
450
|
+
do: 'click';
|
|
451
|
+
selector: string;
|
|
452
|
+
ms?: number;
|
|
453
|
+
} | {
|
|
454
|
+
do: 'type';
|
|
455
|
+
selector: string;
|
|
456
|
+
text: SetupText;
|
|
457
|
+
ms?: number;
|
|
458
|
+
} | {
|
|
459
|
+
do: 'press';
|
|
460
|
+
key: string;
|
|
461
|
+
ms?: number;
|
|
462
|
+
} | {
|
|
463
|
+
do: 'goto';
|
|
464
|
+
url: string;
|
|
465
|
+
}) & {
|
|
466
|
+
id?: string;
|
|
467
|
+
};
|
|
468
|
+
/** Which list a step belongs to, as its messages and log lines name it. */
|
|
469
|
+
type StepPhase = 'setup' | 'teardown';
|
|
470
|
+
/**
|
|
471
|
+
* Why a page address is not one the recorder opens, or null. A script's
|
|
472
|
+
* `url` and a setup's `goto` open a browser, so only http and https are
|
|
473
|
+
* taken: a `file:` address would read this machine's disk into a take
|
|
474
|
+
* and a `javascript:` one would run in the page.
|
|
475
|
+
*/
|
|
476
|
+
declare function urlSchemeProblem(url: string): string | null;
|
|
477
|
+
/**
|
|
478
|
+
* Structural validation, mirrored on `validateActions` for `steps`. The
|
|
479
|
+
* same verbs and rules hold for `teardown`; `phase` names the list.
|
|
480
|
+
*/
|
|
481
|
+
declare function validateSetup(value: unknown, phase?: StepPhase): string[];
|
|
482
|
+
/** The names a setup reads from its env, so a host can say what it must supply. */
|
|
483
|
+
declare function setupEnvNames(steps: SetupStep[] | undefined): string[];
|
|
484
|
+
/**
|
|
485
|
+
* Every name a script reads from its env, its setup's and its teardown's,
|
|
486
|
+
* each once: what a host must supply before the take begins.
|
|
487
|
+
*/
|
|
488
|
+
declare function scriptEnvNames(script: {
|
|
489
|
+
setup?: SetupStep[];
|
|
490
|
+
teardown?: SetupStep[];
|
|
491
|
+
}): string[];
|
|
492
|
+
/** A `{ env }` text resolved, or thrown in words. The value is never returned to a log. */
|
|
493
|
+
declare function resolveSetupText(t: SetupText, env: Record<string, string | undefined>, phase?: StepPhase): {
|
|
494
|
+
value: string;
|
|
495
|
+
secret: boolean;
|
|
496
|
+
};
|
|
497
|
+
/**
|
|
498
|
+
* The first `{ env }` a teardown reads that `env` does not hold, in words,
|
|
499
|
+
* or null. Asked BEFORE the take: a take that creates something its
|
|
500
|
+
* teardown cannot then remove is the one case teardown exists for.
|
|
501
|
+
*/
|
|
502
|
+
declare function teardownEnvProblem(steps: SetupStep[] | undefined, env: Record<string, string | undefined>): string | null;
|
|
503
|
+
interface SetupResult {
|
|
504
|
+
ran: number;
|
|
505
|
+
/** what the log may say about each step: the verb and the selector, never a typed value */
|
|
506
|
+
lines: string[];
|
|
507
|
+
/**
|
|
508
|
+
* The step that failed: for a setup, a selector that never appeared (the
|
|
509
|
+
* take does not start); for a teardown, the step it stopped at. `error`
|
|
510
|
+
* is the driver's reason, one line, never a typed value.
|
|
511
|
+
*/
|
|
512
|
+
failed?: {
|
|
513
|
+
step: number;
|
|
514
|
+
do: string;
|
|
515
|
+
selector?: string;
|
|
516
|
+
error?: string;
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
/** How long a whole teardown may take before it is stopped and reported. */
|
|
520
|
+
declare const TEARDOWN_BOUND_MS = 60000;
|
|
521
|
+
/**
|
|
522
|
+
* What a teardown did, on the take's result: how many of its steps ran,
|
|
523
|
+
* and where it stopped. Never a typed value.
|
|
524
|
+
*/
|
|
525
|
+
interface TeardownReport {
|
|
526
|
+
ran: number;
|
|
527
|
+
of: number;
|
|
528
|
+
failed?: {
|
|
529
|
+
step: number;
|
|
530
|
+
do: string;
|
|
531
|
+
selector?: string;
|
|
532
|
+
error: string;
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
/** The teardown in one line, for the end of a take or a rehearsal. */
|
|
536
|
+
declare function teardownLine(report: TeardownReport): string;
|
|
537
|
+
/**
|
|
538
|
+
* Run the setup (or the teardown) on a page, with plain Playwright actions:
|
|
539
|
+
* no humanized pointer, no cursor events, no frames. A selector that never
|
|
540
|
+
* appears fails the steps there, because a take that begins at a
|
|
541
|
+
* half-finished sign-in is the wall by another name. With `boundMs`, the
|
|
542
|
+
* steps together run no longer than that: the step running when it passes
|
|
543
|
+
* fails, and the call it left pending is abandoned.
|
|
544
|
+
*/
|
|
545
|
+
declare function runSetup(page: RecorderPage, steps: SetupStep[], opts: {
|
|
546
|
+
sleep: (ms: number) => Promise<void>;
|
|
547
|
+
/** Absent means no env at all: a `{ env }` text then fails in words. */
|
|
548
|
+
env?: Record<string, string | undefined>;
|
|
549
|
+
/** How a `goto` opens its page and waits for it (the take's ready mode); absent, network idle. */
|
|
550
|
+
goto?: (url: string) => Promise<unknown>;
|
|
551
|
+
/** Which list these are, for the log and the messages (default `setup`). */
|
|
552
|
+
phase?: StepPhase;
|
|
553
|
+
/** The longest the steps may take together, in ms. */
|
|
554
|
+
boundMs?: number;
|
|
555
|
+
now?: () => number;
|
|
556
|
+
}): Promise<SetupResult>;
|
|
557
|
+
/** A `{ env }` the shell did not provide: a usage error, not a page's. */
|
|
558
|
+
declare class SetupEnvError extends Error {
|
|
559
|
+
constructor(message: string);
|
|
560
|
+
}
|
|
561
|
+
/** A setup step whose selector never appeared: the take does not start. */
|
|
562
|
+
declare class SetupError extends Error {
|
|
563
|
+
failed: NonNullable<SetupResult['failed']>;
|
|
564
|
+
constructor(failed: NonNullable<SetupResult['failed']>);
|
|
565
|
+
}
|
|
566
|
+
/** `--header name=value`, repeatable: extra request headers on every request. */
|
|
567
|
+
declare function parseHeaders(given: string[] | undefined): Record<string, string>;
|
|
568
|
+
|
|
418
569
|
/**
|
|
419
570
|
* The page's own console errors, as the recorder reports them. A page
|
|
420
571
|
* under recording is someone else's, and its errors are context, never the
|
|
@@ -563,99 +714,6 @@ declare function noticeLine(n: Notice): string;
|
|
|
563
714
|
*/
|
|
564
715
|
declare function noticeAdvice(notices: readonly Pick<Notice, 'kind'>[]): string;
|
|
565
716
|
|
|
566
|
-
/**
|
|
567
|
-
* `setup`: the steps that run BEFORE the camera rolls. A sign-in form, a
|
|
568
|
-
* cookie banner, the "choose your editor" modal, an onboarding tour: things
|
|
569
|
-
* a take must get past and must not show. They run after the first
|
|
570
|
-
* navigation and before `Page.startScreencast`, with no cursor synthesis,
|
|
571
|
-
* no pace accounting and nothing written to `meta.steps`. Then the recorder
|
|
572
|
-
* navigates to `url` again and the take begins where the setup left it.
|
|
573
|
-
*
|
|
574
|
-
* A `type` step's `text` may be `{ "env": "DEMO_PASSWORD" }`: resolved at run
|
|
575
|
-
* time from the `env` the caller hands in (the shell's for the CLI, the
|
|
576
|
-
* job's own map for a hosted take), never logged, never stored. The
|
|
577
|
-
* guarantee is narrow and real: the secret is never in a file that travels
|
|
578
|
-
* (`actions.json` is committed and pushed with the take; `meta.json` is read
|
|
579
|
-
* by the digest) and never in the footage.
|
|
580
|
-
*/
|
|
581
|
-
|
|
582
|
-
type SetupText = string | {
|
|
583
|
-
env: string;
|
|
584
|
-
};
|
|
585
|
-
type SetupStep = ({
|
|
586
|
-
do: 'wait';
|
|
587
|
-
ms: number;
|
|
588
|
-
} | {
|
|
589
|
-
do: 'click';
|
|
590
|
-
selector: string;
|
|
591
|
-
ms?: number;
|
|
592
|
-
} | {
|
|
593
|
-
do: 'type';
|
|
594
|
-
selector: string;
|
|
595
|
-
text: SetupText;
|
|
596
|
-
ms?: number;
|
|
597
|
-
} | {
|
|
598
|
-
do: 'press';
|
|
599
|
-
key: string;
|
|
600
|
-
ms?: number;
|
|
601
|
-
} | {
|
|
602
|
-
do: 'goto';
|
|
603
|
-
url: string;
|
|
604
|
-
}) & {
|
|
605
|
-
id?: string;
|
|
606
|
-
};
|
|
607
|
-
/**
|
|
608
|
-
* Why a page address is not one the recorder opens, or null. A script's
|
|
609
|
-
* `url` and a setup's `goto` open a browser, so only http and https are
|
|
610
|
-
* taken: a `file:` address would read this machine's disk into a take
|
|
611
|
-
* and a `javascript:` one would run in the page.
|
|
612
|
-
*/
|
|
613
|
-
declare function urlSchemeProblem(url: string): string | null;
|
|
614
|
-
/** Structural validation, mirrored on `validateActions` for `steps`. */
|
|
615
|
-
declare function validateSetup(value: unknown): string[];
|
|
616
|
-
/** The names a setup reads from its env, so a host can say what it must supply. */
|
|
617
|
-
declare function setupEnvNames(steps: SetupStep[] | undefined): string[];
|
|
618
|
-
/** A `{ env }` text resolved, or thrown in words. The value is never returned to a log. */
|
|
619
|
-
declare function resolveSetupText(t: SetupText, env: Record<string, string | undefined>): {
|
|
620
|
-
value: string;
|
|
621
|
-
secret: boolean;
|
|
622
|
-
};
|
|
623
|
-
interface SetupResult {
|
|
624
|
-
ran: number;
|
|
625
|
-
/** what the log may say about each step: the verb and the selector, never a typed value */
|
|
626
|
-
lines: string[];
|
|
627
|
-
/** a selector that never appeared; the take does not start */
|
|
628
|
-
failed?: {
|
|
629
|
-
step: number;
|
|
630
|
-
do: string;
|
|
631
|
-
selector?: string;
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Run the setup on a page, with plain Playwright actions: no humanized
|
|
636
|
-
* pointer, no cursor events, no frames. A selector that never appears
|
|
637
|
-
* fails the setup, because a take that begins at a half-finished sign-in is
|
|
638
|
-
* the wall by another name.
|
|
639
|
-
*/
|
|
640
|
-
declare function runSetup(page: RecorderPage, steps: SetupStep[], opts: {
|
|
641
|
-
sleep: (ms: number) => Promise<void>;
|
|
642
|
-
/** Absent means no env at all: a `{ env }` text then fails in words. */
|
|
643
|
-
env?: Record<string, string | undefined>;
|
|
644
|
-
/** How a `goto` opens its page and waits for it (the take's ready mode); absent, network idle. */
|
|
645
|
-
goto?: (url: string) => Promise<unknown>;
|
|
646
|
-
}): Promise<SetupResult>;
|
|
647
|
-
/** A `{ env }` the shell did not provide: a usage error, not a page's. */
|
|
648
|
-
declare class SetupEnvError extends Error {
|
|
649
|
-
constructor(message: string);
|
|
650
|
-
}
|
|
651
|
-
/** A setup step whose selector never appeared: the take does not start. */
|
|
652
|
-
declare class SetupError extends Error {
|
|
653
|
-
failed: NonNullable<SetupResult['failed']>;
|
|
654
|
-
constructor(failed: NonNullable<SetupResult['failed']>);
|
|
655
|
-
}
|
|
656
|
-
/** `--header name=value`, repeatable: extra request headers on every request. */
|
|
657
|
-
declare function parseHeaders(given: string[] | undefined): Record<string, string>;
|
|
658
|
-
|
|
659
717
|
/**
|
|
660
718
|
* When a page counts as ready for the take to begin. The default is the
|
|
661
719
|
* DOM: after `load`, the page must make no DOM change for a beat (counted
|
|
@@ -872,6 +930,278 @@ declare function overrunOf(plannedMs: number, tookMs: number): number | null;
|
|
|
872
930
|
/** The overruns in one line for the log and the done event, or null when none. */
|
|
873
931
|
declare function overrunLine(overruns: readonly StepOverrun[]): string | null;
|
|
874
932
|
|
|
933
|
+
/**
|
|
934
|
+
* What an `expect` and an `await` wait for: a condition on the page, read
|
|
935
|
+
* without touching it (no cursor, no input), polled until it holds or the
|
|
936
|
+
* time runs out. `expect` polls on camera for a few seconds; `await` polls
|
|
937
|
+
* off camera for as long as a slow result takes. One reader for both, so
|
|
938
|
+
* "appeared" means the same thing in either.
|
|
939
|
+
*/
|
|
940
|
+
|
|
941
|
+
interface WaitCondition {
|
|
942
|
+
/** an element matching this selector is visible */
|
|
943
|
+
selector?: string;
|
|
944
|
+
/** some visible text on the page contains this */
|
|
945
|
+
text?: string;
|
|
946
|
+
/** no element matching this selector is visible */
|
|
947
|
+
gone?: string;
|
|
948
|
+
/** with `selector`: the element is enabled (true) or disabled (false) */
|
|
949
|
+
enabled?: boolean;
|
|
950
|
+
/**
|
|
951
|
+
* A JavaScript expression evaluated in the page (awaited when it answers
|
|
952
|
+
* a promise): the condition holds when its value is truthy, or, with
|
|
953
|
+
* `equals`, when its value equals that one. For an app that keeps its
|
|
954
|
+
* state in script rather than in the DOM (a canvas, a document model).
|
|
955
|
+
*/
|
|
956
|
+
js?: string;
|
|
957
|
+
/** with `js`: the value the expression must equal (compared as JSON) */
|
|
958
|
+
equals?: unknown;
|
|
959
|
+
}
|
|
960
|
+
/** What the condition found the last time it looked: what a miss is said from. */
|
|
961
|
+
interface ConditionState {
|
|
962
|
+
holds: boolean;
|
|
963
|
+
/** with `selector`: whether a match was visible */
|
|
964
|
+
visible?: boolean;
|
|
965
|
+
/**
|
|
966
|
+
* with `js`: what the expression answered the last time it was read, as
|
|
967
|
+
* JSON when it has a JSON form (absent for `undefined`), and in words
|
|
968
|
+
* either way (`said`), or the error it threw (`threw`).
|
|
969
|
+
*/
|
|
970
|
+
value?: unknown;
|
|
971
|
+
said?: string;
|
|
972
|
+
threw?: string;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* The visible text of the page contains `text`: `innerText` is what the
|
|
976
|
+
* page renders, so a hidden element's words never count.
|
|
977
|
+
*/
|
|
978
|
+
declare function visibleTextScript(text: string): string;
|
|
979
|
+
/** The longest a js value is said in a line, in characters. */
|
|
980
|
+
declare const JS_SAID_MAX = 120;
|
|
981
|
+
/** The most a js value kept on the step holds, in characters of JSON. */
|
|
982
|
+
declare const JS_VALUE_MAX = 2048;
|
|
983
|
+
/**
|
|
984
|
+
* The page script that evaluates a step's expression and answers what it
|
|
985
|
+
* found, as a string (the one evaluate shape every driver shares). The
|
|
986
|
+
* expression is the script author's own, run on their own page: it is
|
|
987
|
+
* wrapped, never parsed, and a newline closes it before the paren so a
|
|
988
|
+
* trailing line comment cannot swallow the wrapper.
|
|
989
|
+
*/
|
|
990
|
+
declare function jsConditionScript(expr: string): string;
|
|
991
|
+
/** Two JSON values alike: the same keys and values whatever the key order. */
|
|
992
|
+
declare function sameJson(a: unknown, b: unknown): boolean;
|
|
993
|
+
/**
|
|
994
|
+
* A js value as a step keeps it (`meta.steps[].value`): the value itself
|
|
995
|
+
* while its JSON fits, else its JSON cut short as a string.
|
|
996
|
+
*/
|
|
997
|
+
declare function keptValue(value: unknown): unknown;
|
|
998
|
+
/** Read the condition once. A page mid-navigation reads as "not yet". */
|
|
999
|
+
declare function readCondition(page: RecorderPage, c: WaitCondition): Promise<ConditionState>;
|
|
1000
|
+
/** What a poll found: whether the condition held, after how long, and the last read. */
|
|
1001
|
+
interface PollResult {
|
|
1002
|
+
ok: boolean;
|
|
1003
|
+
ms: number;
|
|
1004
|
+
last: ConditionState;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Poll the condition every `everyMs` until it holds or `timeoutMs` pass.
|
|
1008
|
+
* `between` runs before each look but the first (an `await`'s reload).
|
|
1009
|
+
* With `confirm`, a hold counts only once it has held on that many reads
|
|
1010
|
+
* in a row, `confirm.gapMs` apart: a page that renders after network quiet
|
|
1011
|
+
* reads half-built for a moment, and a `gone` condition holds on a list
|
|
1012
|
+
* that has not been drawn yet. The clock is the wall's: a rehearsal waits
|
|
1013
|
+
* as long as a take would, because how long a result takes is what a
|
|
1014
|
+
* rehearsal is for.
|
|
1015
|
+
*/
|
|
1016
|
+
declare function pollCondition(page: RecorderPage, c: WaitCondition, opts: {
|
|
1017
|
+
timeoutMs: number;
|
|
1018
|
+
everyMs: number;
|
|
1019
|
+
sleep: (ms: number) => Promise<void>;
|
|
1020
|
+
now?: () => number;
|
|
1021
|
+
between?: () => Promise<void>;
|
|
1022
|
+
confirm?: {
|
|
1023
|
+
reads: number;
|
|
1024
|
+
gapMs: number;
|
|
1025
|
+
};
|
|
1026
|
+
}): Promise<PollResult>;
|
|
1027
|
+
/** The DOM counts as settled after this long with no change. */
|
|
1028
|
+
declare const DOM_QUIET_MS = 800;
|
|
1029
|
+
/** The longest a settle waits on a page that never stops changing. */
|
|
1030
|
+
declare const DOM_SETTLE_CAP_MS = 5000;
|
|
1031
|
+
/**
|
|
1032
|
+
* The page's own count of DOM changes: an observer installed once per
|
|
1033
|
+
* document, read back as a number. A string, the one evaluate shape every
|
|
1034
|
+
* driver shares.
|
|
1035
|
+
*/
|
|
1036
|
+
declare const DOM_CHANGE_PROBE = "(() => {\n if (!window.__vosDomChanges) {\n window.__vosDomChanges = { n: 0 };\n new MutationObserver((list) => { window.__vosDomChanges.n += list.length })\n .observe(document, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n return window.__vosDomChanges.n;\n})()";
|
|
1037
|
+
/**
|
|
1038
|
+
* Wait until the DOM has not changed for `quietMs`, at most `capMs`: what
|
|
1039
|
+
* a page does after its network went quiet (a list rendered from data, a
|
|
1040
|
+
* hydration). The count is polled from here rather than timed in the
|
|
1041
|
+
* page, because a background tab throttles its own timers.
|
|
1042
|
+
*/
|
|
1043
|
+
declare function domSettled(page: RecorderPage, opts: {
|
|
1044
|
+
sleep: (ms: number) => Promise<void>;
|
|
1045
|
+
now?: () => number;
|
|
1046
|
+
quietMs?: number;
|
|
1047
|
+
capMs?: number;
|
|
1048
|
+
tickMs?: number;
|
|
1049
|
+
}): Promise<{
|
|
1050
|
+
settled: boolean;
|
|
1051
|
+
ms: number;
|
|
1052
|
+
}>;
|
|
1053
|
+
/** Seconds as the recorder says them: `5 s`, `2.5 s`, `3 min 20 s`. */
|
|
1054
|
+
declare function sayDuration(ms: number): string;
|
|
1055
|
+
/** What the condition waits for, in words: `'#result' to appear`. */
|
|
1056
|
+
declare function sayCondition(c: WaitCondition): string;
|
|
1057
|
+
/** Why the condition did not hold, in words: `'Generate' stayed disabled for 5 s`. */
|
|
1058
|
+
declare function conditionMiss(c: WaitCondition, last: ConditionState, ms: number): string;
|
|
1059
|
+
/** An expression as a line names it: in backticks, cut short. */
|
|
1060
|
+
declare function sayJs(expr: string): string;
|
|
1061
|
+
/** A kept value as a line says it: its JSON, cut short. */
|
|
1062
|
+
declare function sayValue(value: unknown): string;
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* `peers`: other people on the same page, off camera. A collaboration
|
|
1066
|
+
* product shows best with a second person on the canvas: their cursor, the
|
|
1067
|
+
* shape they drew, the comment they left, arriving in the filmed page the
|
|
1068
|
+
* way the app syncs them. A peer is a second browser context (its own
|
|
1069
|
+
* cookies, so its own user, from its own storage state or none) on the
|
|
1070
|
+
* same URL, driven by its own step list, interleaved with the take's.
|
|
1071
|
+
*
|
|
1072
|
+
* What a peer is, and is not:
|
|
1073
|
+
*
|
|
1074
|
+
* - NOT FILMED. Only the take's own page is captured. A peer's page is
|
|
1075
|
+
* never screencast, scanned, masked or listened to; what it does reaches
|
|
1076
|
+
* the footage only through the app (its sync, its presence, its remote
|
|
1077
|
+
* cursors), which is what a viewer would see.
|
|
1078
|
+
* - NOT ON THE CURSOR TRACK. A peer's pointer moves its own page; the take's
|
|
1079
|
+
* CursorTrack is synthesized from the take's own steps alone, so a zoom,
|
|
1080
|
+
* a click ring or a dwell is never planned on a peer's gesture.
|
|
1081
|
+
* - ORDERED BY THE TAKE'S STEPS. A peer step may name a take step by id:
|
|
1082
|
+
* `with` starts it as that step starts (the two run together), `after` as
|
|
1083
|
+
* that step ends. A step naming neither follows the peer's previous step
|
|
1084
|
+
* at once; a peer's first step with neither starts as the camera rolls.
|
|
1085
|
+
* The take never waits on a peer: it waits on what the peer's work
|
|
1086
|
+
* SHOWS, with an `expect` or an `await` on its own page, so the footage
|
|
1087
|
+
* holds exactly the moment the sync landed. When the take's steps end,
|
|
1088
|
+
* a peer step still waiting on a trigger never runs (said), and one
|
|
1089
|
+
* already running finishes, bounded, before the trailing hold.
|
|
1090
|
+
* - PACED, NOT INSTANT. A peer's pointer glides on the same clock as the
|
|
1091
|
+
* take's (an app that draws remote cursors shows it travelling) and its
|
|
1092
|
+
* typing is paced per key, so what it does reads as a person.
|
|
1093
|
+
* - BOUNDED. Every peer step runs inside its own bound, as a take step
|
|
1094
|
+
* does; a selector that never appears or a check that never holds is a
|
|
1095
|
+
* skip with its reason, listed with the take's (`--strict` fails on it).
|
|
1096
|
+
*
|
|
1097
|
+
* A peer takes the take's gestures and checks (`wait`, `move`, `hover`,
|
|
1098
|
+
* `click`, `type`, `press`, `scroll`, `drag` with an inline `path`, and
|
|
1099
|
+
* `expect`), never a `paste`, a `download`, an `await` (a peer that must
|
|
1100
|
+
* wait for a result is the take's `await`), a guard, a `read`, a `caption`
|
|
1101
|
+
* or `settle`, which all belong to the filmed page.
|
|
1102
|
+
*/
|
|
1103
|
+
|
|
1104
|
+
/** One other person on the page: their own context, their own steps. */
|
|
1105
|
+
interface Peer {
|
|
1106
|
+
/** How the peer is named in lines and in `meta.peers`: a short word. */
|
|
1107
|
+
id: string;
|
|
1108
|
+
/** The page the peer opens; absent, the take's own `url`. */
|
|
1109
|
+
url?: string;
|
|
1110
|
+
/** The peer's viewport in CSS px; absent, the take's. */
|
|
1111
|
+
viewport?: {
|
|
1112
|
+
width: number;
|
|
1113
|
+
height: number;
|
|
1114
|
+
};
|
|
1115
|
+
/**
|
|
1116
|
+
* A Playwright storage state the peer's context is made from: the second
|
|
1117
|
+
* person's own sign-in. The host resolves the name (the CLI: a path from
|
|
1118
|
+
* the actions file's directory) and never sends the file anywhere.
|
|
1119
|
+
* Absent, the peer is signed out.
|
|
1120
|
+
*/
|
|
1121
|
+
storageState?: string;
|
|
1122
|
+
steps: PeerStep[];
|
|
1123
|
+
}
|
|
1124
|
+
/** A peer's step: one of the take's gestures or checks, and when it starts. */
|
|
1125
|
+
type PeerStep = ActionStep & {
|
|
1126
|
+
/**
|
|
1127
|
+
* Start as the take's step with this id starts: the two run together.
|
|
1128
|
+
* (`with`, never `at`: a `type` step's `at` is where its caret goes.)
|
|
1129
|
+
*/
|
|
1130
|
+
with?: string;
|
|
1131
|
+
/** Start as the take's step with this id ends. */
|
|
1132
|
+
after?: string;
|
|
1133
|
+
};
|
|
1134
|
+
/** The verbs a peer takes: the gestures and the on-page check. */
|
|
1135
|
+
declare const PEER_VERBS: readonly ["wait", "move", "hover", "click", "type", "press", "scroll", "drag", "expect"];
|
|
1136
|
+
/** The most peers a take may have: each is a whole browser context. */
|
|
1137
|
+
declare const MAX_PEERS = 4;
|
|
1138
|
+
/** The most steps one peer may take. */
|
|
1139
|
+
declare const MAX_PEER_STEPS = 200;
|
|
1140
|
+
/**
|
|
1141
|
+
* Structural validation of `peers`, given the take's own steps (a trigger
|
|
1142
|
+
* names one of their ids). `validate` is the take's step validator, run on
|
|
1143
|
+
* each peer's list so a peer step is checked in exactly the take's words.
|
|
1144
|
+
*/
|
|
1145
|
+
declare function validatePeers(value: unknown, takeSteps: unknown, validate: (steps: unknown[]) => string[]): string[];
|
|
1146
|
+
/** What a hosted recorder says of a script with peers, or null. */
|
|
1147
|
+
declare function peersHostedRefusal(peers: unknown): string | null;
|
|
1148
|
+
/**
|
|
1149
|
+
* The take's step boundaries, as promises a peer step waits on. The take
|
|
1150
|
+
* calls `begin` as the camera rolls, `start`/`end` around each step and
|
|
1151
|
+
* `close` once its steps are over; a trigger still pending then resolves
|
|
1152
|
+
* false and its step never runs.
|
|
1153
|
+
*/
|
|
1154
|
+
declare class StepSignals {
|
|
1155
|
+
private readonly started;
|
|
1156
|
+
private readonly ended;
|
|
1157
|
+
private readonly began;
|
|
1158
|
+
private closed;
|
|
1159
|
+
constructor(ids: Iterable<string>);
|
|
1160
|
+
begin(): void;
|
|
1161
|
+
start(id: string | undefined): void;
|
|
1162
|
+
end(id: string | undefined): void;
|
|
1163
|
+
close(): void;
|
|
1164
|
+
get isClosed(): boolean;
|
|
1165
|
+
/** When a step with this trigger may start: true, or false for never. */
|
|
1166
|
+
when(trigger: {
|
|
1167
|
+
with?: string;
|
|
1168
|
+
after?: string;
|
|
1169
|
+
}): {
|
|
1170
|
+
ready: Promise<boolean>;
|
|
1171
|
+
already: boolean;
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/** The most a peer step's kept value holds, in characters of JSON (as a take step's). */
|
|
1176
|
+
declare const PEER_VALUE_MAX = 2048;
|
|
1177
|
+
/**
|
|
1178
|
+
* What a peer's check last answered, kept on its step the way the take's
|
|
1179
|
+
* own steps keep theirs (`meta.steps[].value`): the value itself while its
|
|
1180
|
+
* JSON fits, else that JSON cut short as a string; absent when the read
|
|
1181
|
+
* answered nothing JSON can hold, or no value at all (a check that only
|
|
1182
|
+
* holds or not).
|
|
1183
|
+
*/
|
|
1184
|
+
declare function peerValue(last: ConditionState): unknown;
|
|
1185
|
+
/** What a peer did: its steps as they ran, and the ones that never did. */
|
|
1186
|
+
interface PeerRun {
|
|
1187
|
+
id: string;
|
|
1188
|
+
steps: PeerStepSpan[];
|
|
1189
|
+
/** Steps whose trigger never fired before the take's steps were over. */
|
|
1190
|
+
notRun: number[];
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Drive one peer's steps on its page, each when its trigger fires. Never
|
|
1194
|
+
* throws for a page's reasons: a miss is a skip on the run.
|
|
1195
|
+
*/
|
|
1196
|
+
declare function runPeer(peer: Peer, rawPage: RecorderPage, signals: StepSignals, opts: {
|
|
1197
|
+
clock: RecorderClock;
|
|
1198
|
+
/** The take's footage clock, ms: what a span is placed by. */
|
|
1199
|
+
footageMs: () => number;
|
|
1200
|
+
log: (msg: string) => void;
|
|
1201
|
+
/** A rehearsal: no travel, every pause cut short. */
|
|
1202
|
+
dry?: boolean;
|
|
1203
|
+
}): Promise<PeerRun>;
|
|
1204
|
+
|
|
875
1205
|
/**
|
|
876
1206
|
* The action script — the declarative recipe an agent (or human) writes to
|
|
877
1207
|
* drive a take. Small on purpose: selectors + a handful of verbs. The recorder
|
|
@@ -903,6 +1233,15 @@ interface ActionsFile {
|
|
|
903
1233
|
* or stored.
|
|
904
1234
|
*/
|
|
905
1235
|
setup?: SetupStep[];
|
|
1236
|
+
/**
|
|
1237
|
+
* Run AFTER the take, off camera, with the same verbs as `setup`: what
|
|
1238
|
+
* the take created in the product (an API key, a project, an invite)
|
|
1239
|
+
* removed again. They run once the screencast has stopped, on the take's
|
|
1240
|
+
* own page, after a rehearsal too, and when the take stops early or
|
|
1241
|
+
* throws after its first step. A failing teardown never fails the take;
|
|
1242
|
+
* it stops at the step that failed and is reported.
|
|
1243
|
+
*/
|
|
1244
|
+
teardown?: SetupStep[];
|
|
906
1245
|
/**
|
|
907
1246
|
* When the first page counts as ready for step 1: `dom` (default),
|
|
908
1247
|
* once its DOM has made no change for a beat after `load`, at most 8 s;
|
|
@@ -917,6 +1256,15 @@ interface ActionsFile {
|
|
|
917
1256
|
*/
|
|
918
1257
|
settle?: boolean;
|
|
919
1258
|
steps: ActionStep[];
|
|
1259
|
+
/**
|
|
1260
|
+
* Other people on the page, OFF CAMERA: each a browser context of its
|
|
1261
|
+
* own (its own storage state, so its own user) on the same `url`, driven
|
|
1262
|
+
* by its own steps, each started `with` a take step or `after` one (by
|
|
1263
|
+
* id). Only the take's page is filmed, and only its own steps make the
|
|
1264
|
+
* cursor track; a peer's work reaches the footage through the app's own
|
|
1265
|
+
* sync. A hosted take refuses peers.
|
|
1266
|
+
*/
|
|
1267
|
+
peers?: Peer[];
|
|
920
1268
|
}
|
|
921
1269
|
type ActionStep = ({
|
|
922
1270
|
do: 'wait';
|
|
@@ -1037,9 +1385,12 @@ type ActionStep = ({
|
|
|
1037
1385
|
/**
|
|
1038
1386
|
* Check that the page is as the flow expects, with no cursor move: an
|
|
1039
1387
|
* element visible (`selector`; with `enabled`, enabled or disabled), some
|
|
1040
|
-
* visible text containing `text`,
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1388
|
+
* visible text containing `text`, `gone` no longer visible, or `js`, an
|
|
1389
|
+
* expression evaluated in the page that holds when its value is truthy
|
|
1390
|
+
* (with `equals`, when its value equals that one): the state a canvas
|
|
1391
|
+
* app keeps in script, never in the DOM. Exactly one of the four. Waits
|
|
1392
|
+
* up to `timeout` seconds (default 5); a condition that never holds is a
|
|
1393
|
+
* skip with its reason, which names the value a `js` last answered.
|
|
1043
1394
|
*/
|
|
1044
1395
|
| {
|
|
1045
1396
|
do: 'expect';
|
|
@@ -1047,6 +1398,8 @@ type ActionStep = ({
|
|
|
1047
1398
|
text?: string;
|
|
1048
1399
|
gone?: string;
|
|
1049
1400
|
enabled?: boolean;
|
|
1401
|
+
js?: string;
|
|
1402
|
+
equals?: unknown;
|
|
1050
1403
|
timeout?: number;
|
|
1051
1404
|
}
|
|
1052
1405
|
/**
|
|
@@ -1099,6 +1452,15 @@ type ActionStep = ({
|
|
|
1099
1452
|
* `vos actions script` leads the beat with it.
|
|
1100
1453
|
*/
|
|
1101
1454
|
caption?: string;
|
|
1455
|
+
/**
|
|
1456
|
+
* The cut's camera on this step: `true` marks the step as its beat's
|
|
1457
|
+
* payoff, the moment worth the zoom (`vos plan --zooms per-beat` keeps
|
|
1458
|
+
* the proposal on it, and only it); `false` means never zoom here (the
|
|
1459
|
+
* planner's proposal on it is rejected). The planner still decides the
|
|
1460
|
+
* level and the focus; a mark never invents a zoom. On a gesture only
|
|
1461
|
+
* (ZOOM_MARK_VERBS).
|
|
1462
|
+
*/
|
|
1463
|
+
zoom?: boolean;
|
|
1102
1464
|
/**
|
|
1103
1465
|
* A selector whose words the recorder keeps once the step has settled
|
|
1104
1466
|
* (`meta.steps[].text`: trimmed, whitespace collapsed, at most 2 KB), so
|
|
@@ -1116,15 +1478,19 @@ type ActionStep = ({
|
|
|
1116
1478
|
*/
|
|
1117
1479
|
settle?: boolean;
|
|
1118
1480
|
};
|
|
1119
|
-
/** What an `await` waits for: exactly one of the
|
|
1481
|
+
/** What an `await` waits for: exactly one of the four (`equals` rides with `js`). */
|
|
1120
1482
|
interface AwaitUntil {
|
|
1121
1483
|
selector?: string;
|
|
1122
1484
|
text?: string;
|
|
1123
1485
|
gone?: string;
|
|
1486
|
+
js?: string;
|
|
1487
|
+
equals?: unknown;
|
|
1124
1488
|
}
|
|
1125
1489
|
/** The guards a step may carry: one today, a step that spends. */
|
|
1126
1490
|
declare const STEP_GUARDS: readonly ["spend"];
|
|
1127
1491
|
type StepGuard = (typeof STEP_GUARDS)[number];
|
|
1492
|
+
/** The verbs a `zoom` mark may sit on: the gestures a camera can be about. */
|
|
1493
|
+
declare const ZOOM_MARK_VERBS: readonly string[];
|
|
1128
1494
|
/** How long an `expect` waits by default, in seconds. */
|
|
1129
1495
|
declare const EXPECT_TIMEOUT_S = 5;
|
|
1130
1496
|
/** An `await`'s defaults, in seconds. */
|
|
@@ -1168,10 +1534,11 @@ declare function guardVerdict(actions: Pick<ActionsFile, 'steps'>, confirm: read
|
|
|
1168
1534
|
};
|
|
1169
1535
|
/**
|
|
1170
1536
|
* What a hosted recorder cannot do with a script, in words, or []: a
|
|
1171
|
-
* guarded step has nobody to confirm it on a fleet,
|
|
1172
|
-
* take directory to land in there
|
|
1537
|
+
* guarded step has nobody to confirm it on a fleet, a download has no
|
|
1538
|
+
* take directory to land in there, and a `js` check is code a stranger's
|
|
1539
|
+
* script would run in the fleet's browser.
|
|
1173
1540
|
*/
|
|
1174
|
-
declare function hostedRefusals(actions: Pick<ActionsFile, 'steps'>): string[];
|
|
1541
|
+
declare function hostedRefusals(actions: Pick<ActionsFile, 'steps' | 'peers'>): string[];
|
|
1175
1542
|
/**
|
|
1176
1543
|
* The files a script names beside itself, in order: a drag's path file
|
|
1177
1544
|
* and a paste's file. A host reads them before anything is captured.
|
|
@@ -1293,6 +1660,8 @@ interface SkippedStep {
|
|
|
1293
1660
|
selector: string;
|
|
1294
1661
|
/** why, when it is not a selector that never appeared: an expect that never held, a download that never came */
|
|
1295
1662
|
reason?: string;
|
|
1663
|
+
/** A PEER's step (`peers[].id`): `step` is then an index into that peer's steps. */
|
|
1664
|
+
peer?: string;
|
|
1296
1665
|
}
|
|
1297
1666
|
/** A click whose target was disabled when it was pressed: the press happened, and likely did nothing. */
|
|
1298
1667
|
interface DisabledClick {
|
|
@@ -1378,6 +1747,13 @@ interface RecordResult {
|
|
|
1378
1747
|
overruns: StepOverrun[];
|
|
1379
1748
|
/** The actions as recorded, `url` resolved: what a take directory writes back. */
|
|
1380
1749
|
actions: ActionsFile;
|
|
1750
|
+
/** What each peer did, off camera (also `meta.peers`); [] with none. */
|
|
1751
|
+
peers: PeerRun[];
|
|
1752
|
+
/**
|
|
1753
|
+
* What the script's `teardown` did after the take, off camera; null when
|
|
1754
|
+
* it has none. A failure here is reported and never fails the take.
|
|
1755
|
+
*/
|
|
1756
|
+
teardown: TeardownReport | null;
|
|
1381
1757
|
}
|
|
1382
1758
|
interface RecordOpts {
|
|
1383
1759
|
/** Stop the capture at this many seconds (the hosted cap). */
|
|
@@ -1416,9 +1792,10 @@ interface RecordOpts {
|
|
|
1416
1792
|
*/
|
|
1417
1793
|
context?: RecorderContext;
|
|
1418
1794
|
/**
|
|
1419
|
-
* The environment a setup's `{ env }` texts resolve
|
|
1420
|
-
* for the CLI, the job's own map on the fleet. Absent
|
|
1421
|
-
* all, so a setup that reads one fails in words
|
|
1795
|
+
* The environment a setup's and a teardown's `{ env }` texts resolve
|
|
1796
|
+
* from: the shell's for the CLI, the job's own map on the fleet. Absent
|
|
1797
|
+
* means no env at all, so a setup that reads one fails in words, and a
|
|
1798
|
+
* teardown that reads one refuses the take before it begins.
|
|
1422
1799
|
*/
|
|
1423
1800
|
env?: Record<string, string | undefined>;
|
|
1424
1801
|
/** The platform the take is recorded on, for `meta.platform`. */
|
|
@@ -1462,6 +1839,14 @@ interface RecordOpts {
|
|
|
1462
1839
|
stopOnHang?: boolean;
|
|
1463
1840
|
/** How often a long `await` reports it is still waiting (default 30 s). */
|
|
1464
1841
|
awaitHeartbeatMs?: number;
|
|
1842
|
+
/**
|
|
1843
|
+
* Where a peer's `storageState` is read from: the CLI resolves the name
|
|
1844
|
+
* from the actions file's directory to a path the browser opens, and
|
|
1845
|
+
* throws in words when there is none. A host that hands in none cannot
|
|
1846
|
+
* sign a peer in, and such a script is refused before anything is
|
|
1847
|
+
* captured.
|
|
1848
|
+
*/
|
|
1849
|
+
peerStorageState?: (name: string) => Promise<string> | string;
|
|
1465
1850
|
}
|
|
1466
1851
|
/**
|
|
1467
1852
|
* The expression a scroll tick evaluates: move the first scrollable
|
|
@@ -1567,97 +1952,6 @@ declare function splitSegmentsAtSkips(segments: ProjectDoc['segments'], skips: r
|
|
|
1567
1952
|
at: number;
|
|
1568
1953
|
}[] | undefined): ProjectDoc['segments'];
|
|
1569
1954
|
|
|
1570
|
-
/**
|
|
1571
|
-
* What an `expect` and an `await` wait for: a condition on the page, read
|
|
1572
|
-
* without touching it (no cursor, no input), polled until it holds or the
|
|
1573
|
-
* time runs out. `expect` polls on camera for a few seconds; `await` polls
|
|
1574
|
-
* off camera for as long as a slow result takes. One reader for both, so
|
|
1575
|
-
* "appeared" means the same thing in either.
|
|
1576
|
-
*/
|
|
1577
|
-
|
|
1578
|
-
interface WaitCondition {
|
|
1579
|
-
/** an element matching this selector is visible */
|
|
1580
|
-
selector?: string;
|
|
1581
|
-
/** some visible text on the page contains this */
|
|
1582
|
-
text?: string;
|
|
1583
|
-
/** no element matching this selector is visible */
|
|
1584
|
-
gone?: string;
|
|
1585
|
-
/** with `selector`: the element is enabled (true) or disabled (false) */
|
|
1586
|
-
enabled?: boolean;
|
|
1587
|
-
}
|
|
1588
|
-
/** What the condition found the last time it looked: what a miss is said from. */
|
|
1589
|
-
interface ConditionState {
|
|
1590
|
-
holds: boolean;
|
|
1591
|
-
/** with `selector`: whether a match was visible */
|
|
1592
|
-
visible?: boolean;
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* The visible text of the page contains `text`: `innerText` is what the
|
|
1596
|
-
* page renders, so a hidden element's words never count.
|
|
1597
|
-
*/
|
|
1598
|
-
declare function visibleTextScript(text: string): string;
|
|
1599
|
-
/** Read the condition once. A page mid-navigation reads as "not yet". */
|
|
1600
|
-
declare function readCondition(page: RecorderPage, c: WaitCondition): Promise<ConditionState>;
|
|
1601
|
-
/** What a poll found: whether the condition held, after how long, and the last read. */
|
|
1602
|
-
interface PollResult {
|
|
1603
|
-
ok: boolean;
|
|
1604
|
-
ms: number;
|
|
1605
|
-
last: ConditionState;
|
|
1606
|
-
}
|
|
1607
|
-
/**
|
|
1608
|
-
* Poll the condition every `everyMs` until it holds or `timeoutMs` pass.
|
|
1609
|
-
* `between` runs before each look but the first (an `await`'s reload).
|
|
1610
|
-
* With `confirm`, a hold counts only once it has held on that many reads
|
|
1611
|
-
* in a row, `confirm.gapMs` apart: a page that renders after network quiet
|
|
1612
|
-
* reads half-built for a moment, and a `gone` condition holds on a list
|
|
1613
|
-
* that has not been drawn yet. The clock is the wall's: a rehearsal waits
|
|
1614
|
-
* as long as a take would, because how long a result takes is what a
|
|
1615
|
-
* rehearsal is for.
|
|
1616
|
-
*/
|
|
1617
|
-
declare function pollCondition(page: RecorderPage, c: WaitCondition, opts: {
|
|
1618
|
-
timeoutMs: number;
|
|
1619
|
-
everyMs: number;
|
|
1620
|
-
sleep: (ms: number) => Promise<void>;
|
|
1621
|
-
now?: () => number;
|
|
1622
|
-
between?: () => Promise<void>;
|
|
1623
|
-
confirm?: {
|
|
1624
|
-
reads: number;
|
|
1625
|
-
gapMs: number;
|
|
1626
|
-
};
|
|
1627
|
-
}): Promise<PollResult>;
|
|
1628
|
-
/** The DOM counts as settled after this long with no change. */
|
|
1629
|
-
declare const DOM_QUIET_MS = 800;
|
|
1630
|
-
/** The longest a settle waits on a page that never stops changing. */
|
|
1631
|
-
declare const DOM_SETTLE_CAP_MS = 5000;
|
|
1632
|
-
/**
|
|
1633
|
-
* The page's own count of DOM changes: an observer installed once per
|
|
1634
|
-
* document, read back as a number. A string, the one evaluate shape every
|
|
1635
|
-
* driver shares.
|
|
1636
|
-
*/
|
|
1637
|
-
declare const DOM_CHANGE_PROBE = "(() => {\n if (!window.__vosDomChanges) {\n window.__vosDomChanges = { n: 0 };\n new MutationObserver((list) => { window.__vosDomChanges.n += list.length })\n .observe(document, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n return window.__vosDomChanges.n;\n})()";
|
|
1638
|
-
/**
|
|
1639
|
-
* Wait until the DOM has not changed for `quietMs`, at most `capMs`: what
|
|
1640
|
-
* a page does after its network went quiet (a list rendered from data, a
|
|
1641
|
-
* hydration). The count is polled from here rather than timed in the
|
|
1642
|
-
* page, because a background tab throttles its own timers.
|
|
1643
|
-
*/
|
|
1644
|
-
declare function domSettled(page: RecorderPage, opts: {
|
|
1645
|
-
sleep: (ms: number) => Promise<void>;
|
|
1646
|
-
now?: () => number;
|
|
1647
|
-
quietMs?: number;
|
|
1648
|
-
capMs?: number;
|
|
1649
|
-
tickMs?: number;
|
|
1650
|
-
}): Promise<{
|
|
1651
|
-
settled: boolean;
|
|
1652
|
-
ms: number;
|
|
1653
|
-
}>;
|
|
1654
|
-
/** Seconds as the recorder says them: `5 s`, `2.5 s`, `3 min 20 s`. */
|
|
1655
|
-
declare function sayDuration(ms: number): string;
|
|
1656
|
-
/** What the condition waits for, in words: `'#result' to appear`. */
|
|
1657
|
-
declare function sayCondition(c: WaitCondition): string;
|
|
1658
|
-
/** Why the condition did not hold, in words: `'Generate' stayed disabled for 5 s`. */
|
|
1659
|
-
declare function conditionMiss(c: WaitCondition, last: ConditionState, ms: number): string;
|
|
1660
|
-
|
|
1661
1955
|
/** The most a download keeps: a file the page made, never a disk's worth. */
|
|
1662
1956
|
declare const OUTPUT_MAX_BYTES: number;
|
|
1663
1957
|
/**
|
|
@@ -2045,4 +2339,4 @@ declare function inlinePoints(path: {
|
|
|
2045
2339
|
*/
|
|
2046
2340
|
declare function inlineScript<T extends Pick<ActionsFile, 'steps'>>(actions: T, files: LoadedFiles): T;
|
|
2047
2341
|
|
|
2048
|
-
export { APP_QUIET_MS, APP_SETTLE_CAP_MS, AWAIT_HEARTBEAT_MS, AWAIT_POLL_S, AWAIT_TIMEOUT_S, type ActionStep, type ActionsFile, type Arrival, type AwaitUntil, CHANGE_AGE_PROBE, CLICK_BUTTONS, type ClickButton, type ConditionState, DEAD_SHARE_WARN_PCT, DEAD_STRETCH_WARN_MS, DEFAULT_READY, DOM_CHANGE_PROBE, DOM_QUIET_MS, DOM_SETTLE_CAP_MS, DOWNLOAD_TIMEOUT_S, DRAG_HOLD_MS, DRAG_MODIFIERS, type DeadReport, type DeadStep, type DisabledClick, type DragModifier, EXPECT_TIMEOUT_S, EXPOSURE_ADVICE, EXPOSURE_MATCHERS_SRC, EXPOSURE_PROBE, type EncodePageOptions, type Exposure, type ExposureKind, ExposureLog, type FrameRec, type FrameSink, type FreezeSpan, type FreshPlanOptions, type GuardedStep, type HeardSound, IDLE_CALL_MS, KEY_ROUNDTRIP_MS, KEY_SEQUENCE_GAP_MS, type LoadedFiles, MAX_KEYS, MAX_PATH_POINTS, MEDIA_DRAIN_PROBE, MEDIA_WATCH_SCRIPT, MIN_SKIP_MS, MODIFIERS, MOTION_TICK_MS, MULTI_CLICK_GAP_MS, type MaskReport, type MaskRule, type MediaDrain, type MediaNote, type Modifier, NAV_TIMEOUT_MS, NETWORKIDLE_HYDRATION_MS, NOTICE_SRC, type Notice, NoticeLog, OUTPUT_MAX_BYTES, OVERRUN_MIN_MS, OVERRUN_MIN_PLANNED_MS, OVERRUN_SHARE, type OutputSink, PAGE_ERROR_LINE_CHARS, PASTE_MAX_BYTES, PASTE_READ_WINDOW_MS, PASTE_TYPES, PASTE_UNREAD_MS, PATH_DEFAULT_MS, POINTER_MAX_MS, POINTER_MIN_MS, POINTER_MS_PER_PX, PRESS_HOLD_MS, PRESS_KEYS, PRESS_LEAD_MS, type PaceReport, type PageError, PageErrorLog, PageSoundLog, type PasteItem, type PathPoint, type PathSample, type PollResult, type PressKey, QUIET_MS, READY_MODES, READY_SETTLE_CAP_MS, READ_BEAT_MS, RESPONSE_MS, type ReadyMode, type ReadyOpts, type ReadyReport, type RecordOpts, RecordRefusedError, type RecordResult, type RecorderApiResponse, type RecorderBrowser, type RecorderButtonOpts, type RecorderCdp, type RecorderClock, type RecorderConsoleMessage, type RecorderContext, type RecorderDownload, type RecorderLocator, type RecorderLocatorRoot, type RecorderMediaElement, type RecorderPage, type RecorderRect, type RecorderResponse, type RecorderRoute, SCROLL_MAX_MS, SCROLL_MIN_MS, SCROLL_MS_PER_PX, SCROLL_SETTLE_MS, SETTLE_CAP_MS, SETTLE_MS, SETTLE_VERBS, STEP_GUARDS, STEP_MARGIN_MS, type ScannedNotice, type ScriptFiles, SetupEnvError, SetupError, type SetupResult, type SetupStep, type SetupText, type SkippedStep, type SoundSink, StepBound, type StepGuard, type StepOverrun, type StepPace, type StoppedTake, type SurfaceFit, type SurfaceSize, TRAILING_HOLD_MS, TakeClock, WAIT_MARGIN_MS, WALL_PROBE, type WaitCondition, WallError, type WallKind, type WallVerdict, appSettled, askedMs, base64Bytes, bounded, buildEncodePage, buttonNumber, capReached, cappedLine, chordProblem, clampWait, clockMotion, clockTyping, conditionMiss, deadLine, deadTime, deadWarns, domSettled, easeInOutCubic, exposureLine, extForType, fetchInPageScript, fileNameProblem, fitSurfaceToViewport, formatDurationCap, guardVerdict, guardedSteps, hangReason, headersFor, holdLeftMs, hostedRefusals, inlinePoints, inlineScript, isIdpHost, isKeyName, isSignInPath, jpegDims, keySequencePlanMs, loadScriptFiles, maskInitScript, modifierBits, nameFromUrl, noticeAdvice, noticeLine, outputName, overrunLine, overrunOf, paceLine, paceReport, pageErrorLine, parseHeaders, pasteTypeOf, pathDurationMs, plainName, planFreshTake, pointerTravelMs, pollCondition, pressSequence, publicUrl, readAllBytes, readCondition, readMediaSource, readPath, readyLine, readyProblem, realSleep, recordTake, redirectedAway, reloadUntilReady, resolveChord, resolveModifier, resolveSetupText, runSetup, sayCondition, sayDuration, schedulePath, scriptFiles, scrollByScript, scrollTravelMs, settleMs, settleOn, settleVerdict, setupEnvNames, soundSrcForMeta, splitChord, splitSegmentsAtSkips, stageClipboardScript, stepBoundMs, syntheticPasteScript, typeOfName, untilReady, urlSchemeProblem, validateActions, validateSetup, visibleTextScript, wallVerdict, withFittingExport, withPageSound };
|
|
2342
|
+
export { APP_QUIET_MS, APP_SETTLE_CAP_MS, AWAIT_HEARTBEAT_MS, AWAIT_POLL_S, AWAIT_TIMEOUT_S, type ActionStep, type ActionsFile, type Arrival, type AwaitUntil, CHANGE_AGE_PROBE, CLICK_BUTTONS, type ClickButton, type ConditionState, DEAD_SHARE_WARN_PCT, DEAD_STRETCH_WARN_MS, DEFAULT_READY, DOM_CHANGE_PROBE, DOM_QUIET_MS, DOM_SETTLE_CAP_MS, DOWNLOAD_TIMEOUT_S, DRAG_HOLD_MS, DRAG_MODIFIERS, type DeadReport, type DeadStep, type DisabledClick, type DragModifier, EXPECT_TIMEOUT_S, EXPOSURE_ADVICE, EXPOSURE_MATCHERS_SRC, EXPOSURE_PROBE, type EncodePageOptions, type Exposure, type ExposureKind, ExposureLog, type FrameRec, type FrameSink, type FreezeSpan, type FreshPlanOptions, type GuardedStep, type HeardSound, IDLE_CALL_MS, JS_SAID_MAX, JS_VALUE_MAX, KEY_ROUNDTRIP_MS, KEY_SEQUENCE_GAP_MS, type LoadedFiles, MAX_KEYS, MAX_PATH_POINTS, MAX_PEERS, MAX_PEER_STEPS, MEDIA_DRAIN_PROBE, MEDIA_WATCH_SCRIPT, MIN_SKIP_MS, MODIFIERS, MOTION_TICK_MS, MULTI_CLICK_GAP_MS, type MaskReport, type MaskRule, type MediaDrain, type MediaNote, type Modifier, NAV_TIMEOUT_MS, NETWORKIDLE_HYDRATION_MS, NOTICE_SRC, type Notice, NoticeLog, OUTPUT_MAX_BYTES, OVERRUN_MIN_MS, OVERRUN_MIN_PLANNED_MS, OVERRUN_SHARE, type OutputSink, PAGE_ERROR_LINE_CHARS, PASTE_MAX_BYTES, PASTE_READ_WINDOW_MS, PASTE_TYPES, PASTE_UNREAD_MS, PATH_DEFAULT_MS, PEER_VALUE_MAX, PEER_VERBS, POINTER_MAX_MS, POINTER_MIN_MS, POINTER_MS_PER_PX, PRESS_HOLD_MS, PRESS_KEYS, PRESS_LEAD_MS, type PaceReport, type PageError, PageErrorLog, PageSoundLog, type PasteItem, type PathPoint, type PathSample, type Peer, type PeerRun, type PeerStep, type PollResult, type PressKey, QUIET_MS, READY_MODES, READY_SETTLE_CAP_MS, READ_BEAT_MS, RESPONSE_MS, type ReadyMode, type ReadyOpts, type ReadyReport, type RecordOpts, RecordRefusedError, type RecordResult, type RecorderApiResponse, type RecorderBrowser, type RecorderButtonOpts, type RecorderCdp, type RecorderClock, type RecorderConsoleMessage, type RecorderContext, type RecorderDownload, type RecorderLocator, type RecorderLocatorRoot, type RecorderMediaElement, type RecorderPage, type RecorderRect, type RecorderResponse, type RecorderRoute, SCROLL_MAX_MS, SCROLL_MIN_MS, SCROLL_MS_PER_PX, SCROLL_SETTLE_MS, SETTLE_CAP_MS, SETTLE_MS, SETTLE_VERBS, STEP_GUARDS, STEP_MARGIN_MS, type ScannedNotice, type ScriptFiles, SetupEnvError, SetupError, type SetupResult, type SetupStep, type SetupText, type SkippedStep, type SoundSink, StepBound, type StepGuard, type StepOverrun, type StepPace, type StepPhase, StepSignals, type StoppedTake, type SurfaceFit, type SurfaceSize, TEARDOWN_BOUND_MS, TRAILING_HOLD_MS, TakeClock, type TeardownReport, WAIT_MARGIN_MS, WALL_PROBE, type WaitCondition, WallError, type WallKind, type WallVerdict, ZOOM_MARK_VERBS, appSettled, askedMs, base64Bytes, bounded, buildEncodePage, buttonNumber, capReached, cappedLine, chordProblem, clampWait, clockMotion, clockTyping, conditionMiss, deadLine, deadTime, deadWarns, domSettled, easeInOutCubic, exposureLine, extForType, fetchInPageScript, fileNameProblem, fitSurfaceToViewport, formatDurationCap, guardVerdict, guardedSteps, hangReason, headersFor, holdLeftMs, hostedRefusals, inlinePoints, inlineScript, isIdpHost, isKeyName, isSignInPath, jpegDims, jsConditionScript, keptValue, keySequencePlanMs, loadScriptFiles, maskInitScript, modifierBits, nameFromUrl, noticeAdvice, noticeLine, outputName, overrunLine, overrunOf, paceLine, paceReport, pageErrorLine, parseHeaders, pasteTypeOf, pathDurationMs, peerValue, peersHostedRefusal, plainName, planFreshTake, pointerTravelMs, pollCondition, pressSequence, publicUrl, readAllBytes, readCondition, readMediaSource, readPath, readyLine, readyProblem, realSleep, recordTake, redirectedAway, reloadUntilReady, resolveChord, resolveModifier, resolveSetupText, runPeer, runSetup, sameJson, sayCondition, sayDuration, sayJs, sayValue, schedulePath, scriptEnvNames, scriptFiles, scrollByScript, scrollTravelMs, settleMs, settleOn, settleVerdict, setupEnvNames, soundSrcForMeta, splitChord, splitSegmentsAtSkips, stageClipboardScript, stepBoundMs, syntheticPasteScript, teardownEnvProblem, teardownLine, typeOfName, untilReady, urlSchemeProblem, validateActions, validatePeers, validateSetup, visibleTextScript, wallVerdict, withFittingExport, withPageSound };
|