@rstest/browser 0.11.6 → 0.11.8
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/browserRsbuild.d.ts +24 -4
- 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 +27 -19
- package/dist/headedRunRegistry.d.ts +51 -0
- package/dist/headedScheduler.d.ts +10 -10
- package/dist/headlessScheduler.d.ts +5 -4
- package/dist/headlessTransport.d.ts +4 -2
- package/dist/hostPayloads.d.ts +1 -7
- package/dist/index.js +840 -330
- 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 +5 -0
- package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
- package/dist/watchRerunPlanner.d.ts +20 -9
- package/dist/watchSignals.d.ts +8 -1
- package/package.json +11 -11
- 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/683.4f821ce8f1.js +0 -194
- package/dist/browser-container/container-static/js/index.568aa7cb35.js +0 -1
- package/dist/browser.d.ts +0 -2
- package/src/augmentExpect.ts +0 -62
- package/src/browser.ts +0 -3
- package/src/browserExecutor.ts +0 -222
- package/src/browserRpcRegistry.ts +0 -57
- package/src/browserRsbuild.ts +0 -1927
- 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/containerRpc.ts +0 -206
- package/src/dispatchCapabilities.ts +0 -177
- package/src/dispatchRouter.ts +0 -82
- package/src/env.d.ts +0 -54
- package/src/headedScheduler.ts +0 -664
- package/src/headedSerialTaskQueue.ts +0 -23
- package/src/headlessScheduler.ts +0 -566
- package/src/headlessTransport.ts +0 -28
- package/src/hostController.ts +0 -1365
- package/src/hostPayloads.ts +0 -62
- 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/schedulerSeam.ts +0 -49
- package/src/sessionRegistry.ts +0 -89
- package/src/sourceMap/sourceMapLoader.ts +0 -96
- package/src/viewportPresets.ts +0 -69
- package/src/watchRerunPlanner.ts +0 -88
- package/src/watchRuntime.ts +0 -83
- package/src/watchSignals.ts +0 -93
- /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
package/src/hostPayloads.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Reporter, TestFileResult } from '@rstest/core/internal/browser';
|
|
2
|
-
import type { BrowserLogPayload } from './protocol';
|
|
3
|
-
|
|
4
|
-
/** Payload for test file start event */
|
|
5
|
-
export type TestFileStartPayload = {
|
|
6
|
-
testPath: string;
|
|
7
|
-
projectName: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/** Payload for log event — single-sourced from the wire protocol. */
|
|
11
|
-
export type LogPayload = BrowserLogPayload;
|
|
12
|
-
|
|
13
|
-
/** Payload for fatal error event */
|
|
14
|
-
export type FatalPayload = {
|
|
15
|
-
message: string;
|
|
16
|
-
stack?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type ReporterHookArg<THook extends keyof Reporter> =
|
|
20
|
-
NonNullable<Reporter[THook]> extends (...args: infer TArgs) => unknown
|
|
21
|
-
? TArgs[0]
|
|
22
|
-
: never;
|
|
23
|
-
|
|
24
|
-
export type TestFileReadyPayload = ReporterHookArg<'onTestFileReady'>;
|
|
25
|
-
export type TestSuiteStartPayload = ReporterHookArg<'onTestSuiteStart'>;
|
|
26
|
-
export type TestSuiteResultPayload = ReporterHookArg<'onTestSuiteResult'>;
|
|
27
|
-
export type TestCaseStartPayload = ReporterHookArg<'onTestCaseStart'>;
|
|
28
|
-
export type ReloadTestFileAck = {
|
|
29
|
-
runId: string;
|
|
30
|
-
};
|
|
31
|
-
export type HeadedTestFileCompletePayload = TestFileResult & {
|
|
32
|
-
runId?: string;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type DeferredPromise<T> = {
|
|
36
|
-
promise: Promise<T>;
|
|
37
|
-
resolve: (value: T | PromiseLike<T>) => void;
|
|
38
|
-
reject: (reason?: unknown) => void;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const getFileTaskId = (testPath: string): string => {
|
|
42
|
-
return `file:${testPath}`;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const toError = (error: unknown): Error => {
|
|
46
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const createDeferredPromise = <T>(): DeferredPromise<T> => {
|
|
50
|
-
let resolve!: DeferredPromise<T>['resolve'];
|
|
51
|
-
let reject!: DeferredPromise<T>['reject'];
|
|
52
|
-
const promise = new Promise<T>((res, rej) => {
|
|
53
|
-
resolve = res;
|
|
54
|
-
reject = rej;
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
promise,
|
|
59
|
-
resolve,
|
|
60
|
-
reject,
|
|
61
|
-
};
|
|
62
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
BrowserHostModule,
|
|
3
|
-
BrowserTestRunOptions,
|
|
4
|
-
BrowserTestRunResult,
|
|
5
|
-
ListBrowserTestsOptions,
|
|
6
|
-
RstestContext,
|
|
7
|
-
} from '@rstest/core/internal/browser';
|
|
8
|
-
import { createBrowserExecutor } from './browserExecutor';
|
|
9
|
-
import { validateBrowserConfig } from './configValidation';
|
|
10
|
-
import {
|
|
11
|
-
type ListBrowserTestsResult,
|
|
12
|
-
listBrowserTests as listBrowserTestsImpl,
|
|
13
|
-
runBrowserController,
|
|
14
|
-
} from './hostController';
|
|
15
|
-
|
|
16
|
-
export { createBrowserExecutor, validateBrowserConfig };
|
|
17
|
-
|
|
18
|
-
export async function runBrowserTests(
|
|
19
|
-
context: RstestContext,
|
|
20
|
-
options?: BrowserTestRunOptions,
|
|
21
|
-
): Promise<BrowserTestRunResult | void> {
|
|
22
|
-
return runBrowserController(context, options);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function listBrowserTests(
|
|
26
|
-
context: RstestContext,
|
|
27
|
-
options?: ListBrowserTestsOptions,
|
|
28
|
-
): Promise<ListBrowserTestsResult> {
|
|
29
|
-
// Forward `options` (e.g. `shardedEntries`) so `rstest list --shard` lists
|
|
30
|
-
// only the current shard's browser test files, matching the run path.
|
|
31
|
-
return listBrowserTestsImpl(context, options);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Compile-time guard: ensure the public host exports satisfy the core-owned
|
|
36
|
-
* {@link BrowserHostModule} contract (`listBrowserTests` stays a plain public
|
|
37
|
-
* export — core lists through `createBrowserExecutor(...).collect()`). This
|
|
38
|
-
* catches drift such as a dropped `options` argument at the load boundary.
|
|
39
|
-
* No runtime side effect.
|
|
40
|
-
*/
|
|
41
|
-
void ({
|
|
42
|
-
validateBrowserConfig,
|
|
43
|
-
createBrowserExecutor,
|
|
44
|
-
runBrowserTests,
|
|
45
|
-
} satisfies BrowserHostModule);
|
|
46
|
-
|
|
47
|
-
export type {
|
|
48
|
-
BrowserTestRunOptions,
|
|
49
|
-
BrowserTestRunResult,
|
|
50
|
-
ListBrowserTestsResult,
|
|
51
|
-
};
|
package/src/manifest.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
declare module '@rstest/browser-manifest' {
|
|
2
|
-
/** Project configuration from manifest */
|
|
3
|
-
export type ManifestProjectConfig = {
|
|
4
|
-
name: string;
|
|
5
|
-
environmentName: string;
|
|
6
|
-
projectRoot: string;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
/** Test context for a project */
|
|
10
|
-
export type ManifestTestContext = {
|
|
11
|
-
getTestKeys: () => string[];
|
|
12
|
-
loadTest: (key: string) => Promise<unknown>;
|
|
13
|
-
projectRoot: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/** All projects configuration (multi-project support) */
|
|
17
|
-
export const projects: ManifestProjectConfig[];
|
|
18
|
-
|
|
19
|
-
/** Setup loaders for each project, keyed by project name */
|
|
20
|
-
export const projectSetupLoaders: Record<
|
|
21
|
-
string,
|
|
22
|
-
Array<() => Promise<unknown>>
|
|
23
|
-
>;
|
|
24
|
-
|
|
25
|
-
/** Test contexts for each project, keyed by project name */
|
|
26
|
-
export const projectTestContexts: Record<string, ManifestTestContext>;
|
|
27
|
-
|
|
28
|
-
// Backward compatibility exports (use first project as default)
|
|
29
|
-
|
|
30
|
-
/** @deprecated Use `projects[0]` instead */
|
|
31
|
-
export const projectConfig: ManifestProjectConfig;
|
|
32
|
-
|
|
33
|
-
/** @deprecated Use `projectSetupLoaders[projectName]` instead */
|
|
34
|
-
export const setupLoaders: Array<() => Promise<unknown>>;
|
|
35
|
-
|
|
36
|
-
/** @deprecated Use `projectTestContexts[projectName].getTestKeys()` instead */
|
|
37
|
-
export function getTestKeys(): string[];
|
|
38
|
-
|
|
39
|
-
/** @deprecated Use `projectTestContexts[projectName].loadTest(key)` instead */
|
|
40
|
-
export function loadTest(key: string): Promise<unknown>;
|
|
41
|
-
}
|
package/src/protocol.ts
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import type { BrowserViewport } from '@rstest/core/internal/browser';
|
|
2
|
-
import type {
|
|
3
|
-
BrowserRuntimeConfig,
|
|
4
|
-
TestFileResult,
|
|
5
|
-
TestInfo,
|
|
6
|
-
TestResult,
|
|
7
|
-
} from '@rstest/core/internal/browser-runtime';
|
|
8
|
-
import type { SnapshotUpdateState } from '@vitest/snapshot';
|
|
9
|
-
|
|
10
|
-
export type {
|
|
11
|
-
BrowserLocatorIR,
|
|
12
|
-
BrowserRpcRequest,
|
|
13
|
-
SnapshotRpcCall,
|
|
14
|
-
SnapshotRpcMethod,
|
|
15
|
-
SnapshotRpcMethodArgs,
|
|
16
|
-
SnapshotRpcRequest,
|
|
17
|
-
} from './rpcProtocol';
|
|
18
|
-
export { validateBrowserRpcRequest } from './rpcProtocol';
|
|
19
|
-
|
|
20
|
-
export const DISPATCH_MESSAGE_TYPE = '__rstest_dispatch__';
|
|
21
|
-
export const DISPATCH_RESPONSE_TYPE = '__rstest_dispatch_response__';
|
|
22
|
-
export const DISPATCH_RPC_BRIDGE_NAME = '__rstest_dispatch_rpc__';
|
|
23
|
-
export const DISPATCH_RPC_REQUEST_TYPE = 'dispatch-rpc-request';
|
|
24
|
-
export const RSTEST_CONFIG_MESSAGE_TYPE = 'RSTEST_CONFIG';
|
|
25
|
-
|
|
26
|
-
export const DISPATCH_NAMESPACE_RUNNER = 'runner';
|
|
27
|
-
export const DISPATCH_NAMESPACE_BROWSER = 'browser';
|
|
28
|
-
export const DISPATCH_NAMESPACE_SNAPSHOT = 'snapshot';
|
|
29
|
-
export const DISPATCH_METHOD_RPC = 'rpc';
|
|
30
|
-
|
|
31
|
-
export type SerializedRuntimeConfig = BrowserRuntimeConfig;
|
|
32
|
-
|
|
33
|
-
// `BrowserViewport` is a core config type (`@rstest/core` owns the canonical
|
|
34
|
-
// definition used by `NormalizedBrowserModeConfig`). Re-export it so the host
|
|
35
|
-
// assigns the SAME type across the seam instead of a hand-copied duplicate.
|
|
36
|
-
export type { BrowserViewport };
|
|
37
|
-
|
|
38
|
-
export type BrowserProjectRuntime = {
|
|
39
|
-
name: string;
|
|
40
|
-
environmentName: string;
|
|
41
|
-
projectRoot: string;
|
|
42
|
-
runtimeConfig: SerializedRuntimeConfig;
|
|
43
|
-
viewport?: BrowserViewport;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Test file info with associated project name.
|
|
48
|
-
* Used to track which project a test file belongs to.
|
|
49
|
-
*/
|
|
50
|
-
export type TestFileInfo = {
|
|
51
|
-
testPath: string;
|
|
52
|
-
projectName: string;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Execution mode for browser tests.
|
|
57
|
-
* - 'run': Execute tests and report results (default)
|
|
58
|
-
* - 'collect': Only collect test metadata without running
|
|
59
|
-
*/
|
|
60
|
-
export type BrowserExecutionMode = 'run' | 'collect';
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Wire shape of a `log` client message payload. The host receives this and maps
|
|
64
|
-
* it onto core's {@link UserConsoleLog} (notably `level` → `name`); that mapper
|
|
65
|
-
* (`hostController.ts` `handleLog`) annotates its result as `UserConsoleLog`, so
|
|
66
|
-
* the map→core direction is compiler-checked. Owning the wire shape here as one
|
|
67
|
-
* named type keeps the host's input type from drifting away from the producer.
|
|
68
|
-
*/
|
|
69
|
-
export type BrowserLogPayload = {
|
|
70
|
-
level: 'log' | 'warn' | 'error' | 'info' | 'debug';
|
|
71
|
-
content: string;
|
|
72
|
-
/**
|
|
73
|
-
* Owning project, resolved by the client from its manifest. The host must
|
|
74
|
-
* not re-derive it from `testPath` — concurrent projects can run the same
|
|
75
|
-
* file, so a path-keyed lookup can attribute the log to the wrong project.
|
|
76
|
-
*/
|
|
77
|
-
projectName: string;
|
|
78
|
-
taskId?: string;
|
|
79
|
-
taskName?: string;
|
|
80
|
-
taskParentNames?: string[];
|
|
81
|
-
taskType?: 'file' | 'suite' | 'case';
|
|
82
|
-
testPath: string;
|
|
83
|
-
type: 'stdout' | 'stderr';
|
|
84
|
-
trace?: string;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
export type BrowserHostConfig = {
|
|
88
|
-
rootPath: string;
|
|
89
|
-
projects: BrowserProjectRuntime[];
|
|
90
|
-
snapshot: {
|
|
91
|
-
updateSnapshot: SnapshotUpdateState;
|
|
92
|
-
};
|
|
93
|
-
testFile?: string; // Optional: if provided, only run this specific test file
|
|
94
|
-
/**
|
|
95
|
-
* Per-run identifier assigned by the container.
|
|
96
|
-
* Used by browser RPC calls to prevent stale requests from previous reruns.
|
|
97
|
-
*/
|
|
98
|
-
runId?: string;
|
|
99
|
-
/**
|
|
100
|
-
* Base URL for runner (iframe) pages. Container origin; used as a fallback
|
|
101
|
-
* when a project has no entry in `projectRunnerUrls`.
|
|
102
|
-
*/
|
|
103
|
-
runnerUrl?: string;
|
|
104
|
-
/**
|
|
105
|
-
* Per-project runner origin base URLs, keyed by project name. Each browser
|
|
106
|
-
* project runs on its own dev server, so the container must load each test
|
|
107
|
-
* file's iframe from that project's own origin.
|
|
108
|
-
*/
|
|
109
|
-
projectRunnerUrls?: Record<string, string>;
|
|
110
|
-
/**
|
|
111
|
-
* WebSocket port for container RPC.
|
|
112
|
-
*/
|
|
113
|
-
wsPort?: number;
|
|
114
|
-
/**
|
|
115
|
-
* Execution mode. Defaults to 'run'.
|
|
116
|
-
*/
|
|
117
|
-
mode?: BrowserExecutionMode;
|
|
118
|
-
/**
|
|
119
|
-
* Debug mode. When true, enables verbose logging in browser.
|
|
120
|
-
*/
|
|
121
|
-
debug?: boolean;
|
|
122
|
-
/**
|
|
123
|
-
* Timeout for RPC operations in milliseconds (e.g., snapshot file operations).
|
|
124
|
-
* Derived from testTimeout config.
|
|
125
|
-
*/
|
|
126
|
-
rpcTimeout?: number;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export type BrowserClientMessage =
|
|
130
|
-
| { type: 'ready' }
|
|
131
|
-
| {
|
|
132
|
-
type: 'file-start';
|
|
133
|
-
payload: { testPath: string; projectName: string };
|
|
134
|
-
}
|
|
135
|
-
| { type: 'case-result'; payload: TestResult }
|
|
136
|
-
| { type: 'file-complete'; payload: TestFileResult }
|
|
137
|
-
| { type: 'log'; payload: BrowserLogPayload }
|
|
138
|
-
| {
|
|
139
|
-
type: 'fatal';
|
|
140
|
-
payload: { message: string; stack?: string };
|
|
141
|
-
}
|
|
142
|
-
| { type: 'complete' }
|
|
143
|
-
// Collect mode messages
|
|
144
|
-
| {
|
|
145
|
-
type: 'collect-result';
|
|
146
|
-
payload: { testPath: string; project: string; tests: TestInfo[] };
|
|
147
|
-
}
|
|
148
|
-
| { type: 'collect-complete' }
|
|
149
|
-
// Unified RPC envelope for all runner -> container/host capability calls.
|
|
150
|
-
// Snapshot already uses this path via namespace "snapshot". Future PR #948
|
|
151
|
-
// capabilities can add new namespaces instead of adding new message types.
|
|
152
|
-
| {
|
|
153
|
-
type: typeof DISPATCH_RPC_REQUEST_TYPE;
|
|
154
|
-
payload: BrowserDispatchRequest;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Lifecycle methods the runner emits via `dispatchRunnerLifecycle()` as
|
|
159
|
-
* dispatch-rpc-requests on the `runner` namespace (as opposed to the
|
|
160
|
-
* {@link BrowserClientMessage} types it `send()`s). The runner client imports
|
|
161
|
-
* this instead of redeclaring the list, so the emit site cannot drift from the
|
|
162
|
-
* host router.
|
|
163
|
-
*/
|
|
164
|
-
export type RunnerLifecycleMethod =
|
|
165
|
-
'file-ready' | 'suite-start' | 'suite-result' | 'case-start';
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* {@link BrowserClientMessage} types that are forwarded to the `runner`
|
|
169
|
-
* namespace (by message `type`) rather than handled at the transport layer.
|
|
170
|
-
* `Extract` keeps this a checked subset of the message union — renaming a
|
|
171
|
-
* message type drops it here, surfacing as a missing handler downstream.
|
|
172
|
-
*/
|
|
173
|
-
type RunnerMessageMethod = Extract<
|
|
174
|
-
BrowserClientMessage['type'],
|
|
175
|
-
'file-start' | 'case-result' | 'file-complete' | 'log' | 'fatal'
|
|
176
|
-
>;
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Single source of truth for every method handled by the `runner` dispatch
|
|
180
|
-
* namespace. The host handler table is keyed by this union (a missing key is a
|
|
181
|
-
* compile error), so adding a runner method here forces a matching handler and
|
|
182
|
-
* cannot silently no-op at runtime.
|
|
183
|
-
*/
|
|
184
|
-
export type RunnerDispatchMethod = RunnerLifecycleMethod | RunnerMessageMethod;
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Transport-agnostic envelope used by host routing.
|
|
188
|
-
* `namespace + method + args + target` describes an operation independent of
|
|
189
|
-
* the underlying message channel, and `runToken` provides run-level isolation.
|
|
190
|
-
*/
|
|
191
|
-
export type BrowserDispatchRequest = {
|
|
192
|
-
requestId: string;
|
|
193
|
-
// Optional so headed/container paths can adopt the same envelope even when
|
|
194
|
-
// run-token isolation is only enforced in headless scheduling today.
|
|
195
|
-
runToken?: number;
|
|
196
|
-
namespace: string;
|
|
197
|
-
method: string;
|
|
198
|
-
args?: unknown;
|
|
199
|
-
// Routing reads `namespace`, `method`, `runToken`, and `target.sessionId`
|
|
200
|
-
// (see dispatchRouter.ts / dispatchBrowserRpcRequest). `target.testFile` and
|
|
201
|
-
// `target.projectName` are carried for diagnostics / forward-compatibility and
|
|
202
|
-
// are NOT consulted for routing today — adding a routing-relevant field here
|
|
203
|
-
// means wiring a reader on the host side, which structural typing won't force.
|
|
204
|
-
target?: {
|
|
205
|
-
testFile?: string;
|
|
206
|
-
sessionId?: string;
|
|
207
|
-
projectName?: string;
|
|
208
|
-
};
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Dispatch response envelope.
|
|
213
|
-
* `stale: true` signals a safe drop from an older run generation, not a failure.
|
|
214
|
-
*/
|
|
215
|
-
export type BrowserDispatchResponse = {
|
|
216
|
-
requestId: string;
|
|
217
|
-
runToken?: number;
|
|
218
|
-
result?: unknown;
|
|
219
|
-
error?: string;
|
|
220
|
-
stale?: boolean;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
export type BrowserDispatchHandler = (
|
|
224
|
-
request: BrowserDispatchRequest,
|
|
225
|
-
) => Promise<unknown>;
|
package/src/providers/index.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import type { BrowserProvider } from '@rstest/core/internal/browser';
|
|
2
|
-
import type { BrowserRpcRequest } from '../rpcProtocol';
|
|
3
|
-
import { playwrightProviderImplementation } from './playwright';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Browser provider contract hub.
|
|
7
|
-
*
|
|
8
|
-
* When adding a new built-in provider, implement `BrowserProviderImplementation`
|
|
9
|
-
* and register it in `providerImplementations` below.
|
|
10
|
-
*
|
|
11
|
-
* Provider-agnostic policy:
|
|
12
|
-
* - keep shared contracts and behavior provider-neutral
|
|
13
|
-
* - `browser.providerOptions` stays opaque at the framework boundary
|
|
14
|
-
* - do not export provider-owned config types from `@rstest/browser`
|
|
15
|
-
* - do not reference optional peer provider types from public declarations
|
|
16
|
-
* - keep provider-specific behavior and config decoding inside provider implementations
|
|
17
|
-
* - prefer direct passthrough to provider APIs over provider-specific translation
|
|
18
|
-
*
|
|
19
|
-
* The provider-name union is owned by `@rstest/core` (see `BROWSER_PROVIDERS`)
|
|
20
|
-
* because core's CLI `init` templates need it but cannot import this package
|
|
21
|
-
* (peer-dependency direction). `providerImplementations` below is keyed by the
|
|
22
|
-
* re-exported union, so a provider added in core without an implementation here
|
|
23
|
-
* is a compile error.
|
|
24
|
-
*/
|
|
25
|
-
export type { BrowserProvider };
|
|
26
|
-
|
|
27
|
-
/** Minimal console shape needed by host logging bridge. */
|
|
28
|
-
export type BrowserConsoleMessage = {
|
|
29
|
-
text: () => string;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Minimal page API surface required by hostController.
|
|
34
|
-
*
|
|
35
|
-
* This is a structural type (shape interface), NOT a direct Playwright import.
|
|
36
|
-
* It currently mirrors a subset of Playwright's Page API because that is the
|
|
37
|
-
* only provider. When adding a second provider whose page primitive diverges
|
|
38
|
-
* (e.g. WebDriver BiDi), consider pushing page-level orchestration (goto,
|
|
39
|
-
* exposeFunction, addInitScript, event listeners) into provider-specific
|
|
40
|
-
* implementations so hostController only calls high-level semantic methods.
|
|
41
|
-
*/
|
|
42
|
-
export type BrowserProviderPage = {
|
|
43
|
-
goto: (url: string, options?: { waitUntil?: 'load' }) => Promise<unknown>;
|
|
44
|
-
exposeFunction: (name: string, fn: (...args: any[]) => any) => Promise<void>;
|
|
45
|
-
addInitScript: (script: string) => Promise<void>;
|
|
46
|
-
on: {
|
|
47
|
-
(event: 'popup', listener: (page: BrowserProviderPage) => void): void;
|
|
48
|
-
(
|
|
49
|
-
event: 'console',
|
|
50
|
-
listener: (message: BrowserConsoleMessage) => void,
|
|
51
|
-
): void;
|
|
52
|
-
// Page died: renderer crash or unexpected close. Headless scheduling wires
|
|
53
|
-
// these to fail the file immediately. Listeners take no payload.
|
|
54
|
-
(event: 'crash' | 'close', listener: () => void): void;
|
|
55
|
-
};
|
|
56
|
-
close: () => Promise<void>;
|
|
57
|
-
[Symbol.asyncDispose]: () => Promise<void>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/** Minimal browser context API surface required by hostController. */
|
|
61
|
-
export type BrowserProviderContext = {
|
|
62
|
-
newPage: () => Promise<BrowserProviderPage>;
|
|
63
|
-
on: (event: 'page', listener: (page: BrowserProviderPage) => void) => void;
|
|
64
|
-
close: () => Promise<void>;
|
|
65
|
-
[Symbol.asyncDispose]: () => Promise<void>;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/** Minimal browser API surface required by hostController. */
|
|
69
|
-
export type BrowserProviderBrowser = {
|
|
70
|
-
close: () => Promise<void>;
|
|
71
|
-
[Symbol.asyncDispose]: () => Promise<void>;
|
|
72
|
-
newContext: (options: {
|
|
73
|
-
viewport: { width: number; height: number } | null;
|
|
74
|
-
providerOptions?: Record<string, unknown>;
|
|
75
|
-
}) => Promise<BrowserProviderContext>;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/** Provider launch result consumed by hostController. */
|
|
79
|
-
export type BrowserProviderRuntime = {
|
|
80
|
-
browser: BrowserProviderBrowser;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
/** Input contract for browser launch. */
|
|
84
|
-
export type LaunchBrowserInput = {
|
|
85
|
-
browserName: 'chromium' | 'firefox' | 'webkit';
|
|
86
|
-
headless: boolean | undefined;
|
|
87
|
-
providerOptions: Record<string, unknown>;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/** Input contract for provider-side browser RPC dispatch. */
|
|
91
|
-
export type DispatchBrowserRpcInput = {
|
|
92
|
-
containerPage?: BrowserProviderPage;
|
|
93
|
-
runnerPage?: BrowserProviderPage;
|
|
94
|
-
request: BrowserRpcRequest;
|
|
95
|
-
timeoutFallbackMs: number;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Core provider implementation contract.
|
|
100
|
-
*
|
|
101
|
-
* Any new built-in provider must:
|
|
102
|
-
* - launch browser runtime for test execution
|
|
103
|
-
* - execute browser RPC requests (locator actions + assertions)
|
|
104
|
-
*/
|
|
105
|
-
export type BrowserProviderImplementation = {
|
|
106
|
-
name: BrowserProvider;
|
|
107
|
-
launchRuntime: (input: LaunchBrowserInput) => Promise<BrowserProviderRuntime>;
|
|
108
|
-
dispatchRpc: (input: DispatchBrowserRpcInput) => Promise<unknown>;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const providerImplementations: Record<
|
|
112
|
-
BrowserProvider,
|
|
113
|
-
BrowserProviderImplementation
|
|
114
|
-
> = {
|
|
115
|
-
playwright: playwrightProviderImplementation,
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
export function getBrowserProviderImplementation(
|
|
119
|
-
provider: BrowserProvider,
|
|
120
|
-
): BrowserProviderImplementation {
|
|
121
|
-
const implementation = providerImplementations[provider];
|
|
122
|
-
if (!implementation) {
|
|
123
|
-
throw new Error(`Unsupported browser provider: ${String(provider)}`);
|
|
124
|
-
}
|
|
125
|
-
return implementation;
|
|
126
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { FrameLocator, Locator, Page } from 'playwright';
|
|
2
|
-
import type { BrowserLocatorIR } from '../../protocol';
|
|
3
|
-
import { reviveBrowserLocatorText } from './textMatcher';
|
|
4
|
-
|
|
5
|
-
export const compilePlaywrightLocator = (
|
|
6
|
-
frame: FrameLocator | Page,
|
|
7
|
-
locatorIR: BrowserLocatorIR,
|
|
8
|
-
): Locator => {
|
|
9
|
-
const compileFromFrame = (ir: BrowserLocatorIR): Locator => {
|
|
10
|
-
let current: FrameLocator | Page | Locator = frame;
|
|
11
|
-
|
|
12
|
-
const ensureLocator = (): Locator => {
|
|
13
|
-
if ((current as any).filter) {
|
|
14
|
-
return current as Locator;
|
|
15
|
-
}
|
|
16
|
-
// Convert FrameLocator to a Locator within the frame.
|
|
17
|
-
current = (current as FrameLocator).locator(':root');
|
|
18
|
-
return current as Locator;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
for (const step of ir.steps as any[]) {
|
|
22
|
-
switch (step.type) {
|
|
23
|
-
case 'getByRole': {
|
|
24
|
-
const name = step.options?.name
|
|
25
|
-
? reviveBrowserLocatorText(step.options.name)
|
|
26
|
-
: undefined;
|
|
27
|
-
const options = step.options ? { ...step.options, name } : undefined;
|
|
28
|
-
current = (current as any).getByRole(step.role, options);
|
|
29
|
-
break;
|
|
30
|
-
}
|
|
31
|
-
case 'locator':
|
|
32
|
-
current = (current as any).locator(step.selector);
|
|
33
|
-
break;
|
|
34
|
-
case 'getByText':
|
|
35
|
-
current = (current as any).getByText(
|
|
36
|
-
reviveBrowserLocatorText(step.text),
|
|
37
|
-
step.options,
|
|
38
|
-
);
|
|
39
|
-
break;
|
|
40
|
-
case 'getByLabel':
|
|
41
|
-
current = (current as any).getByLabel(
|
|
42
|
-
reviveBrowserLocatorText(step.text),
|
|
43
|
-
step.options,
|
|
44
|
-
);
|
|
45
|
-
break;
|
|
46
|
-
case 'getByPlaceholder':
|
|
47
|
-
current = (current as any).getByPlaceholder(
|
|
48
|
-
reviveBrowserLocatorText(step.text),
|
|
49
|
-
step.options,
|
|
50
|
-
);
|
|
51
|
-
break;
|
|
52
|
-
case 'getByAltText':
|
|
53
|
-
current = (current as any).getByAltText(
|
|
54
|
-
reviveBrowserLocatorText(step.text),
|
|
55
|
-
step.options,
|
|
56
|
-
);
|
|
57
|
-
break;
|
|
58
|
-
case 'getByTitle':
|
|
59
|
-
current = (current as any).getByTitle(
|
|
60
|
-
reviveBrowserLocatorText(step.text),
|
|
61
|
-
step.options,
|
|
62
|
-
);
|
|
63
|
-
break;
|
|
64
|
-
case 'getByTestId':
|
|
65
|
-
current = (current as any).getByTestId(
|
|
66
|
-
reviveBrowserLocatorText(step.text) as any,
|
|
67
|
-
);
|
|
68
|
-
break;
|
|
69
|
-
case 'filter': {
|
|
70
|
-
const locator = ensureLocator();
|
|
71
|
-
const options: {
|
|
72
|
-
hasText?: string | RegExp;
|
|
73
|
-
hasNotText?: string | RegExp;
|
|
74
|
-
has?: Locator;
|
|
75
|
-
hasNot?: Locator;
|
|
76
|
-
} = {};
|
|
77
|
-
if (step.options?.hasText) {
|
|
78
|
-
options.hasText = reviveBrowserLocatorText(step.options.hasText);
|
|
79
|
-
}
|
|
80
|
-
if (step.options?.hasNotText) {
|
|
81
|
-
options.hasNotText = reviveBrowserLocatorText(
|
|
82
|
-
step.options.hasNotText,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
if (step.options?.has) {
|
|
86
|
-
options.has = compileFromFrame(step.options.has);
|
|
87
|
-
}
|
|
88
|
-
if (step.options?.hasNot) {
|
|
89
|
-
options.hasNot = compileFromFrame(step.options.hasNot);
|
|
90
|
-
}
|
|
91
|
-
current = locator.filter(options);
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
case 'and': {
|
|
95
|
-
const locator = ensureLocator();
|
|
96
|
-
const other = compileFromFrame(step.locator);
|
|
97
|
-
current = locator.and(other);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case 'or': {
|
|
101
|
-
const locator = ensureLocator();
|
|
102
|
-
const other = compileFromFrame(step.locator);
|
|
103
|
-
current = locator.or(other);
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
case 'nth': {
|
|
107
|
-
const locator = ensureLocator();
|
|
108
|
-
current = locator.nth(step.index);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
case 'first': {
|
|
112
|
-
const locator = ensureLocator();
|
|
113
|
-
current = locator.first();
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
case 'last': {
|
|
117
|
-
const locator = ensureLocator();
|
|
118
|
-
current = locator.last();
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
default:
|
|
122
|
-
throw new Error(`Unknown locator step: ${String(step?.type)}`);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return ensureLocator();
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
return compileFromFrame(locatorIR);
|
|
130
|
-
};
|