@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
@@ -0,0 +1,675 @@
1
+ import { projectSetupLoaders, projectTestContexts, projects } from "__rstest_virtual_browser_manifest__";
2
+ import { RSTEST_API_GLOBAL_KEY, RSTEST_ENV_SYMBOL_KEY, RSTEST_IMPORT_META_GLOBAL_KEY, SNAPSHOT_HEADER, createBrowserTaskContext, createRstestRuntime, formatConsoleArgs, globalApis, setRealTimers, unwrapRegex } from "@rstest/core/internal/browser-runtime";
3
+ import { normalize } from "pathe";
4
+ import { AnyMap, TraceMap, encodedMap, originalPositionFor } from "@jridgewell/trace-mapping";
5
+ import convert_source_map from "convert-source-map";
6
+ import { createRequestId, createRunnerLifecycleRequest, dispatchRpc, setRpcPhase, disposeDispatchTransport, DISPATCH_NAMESPACE_FILE_CLEANUP, sendDispatchRequest, RSTEST_BROWSER_CACHE_CLEANERS_KEY, RSTEST_CONFIG_MESSAGE_TYPE, DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_SNAPSHOT, getRunIdentity, adoptRunIdentity, getRpcTimeout } from "./240~1.js";
7
+ const flattenSourceMap = (sourceMap, sourceMapUrl)=>encodedMap(new AnyMap(sourceMap, sourceMapUrl));
8
+ const normalizeJavaScriptUrl = (value, options)=>{
9
+ try {
10
+ const url = options?.origin ? new URL(value, options.origin) : new URL(value);
11
+ if ('http:' !== url.protocol && 'https:' !== url.protocol) return null;
12
+ url.hash = '';
13
+ return url.toString();
14
+ } catch {
15
+ return null;
16
+ }
17
+ };
18
+ const resolveInlineSourceMap = (code, sourceMapUrl)=>{
19
+ try {
20
+ const converter = convert_source_map.fromSource(code);
21
+ return converter ? flattenSourceMap(converter.toObject(), sourceMapUrl) : null;
22
+ } catch {
23
+ return null;
24
+ }
25
+ };
26
+ const fetchSourceMap = async (jsUrl, fetcher)=>{
27
+ const jsResponse = await fetcher(jsUrl);
28
+ if (!jsResponse.ok) return null;
29
+ const code = await jsResponse.text();
30
+ const inlineMap = resolveInlineSourceMap(code, jsUrl);
31
+ if (inlineMap) return inlineMap;
32
+ const mapUrl = new URL(jsUrl);
33
+ mapUrl.pathname += '.map';
34
+ const mapResponse = await fetcher(mapUrl.href);
35
+ if (!mapResponse.ok) return null;
36
+ return flattenSourceMap(await mapResponse.json(), mapUrl.href);
37
+ };
38
+ const loadSourceMapWithCache = async ({ jsUrl, cache, force = false, origin, fetcher = fetch })=>{
39
+ const normalizedUrl = normalizeJavaScriptUrl(jsUrl, {
40
+ origin
41
+ });
42
+ if (!normalizedUrl) return null;
43
+ if (!force && cache.has(normalizedUrl)) return cache.get(normalizedUrl) ?? null;
44
+ try {
45
+ const sourceMap = await fetchSourceMap(normalizedUrl, fetcher);
46
+ cache.set(normalizedUrl, sourceMap);
47
+ return sourceMap;
48
+ } catch {
49
+ cache.set(normalizedUrl, null);
50
+ return null;
51
+ }
52
+ };
53
+ const sourceMapCache = new Map();
54
+ const sourceMapPayloadCache = new Map();
55
+ const getSourceMap = (url)=>sourceMapCache.get(url) ?? null;
56
+ const preloadSourceMap = async (jsUrl, force = false)=>{
57
+ const normalizedUrl = normalizeJavaScriptUrl(jsUrl, {
58
+ origin: window.location.origin
59
+ });
60
+ if (!normalizedUrl) return;
61
+ if (!force && sourceMapCache.has(normalizedUrl)) return;
62
+ const sourceMap = await loadSourceMapWithCache({
63
+ jsUrl: normalizedUrl,
64
+ cache: sourceMapPayloadCache,
65
+ force,
66
+ origin: window.location.origin
67
+ });
68
+ sourceMapCache.set(normalizedUrl, sourceMap ? new TraceMap(sourceMap) : null);
69
+ };
70
+ const getScriptUrls = ()=>{
71
+ const scripts = document.querySelectorAll("script[src]");
72
+ const urls = new Set();
73
+ for (const script of scripts){
74
+ const src = script.getAttribute('src');
75
+ if (src) {
76
+ const fullUrl = src.startsWith('http') ? src : `${window.location.origin}${src.startsWith('/') ? '' : '/'}${src}`;
77
+ urls.add(fullUrl);
78
+ }
79
+ }
80
+ return urls;
81
+ };
82
+ const findNewScriptUrl = (beforeUrls, afterUrls)=>{
83
+ for (const url of afterUrls)if (!beforeUrls.has(url)) return url;
84
+ return null;
85
+ };
86
+ const preloadTestFileSourceMap = async (chunkUrl)=>{
87
+ await preloadSourceMap(chunkUrl, true);
88
+ };
89
+ const preloadRunnerSourceMap = async ()=>{
90
+ const runnerUrl = `${window.location.origin}/static/js/runner.js`;
91
+ await preloadSourceMap(runnerUrl);
92
+ };
93
+ const mapStackFrame = (frame)=>{
94
+ const { file, line, column } = frame;
95
+ const fullUrl = normalizeJavaScriptUrl(file, {
96
+ origin: window.location.origin
97
+ });
98
+ if (!fullUrl) return frame;
99
+ const traceMap = getSourceMap(fullUrl);
100
+ if (!traceMap) return frame;
101
+ const pos = originalPositionFor(traceMap, {
102
+ line,
103
+ column: column - 1
104
+ });
105
+ if (pos.source && null != pos.line && null != pos.column) return {
106
+ ...frame,
107
+ file: pos.source,
108
+ line: pos.line,
109
+ column: pos.column + 1,
110
+ method: pos.name || frame.method
111
+ };
112
+ return frame;
113
+ };
114
+ const createSnapshotDispatchRequest = (requestId, call)=>({
115
+ requestId,
116
+ namespace: DISPATCH_NAMESPACE_SNAPSHOT,
117
+ method: call.method,
118
+ args: call.args
119
+ });
120
+ const sendRpcRequest = (call)=>{
121
+ const requestId = createRequestId('snapshot-rpc');
122
+ const rpcTimeout = getRpcTimeout();
123
+ const dispatchRequest = createSnapshotDispatchRequest(requestId, call);
124
+ return dispatchRpc({
125
+ requestId,
126
+ request: dispatchRequest,
127
+ timeoutMs: rpcTimeout,
128
+ staleMessage: 'Stale snapshot RPC request ignored.',
129
+ timeoutMessage: `Snapshot RPC timeout after ${rpcTimeout / 1000}s: ${call.method}`
130
+ });
131
+ };
132
+ class BrowserSnapshotEnvironment {
133
+ getVersion() {
134
+ return '1';
135
+ }
136
+ getHeader() {
137
+ return `${SNAPSHOT_HEADER} v${this.getVersion()}`;
138
+ }
139
+ async resolveRawPath(_testPath, rawPath) {
140
+ return rawPath;
141
+ }
142
+ async resolvePath(filepath) {
143
+ return sendRpcRequest({
144
+ method: 'resolveSnapshotPath',
145
+ args: {
146
+ testPath: filepath
147
+ }
148
+ });
149
+ }
150
+ async prepareDirectory() {}
151
+ async saveSnapshotFile(filepath, snapshot) {
152
+ await sendRpcRequest({
153
+ method: 'saveSnapshotFile',
154
+ args: {
155
+ filepath,
156
+ content: snapshot
157
+ }
158
+ });
159
+ }
160
+ async readSnapshotFile(filepath) {
161
+ return sendRpcRequest({
162
+ method: 'readSnapshotFile',
163
+ args: {
164
+ filepath
165
+ }
166
+ });
167
+ }
168
+ async removeSnapshotFile(filepath) {
169
+ await sendRpcRequest({
170
+ method: 'removeSnapshotFile',
171
+ args: {
172
+ filepath
173
+ }
174
+ });
175
+ }
176
+ processStackTrace(stack) {
177
+ const mapped = mapStackFrame(stack);
178
+ return {
179
+ file: mapped.file,
180
+ line: mapped.line,
181
+ column: mapped.column,
182
+ method: mapped.method || stack.method
183
+ };
184
+ }
185
+ }
186
+ const debugLog = (...args)=>{
187
+ if (window.__RSTEST_BROWSER_OPTIONS__?.debug) console.log(...args);
188
+ };
189
+ const RSTEST_ENV_SYMBOL = Symbol.for(RSTEST_ENV_SYMBOL_KEY);
190
+ const installRuntimeGlobals = (runtime, runtimeConfig)=>{
191
+ Object.assign(globalThis, {
192
+ [RSTEST_API_GLOBAL_KEY]: runtime.api,
193
+ [RSTEST_IMPORT_META_GLOBAL_KEY]: runtime.resolveImportMetaRstest
194
+ });
195
+ if (runtimeConfig.globals) for (const apiKey of globalApis)globalThis[apiKey] = runtime.api[apiKey];
196
+ };
197
+ const clearBrowserTestEntryCache = (testEntryPath)=>{
198
+ const cleaners = globalThis[RSTEST_BROWSER_CACHE_CLEANERS_KEY];
199
+ cleaners?.forEach((clean)=>clean(testEntryPath));
200
+ };
201
+ const restoreRuntimeConfig = (config)=>{
202
+ const { testNamePattern } = config;
203
+ return {
204
+ ...config,
205
+ testNamePattern: 'string' == typeof testNamePattern ? unwrapRegex(testNamePattern) : testNamePattern
206
+ };
207
+ };
208
+ const ensureRuntimeEnv = (env)=>{
209
+ const globalRef = globalThis;
210
+ if (!globalRef.global) globalRef.global = globalRef;
211
+ const existingEnv = globalRef[RSTEST_ENV_SYMBOL];
212
+ let runtimeEnv;
213
+ if (existingEnv && 'object' == typeof existingEnv) runtimeEnv = existingEnv;
214
+ else {
215
+ runtimeEnv = {};
216
+ globalRef[RSTEST_ENV_SYMBOL] = runtimeEnv;
217
+ }
218
+ if (env) for (const [key, value] of Object.entries(env)){
219
+ const normalizedValue = 'string' == typeof value ? value : null == value ? void 0 : String(value);
220
+ if (void 0 === normalizedValue) delete runtimeEnv[key];
221
+ else runtimeEnv[key] = normalizedValue;
222
+ }
223
+ };
224
+ const getFileTaskId = (testPath)=>`file:${testPath}`;
225
+ const interceptConsole = (projectName, getCurrentTask, printConsoleTrace)=>{
226
+ const originalConsole = {
227
+ log: console.log.bind(console),
228
+ warn: console.warn.bind(console),
229
+ error: console.error.bind(console),
230
+ info: console.info.bind(console),
231
+ debug: console.debug.bind(console)
232
+ };
233
+ const getConsoleTrace = ()=>{
234
+ if (!printConsoleTrace) return;
235
+ const stack = new Error('STACK_TRACE').stack;
236
+ return stack?.split('\n').slice(4).join('\n');
237
+ };
238
+ const createConsoleInterceptor = (level)=>(...args)=>{
239
+ originalConsole[level](...args);
240
+ const content = formatConsoleArgs(args);
241
+ const currentTask = getCurrentTask();
242
+ send({
243
+ type: 'log',
244
+ payload: {
245
+ level,
246
+ content,
247
+ projectName,
248
+ taskId: currentTask?.taskId,
249
+ taskName: currentTask?.taskName,
250
+ taskParentNames: currentTask?.taskParentNames,
251
+ taskType: currentTask?.taskType,
252
+ testPath: currentTask?.testPath ?? '',
253
+ type: 'error' === level || 'warn' === level ? 'stderr' : 'stdout',
254
+ trace: getConsoleTrace()
255
+ }
256
+ });
257
+ };
258
+ console.log = createConsoleInterceptor('log');
259
+ console.warn = createConsoleInterceptor('warn');
260
+ console.error = createConsoleInterceptor('error');
261
+ console.info = createConsoleInterceptor('info');
262
+ console.debug = createConsoleInterceptor('debug');
263
+ return ()=>{
264
+ console.log = originalConsole.log;
265
+ console.warn = originalConsole.warn;
266
+ console.error = originalConsole.error;
267
+ console.info = originalConsole.info;
268
+ console.debug = originalConsole.debug;
269
+ };
270
+ };
271
+ const send = (message)=>{
272
+ const envelope = {
273
+ runId: getRunIdentity(),
274
+ message
275
+ };
276
+ if (window.parent !== window) return void window.parent.postMessage({
277
+ type: DISPATCH_MESSAGE_TYPE,
278
+ payload: envelope
279
+ }, '*');
280
+ window[DISPATCH_MESSAGE_TYPE]?.(envelope);
281
+ };
282
+ const dispatchRunnerLifecycle = (method, payload)=>{
283
+ sendDispatchRequest(createRunnerLifecycleRequest(method, payload), (error)=>{
284
+ debugLog('[Runner] Failed to dispatch lifecycle method:', method, error);
285
+ });
286
+ };
287
+ const CONFIG_WAIT_TIMEOUT_MS = 30000;
288
+ const waitForConfig = ()=>{
289
+ if (window.parent === window || window.__RSTEST_BROWSER_OPTIONS__) return Promise.resolve();
290
+ return new Promise((resolve, reject)=>{
291
+ const handleMessage = (event)=>{
292
+ if (event.data?.type === RSTEST_CONFIG_MESSAGE_TYPE && 'string' == typeof event.data.payload?.runId) {
293
+ window.__RSTEST_BROWSER_OPTIONS__ = event.data.payload;
294
+ debugLog('[Runner] Received config from container:', event.data.payload);
295
+ window.removeEventListener('message', handleMessage);
296
+ resolve();
297
+ }
298
+ };
299
+ window.addEventListener('message', handleMessage);
300
+ setTimeout(()=>{
301
+ window.removeEventListener('message', handleMessage);
302
+ reject(new Error(`[Rstest] Failed to receive browser config within ${CONFIG_WAIT_TIMEOUT_MS / 1000}s. This may indicate a connection issue between the runner iframe and container.`));
303
+ }, CONFIG_WAIT_TIMEOUT_MS);
304
+ });
305
+ };
306
+ const toContextKey = (absolutePath, projectRoot)=>{
307
+ const normalizedAbsolute = normalize(absolutePath);
308
+ const normalizedRoot = normalize(projectRoot);
309
+ const withinRoot = normalizedAbsolute === normalizedRoot || normalizedAbsolute.startsWith(`${normalizedRoot}/`);
310
+ if (!withinRoot) return normalizedAbsolute;
311
+ const relative = normalizedAbsolute.slice(normalizedRoot.length);
312
+ return relative.startsWith('/') ? `.${relative}` : `./${relative}`;
313
+ };
314
+ const toAbsolutePath = (key, projectRoot)=>{
315
+ if (!key.startsWith('.')) return key;
316
+ const normalizedRoot = normalize(projectRoot).replace(/\/$/, '');
317
+ return normalizedRoot + key.slice(1);
318
+ };
319
+ const findProjectForTestFile = (testFile, allProjects)=>{
320
+ const normalizedTestFile = normalize(testFile);
321
+ const sorted = [
322
+ ...allProjects
323
+ ].sort((a, b)=>b.projectRoot.length - a.projectRoot.length);
324
+ for (const proj of sorted){
325
+ const normalizedRoot = normalize(proj.projectRoot);
326
+ if (normalizedTestFile.startsWith(normalizedRoot)) return proj;
327
+ }
328
+ return allProjects[0];
329
+ };
330
+ const run = async ()=>{
331
+ await waitForConfig();
332
+ let options = window.__RSTEST_BROWSER_OPTIONS__;
333
+ if (options?.runId) adoptRunIdentity(options.runId);
334
+ const urlParams = new URLSearchParams(window.location.search);
335
+ const urlTestFile = urlParams.get('testFile');
336
+ const urlTestNamePattern = urlParams.get('testNamePattern');
337
+ if (urlTestFile && options) options = {
338
+ ...options,
339
+ testFile: urlTestFile
340
+ };
341
+ if (urlTestNamePattern && options) options = {
342
+ ...options,
343
+ projects: options.projects.map((project)=>({
344
+ ...project,
345
+ runtimeConfig: {
346
+ ...project.runtimeConfig,
347
+ testNamePattern: urlTestNamePattern
348
+ }
349
+ }))
350
+ };
351
+ if (!options) {
352
+ send({
353
+ type: 'fatal',
354
+ payload: {
355
+ message: 'Browser test runtime is not configured.'
356
+ }
357
+ });
358
+ window.__RSTEST_DONE__ = true;
359
+ return;
360
+ }
361
+ send({
362
+ type: 'ready'
363
+ });
364
+ setRealTimers();
365
+ await preloadRunnerSourceMap();
366
+ const targetTestFile = options.testFile;
367
+ const currentProject = targetTestFile ? findProjectForTestFile(targetTestFile, projects) : projects["0"];
368
+ if (!currentProject) {
369
+ send({
370
+ type: 'fatal',
371
+ payload: {
372
+ message: 'No project found for test file'
373
+ }
374
+ });
375
+ window.__RSTEST_DONE__ = true;
376
+ return;
377
+ }
378
+ const projectRuntime = options.projects.find((p)=>p.name === currentProject.name);
379
+ if (!projectRuntime) {
380
+ send({
381
+ type: 'fatal',
382
+ payload: {
383
+ message: `Project ${currentProject.name} not found in runtime options`
384
+ }
385
+ });
386
+ window.__RSTEST_DONE__ = true;
387
+ return;
388
+ }
389
+ const runtimeConfig = restoreRuntimeConfig(projectRuntime.runtimeConfig);
390
+ ensureRuntimeEnv(runtimeConfig.env);
391
+ const currentSetupLoaders = projectSetupLoaders[currentProject.name] || [];
392
+ const currentTestContext = projectTestContexts[currentProject.name];
393
+ if (!currentTestContext) {
394
+ send({
395
+ type: 'fatal',
396
+ payload: {
397
+ message: `Test context not found for project ${currentProject.name}`
398
+ }
399
+ });
400
+ window.__RSTEST_DONE__ = true;
401
+ return;
402
+ }
403
+ const loadSetupFiles = async ()=>{
404
+ for (const loadSetup of currentSetupLoaders)await loadSetup();
405
+ };
406
+ let testKeysToRun;
407
+ if (targetTestFile) {
408
+ const key = toContextKey(targetTestFile, currentProject.projectRoot);
409
+ testKeysToRun = [
410
+ key
411
+ ];
412
+ } else testKeysToRun = currentTestContext.getTestKeys();
413
+ const executionMode = options.mode || 'run';
414
+ if ('collect' === executionMode) {
415
+ for (const key of testKeysToRun){
416
+ const testPath = toAbsolutePath(key, currentProject.projectRoot);
417
+ const workerState = {
418
+ project: projectRuntime.name,
419
+ projectRoot: projectRuntime.projectRoot,
420
+ rootPath: options.rootPath,
421
+ runtimeConfig,
422
+ taskId: 0,
423
+ buildId: 0,
424
+ outputModule: false,
425
+ environment: 'browser',
426
+ testPath,
427
+ distPath: testPath,
428
+ snapshotOptions: {
429
+ updateSnapshot: options.snapshot.updateSnapshot,
430
+ snapshotEnvironment: new BrowserSnapshotEnvironment(),
431
+ snapshotFormat: runtimeConfig.snapshotFormat
432
+ }
433
+ };
434
+ const runtime = await createRstestRuntime(workerState, {
435
+ taskContext: createBrowserTaskContext()
436
+ });
437
+ installRuntimeGlobals(runtime, runtimeConfig);
438
+ try {
439
+ setRpcPhase('framework');
440
+ await loadSetupFiles();
441
+ clearBrowserTestEntryCache(testPath);
442
+ await currentTestContext.loadTest(key);
443
+ const tests = await runtime.runner.collectTests();
444
+ send({
445
+ type: 'collect-result',
446
+ payload: {
447
+ testPath,
448
+ project: projectRuntime.name,
449
+ tests
450
+ }
451
+ });
452
+ } catch (_error) {
453
+ const error = _error instanceof Error ? _error : new Error(String(_error));
454
+ send({
455
+ type: 'fatal',
456
+ payload: {
457
+ message: error.message,
458
+ stack: error.stack
459
+ }
460
+ });
461
+ window.__RSTEST_DONE__ = true;
462
+ return;
463
+ }
464
+ }
465
+ send({
466
+ type: 'collect-complete'
467
+ });
468
+ window.__RSTEST_DONE__ = true;
469
+ return;
470
+ }
471
+ let activeUnhandledErrors;
472
+ const onWindowError = (event)=>{
473
+ activeUnhandledErrors?.push(event.error instanceof Error ? event.error : new Error(event.message || String(event.error)));
474
+ };
475
+ const onUnhandledRejection = (event)=>{
476
+ const { reason } = event;
477
+ activeUnhandledErrors?.push(reason instanceof Error ? reason : new Error(String(reason)));
478
+ };
479
+ window.addEventListener('error', onWindowError);
480
+ window.addEventListener('unhandledrejection', onUnhandledRejection);
481
+ for (const key of testKeysToRun){
482
+ const testPath = toAbsolutePath(key, currentProject.projectRoot);
483
+ const taskStack = [
484
+ {
485
+ taskId: getFileTaskId(testPath),
486
+ taskType: 'file',
487
+ testPath
488
+ }
489
+ ];
490
+ const taskContext = createBrowserTaskContext();
491
+ const shouldInterceptConsole = !runtimeConfig.disableConsoleIntercept || true === runtimeConfig.silent || 'passed-only' === runtimeConfig.silent;
492
+ const restoreConsole = shouldInterceptConsole ? interceptConsole(projectRuntime.name, ()=>taskContext.getCurrent() ?? taskStack[taskStack.length - 1], runtimeConfig.disableConsoleIntercept ? false : runtimeConfig.printConsoleTrace ?? false) : ()=>{};
493
+ const workerState = {
494
+ project: projectRuntime.name,
495
+ projectRoot: projectRuntime.projectRoot,
496
+ rootPath: options.rootPath,
497
+ runtimeConfig,
498
+ taskId: 0,
499
+ buildId: 0,
500
+ outputModule: false,
501
+ environment: 'browser',
502
+ currentTask: taskStack[0],
503
+ testPath,
504
+ distPath: testPath,
505
+ snapshotOptions: {
506
+ updateSnapshot: options.snapshot.updateSnapshot,
507
+ snapshotEnvironment: new BrowserSnapshotEnvironment(),
508
+ snapshotFormat: runtimeConfig.snapshotFormat
509
+ }
510
+ };
511
+ const syncCurrentTask = ()=>{
512
+ workerState.currentTask = taskStack[taskStack.length - 1];
513
+ };
514
+ const removeTaskFromStack = (taskId)=>{
515
+ const taskIndex = taskStack.findLastIndex((task)=>task.taskId === taskId);
516
+ if (taskIndex < 0) return;
517
+ taskStack.splice(taskIndex, 1);
518
+ syncCurrentTask();
519
+ };
520
+ const runtime = await createRstestRuntime(workerState, {
521
+ taskContext
522
+ });
523
+ installRuntimeGlobals(runtime, runtimeConfig);
524
+ let failedTestsCount = 0;
525
+ const dispatchFileCleanup = async (method, result, waitForAcknowledgement = true)=>{
526
+ const requestId = createRequestId(`file-cleanup-${method}`);
527
+ const request = {
528
+ requestId,
529
+ namespace: DISPATCH_NAMESPACE_FILE_CLEANUP,
530
+ method,
531
+ args: {
532
+ projectName: projectRuntime.name,
533
+ result,
534
+ runId: getRunIdentity(),
535
+ testPath
536
+ }
537
+ };
538
+ if (!waitForAcknowledgement) return void sendDispatchRequest(request);
539
+ await dispatchRpc({
540
+ requestId,
541
+ request,
542
+ timeoutMs: getRpcTimeout('framework'),
543
+ timeoutMessage: `File cleanup ${method} acknowledgement timed out for ${testPath}.`,
544
+ staleMessage: `File cleanup ${method} became stale for ${testPath}.`
545
+ });
546
+ };
547
+ const runnerHooks = {
548
+ onFileCleanupStart: async (result)=>{
549
+ if (result && globalThis.__coverage__) result.coverage = globalThis.__coverage__;
550
+ await dispatchFileCleanup('start', result, window.parent !== window);
551
+ },
552
+ onFileCleanupEnd: ()=>dispatchFileCleanup('end', void 0, window.parent !== window),
553
+ onSnapshotSetupStart: async ()=>{
554
+ setRpcPhase('framework');
555
+ },
556
+ onSnapshotSetupEnd: async ()=>{
557
+ setRpcPhase('test');
558
+ },
559
+ onSnapshotFinishStart: async ()=>{
560
+ setRpcPhase('framework');
561
+ },
562
+ onSnapshotFinishEnd: async ()=>{
563
+ setRpcPhase('test');
564
+ },
565
+ onTestFileReady: async (test)=>{
566
+ dispatchRunnerLifecycle('file-ready', test);
567
+ },
568
+ onTestSuiteStart: async (test)=>{
569
+ taskStack.push({
570
+ taskId: test.testId,
571
+ taskName: test.name,
572
+ taskParentNames: test.parentNames,
573
+ taskType: 'suite',
574
+ testPath: test.testPath
575
+ });
576
+ syncCurrentTask();
577
+ dispatchRunnerLifecycle('suite-start', test);
578
+ },
579
+ onTestSuiteResult: async (result)=>{
580
+ removeTaskFromStack(result.testId);
581
+ dispatchRunnerLifecycle('suite-result', result);
582
+ },
583
+ onTestCaseStart: async (test)=>{
584
+ taskStack.push({
585
+ taskId: test.testId,
586
+ taskName: test.name,
587
+ taskParentNames: test.parentNames,
588
+ taskType: 'case',
589
+ testPath: test.testPath
590
+ });
591
+ syncCurrentTask();
592
+ dispatchRunnerLifecycle('case-start', test);
593
+ },
594
+ onTestCaseResult: async (result)=>{
595
+ removeTaskFromStack(result.testId);
596
+ if ('fail' === result.status) failedTestsCount++;
597
+ send({
598
+ type: 'case-result',
599
+ payload: result
600
+ });
601
+ },
602
+ getCountOfFailedTests: async ()=>failedTestsCount
603
+ };
604
+ send({
605
+ type: 'file-start',
606
+ payload: {
607
+ testPath,
608
+ projectName: projectRuntime.name
609
+ }
610
+ });
611
+ const unhandledErrors = [];
612
+ activeUnhandledErrors = unhandledErrors;
613
+ try {
614
+ setRpcPhase('framework');
615
+ await loadSetupFiles();
616
+ const beforeScripts = getScriptUrls();
617
+ await currentTestContext.loadTest(key);
618
+ const afterScripts = getScriptUrls();
619
+ const chunkUrl = findNewScriptUrl(beforeScripts, afterScripts);
620
+ if (chunkUrl) await preloadTestFileSourceMap(chunkUrl);
621
+ const result = await runtime.runner.runTests(testPath, runnerHooks, runtime.api);
622
+ for(let i = 0; i < 2; i++)await new Promise((resolve)=>{
623
+ setTimeout(resolve, 0);
624
+ });
625
+ if (unhandledErrors.length > 0) {
626
+ result.status = 'fail';
627
+ result.errors = [
628
+ ...result.errors ?? [],
629
+ ...unhandledErrors.map((error)=>({
630
+ name: error.name,
631
+ message: error.message,
632
+ stack: error.stack
633
+ }))
634
+ ];
635
+ }
636
+ send({
637
+ type: 'file-complete',
638
+ payload: result
639
+ });
640
+ } catch (_error) {
641
+ const error = _error instanceof Error ? _error : new Error(String(_error));
642
+ send({
643
+ type: 'fatal',
644
+ payload: {
645
+ message: error.message,
646
+ stack: error.stack
647
+ }
648
+ });
649
+ window.__RSTEST_DONE__ = true;
650
+ return;
651
+ } finally{
652
+ restoreConsole();
653
+ activeUnhandledErrors = void 0;
654
+ }
655
+ }
656
+ window.removeEventListener('error', onWindowError);
657
+ window.removeEventListener('unhandledrejection', onUnhandledRejection);
658
+ send({
659
+ type: 'complete'
660
+ });
661
+ window.__RSTEST_DONE__ = true;
662
+ };
663
+ run().catch((error)=>{
664
+ const err = error instanceof Error ? error : new Error(String(error));
665
+ send({
666
+ type: 'fatal',
667
+ payload: {
668
+ message: err.message,
669
+ stack: err.stack
670
+ }
671
+ });
672
+ window.__RSTEST_DONE__ = true;
673
+ }).finally(()=>{
674
+ disposeDispatchTransport();
675
+ });
@@ -0,0 +1,25 @@
1
+ import { type DecodedSourceMapXInput, type EncodedSourceMapXInput } from '@jridgewell/trace-mapping';
2
+ export type SourceMapPayload = EncodedSourceMapXInput | DecodedSourceMapXInput;
3
+ export type LoadedSourceMap = {
4
+ sourceMap: SourceMapPayload;
5
+ sourceMapUrl: string;
6
+ };
7
+ type Fetcher = typeof fetch;
8
+ export declare const normalizeJavaScriptUrl: (value: string, options?: {
9
+ origin?: string;
10
+ }) => string | null;
11
+ export declare const resolveInlineSourceMap: (code: string, sourceMapUrl?: string) => SourceMapPayload | null;
12
+ export declare const loadSourceMapForSource: ({ jsUrl, signal, source, fetcher }: {
13
+ jsUrl: string;
14
+ signal?: AbortSignal;
15
+ source: string;
16
+ fetcher?: Fetcher;
17
+ }) => Promise<LoadedSourceMap | null>;
18
+ export declare const loadSourceMapWithCache: ({ jsUrl, cache, force, origin, fetcher }: {
19
+ jsUrl: string;
20
+ cache: Map<string, SourceMapPayload | null>;
21
+ force?: boolean;
22
+ origin?: string;
23
+ fetcher?: Fetcher;
24
+ }) => Promise<SourceMapPayload | null>;
25
+ export { };