@rstest/core 0.0.1

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/773.js ADDED
@@ -0,0 +1,1709 @@
1
+ export const __webpack_ids__ = [
2
+ "773"
3
+ ];
4
+ export const __webpack_modules__ = {
5
+ "./src/runtime/api/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
6
+ __webpack_require__.d(__webpack_exports__, {
7
+ createRstestRuntime: ()=>createRstestRuntime
8
+ });
9
+ var expect_ = __webpack_require__("@vitest/expect");
10
+ var src_utils = __webpack_require__("./src/utils/index.ts");
11
+ var external_chai_ = __webpack_require__("chai");
12
+ const unsupported = [
13
+ 'matchSnapshot',
14
+ 'toMatchSnapshot',
15
+ 'toMatchInlineSnapshot',
16
+ 'toThrowErrorMatchingSnapshot',
17
+ 'toThrowErrorMatchingInlineSnapshot',
18
+ 'throws',
19
+ 'Throw',
20
+ 'throw',
21
+ 'toThrow',
22
+ 'toThrowError'
23
+ ];
24
+ function createExpectPoll(expect) {
25
+ return function poll(fn, options = {}) {
26
+ const { interval = 50, timeout = 1000, message } = options;
27
+ const assertion = expect(null, message).withContext({
28
+ poll: true
29
+ });
30
+ fn = fn.bind(assertion);
31
+ const test = external_chai_.util.flag(assertion, 'vitest-test');
32
+ if (!test) throw new Error('expect.poll() must be called inside a test');
33
+ const proxy = new Proxy(assertion, {
34
+ get (target, key, receiver) {
35
+ const assertionFunction = Reflect.get(target, key, receiver);
36
+ if ('function' != typeof assertionFunction) return assertionFunction instanceof external_chai_.Assertion ? proxy : assertionFunction;
37
+ if ('assert' === key) return assertionFunction;
38
+ if ('string' == typeof key && unsupported.includes(key)) throw new SyntaxError(`expect.poll() is not supported in combination with .${key}(). Use rstest.waitFor() if your assertion condition is unstable.`);
39
+ return function(...args) {
40
+ const STACK_TRACE_ERROR = new Error('STACK_TRACE_ERROR');
41
+ const promise = ()=>new Promise((resolve, reject)=>{
42
+ let intervalId;
43
+ let timeoutId;
44
+ let lastError;
45
+ const check = async ()=>{
46
+ try {
47
+ external_chai_.util.flag(assertion, '_name', key);
48
+ const obj = await fn();
49
+ external_chai_.util.flag(assertion, 'object', obj);
50
+ resolve(await assertionFunction.call(assertion, ...args));
51
+ clearTimeout(intervalId);
52
+ clearTimeout(timeoutId);
53
+ } catch (err) {
54
+ lastError = err;
55
+ if (!external_chai_.util.flag(assertion, '_isLastPollAttempt')) intervalId = setTimeout(check, interval);
56
+ }
57
+ };
58
+ timeoutId = setTimeout(()=>{
59
+ clearTimeout(intervalId);
60
+ external_chai_.util.flag(assertion, '_isLastPollAttempt', true);
61
+ const rejectWithCause = (cause)=>{
62
+ reject(copyStackTrace(new Error(`Matcher did not succeed in ${timeout}ms`, {
63
+ cause
64
+ }), STACK_TRACE_ERROR));
65
+ };
66
+ check().then(()=>rejectWithCause(lastError)).catch((e)=>rejectWithCause(e));
67
+ }, timeout);
68
+ check();
69
+ });
70
+ let awaited = false;
71
+ test.onFinished ??= [];
72
+ test.onFinished.push(()=>{
73
+ if (!awaited) {
74
+ const negated = external_chai_.util.flag(assertion, 'negate') ? 'not.' : '';
75
+ const name = external_chai_.util.flag(assertion, '_poll.element') ? 'element(locator)' : 'poll(assertion)';
76
+ const assertionString = `expect.${name}.${negated}${String(key)}()`;
77
+ const error = new Error(`${assertionString} was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\n\nawait ${assertionString}\n`);
78
+ throw copyStackTrace(error, STACK_TRACE_ERROR);
79
+ }
80
+ });
81
+ let resultPromise;
82
+ return {
83
+ then (onFulfilled, onRejected) {
84
+ awaited = true;
85
+ resultPromise ||= promise();
86
+ return resultPromise.then(onFulfilled, onRejected);
87
+ },
88
+ catch (onRejected) {
89
+ resultPromise ||= promise();
90
+ return resultPromise.catch(onRejected);
91
+ },
92
+ finally (onFinally) {
93
+ resultPromise ||= promise();
94
+ return resultPromise.finally(onFinally);
95
+ },
96
+ [Symbol.toStringTag]: 'Promise'
97
+ };
98
+ };
99
+ }
100
+ });
101
+ return proxy;
102
+ };
103
+ }
104
+ function copyStackTrace(target, source) {
105
+ if (void 0 !== source.stack) target.stack = source.stack.replace(source.message, target.message);
106
+ return target;
107
+ }
108
+ var snapshot_ = __webpack_require__("@vitest/snapshot");
109
+ let _client;
110
+ function getSnapshotClient() {
111
+ if (!_client) _client = new snapshot_.SnapshotClient({
112
+ isEqual: (received, expected)=>(0, expect_.equals)(received, expected, [
113
+ expect_.iterableEquality,
114
+ expect_.subsetEquality
115
+ ])
116
+ });
117
+ return _client;
118
+ }
119
+ function recordAsyncExpect(_test, promise, assertion, error) {
120
+ const test = _test;
121
+ if (test && promise instanceof Promise) {
122
+ promise = promise.finally(()=>{
123
+ if (!test.promises) return;
124
+ const index = test.promises.indexOf(promise);
125
+ if (-1 !== index) test.promises.splice(index, 1);
126
+ });
127
+ if (!test.promises) test.promises = [];
128
+ test.promises.push(promise);
129
+ let resolved = false;
130
+ test.onFinished ??= [];
131
+ test.onFinished.push(()=>{
132
+ if (!resolved) {
133
+ const processor = globalThis.__vitest_worker__?.onFilterStackTrace || ((s)=>s || '');
134
+ const stack = processor(error.stack);
135
+ console.warn([
136
+ `Promise returned by \`${assertion}\` was not awaited. `,
137
+ 'Rstest currently auto-awaits hanging assertions at the end of the test.',
138
+ 'Please remember to await the assertion.\n',
139
+ stack
140
+ ].join(''));
141
+ }
142
+ });
143
+ return {
144
+ then (onFulfilled, onRejected) {
145
+ resolved = true;
146
+ return promise.then(onFulfilled, onRejected);
147
+ },
148
+ catch (onRejected) {
149
+ return promise.catch(onRejected);
150
+ },
151
+ finally (onFinally) {
152
+ return promise.finally(onFinally);
153
+ },
154
+ [Symbol.toStringTag]: 'Promise'
155
+ };
156
+ }
157
+ return promise;
158
+ }
159
+ function createAssertionMessage(util, assertion, hasArgs) {
160
+ const not = util.flag(assertion, 'negate') ? 'not.' : '';
161
+ const name = `${util.flag(assertion, '_name')}(${hasArgs ? 'expected' : ''})`;
162
+ const promiseName = util.flag(assertion, 'promise');
163
+ const promise = promiseName ? `.${promiseName}` : '';
164
+ return `expect(actual)${promise}.${not}${name}`;
165
+ }
166
+ function getError(expected, promise) {
167
+ if ('function' != typeof expected) {
168
+ if (!promise) throw new Error(`expected must be a function, received ${typeof expected}`);
169
+ return expected;
170
+ }
171
+ try {
172
+ expected();
173
+ } catch (e) {
174
+ return e;
175
+ }
176
+ throw new Error("snapshot function didn't throw");
177
+ }
178
+ function getTestNames(test) {
179
+ return {
180
+ filepath: test.testPath,
181
+ name: (0, src_utils.Yz)(test)
182
+ };
183
+ }
184
+ const SnapshotPlugin = (chai, utils)=>{
185
+ function getTest(assertionName, obj) {
186
+ const test = utils.flag(obj, 'vitest-test');
187
+ if (!test) throw new Error(`'${assertionName}' cannot be used without test context`);
188
+ return test;
189
+ }
190
+ for (const key of [
191
+ 'matchSnapshot',
192
+ 'toMatchSnapshot'
193
+ ])utils.addMethod(chai.Assertion.prototype, key, function(properties, message) {
194
+ utils.flag(this, '_name', key);
195
+ const isNot = utils.flag(this, 'negate');
196
+ if (isNot) throw new Error(`${key} cannot be used with "not"`);
197
+ const expected = utils.flag(this, 'object');
198
+ const test = getTest(key, this);
199
+ if ('string' == typeof properties && void 0 === message) {
200
+ message = properties;
201
+ properties = void 0;
202
+ }
203
+ const errorMessage = utils.flag(this, 'message');
204
+ getSnapshotClient().assert({
205
+ received: expected,
206
+ message,
207
+ isInline: false,
208
+ properties,
209
+ errorMessage,
210
+ ...getTestNames(test)
211
+ });
212
+ });
213
+ utils.addMethod(chai.Assertion.prototype, 'toMatchFileSnapshot', function(file, message) {
214
+ utils.flag(this, '_name', 'toMatchFileSnapshot');
215
+ const isNot = utils.flag(this, 'negate');
216
+ if (isNot) throw new Error('toMatchFileSnapshot cannot be used with "not"');
217
+ const error = new Error('resolves');
218
+ const expected = utils.flag(this, 'object');
219
+ const test = getTest('toMatchFileSnapshot', this);
220
+ const errorMessage = utils.flag(this, 'message');
221
+ const promise = getSnapshotClient().assertRaw({
222
+ received: expected,
223
+ message,
224
+ isInline: false,
225
+ rawSnapshot: {
226
+ file
227
+ },
228
+ errorMessage,
229
+ ...getTestNames(test)
230
+ });
231
+ return recordAsyncExpect(test, promise, createAssertionMessage(utils, this, true), error);
232
+ });
233
+ utils.addMethod(chai.Assertion.prototype, 'toMatchInlineSnapshot', function __INLINE_SNAPSHOT__(properties, inlineSnapshot, message) {
234
+ utils.flag(this, '_name', 'toMatchInlineSnapshot');
235
+ const isNot = utils.flag(this, 'negate');
236
+ if (isNot) throw new Error('toMatchInlineSnapshot cannot be used with "not"');
237
+ const test = getTest('toMatchInlineSnapshot', this);
238
+ const isInsideEach = test.each || test.inTestEach;
239
+ if (isInsideEach) throw new Error('InlineSnapshot cannot be used inside of test.each or describe.each');
240
+ const expected = utils.flag(this, 'object');
241
+ const error = utils.flag(this, 'error');
242
+ if ('string' == typeof properties) {
243
+ message = inlineSnapshot;
244
+ inlineSnapshot = properties;
245
+ properties = void 0;
246
+ }
247
+ if (inlineSnapshot) inlineSnapshot = (0, snapshot_.stripSnapshotIndentation)(inlineSnapshot);
248
+ const errorMessage = utils.flag(this, 'message');
249
+ getSnapshotClient().assert({
250
+ received: expected,
251
+ message,
252
+ isInline: true,
253
+ properties,
254
+ inlineSnapshot,
255
+ error,
256
+ errorMessage,
257
+ ...getTestNames(test)
258
+ });
259
+ });
260
+ utils.addMethod(chai.Assertion.prototype, 'toThrowErrorMatchingSnapshot', function(message) {
261
+ utils.flag(this, '_name', 'toThrowErrorMatchingSnapshot');
262
+ const isNot = utils.flag(this, 'negate');
263
+ if (isNot) throw new Error('toThrowErrorMatchingSnapshot cannot be used with "not"');
264
+ const expected = utils.flag(this, 'object');
265
+ const test = getTest('toThrowErrorMatchingSnapshot', this);
266
+ const promise = utils.flag(this, 'promise');
267
+ const errorMessage = utils.flag(this, 'message');
268
+ getSnapshotClient().assert({
269
+ received: getError(expected, promise),
270
+ message,
271
+ errorMessage,
272
+ ...getTestNames(test)
273
+ });
274
+ });
275
+ utils.addMethod(chai.Assertion.prototype, 'toThrowErrorMatchingInlineSnapshot', function __INLINE_SNAPSHOT__(inlineSnapshot, message) {
276
+ const isNot = utils.flag(this, 'negate');
277
+ if (isNot) throw new Error('toThrowErrorMatchingInlineSnapshot cannot be used with "not"');
278
+ const test = getTest('toThrowErrorMatchingInlineSnapshot', this);
279
+ const expected = utils.flag(this, 'object');
280
+ const error = utils.flag(this, 'error');
281
+ const promise = utils.flag(this, 'promise');
282
+ const errorMessage = utils.flag(this, 'message');
283
+ if (inlineSnapshot) inlineSnapshot = (0, snapshot_.stripSnapshotIndentation)(inlineSnapshot);
284
+ getSnapshotClient().assert({
285
+ received: getError(expected, promise),
286
+ message,
287
+ inlineSnapshot,
288
+ isInline: true,
289
+ error,
290
+ errorMessage,
291
+ ...getTestNames(test)
292
+ });
293
+ });
294
+ utils.addMethod(chai.expect, 'addSnapshotSerializer', snapshot_.addSerializer);
295
+ };
296
+ external_chai_.use(expect_.JestExtend);
297
+ external_chai_.use(expect_.JestChaiExpect);
298
+ external_chai_.use(SnapshotPlugin);
299
+ external_chai_.use(expect_.JestAsymmetricMatchers);
300
+ function createExpect({ getCurrentTest, workerState }) {
301
+ const expect = (value, message)=>{
302
+ const { assertionCalls } = (0, expect_.getState)(expect);
303
+ (0, expect_.setState)({
304
+ assertionCalls: assertionCalls + 1
305
+ }, expect);
306
+ const assert = external_chai_.expect(value, message);
307
+ const _test = getCurrentTest();
308
+ if (_test) return assert.withTest(_test);
309
+ return assert;
310
+ };
311
+ Object.assign(expect, external_chai_.expect);
312
+ Object.assign(expect, globalThis[expect_.ASYMMETRIC_MATCHERS_OBJECT]);
313
+ expect.getState = ()=>(0, expect_.getState)(expect);
314
+ expect.setState = (state)=>(0, expect_.setState)(state, expect);
315
+ const globalState = (0, expect_.getState)(globalThis[expect_.GLOBAL_EXPECT]) || {};
316
+ (0, expect_.setState)({
317
+ ...globalState,
318
+ assertionCalls: 0,
319
+ isExpectingAssertions: false,
320
+ isExpectingAssertionsError: null,
321
+ expectedAssertionsNumber: null,
322
+ expectedAssertionsNumberErrorGen: null,
323
+ get testPath () {
324
+ return workerState.testPath;
325
+ }
326
+ }, expect);
327
+ expect.extend = (matchers)=>external_chai_.expect.extend(expect, matchers);
328
+ expect.addEqualityTesters = (customTesters)=>(0, expect_.addCustomEqualityTesters)(customTesters);
329
+ expect.soft = (...args)=>expect(...args).withContext({
330
+ soft: true
331
+ });
332
+ expect.poll = createExpectPoll(expect);
333
+ expect.unreachable = (message)=>{
334
+ external_chai_.assert.fail(`expected ${message ? `"${message}" ` : ''}not to be reached`);
335
+ };
336
+ function assertions(expected) {
337
+ const errorGen = ()=>new Error(`expected number of assertions to be ${expected}, but got ${expect.getState().assertionCalls}`);
338
+ if (Error.captureStackTrace) Error.captureStackTrace(errorGen(), assertions);
339
+ expect.setState({
340
+ expectedAssertionsNumber: expected,
341
+ expectedAssertionsNumberErrorGen: errorGen
342
+ });
343
+ }
344
+ function hasAssertions() {
345
+ const error = new Error('expected any number of assertion, but got none');
346
+ if (Error.captureStackTrace) Error.captureStackTrace(error, hasAssertions);
347
+ expect.setState({
348
+ isExpectingAssertions: true,
349
+ isExpectingAssertionsError: error
350
+ });
351
+ }
352
+ external_chai_.util.addMethod(expect, 'assertions', assertions);
353
+ external_chai_.util.addMethod(expect, 'hasAssertions', hasAssertions);
354
+ expect.extend(expect_.customMatchers);
355
+ return expect;
356
+ }
357
+ var runtime_util = __webpack_require__("./src/runtime/util.ts");
358
+ const normalizeFixtures = (fixtures = {}, extendFixtures = {})=>{
359
+ const result = {};
360
+ for(const key in fixtures){
361
+ const fixtureOptionKeys = [
362
+ 'auto'
363
+ ];
364
+ const value = fixtures[key];
365
+ if (Array.isArray(value)) {
366
+ if (1 === value.length && 'function' == typeof value[0]) {
367
+ result[key] = {
368
+ isFn: true,
369
+ value: value[0]
370
+ };
371
+ continue;
372
+ }
373
+ if ((0, src_utils.Kn)(value[1]) && Object.keys(value[1]).some((key)=>fixtureOptionKeys.includes(key))) {
374
+ result[key] = {
375
+ isFn: 'function' == typeof value[0],
376
+ value: value[0],
377
+ options: value[1]
378
+ };
379
+ continue;
380
+ }
381
+ }
382
+ result[key] = {
383
+ isFn: 'function' == typeof value,
384
+ value
385
+ };
386
+ }
387
+ const formattedResult = Object.fromEntries(Object.entries(result).map(([key, value])=>{
388
+ if (value.isFn) {
389
+ const usedProps = getFixtureUsedProps(value.value);
390
+ value.deps = usedProps.filter((p)=>p in result || p in extendFixtures);
391
+ }
392
+ return [
393
+ key,
394
+ value
395
+ ];
396
+ }));
397
+ return {
398
+ ...extendFixtures,
399
+ ...formattedResult
400
+ };
401
+ };
402
+ const handleFixtures = async (test, context)=>{
403
+ const cleanups = [];
404
+ if (!test.fixtures) return {
405
+ cleanups
406
+ };
407
+ const doneMap = new Set();
408
+ const pendingMap = new Set();
409
+ const usedKeys = test.originalFn ? getFixtureUsedProps(test.originalFn) : [];
410
+ const useFixture = async (name, NormalizedFixture)=>{
411
+ if (doneMap.has(name)) return;
412
+ if (pendingMap.has(name)) throw new Error(`Circular fixture dependency: ${name}`);
413
+ const { isFn, deps, value: fixtureValue } = NormalizedFixture;
414
+ if (!isFn) {
415
+ context[name] = fixtureValue;
416
+ doneMap.add(name);
417
+ return;
418
+ }
419
+ pendingMap.add(name);
420
+ if (deps?.length) for (const dep of deps)await useFixture(dep, test.fixtures[dep]);
421
+ await new Promise((fixtureResolve)=>{
422
+ let useDone;
423
+ const block = fixtureValue(context, async (value)=>{
424
+ context[name] = value;
425
+ fixtureResolve();
426
+ return new Promise((useFnResolve)=>{
427
+ useDone = useFnResolve;
428
+ });
429
+ });
430
+ cleanups.unshift(()=>{
431
+ useDone?.();
432
+ return block;
433
+ });
434
+ });
435
+ doneMap.add(name);
436
+ pendingMap.delete(name);
437
+ };
438
+ for (const [name, params] of Object.entries(test.fixtures)){
439
+ const shouldAdd = params.options?.auto || usedKeys.includes(name);
440
+ if (shouldAdd) await useFixture(name, params);
441
+ }
442
+ return {
443
+ cleanups
444
+ };
445
+ };
446
+ function splitByComma(s) {
447
+ const result = [];
448
+ const stack = [];
449
+ let start = 0;
450
+ for(let i = 0; i < s.length; i++)if ('{' === s[i] || '[' === s[i]) stack.push('{' === s[i] ? '}' : ']');
451
+ else if (s[i] === stack[stack.length - 1]) stack.pop();
452
+ else if (!stack.length && ',' === s[i]) {
453
+ const token = s.substring(start, i).trim();
454
+ if (token) result.push(token);
455
+ start = i + 1;
456
+ }
457
+ const lastToken = s.substring(start).trim();
458
+ if (lastToken) result.push(lastToken);
459
+ return result;
460
+ }
461
+ function filterOutComments(s) {
462
+ const result = [];
463
+ let commentState = 'none';
464
+ for(let i = 0; i < s.length; ++i)if ('singleline' === commentState) {
465
+ if ('\n' === s[i]) commentState = 'none';
466
+ } else if ('multiline' === commentState) {
467
+ if ('*' === s[i - 1] && '/' === s[i]) commentState = 'none';
468
+ } else if ('none' === commentState) if ('/' === s[i] && '/' === s[i + 1]) commentState = 'singleline';
469
+ else if ('/' === s[i] && '*' === s[i + 1]) {
470
+ commentState = 'multiline';
471
+ i += 2;
472
+ } else result.push(s[i]);
473
+ return result.join('');
474
+ }
475
+ function getFixtureUsedProps(fn) {
476
+ const text = filterOutComments(fn.toString());
477
+ const match = text.match(/(?:async)?(?:\s+function)?[^(]*\(([^)]*)/);
478
+ if (!match) return [];
479
+ const trimmedParams = match[1].trim();
480
+ if (!trimmedParams) return [];
481
+ const [firstParam] = splitByComma(trimmedParams);
482
+ if (firstParam?.[0] !== '{' || '}' !== firstParam[firstParam.length - 1]) {
483
+ if (firstParam?.startsWith('_')) return [];
484
+ throw new Error(`First argument must use the object destructuring pattern: ${firstParam}`);
485
+ }
486
+ const props = splitByComma(firstParam.substring(1, firstParam.length - 1)).map((prop)=>{
487
+ const colon = prop.indexOf(':');
488
+ return -1 === colon ? prop.trim() : prop.substring(0, colon).trim();
489
+ });
490
+ const restProperty = props.find((prop)=>prop.startsWith('...'));
491
+ if (restProperty) throw new Error(`Rest property "${restProperty}" is not supported. List all used fixtures explicitly, separated by comma.`);
492
+ return props;
493
+ }
494
+ const getTestStatus = (results, defaultStatus)=>{
495
+ if (0 === results.length) return defaultStatus;
496
+ return results.some((result)=>'fail' === result.status) ? 'fail' : results.every((result)=>'todo' === result.status) ? 'todo' : results.every((result)=>'skip' === result.status) ? 'skip' : 'pass';
497
+ };
498
+ function hasOnlyTest(test) {
499
+ return test.some((t)=>'only' === t.runMode || 'suite' === t.type && hasOnlyTest(t.tests));
500
+ }
501
+ const shouldTestSkip = (test, runOnly, testNamePattern)=>{
502
+ if (runOnly && 'only' !== test.runMode) return true;
503
+ if (testNamePattern && !(0, src_utils.Yz)(test, '').match(testNamePattern)) return true;
504
+ return false;
505
+ };
506
+ const traverseUpdateTestRunMode = (testSuite, parentRunMode, runOnly, testNamePattern)=>{
507
+ if (0 === testSuite.tests.length) return;
508
+ if (runOnly && 'only' !== testSuite.runMode && !hasOnlyTest(testSuite.tests)) testSuite.runMode = 'skip';
509
+ else if ([
510
+ 'skip',
511
+ 'todo'
512
+ ].includes(parentRunMode)) testSuite.runMode = parentRunMode;
513
+ const tests = testSuite.tests.map((test)=>{
514
+ const runSubOnly = runOnly && 'only' !== testSuite.runMode ? runOnly : hasOnlyTest(testSuite.tests);
515
+ if ('case' === test.type) {
516
+ if ([
517
+ 'skip',
518
+ 'todo'
519
+ ].includes(testSuite.runMode)) test.runMode = testSuite.runMode;
520
+ if (shouldTestSkip(test, runSubOnly, testNamePattern)) test.runMode = 'skip';
521
+ return test;
522
+ }
523
+ traverseUpdateTestRunMode(test, testSuite.runMode, runSubOnly, testNamePattern);
524
+ return test;
525
+ });
526
+ if ('run' !== testSuite.runMode) return;
527
+ const hasRunTest = tests.some((test)=>'run' === test.runMode || 'only' === test.runMode);
528
+ if (hasRunTest) {
529
+ testSuite.runMode = 'run';
530
+ return;
531
+ }
532
+ const allTodoTest = tests.every((test)=>'todo' === test.runMode);
533
+ testSuite.runMode = allTodoTest ? 'todo' : 'skip';
534
+ };
535
+ const updateTestModes = (tests, testNamePattern)=>{
536
+ const hasOnly = hasOnlyTest(tests);
537
+ for (const test of tests)if ('suite' === test.type) traverseUpdateTestRunMode(test, 'run', hasOnly, testNamePattern);
538
+ else if (shouldTestSkip(test, hasOnly, testNamePattern)) test.runMode = 'skip';
539
+ };
540
+ const updateTestParents = (tests, parentNames = [])=>{
541
+ for (const test of tests)if ('suite' === test.type) {
542
+ const names = test.name === src_utils.n1 ? parentNames : parentNames.concat(test.name);
543
+ updateTestParents(test.tests, names);
544
+ } else test.parentNames = parentNames;
545
+ };
546
+ const traverseUpdateTest = (tests, testNamePattern)=>{
547
+ updateTestParents(tests);
548
+ updateTestModes(tests, testNamePattern);
549
+ };
550
+ const markAllTestAsSkipped = (test)=>{
551
+ for (const t of test){
552
+ t.runMode = 'skip';
553
+ if ('suite' === t.type) markAllTestAsSkipped(t.tests);
554
+ }
555
+ };
556
+ function registerTestSuiteListener(suite, key, fn) {
557
+ const listenersKey = `${key}Listeners`;
558
+ suite[listenersKey] ??= [];
559
+ suite[listenersKey].push(fn);
560
+ }
561
+ function makeError(message, stackTraceError) {
562
+ const error = new Error(message);
563
+ if (stackTraceError?.stack) error.stack = stackTraceError.stack.replace(error.message, stackTraceError.message);
564
+ return error;
565
+ }
566
+ function wrapTimeout({ name, fn, timeout, stackTraceError }) {
567
+ if (!timeout) return fn;
568
+ return async (...args)=>{
569
+ let timeoutId;
570
+ const timeoutPromise = new Promise((_, reject)=>{
571
+ timeoutId = setTimeout(()=>reject(makeError(`${name} timed out in ${timeout}ms`, stackTraceError)), timeout);
572
+ });
573
+ try {
574
+ const result = await Promise.race([
575
+ fn(...args),
576
+ timeoutPromise
577
+ ]);
578
+ timeoutId && clearTimeout(timeoutId);
579
+ return result;
580
+ } catch (error) {
581
+ timeoutId && clearTimeout(timeoutId);
582
+ throw error;
583
+ }
584
+ };
585
+ }
586
+ function limitConcurrency(concurrency = Number.POSITIVE_INFINITY) {
587
+ let running = 0;
588
+ const queue = [];
589
+ const runNext = ()=>{
590
+ if (queue.length > 0 && running < concurrency) {
591
+ running++;
592
+ const next = queue.shift();
593
+ next();
594
+ }
595
+ };
596
+ return (func, ...args)=>new Promise((resolve, reject)=>{
597
+ const task = ()=>{
598
+ Promise.resolve(func(...args)).then(resolve).catch(reject).finally(()=>{
599
+ running--;
600
+ runNext();
601
+ });
602
+ };
603
+ if (running < concurrency) {
604
+ running++;
605
+ task();
606
+ } else queue.push(task);
607
+ });
608
+ }
609
+ class TestRunner {
610
+ _test;
611
+ workerState;
612
+ async runTests({ tests, testPath, state, hooks, api }) {
613
+ this.workerState = state;
614
+ const { runtimeConfig: { passWithNoTests, retry, maxConcurrency }, snapshotOptions } = state;
615
+ const results = [];
616
+ const errors = [];
617
+ let defaultStatus = 'pass';
618
+ hooks.onTestFileStart?.({
619
+ testPath
620
+ });
621
+ const snapshotClient = getSnapshotClient();
622
+ await snapshotClient.setup(testPath, snapshotOptions);
623
+ const runTestsCase = async (test, parentHooks)=>{
624
+ if ('skip' === test.runMode) {
625
+ snapshotClient.skipTest(testPath, (0, src_utils.Yz)(test));
626
+ const result = {
627
+ status: 'skip',
628
+ parentNames: test.parentNames,
629
+ name: test.name,
630
+ testPath
631
+ };
632
+ return result;
633
+ }
634
+ if ('todo' === test.runMode) {
635
+ const result = {
636
+ status: 'todo',
637
+ parentNames: test.parentNames,
638
+ name: test.name,
639
+ testPath
640
+ };
641
+ return result;
642
+ }
643
+ let result;
644
+ this.beforeEach(test, state, api);
645
+ const cleanups = [];
646
+ try {
647
+ for (const fn of parentHooks.beforeEachListeners){
648
+ const cleanupFn = await fn();
649
+ cleanupFn && cleanups.push(cleanupFn);
650
+ }
651
+ } catch (error) {
652
+ result = {
653
+ status: 'fail',
654
+ parentNames: test.parentNames,
655
+ name: test.name,
656
+ errors: (0, runtime_util.o)(error),
657
+ testPath
658
+ };
659
+ }
660
+ if (result?.status !== 'fail') if (test.fails) try {
661
+ const fixtureCleanups = await this.beforeRunTest(test, snapshotClient.getSnapshotState(testPath));
662
+ cleanups.push(...fixtureCleanups);
663
+ await test.fn?.(test.context);
664
+ this.afterRunTest(test);
665
+ result = {
666
+ status: 'fail',
667
+ parentNames: test.parentNames,
668
+ name: test.name,
669
+ testPath,
670
+ errors: [
671
+ {
672
+ message: 'Expect test to fail'
673
+ }
674
+ ]
675
+ };
676
+ } catch (error) {
677
+ result = {
678
+ status: 'pass',
679
+ parentNames: test.parentNames,
680
+ name: test.name,
681
+ testPath
682
+ };
683
+ }
684
+ else try {
685
+ const fixtureCleanups = await this.beforeRunTest(test, snapshotClient.getSnapshotState(testPath));
686
+ cleanups.push(...fixtureCleanups);
687
+ await test.fn?.(test.context);
688
+ this.afterRunTest(test);
689
+ result = {
690
+ parentNames: test.parentNames,
691
+ name: test.name,
692
+ status: 'pass',
693
+ testPath
694
+ };
695
+ } catch (error) {
696
+ result = {
697
+ status: 'fail',
698
+ parentNames: test.parentNames,
699
+ name: test.name,
700
+ errors: (0, runtime_util.o)(error),
701
+ testPath
702
+ };
703
+ }
704
+ const afterEachFns = [
705
+ ...parentHooks.afterEachListeners || []
706
+ ].reverse().concat(cleanups);
707
+ try {
708
+ for (const fn of afterEachFns)await fn();
709
+ } catch (error) {
710
+ result.status = 'fail';
711
+ result.errors ??= [];
712
+ result.errors.push(...(0, runtime_util.o)(error));
713
+ }
714
+ this.resetCurrentTest();
715
+ return result;
716
+ };
717
+ const limitMaxConcurrency = limitConcurrency(maxConcurrency);
718
+ const runTests = async (allTest, parentHooks)=>{
719
+ const tests = [
720
+ ...allTest
721
+ ];
722
+ while(tests.length){
723
+ const suite = tests.shift();
724
+ if (suite.concurrent) {
725
+ const cases = [
726
+ suite
727
+ ];
728
+ while(tests[0]?.concurrent)cases.push(tests.shift());
729
+ await Promise.all(cases.map((test)=>{
730
+ if ('suite' === test.type) return runTest(test, parentHooks);
731
+ return limitMaxConcurrency(()=>runTest(test, parentHooks));
732
+ }));
733
+ continue;
734
+ }
735
+ await runTest(suite, parentHooks);
736
+ }
737
+ };
738
+ const runTest = async (test, parentHooks)=>{
739
+ if ('suite' === test.type) {
740
+ if (0 === test.tests.length) {
741
+ if ([
742
+ 'todo',
743
+ 'skip'
744
+ ].includes(test.runMode)) {
745
+ defaultStatus = 'skip';
746
+ return;
747
+ }
748
+ if (passWithNoTests) return;
749
+ const noTestError = {
750
+ message: `No test found in suite: ${test.name}`,
751
+ name: 'No tests'
752
+ };
753
+ errors.push(noTestError);
754
+ const result = {
755
+ status: 'fail',
756
+ parentNames: test.parentNames,
757
+ name: test.name,
758
+ testPath,
759
+ errors: [
760
+ noTestError
761
+ ]
762
+ };
763
+ hooks.onTestCaseResult?.(result);
764
+ }
765
+ const cleanups = [];
766
+ let hasBeforeAllError = false;
767
+ if ([
768
+ 'run',
769
+ 'only'
770
+ ].includes(test.runMode) && test.beforeAllListeners) try {
771
+ for (const fn of test.beforeAllListeners){
772
+ const cleanupFn = await fn({
773
+ filepath: testPath
774
+ });
775
+ cleanupFn && cleanups.push(cleanupFn);
776
+ }
777
+ } catch (error) {
778
+ hasBeforeAllError = true;
779
+ errors.push(...(0, runtime_util.o)(error));
780
+ }
781
+ if (hasBeforeAllError) markAllTestAsSkipped(test.tests);
782
+ await runTests(test.tests, {
783
+ beforeEachListeners: parentHooks.beforeEachListeners.concat(test.beforeEachListeners || []),
784
+ afterEachListeners: parentHooks.afterEachListeners.concat(test.afterEachListeners || [])
785
+ });
786
+ const afterAllFns = [
787
+ ...test.afterAllListeners || []
788
+ ].reverse().concat(cleanups);
789
+ if ([
790
+ 'run',
791
+ 'only'
792
+ ].includes(test.runMode) && afterAllFns.length) try {
793
+ for (const fn of afterAllFns)await fn({
794
+ filepath: testPath
795
+ });
796
+ } catch (error) {
797
+ errors.push(...(0, runtime_util.o)(error));
798
+ }
799
+ } else {
800
+ const start = Date.now();
801
+ let result;
802
+ let retryCount = 0;
803
+ do {
804
+ const currentResult = await runTestsCase(test, parentHooks);
805
+ result = {
806
+ ...currentResult,
807
+ errors: 'fail' === currentResult.status && result && result.errors ? result.errors.concat(...currentResult.errors || []) : currentResult.errors
808
+ };
809
+ retryCount++;
810
+ }while (retryCount <= retry && 'fail' === result.status);
811
+ result.duration = Date.now() - start;
812
+ hooks.onTestCaseResult?.(result);
813
+ results.push(result);
814
+ }
815
+ };
816
+ const start = Date.now();
817
+ if (0 === tests.length) {
818
+ if (passWithNoTests) return {
819
+ testPath,
820
+ name: '',
821
+ status: 'pass',
822
+ results
823
+ };
824
+ return {
825
+ testPath,
826
+ name: '',
827
+ status: 'fail',
828
+ results,
829
+ errors: [
830
+ {
831
+ message: `No test suites found in file: ${testPath}`,
832
+ name: 'No tests'
833
+ }
834
+ ]
835
+ };
836
+ }
837
+ await runTests(tests, {
838
+ beforeEachListeners: [],
839
+ afterEachListeners: []
840
+ });
841
+ const snapshotResult = await snapshotClient.finish(testPath);
842
+ return {
843
+ testPath,
844
+ name: '',
845
+ status: errors.length ? 'fail' : getTestStatus(results, defaultStatus),
846
+ results,
847
+ snapshotResult,
848
+ errors,
849
+ duration: Date.now() - start
850
+ };
851
+ }
852
+ resetCurrentTest() {
853
+ this._test = void 0;
854
+ }
855
+ setCurrentTest(test) {
856
+ this._test = test;
857
+ }
858
+ getCurrentTest() {
859
+ return this._test;
860
+ }
861
+ beforeEach(test, state, api) {
862
+ const { runtimeConfig: { clearMocks, resetMocks, restoreMocks, unstubEnvs, unstubGlobals } } = state;
863
+ this.setCurrentTest(test);
864
+ if (restoreMocks) api.rstest.restoreAllMocks();
865
+ else if (resetMocks) api.rstest.resetAllMocks();
866
+ else if (clearMocks) api.rstest.clearAllMocks();
867
+ if (unstubEnvs) api.rstest.unstubAllEnvs();
868
+ if (unstubGlobals) api.rstest.unstubAllGlobals();
869
+ }
870
+ createTestContext() {
871
+ const context = ()=>{
872
+ throw new Error('done() callback is deprecated, use promise instead');
873
+ };
874
+ let _expect;
875
+ const current = this._test;
876
+ Object.defineProperty(context, 'expect', {
877
+ get: ()=>{
878
+ if (!_expect) _expect = createExpect({
879
+ workerState: this.workerState,
880
+ getCurrentTest: ()=>current
881
+ });
882
+ return _expect;
883
+ }
884
+ });
885
+ Object.defineProperty(context, '_useLocalExpect', {
886
+ get () {
887
+ return null != _expect;
888
+ }
889
+ });
890
+ return context;
891
+ }
892
+ async beforeRunTest(test, snapshotState) {
893
+ (0, expect_.setState)({
894
+ assertionCalls: 0,
895
+ isExpectingAssertions: false,
896
+ isExpectingAssertionsError: null,
897
+ expectedAssertionsNumber: null,
898
+ expectedAssertionsNumberErrorGen: null,
899
+ testPath: test.testPath,
900
+ snapshotState,
901
+ currentTestName: (0, src_utils.Yz)(test)
902
+ }, globalThis[expect_.GLOBAL_EXPECT]);
903
+ const context = this.createTestContext();
904
+ const { cleanups } = await handleFixtures(test, context);
905
+ Object.defineProperty(test, 'context', {
906
+ value: context,
907
+ enumerable: false
908
+ });
909
+ return cleanups;
910
+ }
911
+ afterRunTest(test) {
912
+ const expect = test.context._useLocalExpect ? test.context.expect : globalThis[expect_.GLOBAL_EXPECT];
913
+ const { assertionCalls, expectedAssertionsNumber, expectedAssertionsNumberErrorGen, isExpectingAssertions, isExpectingAssertionsError } = (0, expect_.getState)(expect);
914
+ if (test.result?.state === 'fail') throw test.result.errors;
915
+ if (null !== expectedAssertionsNumber && assertionCalls !== expectedAssertionsNumber) throw expectedAssertionsNumberErrorGen();
916
+ if (true === isExpectingAssertions && 0 === assertionCalls) throw isExpectingAssertionsError;
917
+ }
918
+ }
919
+ class RunnerRuntime {
920
+ tests = [];
921
+ _currentTest = [];
922
+ testPath;
923
+ collectStatus = 'lazy';
924
+ currentCollectList = [];
925
+ defaultHookTimeout = 5000;
926
+ defaultTestTimeout;
927
+ constructor({ testPath, testTimeout }){
928
+ this.testPath = testPath;
929
+ this.defaultTestTimeout = testTimeout;
930
+ }
931
+ afterAll(fn, timeout = this.defaultHookTimeout) {
932
+ const currentSuite = this.getCurrentSuite();
933
+ registerTestSuiteListener(currentSuite, 'afterAll', wrapTimeout({
934
+ name: 'afterAll hook',
935
+ fn,
936
+ timeout,
937
+ stackTraceError: new Error('STACK_TRACE_ERROR')
938
+ }));
939
+ }
940
+ beforeAll(fn, timeout = this.defaultHookTimeout) {
941
+ const currentSuite = this.getCurrentSuite();
942
+ registerTestSuiteListener(currentSuite, 'beforeAll', wrapTimeout({
943
+ name: 'beforeAll hook',
944
+ fn,
945
+ timeout,
946
+ stackTraceError: new Error('STACK_TRACE_ERROR')
947
+ }));
948
+ }
949
+ afterEach(fn, timeout = this.defaultHookTimeout) {
950
+ const currentSuite = this.getCurrentSuite();
951
+ registerTestSuiteListener(currentSuite, 'afterEach', wrapTimeout({
952
+ name: 'afterEach hook',
953
+ fn,
954
+ timeout,
955
+ stackTraceError: new Error('STACK_TRACE_ERROR')
956
+ }));
957
+ }
958
+ beforeEach(fn, timeout = this.defaultHookTimeout) {
959
+ const currentSuite = this.getCurrentSuite();
960
+ registerTestSuiteListener(currentSuite, 'beforeEach', wrapTimeout({
961
+ name: 'beforeEach hook',
962
+ fn,
963
+ timeout,
964
+ stackTraceError: new Error('STACK_TRACE_ERROR')
965
+ }));
966
+ }
967
+ getDefaultRootSuite() {
968
+ return {
969
+ runMode: 'run',
970
+ testPath: this.testPath,
971
+ name: src_utils.n1,
972
+ tests: [],
973
+ type: 'suite'
974
+ };
975
+ }
976
+ describe({ name, fn, runMode = 'run', each = false, concurrent, sequential }) {
977
+ const currentSuite = {
978
+ name,
979
+ runMode,
980
+ tests: [],
981
+ type: 'suite',
982
+ each,
983
+ testPath: this.testPath,
984
+ concurrent,
985
+ sequential
986
+ };
987
+ if (!fn) {
988
+ this.addTest(currentSuite);
989
+ this.resetCurrentTest();
990
+ return;
991
+ }
992
+ this.collectStatus = 'lazy';
993
+ this.currentCollectList.push(async ()=>{
994
+ this.addTest(currentSuite);
995
+ const result = fn();
996
+ if (result instanceof Promise) await result;
997
+ await this.collectCurrentTest();
998
+ this.resetCurrentTest();
999
+ });
1000
+ }
1001
+ resetCurrentTest() {
1002
+ this._currentTest.pop();
1003
+ }
1004
+ addTest(test) {
1005
+ if (0 === this._currentTest.length) this.tests.push(test);
1006
+ else {
1007
+ const current = this._currentTest[this._currentTest.length - 1];
1008
+ if (current.each || current.inTestEach) test.inTestEach = true;
1009
+ if (current.concurrent && true !== test.sequential) test.concurrent = true;
1010
+ if (current.sequential && true !== test.concurrent) test.sequential = true;
1011
+ if ('case' === current.type) throw new Error('Calling the test function inside another test function is not allowed. Please put it inside "describe" so it can be properly collected.');
1012
+ current.tests.push(test);
1013
+ }
1014
+ this._currentTest.push(test);
1015
+ }
1016
+ async collectCurrentTest() {
1017
+ const currentCollectList = this.currentCollectList;
1018
+ this.currentCollectList = [];
1019
+ while(currentCollectList.length > 0){
1020
+ this.collectStatus = 'running';
1021
+ const fn = currentCollectList.shift();
1022
+ await fn();
1023
+ }
1024
+ }
1025
+ async getTests() {
1026
+ while(this.currentCollectList.length > 0)await this.collectCurrentTest();
1027
+ return this.tests;
1028
+ }
1029
+ addTestCase(test) {
1030
+ if ('lazy' === this.collectStatus) this.currentCollectList.push(()=>{
1031
+ this.addTest({
1032
+ ...test,
1033
+ testPath: this.testPath,
1034
+ context: void 0
1035
+ });
1036
+ this.resetCurrentTest();
1037
+ });
1038
+ else {
1039
+ this.addTest({
1040
+ ...test,
1041
+ testPath: this.testPath,
1042
+ context: void 0
1043
+ });
1044
+ this.resetCurrentTest();
1045
+ }
1046
+ }
1047
+ ensureRootSuite() {
1048
+ if (0 === this._currentTest.length) this.addTest(this.getDefaultRootSuite());
1049
+ }
1050
+ it({ name, fn, originalFn = fn, fixtures, timeout = this.defaultTestTimeout, runMode = 'run', fails = false, each = false, concurrent, sequential }) {
1051
+ this.addTestCase({
1052
+ name,
1053
+ originalFn,
1054
+ fn: fn ? wrapTimeout({
1055
+ name: 'test',
1056
+ fn,
1057
+ timeout,
1058
+ stackTraceError: new Error('STACK_TRACE_ERROR')
1059
+ }) : fn,
1060
+ runMode,
1061
+ type: 'case',
1062
+ timeout,
1063
+ fixtures,
1064
+ concurrent,
1065
+ sequential,
1066
+ each,
1067
+ fails
1068
+ });
1069
+ }
1070
+ describeEach({ cases, ...options }) {
1071
+ return (name, fn)=>{
1072
+ for(let i = 0; i < cases.length; i++){
1073
+ const param = cases[i];
1074
+ const params = (0, src_utils.XQ)(param);
1075
+ this.describe({
1076
+ name: (0, runtime_util.K)(name, param, i),
1077
+ fn: ()=>fn?.(...params),
1078
+ ...options,
1079
+ each: true
1080
+ });
1081
+ }
1082
+ };
1083
+ }
1084
+ describeFor({ cases, ...options }) {
1085
+ return (name, fn)=>{
1086
+ for(let i = 0; i < cases.length; i++){
1087
+ const param = cases[i];
1088
+ this.describe({
1089
+ name: (0, runtime_util.K)(name, param, i),
1090
+ fn: ()=>fn?.(param),
1091
+ ...options,
1092
+ each: true
1093
+ });
1094
+ }
1095
+ };
1096
+ }
1097
+ each({ cases, ...options }) {
1098
+ return (name, fn, timeout = this.defaultTestTimeout)=>{
1099
+ for(let i = 0; i < cases.length; i++){
1100
+ const param = cases[i];
1101
+ const params = (0, src_utils.XQ)(param);
1102
+ this.it({
1103
+ name: (0, runtime_util.K)(name, param, i),
1104
+ originalFn: fn,
1105
+ fn: ()=>fn?.(...params),
1106
+ timeout,
1107
+ ...options,
1108
+ each: true
1109
+ });
1110
+ }
1111
+ };
1112
+ }
1113
+ for({ cases, ...options }) {
1114
+ return (name, fn, timeout = this.defaultTestTimeout)=>{
1115
+ for(let i = 0; i < cases.length; i++){
1116
+ const param = cases[i];
1117
+ this.it({
1118
+ name: (0, runtime_util.K)(name, param, i),
1119
+ originalFn: fn,
1120
+ fn: (context)=>fn?.(param, context),
1121
+ timeout,
1122
+ ...options,
1123
+ each: true
1124
+ });
1125
+ }
1126
+ };
1127
+ }
1128
+ getCurrentSuite() {
1129
+ this.ensureRootSuite();
1130
+ for(let i = this._currentTest.length - 1; i >= 0; i--){
1131
+ const test = this._currentTest[i];
1132
+ if ('suite' === test.type) return test;
1133
+ }
1134
+ throw new Error('Expect to find a suite, but got undefined');
1135
+ }
1136
+ }
1137
+ const createRuntimeAPI = ({ testPath, testTimeout })=>{
1138
+ const runtimeInstance = new RunnerRuntime({
1139
+ testPath,
1140
+ testTimeout
1141
+ });
1142
+ const createTestAPI = (options = {})=>{
1143
+ const testFn = (name, fn, timeout)=>runtimeInstance.it({
1144
+ name,
1145
+ fn,
1146
+ timeout,
1147
+ ...options
1148
+ });
1149
+ for (const { name, overrides } of [
1150
+ {
1151
+ name: 'fails',
1152
+ overrides: {
1153
+ fails: true
1154
+ }
1155
+ },
1156
+ {
1157
+ name: 'concurrent',
1158
+ overrides: {
1159
+ concurrent: true
1160
+ }
1161
+ },
1162
+ {
1163
+ name: 'sequential',
1164
+ overrides: {
1165
+ sequential: true
1166
+ }
1167
+ },
1168
+ {
1169
+ name: 'skip',
1170
+ overrides: {
1171
+ runMode: 'skip'
1172
+ }
1173
+ },
1174
+ {
1175
+ name: 'todo',
1176
+ overrides: {
1177
+ runMode: 'todo'
1178
+ }
1179
+ },
1180
+ {
1181
+ name: 'only',
1182
+ overrides: {
1183
+ runMode: 'only'
1184
+ }
1185
+ }
1186
+ ])Object.defineProperty(testFn, name, {
1187
+ get: ()=>createTestAPI({
1188
+ ...options,
1189
+ ...overrides
1190
+ }),
1191
+ enumerable: true
1192
+ });
1193
+ testFn.runIf = (condition)=>condition ? testFn : testFn.skip;
1194
+ testFn.skipIf = (condition)=>condition ? testFn.skip : testFn;
1195
+ testFn.each = (cases)=>runtimeInstance.each({
1196
+ cases,
1197
+ ...options
1198
+ });
1199
+ testFn.for = (cases)=>runtimeInstance.for({
1200
+ cases,
1201
+ ...options
1202
+ });
1203
+ return testFn;
1204
+ };
1205
+ const it = createTestAPI();
1206
+ it.extend = (fixtures)=>{
1207
+ const extend = (fixtures, extendFixtures)=>{
1208
+ const normalizedFixtures = normalizeFixtures(fixtures, extendFixtures);
1209
+ const api = createTestAPI({
1210
+ fixtures: normalizedFixtures
1211
+ });
1212
+ api.extend = (subFixtures)=>extend(subFixtures, normalizedFixtures);
1213
+ return api;
1214
+ };
1215
+ return extend(fixtures);
1216
+ };
1217
+ const createDescribeAPI = (options = {})=>{
1218
+ const describeFn = (name, fn)=>runtimeInstance.describe({
1219
+ name,
1220
+ fn,
1221
+ ...options
1222
+ });
1223
+ for (const { name, overrides } of [
1224
+ {
1225
+ name: 'only',
1226
+ overrides: {
1227
+ runMode: 'only'
1228
+ }
1229
+ },
1230
+ {
1231
+ name: 'todo',
1232
+ overrides: {
1233
+ runMode: 'todo'
1234
+ }
1235
+ },
1236
+ {
1237
+ name: 'skip',
1238
+ overrides: {
1239
+ runMode: 'skip'
1240
+ }
1241
+ },
1242
+ {
1243
+ name: 'concurrent',
1244
+ overrides: {
1245
+ concurrent: true
1246
+ }
1247
+ },
1248
+ {
1249
+ name: 'sequential',
1250
+ overrides: {
1251
+ sequential: true
1252
+ }
1253
+ }
1254
+ ])Object.defineProperty(describeFn, name, {
1255
+ get: ()=>createDescribeAPI({
1256
+ ...options,
1257
+ ...overrides
1258
+ }),
1259
+ enumerable: true
1260
+ });
1261
+ describeFn.skipIf = (condition)=>condition ? describeFn.skip : describeFn;
1262
+ describeFn.runIf = (condition)=>condition ? describeFn : describeFn.skip;
1263
+ describeFn.each = (cases)=>runtimeInstance.describeEach({
1264
+ cases,
1265
+ ...options
1266
+ });
1267
+ describeFn.for = (cases)=>runtimeInstance.describeFor({
1268
+ cases,
1269
+ ...options
1270
+ });
1271
+ return describeFn;
1272
+ };
1273
+ const describe = createDescribeAPI();
1274
+ return {
1275
+ api: {
1276
+ describe,
1277
+ it,
1278
+ test: it,
1279
+ afterAll: runtimeInstance.afterAll.bind(runtimeInstance),
1280
+ beforeAll: runtimeInstance.beforeAll.bind(runtimeInstance),
1281
+ afterEach: runtimeInstance.afterEach.bind(runtimeInstance),
1282
+ beforeEach: runtimeInstance.beforeEach.bind(runtimeInstance)
1283
+ },
1284
+ instance: runtimeInstance
1285
+ };
1286
+ };
1287
+ function createRunner({ workerState }) {
1288
+ const { testPath, runtimeConfig: { testTimeout, testNamePattern } } = workerState;
1289
+ const runtime = createRuntimeAPI({
1290
+ testPath,
1291
+ testTimeout
1292
+ });
1293
+ const testRunner = new TestRunner();
1294
+ return {
1295
+ api: runtime.api,
1296
+ runner: {
1297
+ runTests: async (testPath, hooks, api)=>{
1298
+ const tests = await runtime.instance.getTests();
1299
+ traverseUpdateTest(tests, testNamePattern);
1300
+ const results = await testRunner.runTests({
1301
+ tests,
1302
+ testPath,
1303
+ state: workerState,
1304
+ hooks,
1305
+ api
1306
+ });
1307
+ hooks.onTestFileResult?.(results);
1308
+ return results;
1309
+ },
1310
+ collectTests: async ()=>{
1311
+ const tests = await runtime.instance.getTests();
1312
+ traverseUpdateTest(tests, testNamePattern);
1313
+ return tests;
1314
+ },
1315
+ getCurrentTest: ()=>testRunner.getCurrentTest()
1316
+ }
1317
+ };
1318
+ }
1319
+ function dist_assert(condition, message) {
1320
+ if (!condition) throw new Error(message);
1321
+ }
1322
+ function isType(type, value) {
1323
+ return typeof value === type;
1324
+ }
1325
+ function isPromise(value) {
1326
+ return value instanceof Promise;
1327
+ }
1328
+ function dist_define(obj, key, descriptor) {
1329
+ Object.defineProperty(obj, key, descriptor);
1330
+ }
1331
+ function defineValue(obj, key, value) {
1332
+ dist_define(obj, key, {
1333
+ value,
1334
+ configurable: !0,
1335
+ writable: !0
1336
+ });
1337
+ }
1338
+ var SYMBOL_STATE = Symbol.for("tinyspy:spy");
1339
+ var spies = /* @__PURE__ */ new Set(), dist_reset = (state)=>{
1340
+ state.called = !1, state.callCount = 0, state.calls = [], state.results = [], state.resolves = [], state.next = [];
1341
+ }, defineState = (spy2)=>(dist_define(spy2, SYMBOL_STATE, {
1342
+ value: {
1343
+ reset: ()=>dist_reset(spy2[SYMBOL_STATE])
1344
+ }
1345
+ }), spy2[SYMBOL_STATE]), getInternalState = (spy2)=>spy2[SYMBOL_STATE] || defineState(spy2);
1346
+ function createInternalSpy(cb) {
1347
+ dist_assert(isType("function", cb) || isType("undefined", cb), "cannot spy on a non-function value");
1348
+ let fn = function(...args) {
1349
+ let state2 = getInternalState(fn);
1350
+ state2.called = !0, state2.callCount++, state2.calls.push(args);
1351
+ let next = state2.next.shift();
1352
+ if (next) {
1353
+ state2.results.push(next);
1354
+ let [type2, result2] = next;
1355
+ if ("ok" === type2) return result2;
1356
+ throw result2;
1357
+ }
1358
+ let result, type = "ok", resultIndex = state2.results.length;
1359
+ if (state2.impl) try {
1360
+ new.target ? result = Reflect.construct(state2.impl, args, new.target) : result = state2.impl.apply(this, args), type = "ok";
1361
+ } catch (err) {
1362
+ throw result = err, type = "error", state2.results.push([
1363
+ type,
1364
+ err
1365
+ ]), err;
1366
+ }
1367
+ let resultTuple = [
1368
+ type,
1369
+ result
1370
+ ];
1371
+ return isPromise(result) && result.then((r)=>state2.resolves[resultIndex] = [
1372
+ "ok",
1373
+ r
1374
+ ], (e)=>state2.resolves[resultIndex] = [
1375
+ "error",
1376
+ e
1377
+ ]), state2.results.push(resultTuple), result;
1378
+ };
1379
+ defineValue(fn, "_isMockFunction", !0), defineValue(fn, "length", cb ? cb.length : 0), defineValue(fn, "name", cb && cb.name || "spy");
1380
+ let state = getInternalState(fn);
1381
+ return state.reset(), state.impl = cb, fn;
1382
+ }
1383
+ function isMockFunction(obj) {
1384
+ return !!obj && !0 === obj._isMockFunction;
1385
+ }
1386
+ var getDescriptor = (obj, method)=>{
1387
+ let objDescriptor = Object.getOwnPropertyDescriptor(obj, method);
1388
+ if (objDescriptor) return [
1389
+ obj,
1390
+ objDescriptor
1391
+ ];
1392
+ let currentProto = Object.getPrototypeOf(obj);
1393
+ for(; null !== currentProto;){
1394
+ let descriptor = Object.getOwnPropertyDescriptor(currentProto, method);
1395
+ if (descriptor) return [
1396
+ currentProto,
1397
+ descriptor
1398
+ ];
1399
+ currentProto = Object.getPrototypeOf(currentProto);
1400
+ }
1401
+ }, setPototype = (fn, val)=>{
1402
+ null != val && "function" == typeof val && null != val.prototype && Object.setPrototypeOf(fn.prototype, val.prototype);
1403
+ };
1404
+ function internalSpyOn(obj, methodName, mock) {
1405
+ dist_assert(!isType("undefined", obj), "spyOn could not find an object to spy upon"), dist_assert(isType("object", obj) || isType("function", obj), "cannot spyOn on a primitive value");
1406
+ let [accessName, accessType] = (()=>{
1407
+ if (!isType("object", methodName)) return [
1408
+ methodName,
1409
+ "value"
1410
+ ];
1411
+ if ("getter" in methodName && "setter" in methodName) throw new Error("cannot spy on both getter and setter");
1412
+ if ("getter" in methodName) return [
1413
+ methodName.getter,
1414
+ "get"
1415
+ ];
1416
+ if ("setter" in methodName) return [
1417
+ methodName.setter,
1418
+ "set"
1419
+ ];
1420
+ throw new Error("specify getter or setter to spy on");
1421
+ })(), [originalDescriptorObject, originalDescriptor] = getDescriptor(obj, accessName) || [];
1422
+ dist_assert(originalDescriptor || accessName in obj, `${String(accessName)} does not exist`);
1423
+ let ssr = !1;
1424
+ "value" === accessType && originalDescriptor && !originalDescriptor.value && originalDescriptor.get && (accessType = "get", ssr = !0, mock = originalDescriptor.get());
1425
+ let original;
1426
+ originalDescriptor ? original = originalDescriptor[accessType] : "value" !== accessType ? original = ()=>obj[accessName] : original = obj[accessName], original && isSpyFunction(original) && (original = original[SYMBOL_STATE].getOriginal());
1427
+ let reassign = (cb)=>{
1428
+ let { value, ...desc } = originalDescriptor || {
1429
+ configurable: !0,
1430
+ writable: !0
1431
+ };
1432
+ "value" !== accessType && delete desc.writable, desc[accessType] = cb, dist_define(obj, accessName, desc);
1433
+ }, restore = ()=>{
1434
+ originalDescriptorObject !== obj ? Reflect.deleteProperty(obj, accessName) : originalDescriptor && !original ? dist_define(obj, accessName, originalDescriptor) : reassign(original);
1435
+ };
1436
+ mock || (mock = original);
1437
+ let spy2 = wrap(createInternalSpy(mock), mock);
1438
+ "value" === accessType && setPototype(spy2, original);
1439
+ let state = spy2[SYMBOL_STATE];
1440
+ return defineValue(state, "restore", restore), defineValue(state, "getOriginal", ()=>ssr ? original() : original), defineValue(state, "willCall", (newCb)=>(state.impl = newCb, spy2)), reassign(ssr ? ()=>(setPototype(spy2, mock), spy2) : spy2), spies.add(spy2), spy2;
1441
+ }
1442
+ var ignoreProperties = /* @__PURE__ */ new Set([
1443
+ "length",
1444
+ "name",
1445
+ "prototype"
1446
+ ]);
1447
+ function getAllProperties(original) {
1448
+ let properties = /* @__PURE__ */ new Set(), descriptors2 = {};
1449
+ for(; original && original !== Object.prototype && original !== Function.prototype;){
1450
+ let ownProperties = [
1451
+ ...Object.getOwnPropertyNames(original),
1452
+ ...Object.getOwnPropertySymbols(original)
1453
+ ];
1454
+ for (let prop of ownProperties)descriptors2[prop] || ignoreProperties.has(prop) || (properties.add(prop), descriptors2[prop] = Object.getOwnPropertyDescriptor(original, prop));
1455
+ original = Object.getPrototypeOf(original);
1456
+ }
1457
+ return {
1458
+ properties,
1459
+ descriptors: descriptors2
1460
+ };
1461
+ }
1462
+ function wrap(mock, original) {
1463
+ if (!original || SYMBOL_STATE in original) return mock;
1464
+ let { properties, descriptors: descriptors2 } = getAllProperties(original);
1465
+ for (let key of properties){
1466
+ let descriptor = descriptors2[key];
1467
+ getDescriptor(mock, key) || dist_define(mock, key, descriptor);
1468
+ }
1469
+ return mock;
1470
+ }
1471
+ function isSpyFunction(obj) {
1472
+ return isMockFunction(obj) && "getOriginal" in obj[SYMBOL_STATE];
1473
+ }
1474
+ let callOrder = 0;
1475
+ const mocks = new Set();
1476
+ const wrapSpy = (obj, methodName, mockFn)=>{
1477
+ const spyImpl = internalSpyOn(obj, methodName, mockFn);
1478
+ const spyFn = spyImpl;
1479
+ let mockImplementationOnce = [];
1480
+ let implementation = mockFn;
1481
+ let mockName = mockFn?.name;
1482
+ const initMockState = ()=>({
1483
+ instances: [],
1484
+ contexts: [],
1485
+ invocationCallOrder: []
1486
+ });
1487
+ let mockState = initMockState();
1488
+ const spyState = getInternalState(spyImpl);
1489
+ spyFn.getMockName = ()=>mockName || methodName;
1490
+ spyFn.mockName = (name)=>{
1491
+ mockName = name;
1492
+ return spyFn;
1493
+ };
1494
+ spyFn.getMockImplementation = ()=>mockImplementationOnce.length ? mockImplementationOnce[mockImplementationOnce.length - 1] : implementation;
1495
+ function withImplementation(fn, cb) {
1496
+ const originalImplementation = implementation;
1497
+ const originalMockImplementationOnce = mockImplementationOnce;
1498
+ implementation = fn;
1499
+ mockImplementationOnce = [];
1500
+ spyState.willCall(willCall);
1501
+ const reset = ()=>{
1502
+ implementation = originalImplementation;
1503
+ mockImplementationOnce = originalMockImplementationOnce;
1504
+ };
1505
+ const result = cb();
1506
+ if (result instanceof Promise) return result.then(()=>{
1507
+ reset();
1508
+ });
1509
+ reset();
1510
+ }
1511
+ spyFn.withImplementation = withImplementation;
1512
+ spyFn.mockImplementation = (fn)=>{
1513
+ implementation = fn;
1514
+ return spyFn;
1515
+ };
1516
+ spyFn.mockImplementationOnce = (fn)=>{
1517
+ mockImplementationOnce.push(fn);
1518
+ return spyFn;
1519
+ };
1520
+ spyFn.mockReturnValue = (value)=>spyFn.mockImplementation(()=>value);
1521
+ spyFn.mockReturnValueOnce = (value)=>spyFn.mockImplementationOnce(()=>value);
1522
+ spyFn.mockResolvedValue = (value)=>spyFn.mockImplementation(()=>Promise.resolve(value));
1523
+ spyFn.mockResolvedValueOnce = (value)=>spyFn.mockImplementationOnce(()=>Promise.resolve(value));
1524
+ spyFn.mockRejectedValue = (value)=>spyFn.mockImplementation(()=>Promise.reject(value));
1525
+ spyFn.mockRejectedValueOnce = (value)=>spyFn.mockImplementationOnce(()=>Promise.reject(value));
1526
+ spyFn.mockReturnThis = ()=>spyFn.mockImplementation(function() {
1527
+ return this;
1528
+ });
1529
+ function willCall(...args) {
1530
+ let impl = implementation || spyState.getOriginal();
1531
+ mockState.instances.push(this);
1532
+ mockState.contexts.push(this);
1533
+ mockState.invocationCallOrder.push(++callOrder);
1534
+ if (mockImplementationOnce.length) impl = mockImplementationOnce.shift();
1535
+ return impl?.apply(this, args);
1536
+ }
1537
+ spyState.willCall(willCall);
1538
+ Object.defineProperty(spyFn, 'mock', {
1539
+ get: ()=>({
1540
+ get calls () {
1541
+ return spyState.calls;
1542
+ },
1543
+ get lastCall () {
1544
+ return spyState.calls[spyState.callCount - 1];
1545
+ },
1546
+ get instances () {
1547
+ return mockState.instances;
1548
+ },
1549
+ get contexts () {
1550
+ return mockState.contexts;
1551
+ },
1552
+ get invocationCallOrder () {
1553
+ return mockState.invocationCallOrder;
1554
+ },
1555
+ get results () {
1556
+ return spyState.results.map(([resultType, value])=>{
1557
+ const type = 'error' === resultType ? 'throw' : 'return';
1558
+ return {
1559
+ type: type,
1560
+ value
1561
+ };
1562
+ });
1563
+ },
1564
+ get settledResults () {
1565
+ return spyState.resolves.map(([resultType, value])=>{
1566
+ const type = 'error' === resultType ? 'rejected' : 'fulfilled';
1567
+ return {
1568
+ type,
1569
+ value
1570
+ };
1571
+ });
1572
+ }
1573
+ })
1574
+ });
1575
+ spyFn.mockClear = ()=>{
1576
+ mockState = initMockState();
1577
+ spyState.reset();
1578
+ return spyFn;
1579
+ };
1580
+ spyFn.mockReset = ()=>{
1581
+ spyFn.mockClear();
1582
+ implementation = mockFn;
1583
+ mockImplementationOnce = [];
1584
+ return spyFn;
1585
+ };
1586
+ spyFn.mockRestore = ()=>{
1587
+ spyFn.mockReset();
1588
+ spyState.restore();
1589
+ mockName = mockFn?.name;
1590
+ };
1591
+ mocks.add(spyFn);
1592
+ return spyFn;
1593
+ };
1594
+ const spy_fn = (mockFn)=>{
1595
+ const defaultName = 'rstest.fn()';
1596
+ return wrapSpy({
1597
+ [defaultName]: mockFn
1598
+ }, defaultName, mockFn);
1599
+ };
1600
+ const spy_spyOn = (obj, methodName, accessType)=>{
1601
+ const accessTypeMap = {
1602
+ get: 'getter',
1603
+ set: 'setter'
1604
+ };
1605
+ const method = accessType ? {
1606
+ [accessTypeMap[accessType]]: methodName
1607
+ } : methodName;
1608
+ return wrapSpy(obj, method);
1609
+ };
1610
+ const spy_isMockFunction = (fn)=>'function' == typeof fn && '_isMockFunction' in fn && fn._isMockFunction;
1611
+ const createRstestUtilities = ()=>{
1612
+ const originalEnvValues = new Map();
1613
+ const originalGlobalValues = new Map();
1614
+ const rstest = {
1615
+ fn: spy_fn,
1616
+ spyOn: spy_spyOn,
1617
+ isMockFunction: spy_isMockFunction,
1618
+ clearAllMocks: ()=>{
1619
+ for (const mock of mocks)mock.mockClear();
1620
+ return rstest;
1621
+ },
1622
+ resetAllMocks: ()=>{
1623
+ for (const mock of mocks)mock.mockReset();
1624
+ return rstest;
1625
+ },
1626
+ restoreAllMocks: ()=>{
1627
+ for (const mock of mocks)mock.mockRestore();
1628
+ return rstest;
1629
+ },
1630
+ mock: ()=>{},
1631
+ doMock: ()=>{},
1632
+ unMock: ()=>{},
1633
+ doUnMock: ()=>{},
1634
+ importMock: async ()=>({}),
1635
+ importActual: async ()=>({}),
1636
+ resetModules: ()=>rstest,
1637
+ stubEnv: (name, value)=>{
1638
+ if (!originalEnvValues.has(name)) originalEnvValues.set(name, process.env[name]);
1639
+ if (void 0 === value) delete process.env[name];
1640
+ else process.env[name] = value;
1641
+ return rstest;
1642
+ },
1643
+ unstubAllEnvs: ()=>{
1644
+ for (const [name, value] of originalEnvValues)if (void 0 === value) delete process.env[name];
1645
+ else process.env[name] = value;
1646
+ originalEnvValues.clear();
1647
+ return rstest;
1648
+ },
1649
+ stubGlobal: (name, value)=>{
1650
+ if (!originalGlobalValues.has(name)) originalGlobalValues.set(name, Object.getOwnPropertyDescriptor(globalThis, name));
1651
+ Object.defineProperty(globalThis, name, {
1652
+ value,
1653
+ writable: true,
1654
+ configurable: true,
1655
+ enumerable: true
1656
+ });
1657
+ return rstest;
1658
+ },
1659
+ unstubAllGlobals: ()=>{
1660
+ originalGlobalValues.forEach((original, name)=>{
1661
+ if (original) Object.defineProperty(globalThis, name, original);
1662
+ else Reflect.deleteProperty(globalThis, name);
1663
+ });
1664
+ originalGlobalValues.clear();
1665
+ return rstest;
1666
+ }
1667
+ };
1668
+ return rstest;
1669
+ };
1670
+ const createRstestRuntime = (workerState)=>{
1671
+ const { runner, api: runnerAPI } = createRunner({
1672
+ workerState
1673
+ });
1674
+ const expect = createExpect({
1675
+ workerState,
1676
+ getCurrentTest: ()=>runner.getCurrentTest()
1677
+ });
1678
+ Object.defineProperty(globalThis, expect_.GLOBAL_EXPECT, {
1679
+ value: expect,
1680
+ writable: true,
1681
+ configurable: true
1682
+ });
1683
+ return {
1684
+ runner,
1685
+ api: {
1686
+ ...runnerAPI,
1687
+ expect,
1688
+ assert: external_chai_.assert,
1689
+ rstest: createRstestUtilities()
1690
+ }
1691
+ };
1692
+ };
1693
+ },
1694
+ "./src/utils/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
1695
+ __webpack_require__.d(__webpack_exports__, {
1696
+ Kn: ()=>helper.Kn,
1697
+ AS: ()=>helper.AS,
1698
+ n1: ()=>constants.n1,
1699
+ XQ: ()=>helper.XQ,
1700
+ $_: ()=>helper.$_,
1701
+ Yz: ()=>helper.Yz
1702
+ });
1703
+ var helper = __webpack_require__("./src/utils/helper.ts");
1704
+ __webpack_require__("./src/utils/logger.ts");
1705
+ __webpack_require__("node:fs/promises");
1706
+ __webpack_require__("pathe");
1707
+ var constants = __webpack_require__("./src/utils/constants.ts");
1708
+ }
1709
+ };