@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.
Files changed (86) 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/browserExecutor.d.ts +7 -5
  6. package/dist/browserRsbuild.d.ts +139 -0
  7. package/dist/browserV8Coverage.d.ts +15 -0
  8. package/dist/client/240~1.js +150 -0
  9. package/dist/{augmentExpect.d.ts → client/client/augmentExpect.d.ts} +1 -1
  10. package/dist/client/{browserRpc.d.ts → client/browserRpc.d.ts} +1 -1
  11. package/dist/client/{dispatchTransport.d.ts → client/dispatchTransport.d.ts} +8 -4
  12. package/dist/client/client/index.d.ts +2 -0
  13. package/dist/client/client/runIdentity.d.ts +12 -0
  14. package/dist/client/client/runner.d.ts +4 -0
  15. package/dist/client/client/snapshot.d.ts +27 -0
  16. package/dist/client/client/sourceMapSupport.d.ts +36 -0
  17. package/dist/{browser.js → client/index.js} +3 -102
  18. package/dist/client/protocol.d.ts +225 -0
  19. package/dist/client/rpcProtocol.d.ts +138 -0
  20. package/dist/client/runner.js +675 -0
  21. package/dist/client/sourceMap/sourceMapLoader.d.ts +25 -0
  22. package/dist/containerRpc.d.ts +60 -0
  23. package/dist/dispatchCapabilities.d.ts +1 -2
  24. package/dist/headedRunRegistry.d.ts +51 -0
  25. package/dist/headedScheduler.d.ts +58 -0
  26. package/dist/headlessScheduler.d.ts +38 -0
  27. package/dist/headlessTransport.d.ts +4 -2
  28. package/dist/hostController.d.ts +12 -47
  29. package/dist/hostPayloads.d.ts +24 -0
  30. package/dist/index.js +2019 -1516
  31. package/dist/protocol.d.ts +48 -8
  32. package/dist/providers/index.d.ts +21 -0
  33. package/dist/providers/playwright/v8Coverage.d.ts +2 -0
  34. package/dist/rpcProtocol.d.ts +1 -2
  35. package/dist/schedulerSeam.d.ts +42 -0
  36. package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
  37. package/dist/watchRerunPlanner.d.ts +20 -4
  38. package/dist/watchRuntime.d.ts +21 -0
  39. package/dist/watchSignals.d.ts +29 -0
  40. package/package.json +12 -12
  41. package/dist/33.js +0 -7
  42. package/dist/browser-container/container-static/css/index.0521ff95b1.css +0 -1
  43. package/dist/browser-container/container-static/js/506.b2f920fa67.js +0 -194
  44. package/dist/browser-container/container-static/js/index.d27fd63f5e.js +0 -1
  45. package/dist/browser.d.ts +0 -2
  46. package/dist/headlessLatestRerunScheduler.d.ts +0 -18
  47. package/src/augmentExpect.ts +0 -62
  48. package/src/browser.ts +0 -3
  49. package/src/browserExecutor.ts +0 -140
  50. package/src/browserRpcRegistry.ts +0 -57
  51. package/src/client/api.ts +0 -213
  52. package/src/client/browserRpc.ts +0 -86
  53. package/src/client/dispatchTransport.ts +0 -240
  54. package/src/client/entry.ts +0 -807
  55. package/src/client/locator.ts +0 -448
  56. package/src/client/snapshot.ts +0 -113
  57. package/src/client/sourceMapSupport.ts +0 -159
  58. package/src/concurrency.ts +0 -65
  59. package/src/configValidation.ts +0 -263
  60. package/src/dispatchCapabilities.ts +0 -182
  61. package/src/dispatchRouter.ts +0 -82
  62. package/src/env.d.ts +0 -54
  63. package/src/headedSerialTaskQueue.ts +0 -23
  64. package/src/headlessLatestRerunScheduler.ts +0 -76
  65. package/src/headlessTransport.ts +0 -28
  66. package/src/hostController.ts +0 -4633
  67. package/src/index.ts +0 -51
  68. package/src/manifest.d.ts +0 -41
  69. package/src/protocol.ts +0 -225
  70. package/src/providers/index.ts +0 -126
  71. package/src/providers/playwright/compileLocator.ts +0 -130
  72. package/src/providers/playwright/dispatchBrowserRpc.ts +0 -372
  73. package/src/providers/playwright/expectUtils.ts +0 -57
  74. package/src/providers/playwright/implementation.ts +0 -35
  75. package/src/providers/playwright/index.ts +0 -1
  76. package/src/providers/playwright/runtime.ts +0 -159
  77. package/src/providers/playwright/textMatcher.ts +0 -10
  78. package/src/rpcProtocol.ts +0 -218
  79. package/src/runSession.ts +0 -110
  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 -77
  84. /package/dist/{rslib-runtime.js → 612~0.js} +0 -0
  85. /package/dist/client/{api.d.ts → client/api.d.ts} +0 -0
  86. /package/dist/client/{locator.d.ts → client/locator.d.ts} +0 -0
@@ -1,218 +0,0 @@
1
- export type BrowserLocatorText =
2
- | { type: 'string'; value: string }
3
- | { type: 'regexp'; source: string; flags?: string };
4
-
5
- export type BrowserLocatorStep =
6
- | {
7
- type: 'getByRole';
8
- role: string;
9
- options?: {
10
- name?: BrowserLocatorText;
11
- exact?: boolean;
12
- checked?: boolean;
13
- disabled?: boolean;
14
- expanded?: boolean;
15
- selected?: boolean;
16
- pressed?: boolean;
17
- includeHidden?: boolean;
18
- level?: number;
19
- };
20
- }
21
- | {
22
- type: 'locator';
23
- selector: string;
24
- }
25
- | {
26
- type: 'getByText';
27
- text: BrowserLocatorText;
28
- options?: { exact?: boolean };
29
- }
30
- | {
31
- type: 'getByLabel';
32
- text: BrowserLocatorText;
33
- options?: { exact?: boolean };
34
- }
35
- | {
36
- type: 'getByPlaceholder';
37
- text: BrowserLocatorText;
38
- options?: { exact?: boolean };
39
- }
40
- | {
41
- type: 'getByAltText';
42
- text: BrowserLocatorText;
43
- options?: { exact?: boolean };
44
- }
45
- | {
46
- type: 'getByTitle';
47
- text: BrowserLocatorText;
48
- options?: { exact?: boolean };
49
- }
50
- | {
51
- type: 'getByTestId';
52
- text: BrowserLocatorText;
53
- }
54
- | {
55
- type: 'filter';
56
- options: {
57
- hasText?: BrowserLocatorText;
58
- hasNotText?: BrowserLocatorText;
59
- has?: BrowserLocatorIR;
60
- hasNot?: BrowserLocatorIR;
61
- };
62
- }
63
- | { type: 'and'; locator: BrowserLocatorIR }
64
- | { type: 'or'; locator: BrowserLocatorIR }
65
- | { type: 'nth'; index: number }
66
- | { type: 'first' }
67
- | { type: 'last' };
68
-
69
- export type BrowserLocatorIR = {
70
- steps: BrowserLocatorStep[];
71
- };
72
-
73
- export type BrowserRpcRequest = {
74
- id: string;
75
- /** Absolute test file path for locating runner iframe */
76
- testPath: string;
77
- /** Run identifier generated by container for stale-request protection. */
78
- runId: string;
79
- kind: 'locator' | 'expect' | 'config';
80
- locator: BrowserLocatorIR;
81
- method: string;
82
- args: unknown[];
83
- /**
84
- * Negation for expect matchers (equivalent to Playwright expect(...).not).
85
- * Only meaningful for kind === 'expect'.
86
- */
87
- isNot?: boolean;
88
- /** Optional timeout override (ms). Falls back to browser rpcTimeout. */
89
- timeout?: number;
90
- };
91
-
92
- const isRecord = (value: unknown): value is Record<string, unknown> => {
93
- return typeof value === 'object' && value !== null;
94
- };
95
-
96
- const readString = (
97
- value: Record<string, unknown>,
98
- key: string,
99
- label: string,
100
- ): string => {
101
- const result = value[key];
102
- if (typeof result !== 'string') {
103
- throw new Error(`Invalid browser RPC request: ${label} must be a string`);
104
- }
105
- return result;
106
- };
107
-
108
- const readUnknownArray = (
109
- value: Record<string, unknown>,
110
- key: string,
111
- label: string,
112
- ): unknown[] => {
113
- const result = value[key];
114
- if (!Array.isArray(result)) {
115
- throw new Error(`Invalid browser RPC request: ${label} must be an array`);
116
- }
117
- return result;
118
- };
119
-
120
- const parseBrowserLocatorIR = (
121
- value: unknown,
122
- label: string,
123
- ): BrowserLocatorIR => {
124
- if (!isRecord(value)) {
125
- throw new Error(`Invalid browser RPC request: ${label} must be an object`);
126
- }
127
-
128
- const steps = value.steps;
129
- if (!Array.isArray(steps)) {
130
- throw new Error(
131
- `Invalid browser RPC request: ${label}.steps must be an array`,
132
- );
133
- }
134
-
135
- return value as BrowserLocatorIR;
136
- };
137
-
138
- export const validateBrowserRpcRequest = (
139
- payload: unknown,
140
- ): BrowserRpcRequest => {
141
- if (!isRecord(payload)) {
142
- throw new Error('Invalid browser RPC request: payload must be an object');
143
- }
144
-
145
- const kind = readString(payload, 'kind', 'kind');
146
- if (kind !== 'locator' && kind !== 'expect' && kind !== 'config') {
147
- throw new Error(
148
- `Invalid browser RPC request: unsupported kind ${JSON.stringify(kind)}`,
149
- );
150
- }
151
-
152
- const request: BrowserRpcRequest = {
153
- id: readString(payload, 'id', 'id'),
154
- testPath: readString(payload, 'testPath', 'testPath'),
155
- runId: readString(payload, 'runId', 'runId'),
156
- kind,
157
- locator: parseBrowserLocatorIR(payload.locator, 'locator'),
158
- method: readString(payload, 'method', 'method'),
159
- args: readUnknownArray(payload, 'args', 'args'),
160
- };
161
-
162
- const isNot = payload.isNot;
163
- if (isNot !== undefined) {
164
- if (typeof isNot !== 'boolean') {
165
- throw new Error('Invalid browser RPC request: isNot must be a boolean');
166
- }
167
- request.isNot = isNot;
168
- }
169
-
170
- const timeout = payload.timeout;
171
- if (timeout !== undefined) {
172
- if (typeof timeout !== 'number') {
173
- throw new Error('Invalid browser RPC request: timeout must be a number');
174
- }
175
- request.timeout = timeout;
176
- }
177
-
178
- return request;
179
- };
180
-
181
- /**
182
- * Single source of truth for snapshot RPC methods and their argument shapes.
183
- * The request union, the client sender, both host-side mappers, and every
184
- * exhaustiveness check derive from this map — adding or renaming a method here
185
- * forces a compile error at every site that has not been updated.
186
- */
187
- export type SnapshotRpcMethodArgs = {
188
- resolveSnapshotPath: { testPath: string };
189
- readSnapshotFile: { filepath: string };
190
- saveSnapshotFile: { filepath: string; content: string };
191
- removeSnapshotFile: { filepath: string };
192
- };
193
-
194
- export type SnapshotRpcMethod = keyof SnapshotRpcMethodArgs;
195
-
196
- /**
197
- * Snapshot RPC request from runner iframe.
198
- * The container will forward these to the host via WebSocket RPC.
199
- */
200
- export type SnapshotRpcRequest = {
201
- [M in SnapshotRpcMethod]: {
202
- id: string;
203
- method: M;
204
- args: SnapshotRpcMethodArgs[M];
205
- };
206
- }[SnapshotRpcMethod];
207
-
208
- /**
209
- * Client-side snapshot RPC call (request without the transport `id`).
210
- * Distributive over {@link SnapshotRpcMethod} so `method` and `args` stay paired
211
- * at the call site — a mismatched pair fails to compile.
212
- */
213
- export type SnapshotRpcCall = {
214
- [M in SnapshotRpcMethod]: {
215
- method: M;
216
- args: SnapshotRpcMethodArgs[M];
217
- };
218
- }[SnapshotRpcMethod];
package/src/runSession.ts DELETED
@@ -1,110 +0,0 @@
1
- /**
2
- * Run generation/session lifecycle contract shared by browser scheduling paths.
3
- */
4
- export type RunSession = {
5
- token: number;
6
- cancelled: boolean;
7
- cancelSignal: Promise<void>;
8
- signalCancel: () => void;
9
- done?: Promise<void>;
10
- };
11
-
12
- const createCancelSignal = (): {
13
- signal: Promise<void>;
14
- resolve: () => void;
15
- } => {
16
- let settled = false;
17
- let resolveSignal: () => void = () => {};
18
-
19
- const signal = new Promise<void>((resolve) => {
20
- resolveSignal = () => {
21
- if (!settled) {
22
- settled = true;
23
- resolve();
24
- }
25
- };
26
- });
27
-
28
- return {
29
- signal,
30
- resolve: resolveSignal,
31
- };
32
- };
33
-
34
- export const createRunSession = (token: number): RunSession => {
35
- const { signal, resolve } = createCancelSignal();
36
- return {
37
- token,
38
- cancelled: false,
39
- cancelSignal: signal,
40
- signalCancel: resolve,
41
- };
42
- };
43
-
44
- type CancelOptions<T extends RunSession> = {
45
- waitForDone?: boolean;
46
- onCancel?: (session: T) => Promise<void> | void;
47
- };
48
-
49
- /**
50
- * Canonical run-token lifecycle manager.
51
- * Centralizes token increment, invalidation, and cancellation semantics.
52
- */
53
- export class RunSessionLifecycle<T extends RunSession> {
54
- private currentToken = 0;
55
- private active: T | null = null;
56
-
57
- get activeSession(): T | null {
58
- return this.active;
59
- }
60
-
61
- get activeToken(): number {
62
- return this.currentToken;
63
- }
64
-
65
- createSession(factory: (token: number) => T): T {
66
- const session = factory(++this.currentToken);
67
- this.active = session;
68
- return session;
69
- }
70
-
71
- isTokenActive(token: number): boolean {
72
- return token === this.currentToken;
73
- }
74
-
75
- isTokenStale(token: number): boolean {
76
- return !this.isTokenActive(token);
77
- }
78
-
79
- invalidateActiveToken(): number {
80
- this.currentToken += 1;
81
- return this.currentToken;
82
- }
83
-
84
- clearIfActive(session: T): void {
85
- if (this.active === session) {
86
- this.active = null;
87
- }
88
- }
89
-
90
- async cancel(session: T, options?: CancelOptions<T>): Promise<void> {
91
- const waitForDone = options?.waitForDone ?? true;
92
-
93
- if (!session.cancelled) {
94
- session.cancelled = true;
95
- session.signalCancel();
96
- await options?.onCancel?.(session);
97
- }
98
-
99
- if (waitForDone) {
100
- await session.done?.catch(() => {});
101
- }
102
- }
103
-
104
- async cancelActive(options?: CancelOptions<T>): Promise<void> {
105
- if (!this.active) {
106
- return;
107
- }
108
- await this.cancel(this.active, options);
109
- }
110
- }
@@ -1,89 +0,0 @@
1
- import type { BrowserProviderContext, BrowserProviderPage } from './providers';
2
-
3
- type RunnerSessionRecord = {
4
- id: string;
5
- testFile: string;
6
- projectName: string;
7
- runToken: number;
8
- mode: 'headless-page' | 'headed-iframe';
9
- createdAt: number;
10
- context?: BrowserProviderContext;
11
- page?: BrowserProviderPage;
12
- metadata?: Record<string, unknown>;
13
- };
14
-
15
- type RunnerSessionInput = Omit<RunnerSessionRecord, 'id' | 'createdAt'> & {
16
- id?: string;
17
- createdAt?: number;
18
- };
19
-
20
- /**
21
- * Execution target index for host scheduling.
22
- * Provides lookup by session id, test file, and run token without coupling to UI topology.
23
- */
24
- export class RunnerSessionRegistry {
25
- private nextId = 0;
26
- private sessionsById = new Map<string, RunnerSessionRecord>();
27
- private sessionIdByTestFile = new Map<string, string>();
28
-
29
- register(input: RunnerSessionInput): RunnerSessionRecord {
30
- const id = input.id ?? `runner-session-${++this.nextId}`;
31
- const createdAt = input.createdAt ?? Date.now();
32
-
33
- const record: RunnerSessionRecord = {
34
- ...input,
35
- id,
36
- createdAt,
37
- };
38
-
39
- this.sessionsById.set(id, record);
40
- this.sessionIdByTestFile.set(record.testFile, id);
41
- return record;
42
- }
43
-
44
- getById(id: string): RunnerSessionRecord | undefined {
45
- return this.sessionsById.get(id);
46
- }
47
-
48
- getByTestFile(testFile: string): RunnerSessionRecord | undefined {
49
- const id = this.sessionIdByTestFile.get(testFile);
50
- if (!id) {
51
- return undefined;
52
- }
53
- return this.sessionsById.get(id);
54
- }
55
-
56
- list(): RunnerSessionRecord[] {
57
- return Array.from(this.sessionsById.values());
58
- }
59
-
60
- listByRunToken(runToken: number): RunnerSessionRecord[] {
61
- return this.list().filter((session) => session.runToken === runToken);
62
- }
63
-
64
- deleteById(id: string): boolean {
65
- const record = this.sessionsById.get(id);
66
- if (!record) {
67
- return false;
68
- }
69
-
70
- this.sessionsById.delete(id);
71
- if (this.sessionIdByTestFile.get(record.testFile) === id) {
72
- this.sessionIdByTestFile.delete(record.testFile);
73
- }
74
- return true;
75
- }
76
-
77
- deleteByTestFile(testFile: string): boolean {
78
- const id = this.sessionIdByTestFile.get(testFile);
79
- if (!id) {
80
- return false;
81
- }
82
- return this.deleteById(id);
83
- }
84
-
85
- clear(): void {
86
- this.sessionsById.clear();
87
- this.sessionIdByTestFile.clear();
88
- }
89
- }
@@ -1,96 +0,0 @@
1
- import type {
2
- DecodedSourceMapXInput,
3
- EncodedSourceMapXInput,
4
- } from '@jridgewell/trace-mapping';
5
- import convert from 'convert-source-map';
6
-
7
- export type SourceMapPayload = EncodedSourceMapXInput | DecodedSourceMapXInput;
8
-
9
- type Fetcher = typeof fetch;
10
-
11
- export const normalizeJavaScriptUrl = (
12
- value: string,
13
- options?: {
14
- origin?: string;
15
- },
16
- ): string | null => {
17
- try {
18
- const url = options?.origin
19
- ? new URL(value, options.origin)
20
- : new URL(value);
21
-
22
- if (url.protocol !== 'http:' && url.protocol !== 'https:') {
23
- return null;
24
- }
25
-
26
- url.search = '';
27
- url.hash = '';
28
- return url.toString();
29
- } catch {
30
- return null;
31
- }
32
- };
33
-
34
- const resolveInlineSourceMap = (code: string): SourceMapPayload | null => {
35
- const converter = convert.fromSource(code);
36
- if (!converter) {
37
- return null;
38
- }
39
-
40
- return converter.toObject() as SourceMapPayload;
41
- };
42
-
43
- const fetchSourceMap = async (
44
- jsUrl: string,
45
- fetcher: Fetcher,
46
- ): Promise<SourceMapPayload | null> => {
47
- const jsResponse = await fetcher(jsUrl);
48
- if (!jsResponse.ok) {
49
- return null;
50
- }
51
-
52
- const code = await jsResponse.text();
53
- const inlineMap = resolveInlineSourceMap(code);
54
- if (inlineMap) {
55
- return inlineMap;
56
- }
57
-
58
- const mapResponse = await fetcher(`${jsUrl}.map`);
59
- if (!mapResponse.ok) {
60
- return null;
61
- }
62
-
63
- return (await mapResponse.json()) as SourceMapPayload;
64
- };
65
-
66
- export const loadSourceMapWithCache = async ({
67
- jsUrl,
68
- cache,
69
- force = false,
70
- origin,
71
- fetcher = fetch,
72
- }: {
73
- jsUrl: string;
74
- cache: Map<string, SourceMapPayload | null>;
75
- force?: boolean;
76
- origin?: string;
77
- fetcher?: Fetcher;
78
- }): Promise<SourceMapPayload | null> => {
79
- const normalizedUrl = normalizeJavaScriptUrl(jsUrl, { origin });
80
- if (!normalizedUrl) {
81
- return null;
82
- }
83
-
84
- if (!force && cache.has(normalizedUrl)) {
85
- return cache.get(normalizedUrl) ?? null;
86
- }
87
-
88
- try {
89
- const sourceMap = await fetchSourceMap(normalizedUrl, fetcher);
90
- cache.set(normalizedUrl, sourceMap);
91
- return sourceMap;
92
- } catch {
93
- cache.set(normalizedUrl, null);
94
- return null;
95
- }
96
- };
@@ -1,69 +0,0 @@
1
- /**
2
- * Runtime source of truth for browser viewport presets.
3
- *
4
- * IMPORTANT: Keep this list/map in sync with `DevicePreset` typing in
5
- * `@rstest/core` (`packages/core/src/types/config.ts`) so `defineConfig`
6
- * autocomplete and runtime validation stay consistent.
7
- *
8
- * Upstream source of truth for ids/dimensions is the Chrome DevTools emulated
9
- * device list — mirror each device's `screen.vertical` `{ width, height }`:
10
- * https://github.com/ChromeDevTools/devtools-frontend/blob/main/front_end/models/emulation/EmulatedDevices.ts
11
- * Last verified in sync (all 17): 2026-04-22, devtools-frontend commit abaac05e.
12
- */
13
- export const BROWSER_VIEWPORT_PRESET_IDS = [
14
- 'iPhoneSE',
15
- 'iPhoneXR',
16
- 'iPhone12Pro',
17
- 'iPhone14ProMax',
18
- 'Pixel7',
19
- 'SamsungGalaxyS8Plus',
20
- 'SamsungGalaxyS20Ultra',
21
- 'iPadMini',
22
- 'iPadAir',
23
- 'iPadPro',
24
- 'SurfacePro7',
25
- 'SurfaceDuo',
26
- 'GalaxyZFold5',
27
- 'AsusZenbookFold',
28
- 'SamsungGalaxyA51A71',
29
- 'NestHub',
30
- 'NestHubMax',
31
- ] as const;
32
-
33
- type BrowserViewportPresetId = (typeof BROWSER_VIEWPORT_PRESET_IDS)[number];
34
-
35
- type BrowserViewportSize = {
36
- width: number;
37
- height: number;
38
- };
39
-
40
- export const BROWSER_VIEWPORT_PRESET_DIMENSIONS: Record<
41
- BrowserViewportPresetId,
42
- BrowserViewportSize
43
- > = {
44
- iPhoneSE: { width: 375, height: 667 },
45
- iPhoneXR: { width: 414, height: 896 },
46
- iPhone12Pro: { width: 390, height: 844 },
47
- iPhone14ProMax: { width: 430, height: 932 },
48
- Pixel7: { width: 412, height: 915 },
49
- SamsungGalaxyS8Plus: { width: 360, height: 740 },
50
- SamsungGalaxyS20Ultra: { width: 412, height: 915 },
51
- iPadMini: { width: 768, height: 1024 },
52
- iPadAir: { width: 820, height: 1180 },
53
- iPadPro: { width: 1024, height: 1366 },
54
- SurfacePro7: { width: 912, height: 1368 },
55
- SurfaceDuo: { width: 540, height: 720 },
56
- GalaxyZFold5: { width: 344, height: 882 },
57
- AsusZenbookFold: { width: 853, height: 1280 },
58
- SamsungGalaxyA51A71: { width: 412, height: 914 },
59
- NestHub: { width: 1024, height: 600 },
60
- NestHubMax: { width: 1280, height: 800 },
61
- };
62
-
63
- export const resolveBrowserViewportPreset = (
64
- presetId: string,
65
- ): BrowserViewportSize | null => {
66
- const size =
67
- BROWSER_VIEWPORT_PRESET_DIMENSIONS[presetId as BrowserViewportPresetId];
68
- return size ?? null;
69
- };
@@ -1,77 +0,0 @@
1
- import { normalize } from 'pathe';
2
- import type { TestFileInfo } from './protocol';
3
-
4
- type WatchPlannerProjectEntry = {
5
- project: {
6
- name: string;
7
- };
8
- testFiles: string[];
9
- };
10
-
11
- type WatchRerunPlannerInput = {
12
- projectEntries: WatchPlannerProjectEntry[];
13
- previousTestFiles: TestFileInfo[];
14
- affectedTestFiles: string[];
15
- };
16
-
17
- type WatchRerunPlan = {
18
- currentTestFiles: TestFileInfo[];
19
- filesChanged: boolean;
20
- normalizedAffectedTestFiles: string[];
21
- affectedTestFiles: TestFileInfo[];
22
- };
23
-
24
- const serializeTestFiles = (files: TestFileInfo[]): string => {
25
- return JSON.stringify(
26
- files.map((f) => `${f.projectName}:${f.testPath}`).sort(),
27
- );
28
- };
29
-
30
- const normalizeTestFiles = (files: TestFileInfo[]): TestFileInfo[] => {
31
- return files.map((file) => ({
32
- ...file,
33
- testPath: normalize(file.testPath),
34
- }));
35
- };
36
-
37
- export const collectWatchTestFiles = (
38
- projectEntries: WatchPlannerProjectEntry[],
39
- ): TestFileInfo[] => {
40
- return projectEntries.flatMap((entry) =>
41
- entry.testFiles.map((testPath) => ({
42
- testPath: normalize(testPath),
43
- projectName: entry.project.name,
44
- })),
45
- );
46
- };
47
-
48
- export const planWatchRerun = ({
49
- projectEntries,
50
- previousTestFiles,
51
- affectedTestFiles,
52
- }: WatchRerunPlannerInput): WatchRerunPlan => {
53
- const currentTestFiles = collectWatchTestFiles(projectEntries);
54
- const normalizedPrevious = normalizeTestFiles(previousTestFiles);
55
- const filesChanged =
56
- serializeTestFiles(currentTestFiles) !==
57
- serializeTestFiles(normalizedPrevious);
58
-
59
- const normalizedAffectedTestFiles = affectedTestFiles.map((testFile) =>
60
- normalize(testFile),
61
- );
62
-
63
- const currentFileMap = new Map(
64
- currentTestFiles.map((file) => [file.testPath, file] as const),
65
- );
66
-
67
- const matchedAffectedFiles = normalizedAffectedTestFiles
68
- .map((testFile) => currentFileMap.get(testFile))
69
- .filter((file): file is TestFileInfo => Boolean(file));
70
-
71
- return {
72
- currentTestFiles,
73
- filesChanged,
74
- normalizedAffectedTestFiles,
75
- affectedTestFiles: matchedAffectedFiles,
76
- };
77
- };
File without changes
File without changes