@itmetsam/samurai-framework 0.21.5 → 0.22.1
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/api.d.ts +8 -3
- package/dist/api.js +1 -0
- package/dist/browser/browser-context.d.ts +18 -6
- package/dist/browser/browser-context.js +25 -7
- package/dist/browser/browser.d.ts +4 -4
- package/dist/browser/browser.js +11 -8
- package/dist/browser/chrome-launch.js +9 -1
- package/dist/browser/context-cookie-store.d.ts +17 -0
- package/dist/browser/context-cookie-store.js +90 -0
- package/dist/browser/index.d.ts +3 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/keyboard.d.ts +35 -0
- package/dist/browser/keyboard.js +83 -0
- package/dist/browser/mouse.d.ts +42 -0
- package/dist/browser/mouse.js +66 -0
- package/dist/browser/page-content.d.ts +4 -0
- package/dist/browser/page-content.js +12 -0
- package/dist/browser/page-events.d.ts +11 -0
- package/dist/browser/page-events.js +23 -0
- package/dist/browser/page-logging.d.ts +24 -0
- package/dist/browser/page-logging.js +43 -0
- package/dist/browser/page-navigation.d.ts +0 -2
- package/dist/browser/page-navigation.js +1 -6
- package/dist/browser/page-settings.d.ts +1 -1
- package/dist/browser/page-viewport.d.ts +21 -0
- package/dist/browser/page-viewport.js +33 -0
- package/dist/browser/page.d.ts +23 -16
- package/dist/browser/page.js +48 -71
- package/dist/browser/screenshot.d.ts +6 -0
- package/dist/browser/screenshot.js +14 -0
- package/dist/browser/storage-state.d.ts +0 -2
- package/dist/browser/storage-state.js +0 -20
- package/dist/browser/use-applier.d.ts +16 -5
- package/dist/browser/use-applier.js +44 -17
- package/dist/browser/use-commands.d.ts +36 -0
- package/dist/browser/use-commands.js +120 -0
- package/dist/cli/args.d.ts +8 -4
- package/dist/cli/args.js +8 -5
- package/dist/cli/console-reporter.js +5 -1
- package/dist/cli/main.js +1 -0
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +4 -1
- package/dist/config/base-url.d.ts +4 -0
- package/dist/config/base-url.js +6 -0
- package/dist/config/config.js +7 -0
- package/dist/config/fixture-use.d.ts +19 -0
- package/dist/config/fixture-use.js +44 -0
- package/dist/config/fully-parallel.d.ts +3 -0
- package/dist/config/fully-parallel.js +6 -0
- package/dist/config/group-use.d.ts +10 -0
- package/dist/config/group-use.js +51 -0
- package/dist/config/resolved-config.d.ts +2 -0
- package/dist/config/resolved-config.js +3 -0
- package/dist/config/storage-state-file.d.ts +3 -0
- package/dist/config/storage-state-file.js +20 -0
- package/dist/config/use-options.d.ts +3 -1
- package/dist/config/use-options.js +74 -14
- package/dist/config/web-server-options.d.ts +7 -0
- package/dist/config/web-server-options.js +111 -0
- package/dist/locator/check-actions.js +1 -1
- package/dist/locator/drag-actions.d.ts +17 -0
- package/dist/locator/drag-actions.js +80 -0
- package/dist/locator/element-actions.d.ts +10 -4
- package/dist/locator/element-actions.js +23 -16
- package/dist/locator/element-state.d.ts +5 -0
- package/dist/locator/element-state.js +2 -1
- package/dist/locator/event-actions.d.ts +10 -0
- package/dist/locator/event-actions.js +81 -0
- package/dist/locator/input-actions.d.ts +2 -11
- package/dist/locator/input-actions.js +3 -56
- package/dist/locator/key-actions.d.ts +11 -0
- package/dist/locator/key-actions.js +52 -0
- package/dist/locator/key-map.d.ts +16 -0
- package/dist/locator/key-map.js +76 -0
- package/dist/locator/locator.d.ts +35 -5
- package/dist/locator/locator.js +70 -16
- package/dist/locator/page-scripts.d.ts +2 -0
- package/dist/locator/page-scripts.js +7 -0
- package/dist/locator/pointer-actions.d.ts +44 -0
- package/dist/locator/pointer-actions.js +117 -0
- package/dist/locator/pointer-element-actions.d.ts +21 -0
- package/dist/locator/pointer-element-actions.js +42 -0
- package/dist/request/api-request-context.d.ts +65 -0
- package/dist/request/api-request-context.js +198 -0
- package/dist/request/api-response.d.ts +34 -0
- package/dist/request/api-response.js +57 -0
- package/dist/request/cookie-jar.d.ts +48 -0
- package/dist/request/cookie-jar.js +164 -0
- package/dist/request/http-transport.d.ts +31 -0
- package/dist/request/http-transport.js +113 -0
- package/dist/request/redirect.d.ts +10 -0
- package/dist/request/redirect.js +21 -0
- package/dist/request/request-body.d.ts +27 -0
- package/dist/request/request-body.js +71 -0
- package/dist/request/request.d.ts +16 -0
- package/dist/request/request.js +20 -0
- package/dist/runner/all-hooks.d.ts +7 -1
- package/dist/runner/all-hooks.js +17 -1
- package/dist/runner/fixture-defs.d.ts +2 -1
- package/dist/runner/fixture-defs.js +52 -18
- package/dist/runner/fixture-meta.d.ts +20 -0
- package/dist/runner/fixture-meta.js +109 -0
- package/dist/runner/fixture-options.d.ts +8 -0
- package/dist/runner/fixture-options.js +35 -0
- package/dist/runner/fixture-outputs.d.ts +11 -0
- package/dist/runner/fixture-outputs.js +28 -0
- package/dist/runner/fixture-registry.d.ts +35 -0
- package/dist/runner/fixture-registry.js +73 -0
- package/dist/runner/fixture-scope.d.ts +39 -9
- package/dist/runner/fixture-scope.js +139 -70
- package/dist/runner/fixture-start.d.ts +27 -0
- package/dist/runner/fixture-start.js +76 -0
- package/dist/runner/fixture-use.d.ts +23 -0
- package/dist/runner/fixture-use.js +64 -0
- package/dist/runner/fixture-worker.d.ts +26 -0
- package/dist/runner/fixture-worker.js +46 -0
- package/dist/runner/fixtures.d.ts +4 -1
- package/dist/runner/fixtures.js +3 -2
- package/dist/runner/global-hooks.d.ts +13 -0
- package/dist/runner/global-hooks.js +66 -0
- package/dist/runner/options.d.ts +13 -2
- package/dist/runner/output-tail.d.ts +14 -0
- package/dist/runner/output-tail.js +30 -0
- package/dist/runner/pool-schedule.d.ts +22 -0
- package/dist/runner/pool-schedule.js +55 -0
- package/dist/runner/pool-units.d.ts +34 -0
- package/dist/runner/pool-units.js +85 -0
- package/dist/runner/pooled-run.d.ts +7 -5
- package/dist/runner/pooled-run.js +19 -9
- package/dist/runner/prepare-run.js +5 -0
- package/dist/runner/registry.js +21 -7
- package/dist/runner/reporter.d.ts +13 -1
- package/dist/runner/reporter.js +13 -2
- package/dist/runner/request-fixture.d.ts +14 -0
- package/dist/runner/request-fixture.js +25 -0
- package/dist/runner/run-hooks.d.ts +16 -0
- package/dist/runner/run-hooks.js +52 -0
- package/dist/runner/run-test.d.ts +3 -0
- package/dist/runner/run-test.js +23 -3
- package/dist/runner/run.d.ts +8 -0
- package/dist/runner/run.js +10 -0
- package/dist/runner/select.d.ts +15 -4
- package/dist/runner/select.js +38 -12
- package/dist/runner/serial-run.d.ts +23 -0
- package/dist/runner/serial-run.js +88 -0
- package/dist/runner/serial.d.ts +34 -0
- package/dist/runner/serial.js +63 -0
- package/dist/runner/shard.d.ts +22 -0
- package/dist/runner/shard.js +73 -0
- package/dist/runner/suite.d.ts +3 -3
- package/dist/runner/suite.js +4 -3
- package/dist/runner/test-function.d.ts +15 -3
- package/dist/runner/test-info.js +2 -1
- package/dist/runner/test-runner.d.ts +1 -0
- package/dist/runner/test-runner.js +67 -18
- package/dist/runner/use-options.d.ts +18 -4
- package/dist/runner/use-options.js +33 -6
- package/dist/runner/wait-for-url.d.ts +20 -0
- package/dist/runner/wait-for-url.js +65 -0
- package/dist/runner/web-server.d.ts +16 -0
- package/dist/runner/web-server.js +165 -0
- package/dist/runner/worker-pool.d.ts +13 -5
- package/dist/runner/worker-pool.js +85 -51
- package/dist/runner/worker-protocol.d.ts +8 -0
- package/dist/runner/worker-session.js +9 -1
- package/dist/runner/worker.d.ts +2 -0
- package/dist/runner/worker.js +7 -1
- package/dist/types/config.d.ts +117 -21
- package/dist/types/extend.d.ts +54 -2
- package/dist/types/test.d.ts +42 -0
- package/dist/types/use.d.ts +59 -7
- package/package.json +1 -1
- package/dist/browser/emulation.d.ts +0 -61
- package/dist/browser/emulation.js +0 -180
|
@@ -42,3 +42,14 @@ export declare function sourcesFor(event: PageEventName): EventSource[];
|
|
|
42
42
|
* wait that ran out after `timeout` ms.
|
|
43
43
|
*/
|
|
44
44
|
export declare function waitForPageEvent<E extends PageEventName>(emitter: EventEmitter, event: E, matches: (item: PageEvents[E][0]) => boolean, options: Pick<WaitOptions, "trigger">, timeout: number, onTimeout: (timeout: number) => Error): Promise<PageEvents[E][0]>;
|
|
45
|
+
/** The waits `waitForEvent` hands its event to; `download` and `filechooser` take the predicate too */
|
|
46
|
+
export interface EventWaiters {
|
|
47
|
+
request(accepts: (item: unknown) => boolean, options: WaitOptions): Promise<unknown>;
|
|
48
|
+
response(accepts: (item: unknown) => boolean, options: WaitOptions): Promise<unknown>;
|
|
49
|
+
download(options: WaitOptions, accepts: (item: unknown) => boolean): Promise<unknown>;
|
|
50
|
+
filechooser(options: WaitOptions, accepts: (item: unknown) => boolean): Promise<unknown>;
|
|
51
|
+
}
|
|
52
|
+
/** `page.waitForEvent`: picks the named wait for `event`, with the predicate given as a function or in the options */
|
|
53
|
+
export declare function waitForEventOn<E extends WaitableEventName>(waiters: EventWaiters, event: E, optionsOrPredicate: ((item: PageEvents[E][0]) => boolean) | WaitForEventOptions<PageEvents[E][0]>): Promise<PageEvents[E][0]>;
|
|
54
|
+
/** Starts the parts `event` needs; a failure is reported to `onError`, not thrown */
|
|
55
|
+
export declare function startSources(event: PageEventName, start: Record<EventSource, () => Promise<unknown>>, onError: (err: unknown) => void): void;
|
|
@@ -56,3 +56,26 @@ export function waitForPageEvent(emitter, event, matches, options, timeout, onTi
|
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
+
/** `page.waitForEvent`: picks the named wait for `event`, with the predicate given as a function or in the options */
|
|
60
|
+
export async function waitForEventOn(waiters, event, optionsOrPredicate) {
|
|
61
|
+
const { predicate, ...options } = typeof optionsOrPredicate === "function"
|
|
62
|
+
? { predicate: optionsOrPredicate }
|
|
63
|
+
: optionsOrPredicate;
|
|
64
|
+
const accepts = (predicate ?? (() => true));
|
|
65
|
+
switch (event) {
|
|
66
|
+
case "request":
|
|
67
|
+
return waiters.request(accepts, options);
|
|
68
|
+
case "response":
|
|
69
|
+
return waiters.response(accepts, options);
|
|
70
|
+
case "download":
|
|
71
|
+
return waiters.download(options, accepts);
|
|
72
|
+
case "filechooser":
|
|
73
|
+
return waiters.filechooser(options, accepts);
|
|
74
|
+
default:
|
|
75
|
+
throw new Error(`waitForEvent(): "${String(event)}" is not supported; use page.on()`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Starts the parts `event` needs; a failure is reported to `onError`, not thrown */
|
|
79
|
+
export function startSources(event, start, onError) {
|
|
80
|
+
Promise.all(sourcesFor(event).map((source) => start[source]())).catch(onError);
|
|
81
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type EventEmitter from "node:events";
|
|
2
|
+
import type { BiDiConnector } from "../transport/bidi-connection.js";
|
|
3
|
+
import type { BrowsingContext } from "../types/bidi-modules/browsing-context.js";
|
|
4
|
+
import type { ContextTree } from "./context-tree.js";
|
|
5
|
+
import { PageLogs, type LogRecord, type PageError } from "./page-logs.js";
|
|
6
|
+
/** A page's console and error collection: started on demand, read at once, and whether the runner may fail on its errors */
|
|
7
|
+
export declare class PageLogging {
|
|
8
|
+
private readonly connector;
|
|
9
|
+
private readonly contextId;
|
|
10
|
+
private readonly tree;
|
|
11
|
+
private readonly emitter;
|
|
12
|
+
private lazyLogs;
|
|
13
|
+
private errorsAllowed;
|
|
14
|
+
constructor(connector: BiDiConnector, contextId: BrowsingContext, tree: () => Promise<ContextTree>, emitter: EventEmitter);
|
|
15
|
+
start(): Promise<void>;
|
|
16
|
+
/** Forgets the collection and hands back its start, for the caller to dispose; undefined when it never started */
|
|
17
|
+
take(): Promise<PageLogs> | undefined;
|
|
18
|
+
entries(): readonly LogRecord[];
|
|
19
|
+
errors(): readonly PageError[];
|
|
20
|
+
get dropped(): number;
|
|
21
|
+
clear(): void;
|
|
22
|
+
allowErrors(): void;
|
|
23
|
+
get errorsAreAllowed(): boolean;
|
|
24
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Lazy } from "./lazy.js";
|
|
2
|
+
import { PageLogs } from "./page-logs.js";
|
|
3
|
+
/** A page's console and error collection: started on demand, read at once, and whether the runner may fail on its errors */
|
|
4
|
+
export class PageLogging {
|
|
5
|
+
constructor(connector, contextId, tree, emitter) {
|
|
6
|
+
this.connector = connector;
|
|
7
|
+
this.contextId = contextId;
|
|
8
|
+
this.tree = tree;
|
|
9
|
+
this.emitter = emitter;
|
|
10
|
+
this.lazyLogs = new Lazy();
|
|
11
|
+
this.errorsAllowed = false;
|
|
12
|
+
}
|
|
13
|
+
async start() {
|
|
14
|
+
await this.lazyLogs.get(async () => {
|
|
15
|
+
const logs = await PageLogs.start(this.connector, await this.tree(), this.contextId);
|
|
16
|
+
logs.on("console", (message) => this.emitter.emit("console", message));
|
|
17
|
+
logs.on("pageerror", (error) => this.emitter.emit("pageerror", error));
|
|
18
|
+
return logs;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/** Forgets the collection and hands back its start, for the caller to dispose; undefined when it never started */
|
|
22
|
+
take() {
|
|
23
|
+
return this.lazyLogs.take();
|
|
24
|
+
}
|
|
25
|
+
entries() {
|
|
26
|
+
return this.lazyLogs.peek()?.entries ?? [];
|
|
27
|
+
}
|
|
28
|
+
errors() {
|
|
29
|
+
return this.lazyLogs.peek()?.errors ?? [];
|
|
30
|
+
}
|
|
31
|
+
get dropped() {
|
|
32
|
+
return this.lazyLogs.peek()?.dropped ?? 0;
|
|
33
|
+
}
|
|
34
|
+
clear() {
|
|
35
|
+
this.lazyLogs.peek()?.clear();
|
|
36
|
+
}
|
|
37
|
+
allowErrors() {
|
|
38
|
+
this.errorsAllowed = true;
|
|
39
|
+
}
|
|
40
|
+
get errorsAreAllowed() {
|
|
41
|
+
return this.errorsAllowed;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -29,8 +29,6 @@ export interface NavigationDeps {
|
|
|
29
29
|
timeout: number;
|
|
30
30
|
}): Promise<void>;
|
|
31
31
|
}
|
|
32
|
-
/** Resolves a slash-led `url` against `base`; any other URL is returned as given */
|
|
33
|
-
export declare function resolveRelativeURL(url: string, base: string): string;
|
|
34
32
|
/** Navigating one page: `goto`, `navigateTo`, `reload` and the wait for a load state */
|
|
35
33
|
export declare class PageNavigation {
|
|
36
34
|
private connector;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logger from "../logger/index.js";
|
|
2
|
+
import { RELATIVE_URL, resolveRelativeURL } from "../config/base-url.js";
|
|
2
3
|
import { peekRunSettings } from "../config/run-settings.js";
|
|
3
4
|
import { BiDiError } from "../transport/bidi-error.js";
|
|
4
5
|
import { UnsupportedOperationError } from "../transport/unsupported.js";
|
|
@@ -6,12 +7,6 @@ import { matchUrl } from "../network/url-match.js";
|
|
|
6
7
|
import { waitUntil, WaitTimeoutError } from "../wait/wait-until.js";
|
|
7
8
|
import { LoadStateTimeoutError, NavigationError, UrlTimeoutError, } from "./navigation-error.js";
|
|
8
9
|
import { writeContent } from "./page-content.js";
|
|
9
|
-
/** A URL starting with "/", "./" or "../" */
|
|
10
|
-
const RELATIVE_URL = /^\.{0,2}\//;
|
|
11
|
-
/** Resolves a slash-led `url` against `base`; any other URL is returned as given */
|
|
12
|
-
export function resolveRelativeURL(url, base) {
|
|
13
|
-
return RELATIVE_URL.test(url) ? new URL(url, base).href : url;
|
|
14
|
-
}
|
|
15
10
|
/** Navigating one page: `goto`, `navigateTo`, `reload` and the wait for a load state */
|
|
16
11
|
export class PageNavigation {
|
|
17
12
|
constructor(connector, contextId, deps) {
|
|
@@ -19,7 +19,7 @@ export declare class PageConfig {
|
|
|
19
19
|
timeout?: number;
|
|
20
20
|
waitUntil?: "none" | "interactive" | "complete";
|
|
21
21
|
}>;
|
|
22
|
-
use(): Promise<import("../api.js").UseOptions & {
|
|
22
|
+
use(): Promise<import("../api.js").UseOptions & import("../api.js").FixtureUse & {
|
|
23
23
|
viewport?: {
|
|
24
24
|
width: number;
|
|
25
25
|
height: number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BiDiConnector } from "../transport/bidi-connection.js";
|
|
2
|
+
import type { BrowsingContext } from "../types/bidi-modules/browsing-context.js";
|
|
3
|
+
import type { PageConfig } from "./page-settings.js";
|
|
4
|
+
import { type Viewport } from "./viewport.js";
|
|
5
|
+
/** A page's viewport: the size it was last given and whether Chrome lays it out like a phone */
|
|
6
|
+
export declare class PageViewport {
|
|
7
|
+
private readonly connector;
|
|
8
|
+
private readonly contextId;
|
|
9
|
+
private readonly config;
|
|
10
|
+
private known;
|
|
11
|
+
/** Chrome's phone layout is on (`setMobileLayout`): viewport changes keep it */
|
|
12
|
+
private mobile;
|
|
13
|
+
constructor(connector: BiDiConnector, contextId: BrowsingContext, config: PageConfig);
|
|
14
|
+
set(viewport: Viewport | null): Promise<void>;
|
|
15
|
+
setMobileLayout(): Promise<void>;
|
|
16
|
+
size(): {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
} | null;
|
|
20
|
+
applyDefault(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DEFAULT_VIEWPORT } from "../config/defaults.js";
|
|
2
|
+
import { applyViewport } from "./viewport.js";
|
|
3
|
+
/** A page's viewport: the size it was last given and whether Chrome lays it out like a phone */
|
|
4
|
+
export class PageViewport {
|
|
5
|
+
constructor(connector, contextId, config) {
|
|
6
|
+
this.connector = connector;
|
|
7
|
+
this.contextId = contextId;
|
|
8
|
+
this.config = config;
|
|
9
|
+
this.known = null;
|
|
10
|
+
/** Chrome's phone layout is on (`setMobileLayout`): viewport changes keep it */
|
|
11
|
+
this.mobile = false;
|
|
12
|
+
}
|
|
13
|
+
async set(viewport) {
|
|
14
|
+
await applyViewport(this.connector, this.contextId, viewport, this.mobile);
|
|
15
|
+
this.known = viewport && {
|
|
16
|
+
width: viewport.width,
|
|
17
|
+
height: viewport.height,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async setMobileLayout() {
|
|
21
|
+
this.mobile = true;
|
|
22
|
+
await this.set(this.known);
|
|
23
|
+
}
|
|
24
|
+
size() {
|
|
25
|
+
return this.known && { ...this.known };
|
|
26
|
+
}
|
|
27
|
+
async applyDefault() {
|
|
28
|
+
const { viewport } = await this.config.use();
|
|
29
|
+
if (viewport === null)
|
|
30
|
+
return;
|
|
31
|
+
await this.set(viewport ?? DEFAULT_VIEWPORT);
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/browser/page.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { APIRequestContext } from "../request/api-request-context.js";
|
|
1
2
|
import Locator from "../locator/locator.js";
|
|
2
3
|
import type { FilterOptions } from "../locator/filter-step.js";
|
|
3
4
|
import type { RoleOptions } from "../locator/role-locator.js";
|
|
@@ -7,25 +8,27 @@ import type { Recorder, RecorderOptions } from "../recorder/recorder.js";
|
|
|
7
8
|
import { ContextTree } from "./context-tree.js";
|
|
8
9
|
import type { BrowserContext } from "./browser-context.js";
|
|
9
10
|
import { type PdfOptions } from "./pdf.js";
|
|
10
|
-
import {
|
|
11
|
+
import type { RuntimeUseOptions } from "../types/use.js";
|
|
11
12
|
import type { Download } from "./download.js";
|
|
12
13
|
import type { FileChooser } from "./file-chooser.js";
|
|
13
14
|
import { type ScreenshotOptions } from "./screenshot.js";
|
|
14
|
-
import { Evidence } from "./evidence.js";
|
|
15
|
-
import {
|
|
15
|
+
import type { Evidence } from "./evidence.js";
|
|
16
|
+
import type { LogRecord, PageError } from "./page-logs.js";
|
|
16
17
|
import type { RouteHandler } from "../network/router.js";
|
|
17
18
|
import { Response } from "../network/response.js";
|
|
18
19
|
import type { NetworkMatch } from "../network/network-wait.js";
|
|
19
20
|
import type { UrlPattern } from "../network/url-match.js";
|
|
20
21
|
import type { LoadState, NavigateOptions, NavigationResult } from "./page-navigation.js";
|
|
22
|
+
import Keyboard from "./keyboard.js";
|
|
23
|
+
import Mouse from "./mouse.js";
|
|
21
24
|
import { type PageEventName, type PageEvents, type WaitableEventName, type WaitForEventOptions, type WaitOptions } from "./page-events.js";
|
|
22
25
|
export type { PageEventName, WaitableEventName, WaitForEventOptions, WaitOptions, };
|
|
23
26
|
import { type PageSettings, type ReadinessState } from "./page-settings.js";
|
|
24
27
|
export type { PageSettings, ReadinessState };
|
|
25
|
-
import {
|
|
28
|
+
import type { Viewport } from "./viewport.js";
|
|
26
29
|
import type { PreloadHandle } from "../script/preload.js";
|
|
27
30
|
import type { BiDiConnector } from "../transport/bidi-connection.js";
|
|
28
|
-
import {
|
|
31
|
+
import type { PageFunction } from "../script/call-function.js";
|
|
29
32
|
import type { BrowsingContext } from "../types/bidi-modules/browsing-context.js";
|
|
30
33
|
export type { LoadState, NavigateOptions, NavigationResult };
|
|
31
34
|
export default class Page {
|
|
@@ -36,20 +39,21 @@ export default class Page {
|
|
|
36
39
|
private initScripts;
|
|
37
40
|
private pageConfig;
|
|
38
41
|
private locators;
|
|
42
|
+
/** Real key input to whatever has focus: `press` (also chords such as `Control+a`), `down`, `up`, `type`, `insertText` */
|
|
43
|
+
readonly keyboard: Keyboard;
|
|
44
|
+
/** Real pointer input at viewport coordinates: `move`, `down`, `up`, `click`, `dblclick`, `wheel` */
|
|
45
|
+
readonly mouse: Mouse;
|
|
39
46
|
private pageEvents;
|
|
40
47
|
private documents;
|
|
41
48
|
private nav;
|
|
42
49
|
private net;
|
|
43
50
|
private dialogs;
|
|
44
|
-
private
|
|
45
|
-
private errorsAllowed;
|
|
51
|
+
private logging;
|
|
46
52
|
private isClosed;
|
|
47
53
|
private browserContext;
|
|
48
54
|
private transfers;
|
|
49
55
|
private evidence;
|
|
50
|
-
private
|
|
51
|
-
/** Chrome's phone layout is on (`emulateMobile`): viewport changes keep it */
|
|
52
|
-
private mobile;
|
|
56
|
+
private viewport;
|
|
53
57
|
/** `settings` override what `samurai.config.ts` says; without them the config is read when needed */
|
|
54
58
|
constructor(biDiConnector: BiDiConnector, contextId: string, settings?: PageSettings);
|
|
55
59
|
/** The BiDi browsing context id of this page's top-level context */
|
|
@@ -181,7 +185,7 @@ export default class Page {
|
|
|
181
185
|
*/
|
|
182
186
|
setViewport(viewport: Viewport | null): Promise<void>;
|
|
183
187
|
/** @internal Chrome: lays this page out like a phone from now on (`use.isMobile`), including the size it has now */
|
|
184
|
-
|
|
188
|
+
setMobileLayout(): Promise<void>;
|
|
185
189
|
/** Playwright's name for `setViewport` */
|
|
186
190
|
setViewportSize(size: Viewport): Promise<void>;
|
|
187
191
|
/**
|
|
@@ -213,20 +217,23 @@ export default class Page {
|
|
|
213
217
|
pdf(options?: PdfOptions): Promise<Buffer>;
|
|
214
218
|
/** The browser context (cookies, storage) this page belongs to */
|
|
215
219
|
context(): BrowserContext;
|
|
220
|
+
/** Makes HTTP requests from the test with this page's cookies; the same as `page.context().request` */
|
|
221
|
+
get request(): APIRequestContext;
|
|
216
222
|
/** @internal Called when the page is opened in a context */
|
|
217
223
|
setContext(context: BrowserContext): void;
|
|
218
224
|
/** @internal Marks the page closed after its tab is gone (its context was removed) and releases what it registered */
|
|
219
225
|
detach(): Promise<void>;
|
|
220
226
|
/**
|
|
221
|
-
*
|
|
222
|
-
*
|
|
227
|
+
* Changes the `use` options that can change while the browser runs for this page only: locale, timezone, user
|
|
228
|
+
* agent, geolocation, offline, orientation, screen, hasTouch, javaScriptEnabled. It wins over what the page's
|
|
229
|
+
* context says; `null` puts the real (or the context's) value back. Same options as `test.use()`, applied now.
|
|
223
230
|
* @example
|
|
224
|
-
* await page.
|
|
231
|
+
* await page.use({ locale: "nl-NL", offline: true });
|
|
225
232
|
*/
|
|
226
|
-
|
|
233
|
+
use(options: RuntimeUseOptions): Promise<void>;
|
|
227
234
|
/**
|
|
228
235
|
* Grants a browser permission ("geolocation", "notifications", "camera", …) to the origin this page is on,
|
|
229
|
-
* or to `options.origin`.
|
|
236
|
+
* or to `options.origin`. A geolocation override only answers once this is granted.
|
|
230
237
|
*/
|
|
231
238
|
grantPermission(name: string, options?: {
|
|
232
239
|
origin?: string;
|
package/dist/browser/page.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import Locator from "../locator/locator.js";
|
|
2
2
|
import { attributeSelector, cssSelector, labelSelector, roleSelector, testIdSelector, textSelector, } from "../locator/selector.js";
|
|
3
3
|
import EventEmitter from "node:events";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { projectDir } from "../config/config.js";
|
|
6
|
-
import { DEFAULT_VIEWPORT } from "../config/defaults.js";
|
|
7
4
|
import logger from "../logger/index.js";
|
|
8
5
|
import { ContextTree } from "./context-tree.js";
|
|
9
6
|
import { printPdf } from "./pdf.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { PageLogs } from "./page-logs.js";
|
|
7
|
+
import { applyUse } from "./use-commands.js";
|
|
8
|
+
import { screenshotWithEvidence, } from "./screenshot.js";
|
|
9
|
+
import { PageLogging } from "./page-logging.js";
|
|
14
10
|
import { Lazy } from "./lazy.js";
|
|
15
11
|
import { Response } from "../network/response.js";
|
|
16
12
|
import { traverseHistory } from "./history.js";
|
|
@@ -22,13 +18,14 @@ import { PageTransfers } from "./page-transfers.js";
|
|
|
22
18
|
import { InitScripts } from "./init-script.js";
|
|
23
19
|
import { grantPermission } from "./page-permissions.js";
|
|
24
20
|
import { PageLocators } from "./page-locators.js";
|
|
25
|
-
import
|
|
21
|
+
import Keyboard from "./keyboard.js";
|
|
22
|
+
import Mouse from "./mouse.js";
|
|
23
|
+
import { startSources, waitForEventOn, waitForPageEvent, } from "./page-events.js";
|
|
26
24
|
import { PageConfig, } from "./page-settings.js";
|
|
27
|
-
import {
|
|
25
|
+
import { PageViewport } from "./page-viewport.js";
|
|
28
26
|
import { HelperRealm } from "../locator/helper-realm.js";
|
|
29
27
|
import { BiDiError } from "../transport/bidi-error.js";
|
|
30
|
-
import {
|
|
31
|
-
import { readContent } from "./page-content.js";
|
|
28
|
+
import { readContent, readTitle, readUrl } from "./page-content.js";
|
|
32
29
|
import { evaluateInPage } from "./page-evaluate.js";
|
|
33
30
|
export default class Page {
|
|
34
31
|
/** `settings` override what `samurai.config.ts` says; without them the config is read when needed */
|
|
@@ -36,18 +33,17 @@ export default class Page {
|
|
|
36
33
|
this.lazyTree = new Lazy();
|
|
37
34
|
this.initScripts = new InitScripts();
|
|
38
35
|
this.pageEvents = new EventEmitter();
|
|
39
|
-
this.lazyLogs = new Lazy();
|
|
40
|
-
this.errorsAllowed = false;
|
|
41
36
|
this.isClosed = false;
|
|
42
|
-
this.knownViewport = null;
|
|
43
|
-
/** Chrome's phone layout is on (`emulateMobile`): viewport changes keep it */
|
|
44
|
-
this.mobile = false;
|
|
45
37
|
this.biDiConnector = biDiConnector;
|
|
46
38
|
this.id = contextId;
|
|
47
39
|
this.pageConfig = new PageConfig(settings);
|
|
48
40
|
this.helperRealm = new HelperRealm(biDiConnector, contextId);
|
|
49
41
|
this.locators = new PageLocators(biDiConnector, contextId, this.helperRealm, this.pageConfig, () => this.assertOpen());
|
|
42
|
+
this.keyboard = new Keyboard(biDiConnector, contextId, () => this.assertOpen());
|
|
43
|
+
this.mouse = new Mouse(biDiConnector, contextId, () => this.assertOpen());
|
|
50
44
|
this.documents = new DocumentWatcher(biDiConnector, contextId);
|
|
45
|
+
this.viewport = new PageViewport(biDiConnector, contextId, this.pageConfig);
|
|
46
|
+
this.logging = new PageLogging(biDiConnector, contextId, () => this.tree(), this.pageEvents);
|
|
51
47
|
this.net = new PageNetwork(biDiConnector, contextId, {
|
|
52
48
|
config: this.pageConfig,
|
|
53
49
|
tree: { ensure: () => this.tree(), peek: () => this.lazyTree.peek() },
|
|
@@ -162,7 +158,7 @@ export default class Page {
|
|
|
162
158
|
this.net.disposeTracker(),
|
|
163
159
|
]);
|
|
164
160
|
const tree = this.lazyTree.take();
|
|
165
|
-
const pageLogs = this.
|
|
161
|
+
const pageLogs = this.logging.take();
|
|
166
162
|
results.push(...(await Promise.allSettled([
|
|
167
163
|
tree?.then((resolved) => resolved.dispose()),
|
|
168
164
|
this.documents.dispose(),
|
|
@@ -224,7 +220,7 @@ export default class Page {
|
|
|
224
220
|
/** The URL of the page now */
|
|
225
221
|
async url() {
|
|
226
222
|
this.assertOpen();
|
|
227
|
-
return
|
|
223
|
+
return readUrl(this.biDiConnector, this.id);
|
|
228
224
|
}
|
|
229
225
|
/**
|
|
230
226
|
* Waits until the URL matches `url` (a string equals it, or with `*` / `**` is a glob; a RegExp is tested on it;
|
|
@@ -253,7 +249,7 @@ export default class Page {
|
|
|
253
249
|
/** The title of the document now */
|
|
254
250
|
async title() {
|
|
255
251
|
this.assertOpen();
|
|
256
|
-
return
|
|
252
|
+
return readTitle(this.biDiConnector, this.id);
|
|
257
253
|
}
|
|
258
254
|
/**
|
|
259
255
|
* Runs `fn` in the page, with `arg` as its only argument, and returns the result (a promise is awaited). `fn` is a function,
|
|
@@ -276,16 +272,11 @@ export default class Page {
|
|
|
276
272
|
*/
|
|
277
273
|
async setViewport(viewport) {
|
|
278
274
|
this.assertOpen();
|
|
279
|
-
await
|
|
280
|
-
this.knownViewport = viewport && {
|
|
281
|
-
width: viewport.width,
|
|
282
|
-
height: viewport.height,
|
|
283
|
-
};
|
|
275
|
+
await this.viewport.set(viewport);
|
|
284
276
|
}
|
|
285
277
|
/** @internal Chrome: lays this page out like a phone from now on (`use.isMobile`), including the size it has now */
|
|
286
|
-
async
|
|
287
|
-
this.
|
|
288
|
-
await this.setViewport(this.knownViewport);
|
|
278
|
+
async setMobileLayout() {
|
|
279
|
+
await this.viewport.setMobileLayout();
|
|
289
280
|
}
|
|
290
281
|
/** Playwright's name for `setViewport` */
|
|
291
282
|
setViewportSize(size) {
|
|
@@ -296,14 +287,11 @@ export default class Page {
|
|
|
296
287
|
* browser opened it), read at once; null before one is known, after `setViewport(null)` and when config turns the viewport off.
|
|
297
288
|
*/
|
|
298
289
|
viewportSize() {
|
|
299
|
-
return this.
|
|
290
|
+
return this.viewport.size();
|
|
300
291
|
}
|
|
301
292
|
/** Gives the page the size from config `use.viewport` (1280x720 by default); the browser does this when it opens a page */
|
|
302
293
|
async applyDefaultViewport() {
|
|
303
|
-
|
|
304
|
-
if (viewport === null)
|
|
305
|
-
return;
|
|
306
|
-
await this.setViewport(viewport ?? DEFAULT_VIEWPORT);
|
|
294
|
+
await this.viewport.applyDefault();
|
|
307
295
|
}
|
|
308
296
|
/**
|
|
309
297
|
* What the browser sets up on every page it opens: the default size, then everything that has to be listening
|
|
@@ -324,12 +312,7 @@ export default class Page {
|
|
|
324
312
|
*/
|
|
325
313
|
async screenshot(options = {}) {
|
|
326
314
|
this.assertOpen();
|
|
327
|
-
|
|
328
|
-
if (options.name !== undefined) {
|
|
329
|
-
const evidence = this.evidence ?? new Evidence(path.join(projectDir(), "result"));
|
|
330
|
-
await writeOutput(evidence.fileFor(options.name, options.type).file, image);
|
|
331
|
-
}
|
|
332
|
-
return image;
|
|
315
|
+
return screenshotWithEvidence(this.biDiConnector, this.id, options, this.evidence);
|
|
333
316
|
}
|
|
334
317
|
/** @internal The runner gives each test its own evidence folder */
|
|
335
318
|
setEvidence(evidence) {
|
|
@@ -352,6 +335,10 @@ export default class Page {
|
|
|
352
335
|
throw new Error("this page has no browser context: open it with browser.newPage() or context.newPage()");
|
|
353
336
|
return this.browserContext;
|
|
354
337
|
}
|
|
338
|
+
/** Makes HTTP requests from the test with this page's cookies; the same as `page.context().request` */
|
|
339
|
+
get request() {
|
|
340
|
+
return this.context().request;
|
|
341
|
+
}
|
|
355
342
|
/** @internal Called when the page is opened in a context */
|
|
356
343
|
setContext(context) {
|
|
357
344
|
this.browserContext = context;
|
|
@@ -362,18 +349,19 @@ export default class Page {
|
|
|
362
349
|
await this.dispose().catch((err) => logger.debug("Releasing a detached page failed", { err }));
|
|
363
350
|
}
|
|
364
351
|
/**
|
|
365
|
-
*
|
|
366
|
-
*
|
|
352
|
+
* Changes the `use` options that can change while the browser runs for this page only: locale, timezone, user
|
|
353
|
+
* agent, geolocation, offline, orientation, screen, hasTouch, javaScriptEnabled. It wins over what the page's
|
|
354
|
+
* context says; `null` puts the real (or the context's) value back. Same options as `test.use()`, applied now.
|
|
367
355
|
* @example
|
|
368
|
-
* await page.
|
|
356
|
+
* await page.use({ locale: "nl-NL", offline: true });
|
|
369
357
|
*/
|
|
370
|
-
async
|
|
358
|
+
async use(options) {
|
|
371
359
|
this.assertOpen();
|
|
372
|
-
await
|
|
360
|
+
await applyUse(this.biDiConnector, { contexts: [this.id] }, options);
|
|
373
361
|
}
|
|
374
362
|
/**
|
|
375
363
|
* Grants a browser permission ("geolocation", "notifications", "camera", …) to the origin this page is on,
|
|
376
|
-
* or to `options.origin`.
|
|
364
|
+
* or to `options.origin`. A geolocation override only answers once this is granted.
|
|
377
365
|
*/
|
|
378
366
|
async grantPermission(name, options = {}) {
|
|
379
367
|
this.assertOpen();
|
|
@@ -465,7 +453,7 @@ export default class Page {
|
|
|
465
453
|
network: () => this.startNetworkTracking(),
|
|
466
454
|
bodies: () => this.startBodyCollection(),
|
|
467
455
|
};
|
|
468
|
-
|
|
456
|
+
startSources(event, start, (err) => logger.error("Could not start listening for %s", event, { err }));
|
|
469
457
|
}
|
|
470
458
|
/** Starts following downloads; the browser does this when it opens a page, `page.on("download")` and `waitForDownload` when needed */
|
|
471
459
|
startDownloadTracking() {
|
|
@@ -506,24 +494,18 @@ export default class Page {
|
|
|
506
494
|
* await chooser.setFiles("./myfile.pdf");
|
|
507
495
|
*/
|
|
508
496
|
async waitForEvent(event, optionsOrPredicate = {}) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
:
|
|
512
|
-
|
|
513
|
-
switch (event) {
|
|
514
|
-
case "request":
|
|
515
|
-
return this.waitForRequest(accepts, options);
|
|
516
|
-
case "response":
|
|
517
|
-
return this.waitForResponse(accepts, options);
|
|
518
|
-
case "download":
|
|
497
|
+
return waitForEventOn({
|
|
498
|
+
request: (accepts, options) => this.waitForRequest(accepts, options),
|
|
499
|
+
response: (accepts, options) => this.waitForResponse(accepts, options),
|
|
500
|
+
download: (options, accepts) => {
|
|
519
501
|
this.assertOpen();
|
|
520
502
|
return this.transfers.waitForDownload(options, accepts);
|
|
521
|
-
|
|
503
|
+
},
|
|
504
|
+
filechooser: (options, accepts) => {
|
|
522
505
|
this.assertOpen();
|
|
523
506
|
return this.transfers.waitForFileChooser(options, accepts);
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
507
|
+
},
|
|
508
|
+
}, event, optionsOrPredicate);
|
|
527
509
|
}
|
|
528
510
|
/**
|
|
529
511
|
* Starts keeping response bodies, which is what makes `response.body()` possible: the browser only keeps a body
|
|
@@ -588,27 +570,22 @@ export default class Page {
|
|
|
588
570
|
* early output is kept; `page.on("console" | "pageerror")` starts it when needed.
|
|
589
571
|
*/
|
|
590
572
|
async startLogging() {
|
|
591
|
-
await this.
|
|
592
|
-
const logs = await PageLogs.start(this.biDiConnector, await this.tree(), this.id);
|
|
593
|
-
logs.on("console", (message) => this.pageEvents.emit("console", message));
|
|
594
|
-
logs.on("pageerror", (error) => this.pageEvents.emit("pageerror", error));
|
|
595
|
-
return logs;
|
|
596
|
-
});
|
|
573
|
+
await this.logging.start();
|
|
597
574
|
}
|
|
598
575
|
/** The newest console and error entries of this page (empty until logging started), oldest first */
|
|
599
576
|
getLogs() {
|
|
600
|
-
return this.
|
|
577
|
+
return this.logging.entries();
|
|
601
578
|
}
|
|
602
579
|
/** Uncaught exceptions of the page since logging started or `clearLogs()` */
|
|
603
580
|
pageErrors() {
|
|
604
|
-
return this.
|
|
581
|
+
return this.logging.errors();
|
|
605
582
|
}
|
|
606
583
|
/** How many entries fell out of the page's log buffer */
|
|
607
584
|
get logsDropped() {
|
|
608
|
-
return this.
|
|
585
|
+
return this.logging.dropped;
|
|
609
586
|
}
|
|
610
587
|
clearLogs() {
|
|
611
|
-
this.
|
|
588
|
+
this.logging.clear();
|
|
612
589
|
}
|
|
613
590
|
/** Resolves once everything the page logged before the call has arrived: events and replies share one ordered connection */
|
|
614
591
|
async syncLogs() {
|
|
@@ -616,10 +593,10 @@ export default class Page {
|
|
|
616
593
|
}
|
|
617
594
|
/** Tells the runner not to fail this test on uncaught page exceptions (config `logs.failOnPageError`) */
|
|
618
595
|
allowPageErrors() {
|
|
619
|
-
this.
|
|
596
|
+
this.logging.allowErrors();
|
|
620
597
|
}
|
|
621
598
|
get pageErrorsAllowed() {
|
|
622
|
-
return this.
|
|
599
|
+
return this.logging.errorsAreAllowed;
|
|
623
600
|
}
|
|
624
601
|
/** Starts watching for dialogs; the browser does this when it opens a page, `page.on("dialog")` when needed */
|
|
625
602
|
startDialogHandling() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BiDiConnector } from "../transport/bidi-connection.js";
|
|
2
|
+
import { Evidence } from "./evidence.js";
|
|
2
3
|
export interface ScreenshotOptions {
|
|
3
4
|
/** Also write the image here (folders are created) */
|
|
4
5
|
path?: string;
|
|
@@ -29,3 +30,8 @@ export declare function takeScreenshot(connector: BiDiConnector, context: string
|
|
|
29
30
|
}): Promise<Buffer>;
|
|
30
31
|
/** Writes `data` to `file`, creating the folders; nothing happens without a path */
|
|
31
32
|
export declare function writeOutput(file: string | undefined, data: Buffer): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* `page.screenshot`: `takeScreenshot`, then, with `options.name`, a copy in the evidence folder (the test's own,
|
|
35
|
+
* or `result/` of the project when the page has none)
|
|
36
|
+
*/
|
|
37
|
+
export declare function screenshotWithEvidence(connector: BiDiConnector, context: string, options: ScreenshotOptions, evidence: Evidence | undefined): Promise<Buffer>;
|
|
@@ -2,6 +2,8 @@ import { mkdir, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { callFunction } from "../script/call-function.js";
|
|
4
4
|
import { ElementHandle } from "../script/element-handle.js";
|
|
5
|
+
import { projectDir } from "../config/config.js";
|
|
6
|
+
import { Evidence } from "./evidence.js";
|
|
5
7
|
const MIME = { png: "image/png", jpeg: "image/jpeg" };
|
|
6
8
|
/** The `format` of a capture command; validates the type/quality combination */
|
|
7
9
|
function imageFormat({ type, quality, }) {
|
|
@@ -57,3 +59,15 @@ export async function writeOutput(file, data) {
|
|
|
57
59
|
await mkdir(path.dirname(file), { recursive: true });
|
|
58
60
|
await writeFile(file, data);
|
|
59
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* `page.screenshot`: `takeScreenshot`, then, with `options.name`, a copy in the evidence folder (the test's own,
|
|
64
|
+
* or `result/` of the project when the page has none)
|
|
65
|
+
*/
|
|
66
|
+
export async function screenshotWithEvidence(connector, context, options, evidence) {
|
|
67
|
+
const image = await takeScreenshot(connector, context, options);
|
|
68
|
+
if (options.name !== undefined) {
|
|
69
|
+
const folder = evidence ?? new Evidence(path.join(projectDir(), "result"));
|
|
70
|
+
await writeOutput(folder.fileFor(options.name, options.type).file, image);
|
|
71
|
+
}
|
|
72
|
+
return image;
|
|
73
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { StorageState } from "../types/use.js";
|
|
2
2
|
import type { CookieInput } from "./browser-context.js";
|
|
3
|
-
/** The state itself, or the JSON file (relative to `baseDir`) that holds it. Throws `use(): what is wrong`. */
|
|
4
|
-
export declare function loadStorageState(source: string | StorageState, baseDir: string): StorageState;
|
|
5
3
|
/** The state's cookies as `context.addCookies()` takes them; `expires` of -1 (or none) is a session cookie */
|
|
6
4
|
export declare function cookiesOf(state: StorageState): CookieInput[];
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { checkStorageStateObject } from "../config/use-options.js";
|
|
4
|
-
/** The state itself, or the JSON file (relative to `baseDir`) that holds it. Throws `use(): what is wrong`. */
|
|
5
|
-
export function loadStorageState(source, baseDir) {
|
|
6
|
-
if (typeof source !== "string")
|
|
7
|
-
return source;
|
|
8
|
-
const file = path.resolve(baseDir, source);
|
|
9
|
-
let state;
|
|
10
|
-
try {
|
|
11
|
-
state = JSON.parse(readFileSync(file, "utf8"));
|
|
12
|
-
}
|
|
13
|
-
catch (err) {
|
|
14
|
-
throw new Error(`use(): storageState file ${JSON.stringify(source)} could not be read: ${err instanceof Error ? err.message : String(err)}`);
|
|
15
|
-
}
|
|
16
|
-
if (typeof state !== "object" || state === null || Array.isArray(state))
|
|
17
|
-
throw new Error(`use(): storageState file ${JSON.stringify(source)} must hold an object`);
|
|
18
|
-
checkStorageStateObject(state);
|
|
19
|
-
return state;
|
|
20
|
-
}
|
|
21
1
|
const SAME_SITE = { Strict: "strict", Lax: "lax", None: "none" };
|
|
22
2
|
/** The state's cookies as `context.addCookies()` takes them; `expires` of -1 (or none) is a session cookie */
|
|
23
3
|
export function cookiesOf(state) {
|