@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.
Files changed (88) hide show
  1. package/dist/browser-container/container-static/css/index.43daaf6c93.css +1 -0
  2. package/dist/browser-container/container-static/js/260.3739fe815c.js +194 -0
  3. package/dist/browser-container/container-static/js/index.c0f87bfb3e.js +1 -0
  4. package/dist/browser-container/index.html +1 -1
  5. package/dist/browserRsbuild.d.ts +24 -4
  6. package/dist/browserV8Coverage.d.ts +15 -0
  7. package/dist/client/240~1.js +150 -0
  8. package/dist/{augmentExpect.d.ts → client/client/augmentExpect.d.ts} +1 -1
  9. package/dist/client/{browserRpc.d.ts → client/browserRpc.d.ts} +1 -1
  10. package/dist/client/{dispatchTransport.d.ts → client/dispatchTransport.d.ts} +8 -4
  11. package/dist/client/client/index.d.ts +2 -0
  12. package/dist/client/client/runIdentity.d.ts +12 -0
  13. package/dist/client/client/runner.d.ts +4 -0
  14. package/dist/client/client/snapshot.d.ts +27 -0
  15. package/dist/client/client/sourceMapSupport.d.ts +36 -0
  16. package/dist/{browser.js → client/index.js} +3 -102
  17. package/dist/client/protocol.d.ts +225 -0
  18. package/dist/client/rpcProtocol.d.ts +138 -0
  19. package/dist/client/runner.js +675 -0
  20. package/dist/client/sourceMap/sourceMapLoader.d.ts +25 -0
  21. package/dist/containerRpc.d.ts +27 -19
  22. package/dist/headedRunRegistry.d.ts +51 -0
  23. package/dist/headedScheduler.d.ts +10 -10
  24. package/dist/headlessScheduler.d.ts +5 -4
  25. package/dist/headlessTransport.d.ts +4 -2
  26. package/dist/hostPayloads.d.ts +1 -7
  27. package/dist/index.js +840 -330
  28. package/dist/protocol.d.ts +48 -8
  29. package/dist/providers/index.d.ts +21 -0
  30. package/dist/providers/playwright/v8Coverage.d.ts +2 -0
  31. package/dist/rpcProtocol.d.ts +1 -2
  32. package/dist/schedulerSeam.d.ts +5 -0
  33. package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
  34. package/dist/watchRerunPlanner.d.ts +20 -9
  35. package/dist/watchSignals.d.ts +8 -1
  36. package/package.json +11 -11
  37. package/dist/33.js +0 -7
  38. package/dist/browser-container/container-static/css/index.0521ff95b1.css +0 -1
  39. package/dist/browser-container/container-static/js/683.4f821ce8f1.js +0 -194
  40. package/dist/browser-container/container-static/js/index.568aa7cb35.js +0 -1
  41. package/dist/browser.d.ts +0 -2
  42. package/src/augmentExpect.ts +0 -62
  43. package/src/browser.ts +0 -3
  44. package/src/browserExecutor.ts +0 -222
  45. package/src/browserRpcRegistry.ts +0 -57
  46. package/src/browserRsbuild.ts +0 -1927
  47. package/src/client/api.ts +0 -213
  48. package/src/client/browserRpc.ts +0 -86
  49. package/src/client/dispatchTransport.ts +0 -240
  50. package/src/client/entry.ts +0 -807
  51. package/src/client/locator.ts +0 -448
  52. package/src/client/snapshot.ts +0 -113
  53. package/src/client/sourceMapSupport.ts +0 -159
  54. package/src/concurrency.ts +0 -65
  55. package/src/configValidation.ts +0 -263
  56. package/src/containerRpc.ts +0 -206
  57. package/src/dispatchCapabilities.ts +0 -177
  58. package/src/dispatchRouter.ts +0 -82
  59. package/src/env.d.ts +0 -54
  60. package/src/headedScheduler.ts +0 -664
  61. package/src/headedSerialTaskQueue.ts +0 -23
  62. package/src/headlessScheduler.ts +0 -566
  63. package/src/headlessTransport.ts +0 -28
  64. package/src/hostController.ts +0 -1365
  65. package/src/hostPayloads.ts +0 -62
  66. package/src/index.ts +0 -51
  67. package/src/manifest.d.ts +0 -41
  68. package/src/protocol.ts +0 -225
  69. package/src/providers/index.ts +0 -126
  70. package/src/providers/playwright/compileLocator.ts +0 -130
  71. package/src/providers/playwright/dispatchBrowserRpc.ts +0 -372
  72. package/src/providers/playwright/expectUtils.ts +0 -57
  73. package/src/providers/playwright/implementation.ts +0 -35
  74. package/src/providers/playwright/index.ts +0 -1
  75. package/src/providers/playwright/runtime.ts +0 -159
  76. package/src/providers/playwright/textMatcher.ts +0 -10
  77. package/src/rpcProtocol.ts +0 -218
  78. package/src/runSession.ts +0 -110
  79. package/src/schedulerSeam.ts +0 -49
  80. package/src/sessionRegistry.ts +0 -89
  81. package/src/sourceMap/sourceMapLoader.ts +0 -96
  82. package/src/viewportPresets.ts +0 -69
  83. package/src/watchRerunPlanner.ts +0 -88
  84. package/src/watchRuntime.ts +0 -83
  85. package/src/watchSignals.ts +0 -93
  86. /package/dist/{rslib-runtime.js → 612~0.js} +0 -0
  87. /package/dist/client/{api.d.ts → client/api.d.ts} +0 -0
  88. /package/dist/client/{locator.d.ts → client/locator.d.ts} +0 -0
@@ -1,24 +1,30 @@
1
- import { type TestResult } from '@rstest/core/internal/browser';
2
1
  import { type BirpcReturn } from 'birpc';
3
2
  import { type WebSocket, WebSocketServer } from 'ws';
4
- import type { BrowserDispatchRequest, BrowserDispatchResponse, BrowserHostConfig, TestFileInfo } from './protocol.js';
5
- import type { FatalPayload, HeadedTestFileCompletePayload, LogPayload, ReloadTestFileAck, TestFileStartPayload } from './hostPayloads.js';
6
- /** RPC methods exposed by the host (server) to the container (client) */ export type HostRpcMethods = {
3
+ import type { BrowserDispatchRequest, BrowserDispatchResponse, BrowserHostConfig, TestFileInfo, VersionedTestFileSet } from './protocol.js';
4
+ /**
5
+ * RPC methods exposed by the host (server) to the container (client).
6
+ * Runner lifecycle events (file-start, case-result, file-complete, log,
7
+ * fatal, ...) do NOT get dedicated methods: the container relays every runner
8
+ * message as a `dispatch` request on the `runner` namespace, stamped with the
9
+ * envelope's run identity, so the host has exactly one inbound gate.
10
+ */ export type HostRpcMethods = {
7
11
  rerunTest: (testFile: string, testNamePattern?: string) => Promise<void>;
8
- getTestFiles: () => Promise<TestFileInfo[]>;
9
- onRunnerFramesReady: (testFiles: string[]) => Promise<void>;
10
- // Test result callbacks from container
11
- onTestFileStart: (payload: TestFileStartPayload) => Promise<void>;
12
- onTestCaseResult: (payload: TestResult) => Promise<void>;
13
- onTestFileComplete: (payload: HeadedTestFileCompletePayload) => Promise<void>;
14
- onLog: (payload: LogPayload) => Promise<void>;
15
- onFatal: (payload: FatalPayload) => Promise<void>;
16
- // Generic dispatch endpoint used by runner RPC requests.
12
+ getTestFiles: () => Promise<VersionedTestFileSet>;
13
+ /**
14
+ * The container committed the frame set for this version — every iframe for
15
+ * the set exists in the DOM. Versions are monotonic, so a stale ack can
16
+ * never satisfy a newer wait (a content signature could ABA back to a
17
+ * previously-acked value; a counter cannot).
18
+ */ onFrameSetReady: (version: number) => Promise<void>;
17
19
  dispatch: (request: BrowserDispatchRequest) => Promise<BrowserDispatchResponse>;
18
20
  };
19
21
  /** RPC methods exposed by the container (client) to the host (server) */ export type ContainerRpcMethods = {
20
- onTestFileUpdate: (testFiles: TestFileInfo[]) => Promise<void>;
21
- reloadTestFile: (testFile: string, testNamePattern?: string) => Promise<ReloadTestFileAck>;
22
+ onTestFileUpdate: (testFiles: TestFileInfo[], version: number) => Promise<void>;
23
+ /**
24
+ * Grant `runId` (host-minted, already registered host-side) to this file's
25
+ * frame and navigate it. Identity travels IN — the container never mints or
26
+ * echoes identity back.
27
+ */ reloadTestFile: (testFile: string, runId: string, testNamePattern?: string) => Promise<void>;
22
28
  /**
23
29
  * Replace the container's copy of the host config so runner iframes loaded
24
30
  * from now on receive fresh values (e.g. the 'u' shortcut flipping
@@ -38,15 +44,17 @@ export type ContainerRpc = BirpcReturn<ContainerRpcMethods, HostRpcMethods>;
38
44
  private rpc;
39
45
  private methods;
40
46
  private onDisconnect?;
47
+ private onAttach?;
41
48
  private detachActiveSocketListeners;
42
- constructor(wss: WebSocketServer, methods: HostRpcMethods, onDisconnect?: (error: Error) => void);
43
- /** Update the RPC methods (used when starting a new test run) */ updateMethods(methods: HostRpcMethods, onDisconnect?: (error: Error) => void): void;
49
+ private transportEpoch;
50
+ constructor(wss: WebSocketServer, methods: HostRpcMethods, onDisconnect?: (error: Error) => void, onAttach?: (transportEpoch: number) => void);
51
+ /** Update the RPC methods (used when starting a new test run) */ updateMethods(methods: HostRpcMethods, onDisconnect?: (error: Error) => void, onAttach?: (transportEpoch: number) => void): void;
44
52
  private setupConnectionHandler;
45
53
  private attachWebSocket;
46
54
  /** Check if a container is currently connected */ get isConnected(): boolean;
47
55
  /** Get the current WebSocket instance (for reuse in watch mode) */ get currentWebSocket(): WebSocket | null;
48
56
  /** Reattach an existing WebSocket (for watch mode reuse) */ reattach(ws: WebSocket): void;
49
- /** Notify container of test file changes */ notifyTestFileUpdate(files: TestFileInfo[]): Promise<void>;
57
+ /** Notify container of test file changes */ notifyTestFileUpdate(files: TestFileInfo[], version: number): Promise<void>;
50
58
  /** Push a refreshed host config to the container (watch reruns) */ updateHostConfig(config: BrowserHostConfig): Promise<void>;
51
- /** Request container to reload a specific test file */ reloadTestFile(testFile: string, testNamePattern?: string): Promise<ReloadTestFileAck>;
59
+ /** Grant a run to a test file's frame and navigate it */ reloadTestFile(testFile: string, runId: string, testNamePattern?: string): Promise<void>;
52
60
  }
@@ -0,0 +1,51 @@
1
+ export type HeadedRunRegistry = ReturnType<typeof createHeadedRunRegistry>;
2
+ export declare const createHeadedRunRegistry: () => {
3
+ /**
4
+ * Allocate a run and own its deferred, synchronously — the caller sends
5
+ * the reload RPC only after this returns, so no file-set commit or
6
+ * inbound message can land between "the run exists" and "the table knows
7
+ * it" (the ack-window class of race cannot be constructed).
8
+ */ mint(testPath: string): {
9
+ runId: string;
10
+ settled: Promise<void>;
11
+ };
12
+ /**
13
+ * The one liveness question, asked once per inbound message: may this
14
+ * identity be processed? Any answer of `true` also proves the run's
15
+ * document booted, which disarms the boot deadline.
16
+ *
17
+ * `terminal` marks a message that ends the run ("file-complete" /
18
+ * "fatal"). It claims settlement for the caller's handler and must be
19
+ * asked synchronously, before the handler's first await, so a file-set
20
+ * commit racing the handler cannot settle the run a second time. A second
21
+ * terminal for the same run is answered `false` — it is a duplicate.
22
+ */ admit(runId: string, terminal: boolean): boolean;
23
+ /**
24
+ * A run whose fixture cleanup never finishes will never send its
25
+ * terminal message — a way to go silent that no other deadline covers,
26
+ * so it is a settlement obligation and lives here: the deadline dies
27
+ * with the record in the one guarded delete, which is what makes "run
28
+ * settled elsewhere, timer fires anyway" unrepresentable. Expiry fires
29
+ * only while the run is still open and CLAIMS it in the same synchronous
30
+ * step, exactly like a terminal message's admit: `onExpire`'s handler
31
+ * now owns the settlement, and the recovery it performs (tearing down
32
+ * the container transport) can no longer sweep this run out from under
33
+ * itself. Re-arming replaces the previous deadline.
34
+ */ armCleanupDeadline(runId: string, ms: number, onExpire: () => void): void;
35
+ disarmCleanupDeadline(runId: string): void;
36
+ resolve(runId: string): void;
37
+ reject(runId: string, error: unknown): void;
38
+ /**
39
+ * The file-set commit's settlement obligation: close every open run whose
40
+ * path left the committed set — the container is about to unmount those
41
+ * frames, so their completions can never arrive (and if one is already in
42
+ * transport, its runId is gone from the table and drops by rule).
43
+ */ retainPaths(paths: readonly string[]): void;
44
+ /** Transport death: no completion can arrive for any open run. */ rejectAll(error: Error): void;
45
+ /**
46
+ * A new transport attachment orphans every run leased under the previous
47
+ * one, even when the old socket never fired `close` (its listeners are
48
+ * detached before the event can). Runs minted from now on carry the new
49
+ * epoch.
50
+ */ setTransportEpoch(epoch: number): void;
51
+ };
@@ -1,10 +1,9 @@
1
- import type { RstestContext, TestFileResult, TestResult } from '@rstest/core/internal/browser';
1
+ import type { RstestContext, TestFileResult } from '@rstest/core/internal/browser';
2
2
  import { type BrowserRuntime } from './browserRsbuild.js';
3
3
  import type { HostDispatchRouter } from './dispatchRouter.js';
4
- import { type FatalPayload, type LogPayload, type TestFileStartPayload } from './hostPayloads.js';
5
4
  import type { BrowserHostConfig, TestFileInfo } from './protocol.js';
6
5
  import { planWatchRerun } from './watchRerunPlanner.js';
7
- import type { BrowserWatchSession, DispatchPageResolver, SchedulerRunResult } from './schedulerSeam.js';
6
+ import type { BrowserV8CoverageRuntime, BrowserWatchSession, DispatchPageResolver, SchedulerRunResult } from './schedulerSeam.js';
8
7
  import type { WatchSignals } from './watchSignals.js';
9
8
  type HeadedSchedulerContext = Pick<RstestContext, 'rootPath' | 'snapshotManager' | 'updateReporterResultState'> & {
10
9
  normalizedConfig: Pick<RstestContext['normalizedConfig'], 'name'>;
@@ -14,21 +13,22 @@ type HeadedSchedulerDeps = {
14
13
  runtime: BrowserRuntime;
15
14
  allTestFiles: TestFileInfo[];
16
15
  hostOptions: BrowserHostConfig;
16
+ v8Coverage?: BrowserV8CoverageRuntime;
17
+ projectRoots: Map<string, string>;
17
18
  isWatchMode: boolean;
18
19
  createDispatchRouter: () => HostDispatchRouter;
19
20
  handlers: {
20
- handleTestFileStart: (payload: TestFileStartPayload) => Promise<void>;
21
- handleTestCaseResult: (payload: TestResult) => Promise<void>;
21
+ // For the one result the host authors itself (the cleanup-timeout
22
+ // failure); every runner-authored result flows through the dispatch
23
+ // router instead.
22
24
  handleTestFileComplete: (payload: TestFileResult) => Promise<void>;
23
- handleLog: (payload: LogPayload) => Promise<void>;
24
- handleFatal: (payload: FatalPayload) => Promise<void>;
25
25
  };
26
26
  fatalErrorRef: {
27
27
  current: Error | null;
28
28
  };
29
- watchSignals: Pick<WatchSignals, 'setDispatchRerun' | 'signalInvalidation' | 'awaitSignalledCycle'>;
29
+ watchSignals: Pick<WatchSignals, 'setDispatchRerun' | 'signalInvalidation'>;
30
30
  setDispatchPageResolver: (resolver: DispatchPageResolver) => void;
31
- createWatchSession: (execute: (testPaths: string[]) => Promise<void>) => BrowserWatchSession;
31
+ createWatchSession: (execute: (testPaths: string[]) => Promise<unknown[]>) => BrowserWatchSession;
32
32
  collectProjectEntries: () => Promise<Parameters<typeof planWatchRerun>[0]['projectEntries']>;
33
33
  logWatchReady: () => void;
34
34
  destroyRuntime: () => Promise<void>;
@@ -54,5 +54,5 @@ type HeadedSchedulerDeps = {
54
54
  file: TestFileInfo;
55
55
  testNamePattern?: string;
56
56
  }[];
57
- export declare const createHeadedScheduler: ({ context, runtime, allTestFiles, hostOptions, isWatchMode, createDispatchRouter, handlers: { handleTestFileStart, handleTestCaseResult, handleTestFileComplete, handleLog, handleFatal }, fatalErrorRef, watchSignals, setDispatchPageResolver, createWatchSession, collectProjectEntries, logWatchReady, destroyRuntime }: HeadedSchedulerDeps) => Promise<SchedulerRunResult>;
57
+ export declare const createHeadedScheduler: ({ context, runtime, allTestFiles, hostOptions, v8Coverage, projectRoots, isWatchMode, createDispatchRouter, handlers: { handleTestFileComplete }, fatalErrorRef, watchSignals, setDispatchPageResolver, createWatchSession, collectProjectEntries, logWatchReady, destroyRuntime }: HeadedSchedulerDeps) => Promise<SchedulerRunResult>;
58
58
  export { };
@@ -6,9 +6,9 @@ import { type FatalPayload } from './hostPayloads.js';
6
6
  import type { BrowserHostConfig, BrowserProjectRuntime, TestFileInfo } from './protocol.js';
7
7
  import type { BrowserProviderBrowser } from './providers/index.js';
8
8
  import { planWatchRerun } from './watchRerunPlanner.js';
9
- import type { BrowserWatchSession, DispatchPageResolver, SchedulerRunResult } from './schedulerSeam.js';
9
+ import type { BrowserV8CoverageRuntime, BrowserWatchSession, DispatchPageResolver, SchedulerRunResult } from './schedulerSeam.js';
10
10
  import type { WatchSignals } from './watchSignals.js';
11
- type HeadlessSchedulerContext = Pick<RstestContext, 'command' | 'snapshotManager' | 'stateManager' | 'updateReporterResultState'> & {
11
+ type HeadlessSchedulerContext = Pick<RstestContext, 'command' | 'rootPath' | 'snapshotManager' | 'stateManager' | 'updateReporterResultState'> & {
12
12
  normalizedConfig: Pick<RstestContext['normalizedConfig'], 'bail' | 'pool'>;
13
13
  };
14
14
  type HeadlessSchedulerDeps = {
@@ -16,6 +16,7 @@ type HeadlessSchedulerDeps = {
16
16
  browser: BrowserProviderBrowser;
17
17
  browserLaunchOptions: BrowserRuntime['browserLaunchOptions'];
18
18
  projectServers: BrowserRuntime['projectServers'];
19
+ v8Coverage?: BrowserV8CoverageRuntime;
19
20
  allTestFiles: TestFileInfo[];
20
21
  projectRuntimeConfigs: BrowserProjectRuntime[];
21
22
  hostOptions: BrowserHostConfig;
@@ -28,10 +29,10 @@ type HeadlessSchedulerDeps = {
28
29
  };
29
30
  watchSignals: Pick<WatchSignals, 'setDispatchRerun' | 'setInterrupt' | 'signalInvalidation'>;
30
31
  setDispatchPageResolver: (resolver: DispatchPageResolver) => void;
31
- createWatchSession: (execute: (testPaths: string[]) => Promise<void>) => BrowserWatchSession;
32
+ createWatchSession: (execute: (testPaths: string[]) => Promise<unknown[]>) => BrowserWatchSession;
32
33
  collectProjectEntries: () => Promise<Parameters<typeof planWatchRerun>[0]['projectEntries']>;
33
34
  logWatchReady: () => void;
34
35
  destroyRuntime: () => Promise<void>;
35
36
  };
36
- export declare const createHeadlessScheduler: ({ context, browser, browserLaunchOptions, projectServers, allTestFiles, projectRuntimeConfigs, hostOptions, watchState, isWatchMode, createDispatchRouter, handlers: { handleFatal, handleTestFileComplete }, watchSignals, setDispatchPageResolver, createWatchSession, collectProjectEntries, logWatchReady, destroyRuntime }: HeadlessSchedulerDeps) => Promise<SchedulerRunResult>;
37
+ export declare const createHeadlessScheduler: ({ context, browser, browserLaunchOptions, projectServers, v8Coverage, allTestFiles, projectRuntimeConfigs, hostOptions, watchState, isWatchMode, createDispatchRouter, handlers: { handleFatal, handleTestFileComplete }, watchSignals, setDispatchPageResolver, createWatchSession, collectProjectEntries, logWatchReady, destroyRuntime }: HeadlessSchedulerDeps) => Promise<SchedulerRunResult>;
37
38
  export { };
@@ -1,7 +1,9 @@
1
- import type { BrowserClientMessage, BrowserDispatchRequest, BrowserDispatchResponse } from './protocol.js';
1
+ import type { BrowserDispatchRequest, BrowserDispatchResponse, RunnerEnvelope } from './protocol.js';
2
2
  import type { BrowserProviderPage } from './providers/index.js';
3
3
  type HeadlessRunnerTransportHandlers = {
4
- onDispatchMessage: (message: BrowserClientMessage) => Promise<void>;
4
+ // The envelope's `runId` is ignored here: headless identity is the
5
+ // host-injected `runToken` bound at this transport attachment.
6
+ onDispatchMessage: (envelope: RunnerEnvelope) => Promise<void>;
5
7
  onDispatchRpc: (request: BrowserDispatchRequest) => Promise<BrowserDispatchResponse>;
6
8
  };
7
9
  /**
@@ -1,4 +1,4 @@
1
- import type { Reporter, TestFileResult } from '@rstest/core/internal/browser';
1
+ import type { Reporter } from '@rstest/core/internal/browser';
2
2
  import type { BrowserLogPayload } from './protocol.js';
3
3
  /** Payload for test file start event */ export type TestFileStartPayload = {
4
4
  testPath: string;
@@ -14,12 +14,6 @@ export type TestFileReadyPayload = ReporterHookArg<'onTestFileReady'>;
14
14
  export type TestSuiteStartPayload = ReporterHookArg<'onTestSuiteStart'>;
15
15
  export type TestSuiteResultPayload = ReporterHookArg<'onTestSuiteResult'>;
16
16
  export type TestCaseStartPayload = ReporterHookArg<'onTestCaseStart'>;
17
- export type ReloadTestFileAck = {
18
- runId: string;
19
- };
20
- export type HeadedTestFileCompletePayload = TestFileResult & {
21
- runId?: string;
22
- };
23
17
  export type DeferredPromise<T> = {
24
18
  promise: Promise<T>;
25
19
  resolve: (value: T | PromiseLike<T>) => void;