@rstest/browser 0.11.5 → 0.11.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-container/container-static/css/index.43daaf6c93.css +1 -0
- package/dist/browser-container/container-static/js/260.3739fe815c.js +194 -0
- package/dist/browser-container/container-static/js/index.c0f87bfb3e.js +1 -0
- package/dist/browser-container/index.html +1 -1
- package/dist/browserExecutor.d.ts +7 -5
- package/dist/browserRsbuild.d.ts +139 -0
- package/dist/browserV8Coverage.d.ts +15 -0
- package/dist/client/240~1.js +150 -0
- package/dist/{augmentExpect.d.ts → client/client/augmentExpect.d.ts} +1 -1
- package/dist/client/{browserRpc.d.ts → client/browserRpc.d.ts} +1 -1
- package/dist/client/{dispatchTransport.d.ts → client/dispatchTransport.d.ts} +8 -4
- package/dist/client/client/index.d.ts +2 -0
- package/dist/client/client/runIdentity.d.ts +12 -0
- package/dist/client/client/runner.d.ts +4 -0
- package/dist/client/client/snapshot.d.ts +27 -0
- package/dist/client/client/sourceMapSupport.d.ts +36 -0
- package/dist/{browser.js → client/index.js} +3 -102
- package/dist/client/protocol.d.ts +225 -0
- package/dist/client/rpcProtocol.d.ts +138 -0
- package/dist/client/runner.js +675 -0
- package/dist/client/sourceMap/sourceMapLoader.d.ts +25 -0
- package/dist/containerRpc.d.ts +60 -0
- package/dist/dispatchCapabilities.d.ts +1 -2
- package/dist/headedRunRegistry.d.ts +51 -0
- package/dist/headedScheduler.d.ts +58 -0
- package/dist/headlessScheduler.d.ts +38 -0
- package/dist/headlessTransport.d.ts +4 -2
- package/dist/hostController.d.ts +12 -47
- package/dist/hostPayloads.d.ts +24 -0
- package/dist/index.js +2019 -1516
- package/dist/protocol.d.ts +48 -8
- package/dist/providers/index.d.ts +21 -0
- package/dist/providers/playwright/v8Coverage.d.ts +2 -0
- package/dist/rpcProtocol.d.ts +1 -2
- package/dist/schedulerSeam.d.ts +42 -0
- package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
- package/dist/watchRerunPlanner.d.ts +20 -4
- package/dist/watchRuntime.d.ts +21 -0
- package/dist/watchSignals.d.ts +29 -0
- package/package.json +12 -12
- package/dist/33.js +0 -7
- package/dist/browser-container/container-static/css/index.0521ff95b1.css +0 -1
- package/dist/browser-container/container-static/js/506.b2f920fa67.js +0 -194
- package/dist/browser-container/container-static/js/index.d27fd63f5e.js +0 -1
- package/dist/browser.d.ts +0 -2
- package/dist/headlessLatestRerunScheduler.d.ts +0 -18
- package/src/augmentExpect.ts +0 -62
- package/src/browser.ts +0 -3
- package/src/browserExecutor.ts +0 -140
- package/src/browserRpcRegistry.ts +0 -57
- package/src/client/api.ts +0 -213
- package/src/client/browserRpc.ts +0 -86
- package/src/client/dispatchTransport.ts +0 -240
- package/src/client/entry.ts +0 -807
- package/src/client/locator.ts +0 -448
- package/src/client/snapshot.ts +0 -113
- package/src/client/sourceMapSupport.ts +0 -159
- package/src/concurrency.ts +0 -65
- package/src/configValidation.ts +0 -263
- package/src/dispatchCapabilities.ts +0 -182
- package/src/dispatchRouter.ts +0 -82
- package/src/env.d.ts +0 -54
- package/src/headedSerialTaskQueue.ts +0 -23
- package/src/headlessLatestRerunScheduler.ts +0 -76
- package/src/headlessTransport.ts +0 -28
- package/src/hostController.ts +0 -4633
- package/src/index.ts +0 -51
- package/src/manifest.d.ts +0 -41
- package/src/protocol.ts +0 -225
- package/src/providers/index.ts +0 -126
- package/src/providers/playwright/compileLocator.ts +0 -130
- package/src/providers/playwright/dispatchBrowserRpc.ts +0 -372
- package/src/providers/playwright/expectUtils.ts +0 -57
- package/src/providers/playwright/implementation.ts +0 -35
- package/src/providers/playwright/index.ts +0 -1
- package/src/providers/playwright/runtime.ts +0 -159
- package/src/providers/playwright/textMatcher.ts +0 -10
- package/src/rpcProtocol.ts +0 -218
- package/src/runSession.ts +0 -110
- package/src/sessionRegistry.ts +0 -89
- package/src/sourceMap/sourceMapLoader.ts +0 -96
- package/src/viewportPresets.ts +0 -69
- package/src/watchRerunPlanner.ts +0 -77
- /package/dist/{rslib-runtime.js → 612~0.js} +0 -0
- /package/dist/client/{api.d.ts → client/api.d.ts} +0 -0
- /package/dist/client/{locator.d.ts → client/locator.d.ts} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser snapshot environment that proxies file operations to the host
|
|
3
|
+
* via postMessage RPC through the container.
|
|
4
|
+
*/ export declare class BrowserSnapshotEnvironment {
|
|
5
|
+
getVersion(): string;
|
|
6
|
+
getHeader(): string;
|
|
7
|
+
resolveRawPath(_testPath: string, rawPath: string): Promise<string>;
|
|
8
|
+
resolvePath(filepath: string): Promise<string>;
|
|
9
|
+
prepareDirectory(): Promise<void>;
|
|
10
|
+
saveSnapshotFile(filepath: string, snapshot: string): Promise<void>;
|
|
11
|
+
readSnapshotFile(filepath: string): Promise<string | null>;
|
|
12
|
+
removeSnapshotFile(filepath: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Process stack trace for inline snapshots.
|
|
15
|
+
* Maps bundled URLs back to original source file paths.
|
|
16
|
+
*/ processStackTrace(stack: {
|
|
17
|
+
file: string;
|
|
18
|
+
line: number;
|
|
19
|
+
column: number;
|
|
20
|
+
method: string;
|
|
21
|
+
}): {
|
|
22
|
+
file: string;
|
|
23
|
+
line: number;
|
|
24
|
+
column: number;
|
|
25
|
+
method: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get all script URLs currently on the page.
|
|
3
|
+
* Used to detect newly loaded chunk scripts.
|
|
4
|
+
*/ export declare const getScriptUrls: () => Set<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Find the newly added script URL by comparing script sets.
|
|
7
|
+
* Returns the first new script URL found, or null if none.
|
|
8
|
+
*/ export declare const findNewScriptUrl: (beforeUrls: Set<string>, afterUrls: Set<string>) => string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Preload source map for a test file's chunk URL.
|
|
11
|
+
*
|
|
12
|
+
* Always fetches fresh source map to handle file changes during watch mode.
|
|
13
|
+
*
|
|
14
|
+
* @param chunkUrl - The full URL of the chunk JS file
|
|
15
|
+
*/ export declare const preloadTestFileSourceMap: (chunkUrl: string) => Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Preload source map for the runner.js file.
|
|
18
|
+
*
|
|
19
|
+
* This is essential for inline snapshot support because the snapshot code
|
|
20
|
+
* runs in runner.js (which contains @rstest/core/internal/browser-runtime).
|
|
21
|
+
* Without this, stack traces from inline snapshots cannot be mapped back
|
|
22
|
+
* to the original source files.
|
|
23
|
+
*/ export declare const preloadRunnerSourceMap: () => Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Stack frame interface matching @vitest/snapshot's format
|
|
26
|
+
*/ interface StackFrame {
|
|
27
|
+
file: string;
|
|
28
|
+
line: number;
|
|
29
|
+
column: number;
|
|
30
|
+
method?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Map a stack frame from bundled URL to original source file.
|
|
34
|
+
* This is used by BrowserSnapshotEnvironment.processStackTrace
|
|
35
|
+
*/ export declare const mapStackFrame: (frame: StackFrame) => StackFrame;
|
|
36
|
+
export { };
|
|
@@ -1,81 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const getRpcTimeout = ()=>window.__RSTEST_BROWSER_OPTIONS__?.rpcTimeout ?? DEFAULT_RPC_TIMEOUT_MS;
|
|
4
|
-
const pendingRequests = new Map();
|
|
5
|
-
let requestIdCounter = 0;
|
|
6
|
-
let messageListenerInitialized = false;
|
|
7
|
-
const createRequestId = (prefix)=>{
|
|
8
|
-
if ('function' == typeof globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();
|
|
9
|
-
requestIdCounter += 1;
|
|
10
|
-
return `${prefix}-${Date.now().toString(36)}-${requestIdCounter.toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
11
|
-
};
|
|
12
|
-
const isDispatchResponse = (value)=>'object' == typeof value && null !== value && 'requestId' in value && 'string' == typeof value.requestId;
|
|
13
|
-
const settlePendingRequest = (response)=>{
|
|
14
|
-
const pending = pendingRequests.get(response.requestId);
|
|
15
|
-
if (!pending) return;
|
|
16
|
-
pendingRequests.delete(response.requestId);
|
|
17
|
-
if (response.stale) return void pending.reject(new Error(pending.staleMessage));
|
|
18
|
-
if (response.error) return void pending.reject(new Error(response.error));
|
|
19
|
-
pending.resolve(response.result);
|
|
20
|
-
};
|
|
21
|
-
const initMessageListener = ()=>{
|
|
22
|
-
if (messageListenerInitialized) return;
|
|
23
|
-
messageListenerInitialized = true;
|
|
24
|
-
window.addEventListener('message', (event)=>{
|
|
25
|
-
if (event.data?.type === DISPATCH_RESPONSE_TYPE) settlePendingRequest(event.data.payload);
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const unwrapDispatchBridgeResult = (requestId, result, staleMessage)=>{
|
|
29
|
-
if (!isDispatchResponse(result)) throw new Error('Invalid dispatch bridge response payload.');
|
|
30
|
-
if (result.requestId !== requestId) throw new Error(`Mismatched dispatch response id: expected ${requestId}, got ${result.requestId}`);
|
|
31
|
-
if (result.stale) throw new Error(staleMessage);
|
|
32
|
-
if (result.error) throw new Error(result.error);
|
|
33
|
-
return result.result;
|
|
34
|
-
};
|
|
35
|
-
const dispatchRpc = ({ requestId, request, timeoutMs, timeoutMessage, staleMessage })=>{
|
|
36
|
-
if (window.parent === window) {
|
|
37
|
-
const dispatchBridge = window[protocol_DISPATCH_RPC_BRIDGE_NAME];
|
|
38
|
-
if (!dispatchBridge) throw new Error('Dispatch RPC bridge is not available in top-level runner.');
|
|
39
|
-
return new Promise((resolve, reject)=>{
|
|
40
|
-
const timeoutId = setTimeout(()=>{
|
|
41
|
-
reject(new Error(timeoutMessage));
|
|
42
|
-
}, timeoutMs);
|
|
43
|
-
const call = Promise.resolve(dispatchBridge(request)).then((result)=>unwrapDispatchBridgeResult(requestId, result, staleMessage));
|
|
44
|
-
call.then((result)=>{
|
|
45
|
-
clearTimeout(timeoutId);
|
|
46
|
-
resolve(result);
|
|
47
|
-
}).catch((error)=>{
|
|
48
|
-
clearTimeout(timeoutId);
|
|
49
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
initMessageListener();
|
|
54
|
-
return new Promise((resolve, reject)=>{
|
|
55
|
-
const timeoutId = setTimeout(()=>{
|
|
56
|
-
pendingRequests.delete(requestId);
|
|
57
|
-
reject(new Error(timeoutMessage));
|
|
58
|
-
}, timeoutMs);
|
|
59
|
-
pendingRequests.set(requestId, {
|
|
60
|
-
staleMessage,
|
|
61
|
-
resolve: (value)=>{
|
|
62
|
-
clearTimeout(timeoutId);
|
|
63
|
-
resolve(value);
|
|
64
|
-
},
|
|
65
|
-
reject: (error)=>{
|
|
66
|
-
clearTimeout(timeoutId);
|
|
67
|
-
reject(error);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
window.parent.postMessage({
|
|
71
|
-
type: protocol_DISPATCH_MESSAGE_TYPE,
|
|
72
|
-
payload: {
|
|
73
|
-
type: protocol_DISPATCH_RPC_REQUEST_TYPE,
|
|
74
|
-
payload: request
|
|
75
|
-
}
|
|
76
|
-
}, '*');
|
|
77
|
-
});
|
|
78
|
-
};
|
|
1
|
+
import { registerElementExpect } from "@rstest/core/internal/browser-runtime";
|
|
2
|
+
import { createRequestId, DISPATCH_NAMESPACE_BROWSER, dispatchRpc, getRpcTimeout } from "./240~1.js";
|
|
79
3
|
const getUrlSearchParam = (name)=>{
|
|
80
4
|
try {
|
|
81
5
|
const value = new URL(window.location.href).searchParams.get(name);
|
|
@@ -89,11 +13,6 @@ const getCurrentTestPath = ()=>{
|
|
|
89
13
|
if (!testPath) throw new Error("Browser RPC requires testFile in __RSTEST_BROWSER_OPTIONS__. This usually indicates the runner iframe was not configured by the container or URL.");
|
|
90
14
|
return testPath;
|
|
91
15
|
};
|
|
92
|
-
const getCurrentRunId = ()=>{
|
|
93
|
-
const runId = window.__RSTEST_BROWSER_OPTIONS__?.runId ?? getUrlSearchParam('runId');
|
|
94
|
-
if (!runId) throw new Error("Browser RPC requires runId in __RSTEST_BROWSER_OPTIONS__. This usually indicates the runner iframe URL/config is stale or incomplete.");
|
|
95
|
-
return runId;
|
|
96
|
-
};
|
|
97
16
|
const createBrowserDispatchRequest = (requestId, request)=>({
|
|
98
17
|
requestId,
|
|
99
18
|
namespace: DISPATCH_NAMESPACE_BROWSER,
|
|
@@ -110,7 +29,6 @@ const callBrowserRpc = async (payload)=>{
|
|
|
110
29
|
const request = {
|
|
111
30
|
id,
|
|
112
31
|
testPath: getCurrentTestPath(),
|
|
113
|
-
runId: getCurrentRunId(),
|
|
114
32
|
...payload
|
|
115
33
|
};
|
|
116
34
|
const dispatchRequest = createBrowserDispatchRequest(id, request);
|
|
@@ -562,22 +480,5 @@ const api_element = (locator)=>{
|
|
|
562
480
|
if (!isLocator(locator)) throw new TypeError('expect.element() expects a Locator returned from @rstest/browser page.getBy* APIs.');
|
|
563
481
|
return createElementExpect(locator, false);
|
|
564
482
|
};
|
|
565
|
-
|
|
566
|
-
Object.defineProperty(api_element, '__rstestBrowser', {
|
|
567
|
-
value: true,
|
|
568
|
-
configurable: false,
|
|
569
|
-
enumerable: false,
|
|
570
|
-
writable: false
|
|
571
|
-
});
|
|
572
|
-
};
|
|
573
|
-
const installExpectElement = ()=>{
|
|
574
|
-
const api = globalThis.RSTEST_API;
|
|
575
|
-
const target = api?.expect;
|
|
576
|
-
if (!target) throw new Error('RSTEST_API.expect is not registered yet. This usually indicates @rstest/browser was imported too early.');
|
|
577
|
-
if ('function' != typeof target.element || !target.element.__rstestBrowser) {
|
|
578
|
-
markBrowserElement();
|
|
579
|
-
target.element = api_element;
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
installExpectElement();
|
|
483
|
+
registerElementExpect(api_element);
|
|
583
484
|
export { Locator, page, setTestIdAttribute };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { BrowserViewport } from '@rstest/core/internal/browser';
|
|
2
|
+
import type { BrowserRuntimeConfig, TestFileResult, TestInfo, TestResult } from '@rstest/core/internal/browser-runtime';
|
|
3
|
+
import type { SnapshotUpdateState } from '@vitest/snapshot';
|
|
4
|
+
export type { BrowserLocatorIR, BrowserRpcRequest, SnapshotRpcCall, SnapshotRpcMethod, SnapshotRpcMethodArgs, SnapshotRpcRequest } from './rpcProtocol.js';
|
|
5
|
+
export { validateBrowserRpcRequest } from './rpcProtocol.js';
|
|
6
|
+
export declare const DISPATCH_MESSAGE_TYPE = '__rstest_dispatch__';
|
|
7
|
+
export declare const DISPATCH_RESPONSE_TYPE = '__rstest_dispatch_response__';
|
|
8
|
+
export declare const DISPATCH_RPC_BRIDGE_NAME = '__rstest_dispatch_rpc__';
|
|
9
|
+
export declare const DISPATCH_RPC_REQUEST_TYPE = 'dispatch-rpc-request';
|
|
10
|
+
export declare const RSTEST_CONFIG_MESSAGE_TYPE = 'RSTEST_CONFIG';
|
|
11
|
+
export declare const NO_RPC_TIMEOUT = -1;
|
|
12
|
+
export declare const DISPATCH_NAMESPACE_RUNNER = 'runner';
|
|
13
|
+
export declare const DISPATCH_NAMESPACE_BROWSER = 'browser';
|
|
14
|
+
export declare const DISPATCH_NAMESPACE_FILE_CLEANUP = 'file-cleanup';
|
|
15
|
+
export declare const DISPATCH_NAMESPACE_SNAPSHOT = 'snapshot';
|
|
16
|
+
export declare const DISPATCH_METHOD_RPC = 'rpc';
|
|
17
|
+
export type SerializedRuntimeConfig = BrowserRuntimeConfig;
|
|
18
|
+
// `BrowserViewport` is a core config type (`@rstest/core` owns the canonical
|
|
19
|
+
// definition used by `NormalizedBrowserModeConfig`). Re-export it so the host
|
|
20
|
+
// assigns the SAME type across the seam instead of a hand-copied duplicate.
|
|
21
|
+
export type { BrowserViewport };
|
|
22
|
+
export type BrowserProjectRuntime = {
|
|
23
|
+
name: string;
|
|
24
|
+
environmentName: string;
|
|
25
|
+
projectRoot: string;
|
|
26
|
+
runtimeConfig: SerializedRuntimeConfig;
|
|
27
|
+
viewport?: BrowserViewport;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Test file info with associated project name.
|
|
31
|
+
* Used to track which project a test file belongs to.
|
|
32
|
+
*/ export type TestFileInfo = {
|
|
33
|
+
testPath: string;
|
|
34
|
+
projectName: string;
|
|
35
|
+
};
|
|
36
|
+
export type FileCleanupDispatchMethod = 'start' | 'end';
|
|
37
|
+
export type FileCleanupDispatchPayload = {
|
|
38
|
+
projectName: string;
|
|
39
|
+
result?: TestFileResult;
|
|
40
|
+
runId?: string;
|
|
41
|
+
testPath: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The committed test-file set plus its monotonic version. The version is what
|
|
45
|
+
* the container acks once every iframe for that set exists in the DOM, so both
|
|
46
|
+
* halves must travel together — a set without its version cannot be acked.
|
|
47
|
+
*/ export type VersionedTestFileSet = {
|
|
48
|
+
files: TestFileInfo[];
|
|
49
|
+
version: number;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Execution mode for browser tests.
|
|
53
|
+
* - 'run': Execute tests and report results (default)
|
|
54
|
+
* - 'collect': Only collect test metadata without running
|
|
55
|
+
*/ export type BrowserExecutionMode = 'run' | 'collect';
|
|
56
|
+
/**
|
|
57
|
+
* Wire shape of a `log` client message payload. The host receives this and maps
|
|
58
|
+
* it onto core's {@link UserConsoleLog} (notably `level` → `name`); that mapper
|
|
59
|
+
* (`hostController.ts` `handleLog`) annotates its result as `UserConsoleLog`, so
|
|
60
|
+
* the map→core direction is compiler-checked. Owning the wire shape here as one
|
|
61
|
+
* named type keeps the host's input type from drifting away from the producer.
|
|
62
|
+
*/ export type BrowserLogPayload = {
|
|
63
|
+
level: 'log' | 'warn' | 'error' | 'info' | 'debug';
|
|
64
|
+
content: string;
|
|
65
|
+
/**
|
|
66
|
+
* Owning project, resolved by the client from its manifest. The host must
|
|
67
|
+
* not re-derive it from `testPath` — concurrent projects can run the same
|
|
68
|
+
* file, so a path-keyed lookup can attribute the log to the wrong project.
|
|
69
|
+
*/ projectName: string;
|
|
70
|
+
taskId?: string;
|
|
71
|
+
taskName?: string;
|
|
72
|
+
taskParentNames?: string[];
|
|
73
|
+
taskType?: 'file' | 'suite' | 'case';
|
|
74
|
+
testPath: string;
|
|
75
|
+
type: 'stdout' | 'stderr';
|
|
76
|
+
trace?: string;
|
|
77
|
+
};
|
|
78
|
+
export type BrowserHostConfig = {
|
|
79
|
+
rootPath: string;
|
|
80
|
+
projects: BrowserProjectRuntime[];
|
|
81
|
+
snapshot: {
|
|
82
|
+
updateSnapshot: SnapshotUpdateState;
|
|
83
|
+
};
|
|
84
|
+
testFile?: string;
|
|
85
|
+
/**
|
|
86
|
+
* The run identity this document executes under — the runner's SOLE identity
|
|
87
|
+
* source, adopted once at boot and stamped on every outbound message. Headed:
|
|
88
|
+
* the container confers its frame's current lease over the config handshake
|
|
89
|
+
* (so even an HMR full reload boots with the run the host is awaiting NOW).
|
|
90
|
+
* Headless: injected host-side as `${run.token}:${session.id}`. Never
|
|
91
|
+
* derivable from the URL.
|
|
92
|
+
*/ runId?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Base URL for runner (iframe) pages. Container origin; used as a fallback
|
|
95
|
+
* when a project has no entry in `projectRunnerUrls`.
|
|
96
|
+
*/ runnerUrl?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Per-project runner origin base URLs, keyed by project name. Each browser
|
|
99
|
+
* project runs on its own dev server, so the container must load each test
|
|
100
|
+
* file's iframe from that project's own origin.
|
|
101
|
+
*/ projectRunnerUrls?: Record<string, string>;
|
|
102
|
+
/**
|
|
103
|
+
* WebSocket port for container RPC.
|
|
104
|
+
*/ wsPort?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Execution mode. Defaults to 'run'.
|
|
107
|
+
*/ mode?: BrowserExecutionMode;
|
|
108
|
+
/**
|
|
109
|
+
* Debug mode. When true, enables verbose logging in browser.
|
|
110
|
+
*/ debug?: boolean;
|
|
111
|
+
/** Timeout for RPC operations in milliseconds; negative values disable it. */ rpcTimeout?: number;
|
|
112
|
+
};
|
|
113
|
+
export declare const RSTEST_BROWSER_CACHE_CLEANERS_KEY = '@rstest/browser/cache-cleaners';
|
|
114
|
+
/**
|
|
115
|
+
* The wrapper every runner document posts over `postMessage` / the headless
|
|
116
|
+
* bridge. Identity rides BESIDE the payload, never inside it: `message`
|
|
117
|
+
* payloads reach core reporting (`RunnerEventSink`, `BlobReporter`) as-is, so a
|
|
118
|
+
* transport identity spread into them would leak a nondeterministic UUID into
|
|
119
|
+
* reporter output. `runId` is the identity the document was granted at boot
|
|
120
|
+
* (headed: the container's config handshake; headless: the injected inline
|
|
121
|
+
* options) — never re-derived from the URL or the frame. Absent only for a
|
|
122
|
+
* document that was never granted one; the headed host drops such messages.
|
|
123
|
+
*/ export type RunnerEnvelope = {
|
|
124
|
+
runId?: string;
|
|
125
|
+
message: BrowserClientMessage;
|
|
126
|
+
};
|
|
127
|
+
export type BrowserClientMessage = {
|
|
128
|
+
type: 'ready';
|
|
129
|
+
} | {
|
|
130
|
+
type: 'file-start';
|
|
131
|
+
payload: {
|
|
132
|
+
testPath: string;
|
|
133
|
+
projectName: string;
|
|
134
|
+
};
|
|
135
|
+
} | {
|
|
136
|
+
type: 'case-result';
|
|
137
|
+
payload: TestResult;
|
|
138
|
+
} | {
|
|
139
|
+
type: 'file-complete';
|
|
140
|
+
payload: TestFileResult;
|
|
141
|
+
} | {
|
|
142
|
+
type: 'log';
|
|
143
|
+
payload: BrowserLogPayload;
|
|
144
|
+
} | {
|
|
145
|
+
type: 'fatal';
|
|
146
|
+
payload: {
|
|
147
|
+
message: string;
|
|
148
|
+
stack?: string;
|
|
149
|
+
};
|
|
150
|
+
} | {
|
|
151
|
+
type: 'complete';
|
|
152
|
+
} | {
|
|
153
|
+
type: 'collect-result';
|
|
154
|
+
payload: {
|
|
155
|
+
testPath: string;
|
|
156
|
+
project: string;
|
|
157
|
+
tests: TestInfo[];
|
|
158
|
+
};
|
|
159
|
+
} | {
|
|
160
|
+
type: 'collect-complete';
|
|
161
|
+
} | {
|
|
162
|
+
type: typeof DISPATCH_RPC_REQUEST_TYPE;
|
|
163
|
+
payload: BrowserDispatchRequest;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Lifecycle methods the runner emits via `dispatchRunnerLifecycle()` as
|
|
167
|
+
* dispatch-rpc-requests on the `runner` namespace (as opposed to the
|
|
168
|
+
* {@link BrowserClientMessage} types it `send()`s). The runner client imports
|
|
169
|
+
* this instead of redeclaring the list, so the emit site cannot drift from the
|
|
170
|
+
* host router.
|
|
171
|
+
*/ export type RunnerLifecycleMethod = 'file-ready' | 'suite-start' | 'suite-result' | 'case-start';
|
|
172
|
+
/**
|
|
173
|
+
* {@link BrowserClientMessage} types that are forwarded to the `runner`
|
|
174
|
+
* namespace (by message `type`) rather than handled at the transport layer.
|
|
175
|
+
* `Extract` keeps this a checked subset of the message union. `ready` and
|
|
176
|
+
* `complete` are deliberately absent: they still arrive, but their only job
|
|
177
|
+
* is done at the dispatch gate and the router ignores them silently.
|
|
178
|
+
*/ type RunnerMessageMethod = Extract<BrowserClientMessage['type'], 'file-start' | 'case-result' | 'file-complete' | 'log' | 'fatal'>;
|
|
179
|
+
/**
|
|
180
|
+
* Single source of truth for every method handled by the `runner` dispatch
|
|
181
|
+
* namespace. The host handler table is keyed by this union (a missing key is a
|
|
182
|
+
* compile error), so adding a runner method here forces a matching handler and
|
|
183
|
+
* cannot silently no-op at runtime.
|
|
184
|
+
*/ export type RunnerDispatchMethod = RunnerLifecycleMethod | RunnerMessageMethod;
|
|
185
|
+
/**
|
|
186
|
+
* Transport-agnostic envelope used by host routing.
|
|
187
|
+
* `namespace + method + args + target` describes an operation independent of
|
|
188
|
+
* the underlying message channel, and `runToken` provides run-level isolation.
|
|
189
|
+
*/ export type BrowserDispatchRequest = {
|
|
190
|
+
requestId: string;
|
|
191
|
+
// Optional so headed/container paths can adopt the same envelope even when
|
|
192
|
+
// run-token isolation is only enforced in headless scheduling today.
|
|
193
|
+
runToken?: number;
|
|
194
|
+
/**
|
|
195
|
+
* Headed run identity, stamped by the runner's dispatch transport from the
|
|
196
|
+
* identity its document adopted at boot. The headed host accepts a request
|
|
197
|
+
* iff this names a live run; headless keeps using the host-injected
|
|
198
|
+
* `runToken` instead (`runToken` is the CYCLE generation, `runId` is the
|
|
199
|
+
* RUN identity — they are not interchangeable).
|
|
200
|
+
*/ runId?: string;
|
|
201
|
+
namespace: string;
|
|
202
|
+
method: string;
|
|
203
|
+
args?: unknown;
|
|
204
|
+
// Routing reads `namespace`, `method`, `runToken`, and `target.sessionId`
|
|
205
|
+
// (see dispatchRouter.ts / dispatchBrowserRpcRequest). `target.testFile` and
|
|
206
|
+
// `target.projectName` are carried for diagnostics / forward-compatibility and
|
|
207
|
+
// are NOT consulted for routing today — adding a routing-relevant field here
|
|
208
|
+
// means wiring a reader on the host side, which structural typing won't force.
|
|
209
|
+
target?: {
|
|
210
|
+
testFile?: string;
|
|
211
|
+
sessionId?: string;
|
|
212
|
+
projectName?: string;
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Dispatch response envelope.
|
|
217
|
+
* `stale: true` signals a safe drop from an older run generation, not a failure.
|
|
218
|
+
*/ export type BrowserDispatchResponse = {
|
|
219
|
+
requestId: string;
|
|
220
|
+
runToken?: number;
|
|
221
|
+
result?: unknown;
|
|
222
|
+
error?: string;
|
|
223
|
+
stale?: boolean;
|
|
224
|
+
};
|
|
225
|
+
export type BrowserDispatchHandler = (request: BrowserDispatchRequest) => Promise<unknown>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export type BrowserLocatorText = {
|
|
2
|
+
type: 'string';
|
|
3
|
+
value: string;
|
|
4
|
+
} | {
|
|
5
|
+
type: 'regexp';
|
|
6
|
+
source: string;
|
|
7
|
+
flags?: string;
|
|
8
|
+
};
|
|
9
|
+
export type BrowserLocatorStep = {
|
|
10
|
+
type: 'getByRole';
|
|
11
|
+
role: string;
|
|
12
|
+
options?: {
|
|
13
|
+
name?: BrowserLocatorText;
|
|
14
|
+
exact?: boolean;
|
|
15
|
+
checked?: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
expanded?: boolean;
|
|
18
|
+
selected?: boolean;
|
|
19
|
+
pressed?: boolean;
|
|
20
|
+
includeHidden?: boolean;
|
|
21
|
+
level?: number;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
type: 'locator';
|
|
25
|
+
selector: string;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'getByText';
|
|
28
|
+
text: BrowserLocatorText;
|
|
29
|
+
options?: {
|
|
30
|
+
exact?: boolean;
|
|
31
|
+
};
|
|
32
|
+
} | {
|
|
33
|
+
type: 'getByLabel';
|
|
34
|
+
text: BrowserLocatorText;
|
|
35
|
+
options?: {
|
|
36
|
+
exact?: boolean;
|
|
37
|
+
};
|
|
38
|
+
} | {
|
|
39
|
+
type: 'getByPlaceholder';
|
|
40
|
+
text: BrowserLocatorText;
|
|
41
|
+
options?: {
|
|
42
|
+
exact?: boolean;
|
|
43
|
+
};
|
|
44
|
+
} | {
|
|
45
|
+
type: 'getByAltText';
|
|
46
|
+
text: BrowserLocatorText;
|
|
47
|
+
options?: {
|
|
48
|
+
exact?: boolean;
|
|
49
|
+
};
|
|
50
|
+
} | {
|
|
51
|
+
type: 'getByTitle';
|
|
52
|
+
text: BrowserLocatorText;
|
|
53
|
+
options?: {
|
|
54
|
+
exact?: boolean;
|
|
55
|
+
};
|
|
56
|
+
} | {
|
|
57
|
+
type: 'getByTestId';
|
|
58
|
+
text: BrowserLocatorText;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'filter';
|
|
61
|
+
options: {
|
|
62
|
+
hasText?: BrowserLocatorText;
|
|
63
|
+
hasNotText?: BrowserLocatorText;
|
|
64
|
+
has?: BrowserLocatorIR;
|
|
65
|
+
hasNot?: BrowserLocatorIR;
|
|
66
|
+
};
|
|
67
|
+
} | {
|
|
68
|
+
type: 'and';
|
|
69
|
+
locator: BrowserLocatorIR;
|
|
70
|
+
} | {
|
|
71
|
+
type: 'or';
|
|
72
|
+
locator: BrowserLocatorIR;
|
|
73
|
+
} | {
|
|
74
|
+
type: 'nth';
|
|
75
|
+
index: number;
|
|
76
|
+
} | {
|
|
77
|
+
type: 'first';
|
|
78
|
+
} | {
|
|
79
|
+
type: 'last';
|
|
80
|
+
};
|
|
81
|
+
export type BrowserLocatorIR = {
|
|
82
|
+
steps: BrowserLocatorStep[];
|
|
83
|
+
};
|
|
84
|
+
export type BrowserRpcRequest = {
|
|
85
|
+
id: string;
|
|
86
|
+
/** Absolute test file path for locating runner iframe */ testPath: string;
|
|
87
|
+
kind: 'locator' | 'expect' | 'config';
|
|
88
|
+
locator: BrowserLocatorIR;
|
|
89
|
+
method: string;
|
|
90
|
+
args: unknown[];
|
|
91
|
+
/**
|
|
92
|
+
* Negation for expect matchers (equivalent to Playwright expect(...).not).
|
|
93
|
+
* Only meaningful for kind === 'expect'.
|
|
94
|
+
*/ isNot?: boolean;
|
|
95
|
+
/** Optional assertion timeout override (ms). Falls back to the host-provided assertion timeout. */ timeout?: number;
|
|
96
|
+
};
|
|
97
|
+
export declare const validateBrowserRpcRequest: (payload: unknown) => BrowserRpcRequest;
|
|
98
|
+
/**
|
|
99
|
+
* Single source of truth for snapshot RPC methods and their argument shapes.
|
|
100
|
+
* The request union, the client sender, both host-side mappers, and every
|
|
101
|
+
* exhaustiveness check derive from this map — adding or renaming a method here
|
|
102
|
+
* forces a compile error at every site that has not been updated.
|
|
103
|
+
*/ export type SnapshotRpcMethodArgs = {
|
|
104
|
+
resolveSnapshotPath: {
|
|
105
|
+
testPath: string;
|
|
106
|
+
};
|
|
107
|
+
readSnapshotFile: {
|
|
108
|
+
filepath: string;
|
|
109
|
+
};
|
|
110
|
+
saveSnapshotFile: {
|
|
111
|
+
filepath: string;
|
|
112
|
+
content: string;
|
|
113
|
+
};
|
|
114
|
+
removeSnapshotFile: {
|
|
115
|
+
filepath: string;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
export type SnapshotRpcMethod = keyof SnapshotRpcMethodArgs;
|
|
119
|
+
/**
|
|
120
|
+
* Snapshot RPC request from runner iframe.
|
|
121
|
+
* The container will forward these to the host via WebSocket RPC.
|
|
122
|
+
*/ export type SnapshotRpcRequest = {
|
|
123
|
+
[M in SnapshotRpcMethod]: {
|
|
124
|
+
id: string;
|
|
125
|
+
method: M;
|
|
126
|
+
args: SnapshotRpcMethodArgs[M];
|
|
127
|
+
};
|
|
128
|
+
}[SnapshotRpcMethod];
|
|
129
|
+
/**
|
|
130
|
+
* Client-side snapshot RPC call (request without the transport `id`).
|
|
131
|
+
* Distributive over {@link SnapshotRpcMethod} so `method` and `args` stay paired
|
|
132
|
+
* at the call site — a mismatched pair fails to compile.
|
|
133
|
+
*/ export type SnapshotRpcCall = {
|
|
134
|
+
[M in SnapshotRpcMethod]: {
|
|
135
|
+
method: M;
|
|
136
|
+
args: SnapshotRpcMethodArgs[M];
|
|
137
|
+
};
|
|
138
|
+
}[SnapshotRpcMethod];
|