@rstest/core 0.7.7 → 0.7.9

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 (57) hide show
  1. package/LICENSE.md +294 -0
  2. package/dist/0~130.js +2 -2
  3. package/dist/0~1472.js +48 -0
  4. package/dist/0~1981.js +3 -0
  5. package/dist/0~2173.js +25 -10
  6. package/dist/0~2255.js +2 -2
  7. package/dist/0~3062.js +0 -5
  8. package/dist/0~3919.js +1 -1
  9. package/dist/0~4403.js +6 -5
  10. package/dist/0~4809.js +4 -4
  11. package/dist/0~5835.js +2 -2
  12. package/dist/0~62.js +3 -3
  13. package/dist/0~6588.js +3 -3
  14. package/dist/0~6923.js +2 -2
  15. package/dist/0~7583.js +9 -8
  16. package/dist/0~7882.js +1144 -0
  17. package/dist/0~8426.js +1 -2
  18. package/dist/0~89.js +33 -24
  19. package/dist/0~9348.js +953 -0
  20. package/dist/0~9634.js +58 -10
  21. package/dist/1157.js +13 -118
  22. package/dist/{7913.js → 1294.js} +51 -1745
  23. package/dist/2672.js +647 -0
  24. package/dist/3278.js +3 -450
  25. package/dist/4484.js +38 -0
  26. package/dist/487.js +1739 -0
  27. package/dist/4899.js +11 -0
  28. package/dist/5734.js +1 -1
  29. package/dist/{0~6151.js → 6151.js} +169 -21
  30. package/dist/{0~6973.js → 6973.js} +5 -5
  31. package/dist/721.js +9 -0
  32. package/dist/9131.js +559 -502
  33. package/dist/browser-runtime/2~907.js +1211 -0
  34. package/dist/browser-runtime/2~907.js.map +1 -0
  35. package/dist/browser-runtime/389.js +22071 -0
  36. package/dist/browser-runtime/389.js.LICENSE.txt +329 -0
  37. package/dist/browser-runtime/389.js.map +1 -0
  38. package/dist/browser-runtime/index.d.ts +2806 -0
  39. package/dist/browser-runtime/index.js +1 -0
  40. package/dist/browser-runtime/rslib-runtime.js +50 -0
  41. package/dist/browser-runtime/rslib-runtime.js.map +1 -0
  42. package/dist/browser.d.ts +3329 -0
  43. package/dist/browser.js +14 -0
  44. package/dist/cssFilterLoader.mjs +1 -1
  45. package/dist/globalSetupWorker.js +3 -2
  46. package/dist/index.d.ts +67 -2
  47. package/dist/index.js +2 -1
  48. package/dist/rslib-runtime.js +27 -0
  49. package/dist/rstestSuppressWarnings.cjs +9 -0
  50. package/dist/worker.d.ts +66 -2
  51. package/dist/worker.js +415 -1
  52. package/package.json +29 -14
  53. package/dist/0~8957.js +0 -149
  54. package/dist/554.js +0 -417
  55. package/dist/5693.js +0 -91
  56. /package/dist/{7913.js.LICENSE.txt → 1294.js.LICENSE.txt} +0 -0
  57. /package/dist/{0~6151.js.LICENSE.txt → 6151.js.LICENSE.txt} +0 -0
package/dist/worker.js CHANGED
@@ -1,3 +1,417 @@
1
1
  import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
- export { default } from "./554.js";
3
+ import { __webpack_require__ } from "./rslib-runtime.js";
4
+ import { basename, isAbsolute, undoSerializableConfig, dirname, resolve as pathe_M_eThtNZ_resolve, join } from "./2672.js";
5
+ import "./487.js";
6
+ import { node_v8, createBirpc } from "./3216.js";
7
+ import { createCoverageProvider } from "./5734.js";
8
+ import { formatTestError, setRealTimers, getRealTimers } from "./1294.js";
9
+ import { globalApis } from "./1157.js";
10
+ const processSend = process.send.bind(process);
11
+ const processOn = process.on.bind(process);
12
+ const processOff = process.off.bind(process);
13
+ function createForksRpcOptions({ nodeV8 = node_v8, dispose = [] }) {
14
+ return {
15
+ serialize: nodeV8.serialize,
16
+ deserialize: (v)=>nodeV8.deserialize(Buffer.from(v)),
17
+ post (v) {
18
+ processSend(v);
19
+ },
20
+ on (fn) {
21
+ const handler = (message, ...extras)=>{
22
+ if (message?.__tinypool_worker_message__) return;
23
+ return fn(message, ...extras);
24
+ };
25
+ processOn('message', handler);
26
+ dispose.push(()=>processOff('message', handler));
27
+ }
28
+ };
29
+ }
30
+ function createRuntimeRpc(options, { originalConsole }) {
31
+ const rpc = createBirpc({}, {
32
+ ...options,
33
+ onTimeoutError: (functionName, error)=>{
34
+ switch(functionName){
35
+ case 'onTestCaseStart':
36
+ {
37
+ const caseTest = error[0];
38
+ console.error(`[Rstest] timeout on calling "onTestCaseStart" rpc method (Case: "${caseTest.name}")`);
39
+ return true;
40
+ }
41
+ case 'onTestCaseResult':
42
+ {
43
+ const caseResult = error[0];
44
+ console.error(`[Rstest] timeout on calling "onTestCaseResult" rpc method (Case: "${caseResult.name}", Result: "${caseResult.status}")`);
45
+ return true;
46
+ }
47
+ case 'onConsoleLog':
48
+ originalConsole.error(`[Rstest] timeout on calling "onConsoleLog" rpc method (Original log: ${error[0].content})`);
49
+ return true;
50
+ default:
51
+ return false;
52
+ }
53
+ }
54
+ });
55
+ return {
56
+ rpc
57
+ };
58
+ }
59
+ const external_node_fs_ = __webpack_require__("fs");
60
+ class NodeSnapshotEnvironment {
61
+ constructor(options = {}){
62
+ this.options = options;
63
+ }
64
+ getVersion() {
65
+ return "1";
66
+ }
67
+ getHeader() {
68
+ return `// Snapshot v${this.getVersion()}`;
69
+ }
70
+ async resolveRawPath(testPath, rawPath) {
71
+ return isAbsolute(rawPath) ? rawPath : pathe_M_eThtNZ_resolve(dirname(testPath), rawPath);
72
+ }
73
+ async resolvePath(filepath) {
74
+ return join(join(dirname(filepath), this.options.snapshotsDirName ?? "__snapshots__"), `${basename(filepath)}.snap`);
75
+ }
76
+ async prepareDirectory(dirPath) {
77
+ await external_node_fs_.promises.mkdir(dirPath, {
78
+ recursive: true
79
+ });
80
+ }
81
+ async saveSnapshotFile(filepath, snapshot) {
82
+ await external_node_fs_.promises.mkdir(dirname(filepath), {
83
+ recursive: true
84
+ });
85
+ await external_node_fs_.promises.writeFile(filepath, snapshot, "utf-8");
86
+ }
87
+ async readSnapshotFile(filepath) {
88
+ if (!(0, external_node_fs_.existsSync)(filepath)) return null;
89
+ return external_node_fs_.promises.readFile(filepath, "utf-8");
90
+ }
91
+ async removeSnapshotFile(filepath) {
92
+ if ((0, external_node_fs_.existsSync)(filepath)) await external_node_fs_.promises.unlink(filepath);
93
+ }
94
+ }
95
+ class RstestSnapshotEnvironment extends NodeSnapshotEnvironment {
96
+ resolveSnapshotPath;
97
+ constructor(options){
98
+ super();
99
+ this.resolveSnapshotPath = options.resolveSnapshotPath;
100
+ }
101
+ getHeader() {
102
+ return `// Rstest Snapshot v${this.getVersion()}`;
103
+ }
104
+ resolvePath(filepath) {
105
+ return this.resolveSnapshotPath(filepath);
106
+ }
107
+ }
108
+ const source_map_support = __webpack_require__("../../node_modules/.pnpm/source-map-support@0.5.21/node_modules/source-map-support/source-map-support.js");
109
+ const picocolors = __webpack_require__("../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js");
110
+ var picocolors_default = /*#__PURE__*/ __webpack_require__.n(picocolors);
111
+ let sourceMaps = {};
112
+ (0, source_map_support.install)({
113
+ environment: 'node',
114
+ handleUncaughtExceptions: false,
115
+ retrieveSourceMap: (source)=>{
116
+ if (sourceMaps[source]) return {
117
+ url: source,
118
+ map: JSON.parse(sourceMaps[source])
119
+ };
120
+ return null;
121
+ }
122
+ });
123
+ const registerGlobalApi = (api)=>globalApis.reduce((apis, key)=>{
124
+ globalThis[key] = api[key];
125
+ return apis;
126
+ }, {});
127
+ const globalCleanups = [];
128
+ let isTeardown = false;
129
+ const setupEnv = (env)=>{
130
+ if (env) Object.assign(process.env, env);
131
+ };
132
+ const preparePool = async ({ entryInfo: { distPath, testPath }, updateSnapshot, context })=>{
133
+ globalCleanups.forEach((fn)=>{
134
+ fn();
135
+ });
136
+ globalCleanups.length = 0;
137
+ setRealTimers();
138
+ context.runtimeConfig = undoSerializableConfig(context.runtimeConfig);
139
+ process.env.RSTEST_WORKER_ID = String(process.__tinypool_state__.workerId || context.taskId);
140
+ const cleanupFns = [];
141
+ const originalConsole = global.console;
142
+ const disposeFns = [];
143
+ const { rpc } = createRuntimeRpc(createForksRpcOptions({
144
+ dispose: disposeFns
145
+ }), {
146
+ originalConsole
147
+ });
148
+ globalCleanups.push(()=>{
149
+ disposeFns.forEach((fn)=>{
150
+ fn();
151
+ });
152
+ rpc.$close();
153
+ });
154
+ const { runtimeConfig: { globals, printConsoleTrace, disableConsoleIntercept, testEnvironment, snapshotFormat, env } } = context;
155
+ setupEnv(env);
156
+ if (!disableConsoleIntercept) {
157
+ const { createCustomConsole } = await import("./0~130.js").then((mod)=>({
158
+ createCustomConsole: mod.createCustomConsole
159
+ }));
160
+ global.console = createCustomConsole({
161
+ rpc,
162
+ testPath,
163
+ printConsoleTrace
164
+ });
165
+ }
166
+ const interopDefault = true;
167
+ const workerState = {
168
+ ...context,
169
+ snapshotOptions: {
170
+ updateSnapshot,
171
+ snapshotEnvironment: new RstestSnapshotEnvironment({
172
+ resolveSnapshotPath: (filepath)=>rpc.resolveSnapshotPath(filepath)
173
+ }),
174
+ snapshotFormat
175
+ },
176
+ distPath,
177
+ testPath,
178
+ environment: 'node'
179
+ };
180
+ const { createRstestRuntime } = await import("./6151.js").then((mod)=>({
181
+ createRstestRuntime: mod.createRstestRuntime
182
+ }));
183
+ const unhandledErrors = [];
184
+ const handleError = (e, type)=>{
185
+ const error = 'string' == typeof e ? new Error(e) : e;
186
+ error.name = type;
187
+ if (isTeardown) {
188
+ error.stack = `${picocolors_default().yellow('Caught error after test environment was torn down:')}\n\n${error.stack}`;
189
+ console.error(error);
190
+ } else {
191
+ console.error(error);
192
+ unhandledErrors.push(error);
193
+ }
194
+ };
195
+ const uncaughtException = (e)=>handleError(e, 'uncaughtException');
196
+ const unhandledRejection = (e)=>handleError(e, 'unhandledRejection');
197
+ process.on('uncaughtException', uncaughtException);
198
+ process.on('unhandledRejection', unhandledRejection);
199
+ globalCleanups.push(()=>{
200
+ process.off('uncaughtException', uncaughtException);
201
+ process.off('unhandledRejection', unhandledRejection);
202
+ });
203
+ const { api, runner } = await createRstestRuntime(workerState);
204
+ switch(testEnvironment.name){
205
+ case 'node':
206
+ break;
207
+ case 'jsdom':
208
+ {
209
+ const { environment } = await import("./0~62.js").then((mod)=>({
210
+ environment: mod.environment
211
+ }));
212
+ const { teardown } = await environment.setup(global, testEnvironment.options || {});
213
+ cleanupFns.push(()=>teardown(global));
214
+ break;
215
+ }
216
+ case 'happy-dom':
217
+ {
218
+ const { environment } = await import("./0~4809.js").then((mod)=>({
219
+ environment: mod.environment
220
+ }));
221
+ const { teardown } = await environment.setup(global, testEnvironment.options || {});
222
+ cleanupFns.push(async ()=>teardown(global));
223
+ break;
224
+ }
225
+ default:
226
+ throw new Error(`Unknown test environment: ${testEnvironment.name}`);
227
+ }
228
+ if (globals) registerGlobalApi(api);
229
+ const rstestContext = {
230
+ global,
231
+ console: global.console,
232
+ Error
233
+ };
234
+ rstestContext.global['@rstest/core'] = api;
235
+ return {
236
+ interopDefault,
237
+ rstestContext,
238
+ runner,
239
+ rpc,
240
+ api,
241
+ unhandledErrors,
242
+ cleanup: async ()=>{
243
+ await Promise.all(cleanupFns.map((fn)=>fn()));
244
+ }
245
+ };
246
+ };
247
+ const loadFiles = async ({ setupEntries, assetFiles, rstestContext, distPath, testPath, interopDefault, isolate, outputModule })=>{
248
+ const { loadModule, updateLatestAssetFiles } = outputModule ? await import("./0~6923.js").then((mod)=>({
249
+ EsmMode: mod.loadEsModule_EsmMode,
250
+ asModule: mod.asModule,
251
+ loadModule: mod.loadModule,
252
+ updateLatestAssetFiles: mod.updateLatestAssetFiles
253
+ })) : await import("./0~5835.js").then((mod)=>({
254
+ cacheableLoadModule: mod.cacheableLoadModule,
255
+ loadModule: mod.loadModule,
256
+ updateLatestAssetFiles: mod.updateLatestAssetFiles
257
+ }));
258
+ if (!isolate) {
259
+ updateLatestAssetFiles(assetFiles);
260
+ await loadModule({
261
+ codeContent: `if (global && typeof global.__rstest_clean_core_cache__ === 'function') {
262
+ global.__rstest_clean_core_cache__();
263
+ }`,
264
+ distPath: '',
265
+ testPath,
266
+ rstestContext,
267
+ assetFiles,
268
+ interopDefault
269
+ });
270
+ }
271
+ for (const { distPath, testPath } of setupEntries){
272
+ const setupCodeContent = assetFiles[distPath];
273
+ await loadModule({
274
+ codeContent: setupCodeContent,
275
+ distPath,
276
+ testPath,
277
+ rstestContext,
278
+ assetFiles,
279
+ interopDefault
280
+ });
281
+ }
282
+ await loadModule({
283
+ codeContent: assetFiles[distPath],
284
+ distPath,
285
+ testPath,
286
+ rstestContext,
287
+ assetFiles,
288
+ interopDefault
289
+ });
290
+ };
291
+ const runInPool = async (options)=>{
292
+ isTeardown = false;
293
+ const { entryInfo: { distPath, testPath }, setupEntries, assets, type, context: { project, runtimeConfig: { isolate, bail } } } = options;
294
+ const cleanups = [];
295
+ const exit = process.exit.bind(process);
296
+ process.exit = (code = process.exitCode || 0)=>{
297
+ throw new Error(`process.exit unexpectedly called with "${code}"`);
298
+ };
299
+ const kill = process.kill.bind(process);
300
+ process.kill = (pid, signal)=>{
301
+ if (-1 === pid || Math.abs(pid) === process.pid) throw new Error(`process.kill unexpectedly called with "${pid}" and "${signal}"`);
302
+ return kill(pid, signal);
303
+ };
304
+ cleanups.push(()=>{
305
+ process.kill = kill;
306
+ process.exit = exit;
307
+ });
308
+ const teardown = async ()=>{
309
+ await new Promise((resolve)=>getRealTimers().setTimeout(resolve));
310
+ await Promise.all(cleanups.map((fn)=>fn()));
311
+ isTeardown = true;
312
+ };
313
+ if ('collect' === type) try {
314
+ const { rstestContext, runner, rpc, cleanup, unhandledErrors, interopDefault } = await preparePool(options);
315
+ const { assetFiles, sourceMaps: sourceMapsFromAssets } = assets || await rpc.getAssetsByEntry();
316
+ sourceMaps = sourceMapsFromAssets;
317
+ cleanups.push(cleanup);
318
+ await loadFiles({
319
+ rstestContext,
320
+ distPath,
321
+ testPath,
322
+ assetFiles,
323
+ setupEntries,
324
+ interopDefault,
325
+ isolate,
326
+ outputModule: options.context.outputModule
327
+ });
328
+ const tests = await runner.collectTests();
329
+ return {
330
+ project,
331
+ testPath,
332
+ tests,
333
+ errors: formatTestError(unhandledErrors)
334
+ };
335
+ } catch (err) {
336
+ return {
337
+ project,
338
+ testPath,
339
+ tests: [],
340
+ errors: formatTestError(err)
341
+ };
342
+ } finally{
343
+ await teardown();
344
+ }
345
+ try {
346
+ const { rstestContext, runner, rpc, api, cleanup, unhandledErrors, interopDefault } = await preparePool(options);
347
+ if (bail && await rpc.getCountOfFailedTests() >= bail) return {
348
+ testId: '0',
349
+ project,
350
+ testPath,
351
+ status: 'skip',
352
+ name: '',
353
+ results: []
354
+ };
355
+ const coverageProvider = await createCoverageProvider(options.context.runtimeConfig.coverage || {}, options.context.rootPath);
356
+ if (coverageProvider) coverageProvider.init();
357
+ const { assetFiles, sourceMaps: sourceMapsFromAssets } = assets || await rpc.getAssetsByEntry();
358
+ sourceMaps = sourceMapsFromAssets;
359
+ cleanups.push(cleanup);
360
+ rpc.onTestFileStart?.({
361
+ testPath,
362
+ tests: []
363
+ });
364
+ await loadFiles({
365
+ rstestContext,
366
+ distPath,
367
+ testPath,
368
+ assetFiles,
369
+ setupEntries,
370
+ interopDefault,
371
+ isolate,
372
+ outputModule: options.context.outputModule
373
+ });
374
+ const results = await runner.runTests(testPath, {
375
+ onTestFileReady: async (test)=>{
376
+ await rpc.onTestFileReady(test);
377
+ },
378
+ onTestSuiteStart: async (test)=>{
379
+ await rpc.onTestSuiteStart(test);
380
+ },
381
+ onTestSuiteResult: async (result)=>{
382
+ await rpc.onTestSuiteResult(result);
383
+ },
384
+ onTestCaseStart: async (test)=>{
385
+ await rpc.onTestCaseStart(test);
386
+ },
387
+ onTestCaseResult: async (result)=>{
388
+ await rpc.onTestCaseResult(result);
389
+ },
390
+ getCountOfFailedTests: async ()=>rpc.getCountOfFailedTests()
391
+ }, api);
392
+ if (unhandledErrors.length > 0) {
393
+ results.status = 'fail';
394
+ results.errors = (results.errors || []).concat(...formatTestError(unhandledErrors));
395
+ }
396
+ if (coverageProvider) {
397
+ const coverageMap = coverageProvider.collect();
398
+ if (coverageMap) results.coverage = coverageMap.toJSON();
399
+ coverageProvider.cleanup();
400
+ }
401
+ return results;
402
+ } catch (err) {
403
+ return {
404
+ testId: '0',
405
+ project,
406
+ testPath,
407
+ status: 'fail',
408
+ name: '',
409
+ results: [],
410
+ errors: formatTestError(err)
411
+ };
412
+ } finally{
413
+ await teardown();
414
+ }
415
+ };
416
+ const worker = runInPool;
417
+ export default worker;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rstest/core",
3
- "version": "0.7.7",
3
+ "version": "0.7.9",
4
4
  "description": "The Rsbuild-based test tool.",
5
5
  "bugs": {
6
6
  "url": "https://github.com/web-infra-dev/rstest/issues"
@@ -28,6 +28,14 @@
28
28
  "types": "./dist/index.d.ts",
29
29
  "default": "./dist/index.js"
30
30
  },
31
+ "./browser": {
32
+ "types": "./dist/browser.d.ts",
33
+ "default": "./dist/browser.js"
34
+ },
35
+ "./browser-runtime": {
36
+ "types": "./dist/browser-runtime/index.d.ts",
37
+ "default": "./dist/browser-runtime/index.js"
38
+ },
31
39
  "./package.json": {
32
40
  "default": "./package.json"
33
41
  },
@@ -46,46 +54,53 @@
46
54
  "importMeta.d.ts"
47
55
  ],
48
56
  "dependencies": {
57
+ "@rsbuild/core": "1.7.1",
49
58
  "@types/chai": "^5.2.3",
50
- "@rsbuild/core": "1.7.0-beta.1",
51
59
  "tinypool": "^1.1.1"
52
60
  },
53
61
  "devDependencies": {
54
- "chai": "^5.3.3",
55
- "pathe": "^2.0.3",
56
- "birpc": "2.9.0",
57
- "@vitest/expect": "^3.2.4",
58
- "@vitest/snapshot": "^3.2.4",
59
62
  "@babel/code-frame": "^7.27.1",
60
63
  "@jridgewell/trace-mapping": "0.3.31",
61
64
  "@microsoft/api-extractor": "^7.55.2",
62
- "@rslib/core": "^0.18.6",
65
+ "@rsbuild/plugin-node-polyfill": "^1.3.0",
66
+ "@rslib/core": "^0.19.0",
63
67
  "@sinonjs/fake-timers": "^15.1.0",
64
68
  "@types/babel__code-frame": "^7.0.6",
65
- "@types/istanbul-reports": "^3.0.4",
66
69
  "@types/istanbul-lib-coverage": "^2.0.6",
67
70
  "@types/istanbul-lib-report": "^3.0.3",
71
+ "@types/istanbul-reports": "^3.0.4",
68
72
  "@types/jsdom": "^21.1.7",
73
+ "@types/picomatch": "^4.0.2",
69
74
  "@types/sinonjs__fake-timers": "^8.1.5",
75
+ "@clack/prompts": "^0.10.1",
76
+ "@vercel/detect-agent": "^1.0.0",
70
77
  "@types/source-map-support": "^0.5.10",
71
- "@types/picomatch": "^4.0.2",
78
+ "@vitest/expect": "^3.2.4",
79
+ "@vitest/snapshot": "^3.2.4",
80
+ "birpc": "2.9.0",
72
81
  "cac": "^6.7.14",
82
+ "chai": "^5.3.3",
73
83
  "chokidar": "^4.0.3",
74
84
  "happy-dom": "^20.0.11",
75
85
  "jest-diff": "^30.2.0",
76
86
  "jsdom": "^26.1.0",
77
- "webpack-license-plugin": "^4.5.1",
87
+ "memfs": "^4.51.1",
88
+ "package-manager-detector": "^1.6.0",
89
+ "pathe": "^2.0.3",
78
90
  "picocolors": "^1.1.1",
91
+ "picomatch": "^4.0.3",
79
92
  "pretty-format": "^30.2.0",
80
93
  "rslog": "^1.3.2",
81
94
  "source-map-support": "^0.5.21",
82
- "std-env": "^3.10.0",
83
95
  "stacktrace-parser": "0.1.11",
96
+ "std-env": "^3.10.0",
84
97
  "strip-ansi": "^7.1.2",
85
98
  "tinyglobby": "^0.2.15",
86
99
  "tinyspy": "^4.0.4",
87
- "picomatch": "^4.0.3",
88
- "@rstest/tsconfig": "0.0.1"
100
+ "url-extras": "^0.1.0",
101
+ "webpack-license-plugin": "^4.5.1",
102
+ "@rstest/tsconfig": "0.0.1",
103
+ "@rstest/browser-ui": "0.7.9"
89
104
  },
90
105
  "peerDependencies": {
91
106
  "happy-dom": "*",
package/dist/0~8957.js DELETED
@@ -1,149 +0,0 @@
1
- import 'module';
2
- /*#__PURE__*/ import.meta.url;
3
- import { M, T } from "./0~6151.js";
4
- const isMockFunction = (fn)=>'function' == typeof fn && '_isMockFunction' in fn && fn._isMockFunction;
5
- const initSpy = ()=>{
6
- let callOrder = 0;
7
- const mocks = new Set();
8
- const wrapSpy = (obj, methodName, mockFn)=>{
9
- const spyImpl = M(obj, methodName, mockFn);
10
- const spyFn = spyImpl;
11
- let mockImplementationOnce = [];
12
- let implementation = mockFn;
13
- let mockName = mockFn?.name;
14
- const initMockState = ()=>({
15
- instances: [],
16
- contexts: [],
17
- invocationCallOrder: []
18
- });
19
- let mockState = initMockState();
20
- const spyState = T(spyImpl);
21
- spyFn.getMockName = ()=>mockName || methodName;
22
- spyFn.mockName = (name)=>{
23
- mockName = name;
24
- return spyFn;
25
- };
26
- spyFn.getMockImplementation = ()=>mockImplementationOnce.length ? mockImplementationOnce[mockImplementationOnce.length - 1] : implementation;
27
- function withImplementation(fn, cb) {
28
- const originalImplementation = implementation;
29
- const originalMockImplementationOnce = mockImplementationOnce;
30
- implementation = fn;
31
- mockImplementationOnce = [];
32
- spyState.willCall(willCall);
33
- const reset = ()=>{
34
- implementation = originalImplementation;
35
- mockImplementationOnce = originalMockImplementationOnce;
36
- };
37
- const result = cb();
38
- if (result instanceof Promise) return result.then(()=>{
39
- reset();
40
- });
41
- reset();
42
- }
43
- spyFn.withImplementation = withImplementation;
44
- spyFn.mockImplementation = (fn)=>{
45
- implementation = fn;
46
- return spyFn;
47
- };
48
- spyFn.mockImplementationOnce = (fn)=>{
49
- mockImplementationOnce.push(fn);
50
- return spyFn;
51
- };
52
- spyFn.mockReturnValue = (value)=>spyFn.mockImplementation(()=>value);
53
- spyFn.mockReturnValueOnce = (value)=>spyFn.mockImplementationOnce(()=>value);
54
- spyFn.mockResolvedValue = (value)=>spyFn.mockImplementation(()=>Promise.resolve(value));
55
- spyFn.mockResolvedValueOnce = (value)=>spyFn.mockImplementationOnce(()=>Promise.resolve(value));
56
- spyFn.mockRejectedValue = (value)=>spyFn.mockImplementation(()=>Promise.reject(value));
57
- spyFn.mockRejectedValueOnce = (value)=>spyFn.mockImplementationOnce(()=>Promise.reject(value));
58
- spyFn.mockReturnThis = ()=>spyFn.mockImplementation(function() {
59
- return this;
60
- });
61
- function willCall(...args) {
62
- let impl = implementation || spyState.getOriginal();
63
- mockState.instances.push(this);
64
- mockState.contexts.push(this);
65
- mockState.invocationCallOrder.push(++callOrder);
66
- if (mockImplementationOnce.length) impl = mockImplementationOnce.shift();
67
- return impl?.apply(this, args);
68
- }
69
- spyState.willCall(willCall);
70
- Object.defineProperty(spyFn, 'mock', {
71
- get: ()=>({
72
- get calls () {
73
- return spyState.calls;
74
- },
75
- get lastCall () {
76
- return spyState.calls[spyState.callCount - 1];
77
- },
78
- get instances () {
79
- return mockState.instances;
80
- },
81
- get contexts () {
82
- return mockState.contexts;
83
- },
84
- get invocationCallOrder () {
85
- return mockState.invocationCallOrder;
86
- },
87
- get results () {
88
- return spyState.results.map(([resultType, value])=>{
89
- const type = 'error' === resultType ? 'throw' : 'return';
90
- return {
91
- type: type,
92
- value
93
- };
94
- });
95
- },
96
- get settledResults () {
97
- return spyState.resolves.map(([resultType, value])=>{
98
- const type = 'error' === resultType ? 'rejected' : 'fulfilled';
99
- return {
100
- type,
101
- value
102
- };
103
- });
104
- }
105
- })
106
- });
107
- spyFn.mockClear = ()=>{
108
- mockState = initMockState();
109
- spyState.reset();
110
- return spyFn;
111
- };
112
- spyFn.mockReset = ()=>{
113
- spyFn.mockClear();
114
- implementation = mockFn;
115
- mockImplementationOnce = [];
116
- return spyFn;
117
- };
118
- spyFn.mockRestore = ()=>{
119
- spyFn.mockReset();
120
- spyState.restore();
121
- mockName = mockFn?.name;
122
- };
123
- mocks.add(spyFn);
124
- return spyFn;
125
- };
126
- const fn = (mockFn)=>{
127
- const defaultName = 'rstest.fn()';
128
- return wrapSpy({
129
- [defaultName]: mockFn
130
- }, defaultName, mockFn);
131
- };
132
- const spyOn = (obj, methodName, accessType)=>{
133
- const accessTypeMap = {
134
- get: 'getter',
135
- set: 'setter'
136
- };
137
- const method = accessType ? {
138
- [accessTypeMap[accessType]]: methodName
139
- } : methodName;
140
- return wrapSpy(obj, method);
141
- };
142
- return {
143
- isMockFunction: isMockFunction,
144
- spyOn,
145
- fn,
146
- mocks
147
- };
148
- };
149
- export { initSpy };