@exodus/test 1.0.0-rc.114 → 1.0.0-rc.115
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/README.md +27 -24
- package/bin/browsers.js +7 -1
- package/bin/index.js +5 -4
- package/package.json +12 -11
- package/src/engine.pure.cjs +33 -40
- package/src/engine.pure.mock.module.cjs +44 -0
- package/src/engine.pure.snapshot.cjs +1 -1
- package/src/expect.cjs +3 -0
- package/src/jest.mock.js +0 -1
package/README.md
CHANGED
|
@@ -12,27 +12,28 @@ A runner for `node:test`, `jest`, and `tape` test suites on top of `node:test` (
|
|
|
12
12
|
|
|
13
13
|
It can run your existing tests on [all runtimes and also browsers](#engines), with snapshots and module mocks:
|
|
14
14
|
|
|
15
|
-
[](https://nodejs.org/api/test.html)
|
|
16
|
+
[](https://deno.com/)
|
|
17
|
+
[](https://bun.sh/)
|
|
18
|
+
[](http://electronjs.org/)
|
|
19
|
+
[](https://github.com/cloudflare/workerd)\
|
|
20
|
+
[](https://www.chromium.org/Home/)
|
|
21
|
+
[](http://webkit.org/)
|
|
22
|
+
[](https://github.com/mozilla-firefox)
|
|
23
|
+
[](https://github.com/brave)
|
|
24
|
+
[](https://github.com/microsoftedge)
|
|
25
|
+
[](https://servo.org/)\
|
|
26
|
+
[](https://hermesengine.dev)
|
|
27
|
+
[](https://v8.dev/docs/d8)
|
|
28
|
+
[](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html)
|
|
29
|
+
[](https://spidermonkey.dev/)\
|
|
30
|
+
[](https://github.com/quickjs-ng/quickjs)
|
|
31
|
+
[](https://github.com/Moddable-OpenSource/moddable)
|
|
32
|
+
[](https://github.com/oracle/graaljs)
|
|
33
|
+
[](https://github.com/boa-dev/boa)
|
|
34
|
+
[](https://github.com/trynova/nova)
|
|
35
|
+
[](https://github.com/Samsung/escargot)
|
|
36
|
+
[](https://github.com/engine262/engine262)
|
|
36
37
|
|
|
37
38
|
Compatible with tests written in:
|
|
38
39
|
|
|
@@ -44,10 +45,11 @@ See [documentation](https://exodusoss.github.io/test/).
|
|
|
44
45
|
|
|
45
46
|
## Features
|
|
46
47
|
|
|
48
|
+
- Zero learning curve: runs your existing tests
|
|
49
|
+
- Runs anywhere (including Hermes, the [React Native](https://reactnative.dev/) JavaScript engine)
|
|
47
50
|
- Native ESM, including in Jest tests
|
|
48
51
|
- Esbuild on the fly for old faux-ESM interop (enable via `--esbuild`)
|
|
49
52
|
- TypeScript support
|
|
50
|
-
- Runs anywhere (including Hermes, the [React Native](https://reactnative.dev/) JavaScript engine)
|
|
51
53
|
- Use snapshots to cross-compare between runtimes, browsers and barebones (including Hermes)
|
|
52
54
|
- Testsuite-agnostic — can run any file as long as it sets exit code based on test results
|
|
53
55
|
- Built-in [Jest](https://jestjs.io) compatibility (with `--jest`), including `jest.*` global
|
|
@@ -65,8 +67,8 @@ See [documentation](https://exodusoss.github.io/test/).
|
|
|
65
67
|
- JSDOM env support
|
|
66
68
|
- Hanging tests error by default (unlike `jest`)
|
|
67
69
|
- Babel support, picks up your Babel config (enable via `--babel`)
|
|
68
|
-
- Unlike `bun:test`, it runs test files in isolated contexts \
|
|
69
|
-
Bun leaks globals / side effects between test files ([ref](https://github.com/oven-sh/bun/issues/6024)),
|
|
70
|
+
- Unlike `bun:test`, it runs test files in isolated contexts on Bun. \
|
|
71
|
+
Without this, Bun leaks globals / side effects between test files ([ref](https://github.com/oven-sh/bun/issues/6024)),
|
|
70
72
|
and has incompatible `test()` lifecycle / order
|
|
71
73
|
|
|
72
74
|
## Getting started
|
|
@@ -178,6 +180,7 @@ Use `--engine` (or `EXODUS_TEST_ENGINE=`) to specify one of:
|
|
|
178
180
|
- `graaljs:bundle` — [GraalJS](https://github.com/oracle/graaljs)
|
|
179
181
|
- `escargot:bundle` — [Escargot](https://github.com/Samsung/escargot)
|
|
180
182
|
- `boa:bundle` — [Boa](https://github.com/boa-dev/boa)
|
|
183
|
+
- `nova:bundle` — [Nova](https://github.com/trynova/nova) (note that Nova itself is a Work In Progress)
|
|
181
184
|
- `engine262:bundle` - [engine262](https://github.com/engine262/engine262), the per-spec implementation of ECMA-262
|
|
182
185
|
(install with [esvu](https://npmjs.com/package/esvu))
|
|
183
186
|
|
package/bin/browsers.js
CHANGED
|
@@ -75,7 +75,13 @@ export async function run(runner, args, { binary, devtools, dropNetwork, timeout
|
|
|
75
75
|
const [stdout, stderr] = [[], []]
|
|
76
76
|
|
|
77
77
|
assert(Object.hasOwn(launchers, runner), 'Unexpected runner')
|
|
78
|
-
|
|
78
|
+
try {
|
|
79
|
+
if (!launched[runner]) launched[runner] = launchers[runner]({ binary, devtools: !!devtools })
|
|
80
|
+
} catch {
|
|
81
|
+
// Try a second time, this sometime times out
|
|
82
|
+
if (!launched[runner]) launched[runner] = launchers[runner]({ binary, devtools: !!devtools })
|
|
83
|
+
}
|
|
84
|
+
|
|
79
85
|
const { page, context } = await newPage(runner, await launched[runner], { binary, dropNetwork })
|
|
80
86
|
|
|
81
87
|
if (throttle) {
|
package/bin/index.js
CHANGED
|
@@ -39,6 +39,7 @@ const ENGINES = new Map(
|
|
|
39
39
|
'deno:test': { binary: 'deno', binaryArgs: denoT, loader: '--preload', ts: 'auto' },
|
|
40
40
|
'deno:pure': { binary: 'deno', binaryArgs: denoA, pure: true, loader: '--preload', ts: 'auto' },
|
|
41
41
|
'deno:bundle': { binary: 'deno', binaryArgs: ['run'], target: 'deno1', ...bundleOpts },
|
|
42
|
+
'workerd:bundle': { binary: 'workerd', binaryArgs: ['test'], ...bundleOpts },
|
|
42
43
|
// Barebone engines
|
|
43
44
|
'v8:bundle': { binary: 'd8', binaryArgs: ['--expose-gc'], ...bareboneOpts },
|
|
44
45
|
'jsc:bundle': { binary: 'jsc', target: 'safari13', ...bareboneOpts },
|
|
@@ -58,7 +59,6 @@ const ENGINES = new Map(
|
|
|
58
59
|
'porffor:bundle': { binary: 'porffor', ...bareboneOpts }, // blocked on https://github.com/CanadaHonk/porffor/issues/176
|
|
59
60
|
// Special case: running a browser from CLI like a bundle
|
|
60
61
|
'servo:bundle': { binary: 'servo', binaryArgs: ['--headless'], ...bundleOpts, html: true },
|
|
61
|
-
'workerd:bundle': { binary: 'workerd', binaryArgs: ['test'], ...bundleOpts, workerd: true },
|
|
62
62
|
// Browser engines
|
|
63
63
|
'chrome:puppeteer': { binary: 'chrome', browsers: 'puppeteer', ...bundleOpts },
|
|
64
64
|
'firefox:puppeteer': { binary: 'firefox', browsers: 'puppeteer', ...bundleOpts },
|
|
@@ -72,7 +72,7 @@ const ENGINES = new Map(
|
|
|
72
72
|
})
|
|
73
73
|
)
|
|
74
74
|
const bareOk = ['v8', 'd8', 'spidermonkey', 'quickjs', 'xs', 'hermes', 'shermes']
|
|
75
|
-
const bareNotrack = ['jsc', 'escargot', 'boa', 'graaljs', 'jerryscript', 'engine262'
|
|
75
|
+
const bareNotrack = ['jsc', 'escargot', 'boa', 'graaljs', 'jerryscript', 'engine262']
|
|
76
76
|
const bareIncomplete = ['ladybird-js', 'nova', 'duktape']
|
|
77
77
|
|
|
78
78
|
const getEnvFlag = (name) => {
|
|
@@ -663,7 +663,8 @@ async function launch(binary, args, opts = {}, buffering = false) {
|
|
|
663
663
|
}
|
|
664
664
|
|
|
665
665
|
const barebones = [...bareOk, ...bareNotrack, ...bareIncomplete]
|
|
666
|
-
|
|
666
|
+
const bins = ['node', 'bun', 'deno', 'electron', 'workerd', 'servo', 'jerry', 'duk', ...barebones]
|
|
667
|
+
assertBinary(binary, bins)
|
|
667
668
|
if (binary === c8 && process.platform === 'win32') {
|
|
668
669
|
;[binary, args] = ['node', [binary, ...args]]
|
|
669
670
|
}
|
|
@@ -708,7 +709,7 @@ if (options.pure) {
|
|
|
708
709
|
await writeFile(bundled.fileHtml, `<script src="${bundled.file}"></script>`)
|
|
709
710
|
}
|
|
710
711
|
|
|
711
|
-
if (bundled && options.workerd) {
|
|
712
|
+
if (bundled && options.platform === 'workerd') {
|
|
712
713
|
bundled.fileWrapper = `${bundled.file}.wrapper.js`
|
|
713
714
|
bundled.fileConfig = `${bundled.file}.capnp`
|
|
714
715
|
assert(/^[a-z0-9/_.-]+\.js$/iu.test(bundled.file), bundled.file)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/test",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.115",
|
|
4
4
|
"author": "Exodus Movement, Inc.",
|
|
5
5
|
"description": "A test suite runner",
|
|
6
6
|
"homepage": "https://github.com/ExodusOSS/test",
|
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
"src/engine.js",
|
|
89
89
|
"src/engine.node.cjs",
|
|
90
90
|
"src/engine.pure.cjs",
|
|
91
|
+
"src/engine.pure.mock.module.cjs",
|
|
91
92
|
"src/engine.pure.snapshot.cjs",
|
|
92
93
|
"src/engine.select.cjs",
|
|
93
94
|
"src/exodus.js",
|
|
@@ -125,22 +126,22 @@
|
|
|
125
126
|
"tape.js"
|
|
126
127
|
],
|
|
127
128
|
"scripts": {
|
|
128
|
-
"test:_bundle": "EXODUS_TEST_IGNORE='tests/{{jest-extended,inband}/**,jest-when/when.test.*,jest/jest.resetModules.*,jest/mock/jest.mock.mocks-dir.test.js}' npm run test --",
|
|
129
|
+
"test:_bundle": "EXODUS_TEST_IGNORE='tests/{{vendor/jest-extended,inband}/**,vendor/jest-when/when.test.*,jest/jest.resetModules.*,jest/mock/jest.mock.mocks-dir.test.js}' npm run test --",
|
|
129
130
|
"test": "npm run test:jest --",
|
|
130
131
|
"test:all": "npm run test:simple && npm run test:jest && npm run test:tape && npm run test:native && npm run test:esbuild && npm run test:pure && npm run test:fetch && npm run test:jsdom && npm run test:bundle",
|
|
131
|
-
"test:native": "EXODUS_TEST_IGNORE='
|
|
132
|
+
"test:native": "EXODUS_TEST_IGNORE='**/jest.transformed/**/*' ./bin/index.js --jest 'tests/**/*.test.{js,cjs,mjs}'",
|
|
132
133
|
"test:typescript": "node ./bin/index.js --jest --typescript tests/typescript.test.ts",
|
|
133
|
-
"test:jest": "node ./bin/index.js --jest --esbuild=ts,
|
|
134
|
+
"test:jest": "node ./bin/index.js --jest --esbuild=ts,sum.test.js",
|
|
134
135
|
"test:esbuild": "node ./bin/index.js --jest --esbuild",
|
|
135
|
-
"test:tape": "node ./bin/index.js
|
|
136
|
+
"test:tape": "node ./bin/index.js tests/vendor/tape/test/*.js tests/tape/*.test.*js",
|
|
136
137
|
"test:simple": "node ./bin/index.js 'tests/*.test.js'",
|
|
137
138
|
"test:pure": "EXODUS_TEST_ENGINE=node:pure npm run test --",
|
|
138
139
|
"test:bundle": "EXODUS_TEST_ENGINE=node:bundle npm run test:_bundle --",
|
|
139
140
|
"test:bun:test": "EXODUS_TEST_ENGINE=bun:test npm run test --",
|
|
140
141
|
"test:bun:pure": "EXODUS_TEST_ENGINE=bun:pure npm run test --",
|
|
141
142
|
"test:bun:bundle": "EXODUS_TEST_ENGINE=bun:bundle npm run test:_bundle",
|
|
142
|
-
"test:deno:test": "EXODUS_TEST_ENGINE=deno:test node ./bin/index.js tests/tape
|
|
143
|
-
"test:deno:pure": "EXODUS_TEST_IGNORE='**/jest
|
|
143
|
+
"test:deno:test": "EXODUS_TEST_ENGINE=deno:test node ./bin/index.js tests/tape/*.test.*js tests/simple.test.js tests/env.test.js 'tests/engines/**.test.js' tests/node/simple.test.js tests/node/order.test.js tests/node/snapshot.test.js tests/node/mock/mock.import.test.js",
|
|
144
|
+
"test:deno:pure": "EXODUS_TEST_IGNORE='**/jest/examples/timer/**' EXODUS_TEST_ENGINE=deno:pure npm run test --",
|
|
144
145
|
"test:deno:bundle": "EXODUS_TEST_ENGINE=deno:bundle npm run test:_bundle --",
|
|
145
146
|
"test:electron:node": "EXODUS_TEST_ENGINE=electron-as-node:test npm run test",
|
|
146
147
|
"test:electron:node:pure": "EXODUS_TEST_ENGINE=electron-as-node:pure npm run test --",
|
|
@@ -175,20 +176,20 @@
|
|
|
175
176
|
"playwright": "node ./bin/index.js --playwright",
|
|
176
177
|
"esvu": "esvu",
|
|
177
178
|
"jsvu": "jsvu",
|
|
178
|
-
"jest": "NODE_OPTIONS=--experimental-vm-modules jest tests/jest/ tests/jest-when/",
|
|
179
|
+
"jest": "NODE_OPTIONS=--experimental-vm-modules jest tests/jest/ tests/vendor/jest/ tests/vendor/jest-when/",
|
|
179
180
|
"lint": "prettier --list-different . && eslint .",
|
|
180
181
|
"lint:fix": "prettier --write . && eslint --fix ."
|
|
181
182
|
},
|
|
182
183
|
"optionalDependencies": {
|
|
183
184
|
"@chalker/queue": "^1.0.1",
|
|
184
185
|
"@exodus/replay": "^1.0.0-rc.11",
|
|
185
|
-
"@exodus/test-bundler": "1.0.0-rc.
|
|
186
|
+
"@exodus/test-bundler": "1.0.0-rc.16",
|
|
186
187
|
"c8": "^9.1.0",
|
|
187
188
|
"expect": "^30.2.0",
|
|
188
189
|
"fast-glob": "^3.2.11",
|
|
189
|
-
"playwright-core": "^1.
|
|
190
|
+
"playwright-core": "^1.58.2",
|
|
190
191
|
"pretty-format": "^30.2.0",
|
|
191
|
-
"puppeteer-core": "^24.
|
|
192
|
+
"puppeteer-core": "^24.37.2",
|
|
192
193
|
"tsx": "^4.21.0"
|
|
193
194
|
},
|
|
194
195
|
"devDependencies": {
|
package/src/engine.pure.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const assert = require('node:assert/strict')
|
|
2
2
|
const assertLoose = require('node:assert')
|
|
3
3
|
const { matchSnapshot } = require('./engine.pure.snapshot.cjs')
|
|
4
|
+
const { mockModule, baseFile, ...mockModuleMethods } = require('./engine.pure.mock.module.cjs')
|
|
4
5
|
|
|
5
6
|
const { setTimeout, setInterval, setImmediate, Date } = globalThis
|
|
6
7
|
const { clearTimeout, clearInterval, clearImmediate } = globalThis
|
|
@@ -44,6 +45,7 @@ class Context {
|
|
|
44
45
|
#fullName
|
|
45
46
|
#assert
|
|
46
47
|
#hooks
|
|
48
|
+
#mock
|
|
47
49
|
|
|
48
50
|
constructor(parent, name, options = {}) {
|
|
49
51
|
if (!name || typeof name !== 'string') name = '<anonymous>'
|
|
@@ -80,6 +82,11 @@ class Context {
|
|
|
80
82
|
return this.#assert
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
get mock() {
|
|
86
|
+
if (!this.#mock) this.#mock = new MockTracker()
|
|
87
|
+
return this.#mock
|
|
88
|
+
}
|
|
89
|
+
|
|
83
90
|
async addHook(type, fn) {
|
|
84
91
|
if (!this.#hooks) this.#hooks = Object.create(null)
|
|
85
92
|
if (!this.#hooks[type]) this.#hooks[type] = []
|
|
@@ -252,13 +259,18 @@ test.todo = (...args) => {
|
|
|
252
259
|
return test(name, { ...options, todo: true }, fn)
|
|
253
260
|
}
|
|
254
261
|
|
|
262
|
+
const codeError = (msg, code) => Object.assign(new Error(msg), { code })
|
|
263
|
+
|
|
264
|
+
let mockTimersEnabled = false
|
|
265
|
+
|
|
255
266
|
class MockTimers {
|
|
256
267
|
#enabled = false
|
|
257
268
|
#base = 0
|
|
258
269
|
#elapsed = 0
|
|
259
270
|
#queue = []
|
|
260
271
|
enable({ now = 0, apis = ['setInterval', 'setTimeout', 'setImmediate', 'Date'] } = {}) {
|
|
261
|
-
|
|
272
|
+
if (mockTimersEnabled) throw codeError('MockTimers is already enabled!', 'ERR_INVALID_STATE')
|
|
273
|
+
mockTimersEnabled = this.#enabled = true
|
|
262
274
|
this.#base = +now
|
|
263
275
|
this.#elapsed = 0
|
|
264
276
|
if (apis.includes('setInterval')) {
|
|
@@ -301,7 +313,8 @@ class MockTimers {
|
|
|
301
313
|
}
|
|
302
314
|
|
|
303
315
|
reset() {
|
|
304
|
-
this.#enabled
|
|
316
|
+
if (!this.#enabled) return
|
|
317
|
+
mockTimersEnabled = this.#enabled = false
|
|
305
318
|
Object.assign(globalThis, { setTimeout, setInterval, setImmediate, Date })
|
|
306
319
|
Object.assign(globalThis, { clearTimeout, clearInterval, clearImmediate })
|
|
307
320
|
}
|
|
@@ -381,10 +394,18 @@ class MockTimers {
|
|
|
381
394
|
}
|
|
382
395
|
}
|
|
383
396
|
|
|
384
|
-
|
|
385
|
-
module
|
|
386
|
-
|
|
387
|
-
|
|
397
|
+
class MockTracker {
|
|
398
|
+
get module() {
|
|
399
|
+
return mockModule
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
#timers
|
|
403
|
+
get timers() {
|
|
404
|
+
if (!this.#timers) this.#timers = new MockTimers()
|
|
405
|
+
return this.#timers
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
fn(original = () => {}, implementation = original) {
|
|
388
409
|
let impl = implementation
|
|
389
410
|
const _mock = {
|
|
390
411
|
calls: [],
|
|
@@ -460,20 +481,10 @@ const mock = {
|
|
|
460
481
|
return Object.getOwnPropertyDescriptor(target, key)
|
|
461
482
|
},
|
|
462
483
|
})
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
if (
|
|
467
|
-
process.env.EXODUS_TEST_ENGINE === 'node:pure' ||
|
|
468
|
-
process.env.EXODUS_TEST_ENGINE === 'electron-as-node:pure'
|
|
469
|
-
) {
|
|
470
|
-
// Try load module mocks from node:test, if present
|
|
471
|
-
try {
|
|
472
|
-
const nodeTest = require('node:test')
|
|
473
|
-
mock.module = nodeTest.mock.module.bind(nodeTest.mock)
|
|
474
|
-
} catch {}
|
|
484
|
+
}
|
|
475
485
|
}
|
|
476
486
|
|
|
487
|
+
const mock = new MockTracker()
|
|
477
488
|
const beforeEach = (fn) => context.addHook('beforeEach', fn)
|
|
478
489
|
const afterEach = (fn) => context.addHook('afterEach', fn)
|
|
479
490
|
const before = (fn) => context.addHook('before', fn)
|
|
@@ -530,35 +541,18 @@ const awaitForMicrotaskQueue = async () => {
|
|
|
530
541
|
for (let i = 0; i < tickPromiseRounds; i++) await promise
|
|
531
542
|
}
|
|
532
543
|
|
|
533
|
-
let
|
|
534
|
-
let requireIsRelative = false
|
|
535
|
-
let relativeRequire, baseFile, isTopLevelESM, syncBuiltinESMExports, readSnapshot, utilFormat
|
|
544
|
+
let readSnapshot, utilFormat
|
|
536
545
|
if (process.env.EXODUS_TEST_ENVIRONMENT === 'bundle') {
|
|
537
|
-
// eslint-disable-next-line no-undef
|
|
538
|
-
const files = EXODUS_TEST_FILES
|
|
539
|
-
baseFile = files.length === 1 ? files[0] : undefined
|
|
540
|
-
isTopLevelESM = () => false
|
|
541
546
|
// eslint-disable-next-line no-undef
|
|
542
547
|
const bundleSnaps = typeof EXODUS_TEST_SNAPSHOTS !== 'undefined' && new Map(EXODUS_TEST_SNAPSHOTS)
|
|
543
548
|
const resolveSnapshot = (f) => snapshotResolver(f[0], f[1]).join('/')
|
|
544
549
|
readSnapshot = (f = baseFile) => (f && bundleSnaps?.get(resolveSnapshot(f))) || null
|
|
545
550
|
utilFormat = require('exodus-test:util-format')
|
|
546
551
|
} else {
|
|
547
|
-
const {
|
|
548
|
-
const { dirname, basename,
|
|
549
|
-
const nodeModule = require('node:module')
|
|
550
|
-
const files = process.argv.slice(1)
|
|
551
|
-
baseFile = files.length === 1 && existsSync(files[0]) ? normalize(files[0]) : undefined
|
|
552
|
-
requireIsRelative = Boolean(baseFile)
|
|
553
|
-
relativeRequire = baseFile ? nodeModule.createRequire(baseFile) : require
|
|
554
|
-
isTopLevelESM = () =>
|
|
555
|
-
!baseFile || // assume ESM otherwise
|
|
556
|
-
!Object.hasOwn(relativeRequire.cache, baseFile) || // node esm
|
|
557
|
-
relativeRequire.cache[baseFile].exports[Symbol.toStringTag] === 'Module' // bun esm
|
|
552
|
+
const { readFileSync } = require('node:fs')
|
|
553
|
+
const { dirname, basename, join } = require('node:path')
|
|
558
554
|
const resolveSnapshot = (f) => join(...snapshotResolver(dirname(f), basename(f)))
|
|
559
555
|
readSnapshot = (f = baseFile) => (f ? readFileSync(resolveSnapshot(f), 'utf8') : null)
|
|
560
|
-
builtinModules = nodeModule.builtinModules
|
|
561
|
-
syncBuiltinESMExports = nodeModule.syncBuiltinESMExports || nodeModule.syncBuiltinExports // bun has it under a different name (also a no-op and always synced atm)
|
|
562
556
|
utilFormat = require('node:util').format
|
|
563
557
|
}
|
|
564
558
|
|
|
@@ -586,9 +580,8 @@ module.exports = {
|
|
|
586
580
|
engine: 'pure',
|
|
587
581
|
...{ assert, assertLoose },
|
|
588
582
|
...{ mock, describe, test, beforeEach, afterEach, before, after },
|
|
589
|
-
...{ builtinModules, syncBuiltinESMExports },
|
|
590
583
|
...{ utilFormat, isPromise, nodeVersion, awaitForMicrotaskQueue },
|
|
591
|
-
...{
|
|
584
|
+
...{ mockModule, baseFile, ...mockModuleMethods },
|
|
592
585
|
...{ readSnapshot, setSnapshotSerializers, setSnapshotResolver },
|
|
593
586
|
}
|
|
594
587
|
/* eslint-enable unicorn/no-useless-spread */
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
let mockModule
|
|
2
|
+
let builtinModules = []
|
|
3
|
+
let requireIsRelative = false
|
|
4
|
+
let relativeRequire, baseFile, isTopLevelESM, syncBuiltinESMExports
|
|
5
|
+
if (process.env.EXODUS_TEST_ENVIRONMENT === 'bundle') {
|
|
6
|
+
// eslint-disable-next-line no-undef
|
|
7
|
+
const files = EXODUS_TEST_FILES
|
|
8
|
+
baseFile = files.length === 1 ? files[0] : undefined
|
|
9
|
+
isTopLevelESM = () => false
|
|
10
|
+
} else {
|
|
11
|
+
const { existsSync } = require('node:fs')
|
|
12
|
+
const { normalize } = require('node:path')
|
|
13
|
+
const nodeModule = require('node:module')
|
|
14
|
+
const files = process.argv.slice(1)
|
|
15
|
+
baseFile = files.length === 1 && existsSync(files[0]) ? normalize(files[0]) : undefined
|
|
16
|
+
requireIsRelative = Boolean(baseFile)
|
|
17
|
+
relativeRequire = baseFile ? nodeModule.createRequire(baseFile) : require
|
|
18
|
+
isTopLevelESM = () =>
|
|
19
|
+
!baseFile || // assume ESM otherwise
|
|
20
|
+
!Object.hasOwn(relativeRequire.cache, baseFile) || // node esm
|
|
21
|
+
relativeRequire.cache[baseFile].exports[Symbol.toStringTag] === 'Module' // bun esm
|
|
22
|
+
builtinModules = nodeModule.builtinModules
|
|
23
|
+
syncBuiltinESMExports = nodeModule.syncBuiltinESMExports || nodeModule.syncBuiltinExports // bun has it under a different name (also a no-op and always synced atm)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (
|
|
27
|
+
process.env.EXODUS_TEST_ENGINE === 'node:pure' ||
|
|
28
|
+
process.env.EXODUS_TEST_ENGINE === 'electron-as-node:pure'
|
|
29
|
+
) {
|
|
30
|
+
// Try load module mocks from node:test, if present
|
|
31
|
+
try {
|
|
32
|
+
const nodeTest = require('node:test')
|
|
33
|
+
mockModule = nodeTest.mock.module.bind(nodeTest.mock)
|
|
34
|
+
} catch {}
|
|
35
|
+
} else if (process.env.EXODUS_TEST_ENVIRONMENT === 'bundle') {
|
|
36
|
+
globalThis.EXODUS_TEST_MOCK_BUILTINS = new Map()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* eslint-disable unicorn/no-useless-spread */
|
|
40
|
+
module.exports = {
|
|
41
|
+
...{ mockModule, builtinModules, syncBuiltinESMExports },
|
|
42
|
+
...{ requireIsRelative, relativeRequire, baseFile, isTopLevelESM },
|
|
43
|
+
}
|
|
44
|
+
/* eslint-enable unicorn/no-useless-spread */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const nameCounts = new Map()
|
|
2
2
|
let snapshotText, snapshotTextClean
|
|
3
3
|
|
|
4
|
-
const escapeSnapshot = (str) => str.replaceAll(/([\\`]|\$\{)/gu,
|
|
4
|
+
const escapeSnapshot = (str) => str.replaceAll(/([\\`]|\$\{)/gu, (x) => `\\${x}`)
|
|
5
5
|
const escapeSnapshotKey = (s) => escapeSnapshot(s).replaceAll('\n', '\\n').replaceAll('"', '\\"')
|
|
6
6
|
|
|
7
7
|
function matchSnapshot(readSnapshot, assert, name, serialized) {
|
package/src/expect.cjs
CHANGED
package/src/jest.mock.js
CHANGED
|
@@ -47,7 +47,6 @@ export const jestModuleMocks = {
|
|
|
47
47
|
jestModuleMocks.dontMock = jestModuleMocks.unmock
|
|
48
48
|
|
|
49
49
|
if (process.env.EXODUS_TEST_ENVIRONMENT === 'bundle') {
|
|
50
|
-
globalThis.EXODUS_TEST_MOCK_BUILTINS = new Map()
|
|
51
50
|
Object.assign(jestModuleMocks, {
|
|
52
51
|
__mockBundle(name, builtin, actual, mock) {
|
|
53
52
|
jestmock(name, mock, { actual, builtin, override: true })
|