@exodus/test 1.0.0-rc.40 → 1.0.0-rc.42

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/bin/index.js CHANGED
@@ -54,6 +54,7 @@ function parseOptions() {
54
54
  ideaCompat: false,
55
55
  engine: process.env.EXODUS_TEST_ENGINE ?? 'node:test',
56
56
  require: [],
57
+ testNamePattern: [],
57
58
  }
58
59
 
59
60
  const args = [...process.argv]
@@ -69,16 +70,22 @@ function parseOptions() {
69
70
 
70
71
  while (args[0]?.startsWith('-')) {
71
72
  const option = args.shift()
73
+ if (option.includes('=')) {
74
+ const [optionName, ...rest] = option.split('=')
75
+ args.unshift(optionName, rest.join('='))
76
+ continue
77
+ }
78
+
72
79
  if (options.ideaCompat) {
73
80
  // Ignore some options IntelliJ IDEA is passing
74
81
  switch (option) {
75
82
  case '--reporters':
83
+ case '--testTimeout':
76
84
  args.shift()
77
85
  continue
78
86
  case '--verbose':
79
87
  case '--runTestsByPath':
80
88
  case '--runInBand':
81
- case '--testTimeout=7200000':
82
89
  continue
83
90
  }
84
91
  }
@@ -147,6 +154,10 @@ function parseOptions() {
147
154
  case '--idea-compat':
148
155
  options.ideaCompat = true
149
156
  break
157
+ case '--test-name-pattern':
158
+ case '--testNamePattern':
159
+ options.testNamePattern.push(args.shift())
160
+ break
150
161
  default:
151
162
  throw new Error(`Unknown option: ${option}`)
152
163
  }
@@ -174,6 +185,11 @@ const resolveRequire = (query) => require.resolve(query)
174
185
  const resolveImport = import.meta.resolve && ((query) => fileURLToPath(import.meta.resolve(query)))
175
186
 
176
187
  const args = []
188
+
189
+ if (haveModuleMocks && ['node:test', 'node:pure'].includes(options.engine)) {
190
+ args.push('--experimental-test-module-mocks')
191
+ }
192
+
177
193
  if (options.pure) {
178
194
  if (options.bundle) {
179
195
  assert(!options.coverage, `Can not use --coverage with ${options.engine} engine`)
@@ -185,10 +201,10 @@ if (options.pure) {
185
201
  assert(!options.writeSnapshots, `Can not use write snapshots with ${options.engine} engine`)
186
202
  assert(!options.forceExit, `Can not use --force-exit with ${options.engine} engine yet`) // TODO
187
203
  assert(!options.watch, `Can not use --watch with with ${options.engine} engine`)
204
+ assert(options.testNamePattern.length === 0, '--test-name-pattern requires node:test engine now')
188
205
  } else if (options.engine === 'node:test') {
189
206
  args.push('--test', '--no-warnings=ExperimentalWarning', '--test-reporter=spec')
190
207
 
191
- if (haveModuleMocks) args.push('--experimental-test-module-mocks')
192
208
  if (haveSnapshots) args.push('--experimental-test-snapshots')
193
209
 
194
210
  if (options.writeSnapshots) {
@@ -204,6 +220,8 @@ if (options.pure) {
204
220
  if (options.watch) args.push('--watch')
205
221
  if (options.only) args.push('--test-only')
206
222
 
223
+ for (const pattern of options.testNamePattern) args.push('--test-name-pattern', pattern)
224
+
207
225
  args.push('--expose-internals') // this is unoptimal and hopefully temporary, see rationale in src/dark.cjs
208
226
  } else {
209
227
  throw new Error('Unreachable')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/test",
3
- "version": "1.0.0-rc.40",
3
+ "version": "1.0.0-rc.42",
4
4
  "author": "Exodus Movement, Inc.",
5
5
  "description": "A test suite runner",
6
6
  "homepage": "https://github.com/ExodusMovement/test",
@@ -110,7 +110,7 @@
110
110
  "c8": "^9.1.0",
111
111
  "constants-browserify": "^1.0.0",
112
112
  "crypto-browserify": "^3.12.0",
113
- "esbuild": "~0.21.5",
113
+ "esbuild": "~0.23.1",
114
114
  "events": "^3.3.0",
115
115
  "expect": "^29.7.0",
116
116
  "fast-glob": "^3.2.11",
@@ -124,7 +124,7 @@
124
124
  "stream-browserify": "^3.0.0",
125
125
  "text-encoding": "^0.7.0",
126
126
  "timers-browserify": "^2.0.12",
127
- "tsx": "^4.16.2",
127
+ "tsx": "^4.19.0",
128
128
  "url": "^0.11.0",
129
129
  "util": "^0.12.5"
130
130
  },
@@ -391,6 +391,14 @@ const mock = {
391
391
  },
392
392
  }
393
393
 
394
+ if (process.env.EXODUS_TEST_ENGINE === 'node:pure') {
395
+ // Try load module mocks from node:test, if present
396
+ try {
397
+ const nodeTest = require('node:test')
398
+ mock.module = nodeTest.mock.module.bind(nodeTest.mock)
399
+ } catch {}
400
+ }
401
+
394
402
  const beforeEach = (fn) => context.hooks.beforeEach.push(fn)
395
403
  const afterEach = (fn) => context.hooks.afterEach.push(fn)
396
404
  const before = (fn) => context.hooks.before.push(fn)
@@ -6,7 +6,7 @@ export const specialEnvironments = {
6
6
  setup: (require) => {
7
7
  const { JSDOM, VirtualConsole } = require('jsdom')
8
8
  const virtualConsole = new VirtualConsole()
9
- const { window } = new JSDOM('<!DOCTYPE html>', {
9
+ const dom = new JSDOM('<!DOCTYPE html>', {
10
10
  url: 'http://localhost/',
11
11
  pretendToBeVisual: true,
12
12
  runScripts: 'dangerously',
@@ -17,17 +17,21 @@ export const specialEnvironments = {
17
17
  throw error
18
18
  })
19
19
  const assignMissing = (target, source) => {
20
- const entries = Object.entries(source).filter(([key]) => !Object.hasOwn(target, key))
21
- Object.assign(target, Object.fromEntries(entries))
20
+ const descriptors = Object.getOwnPropertyDescriptors(source)
21
+ const entries = Object.entries(descriptors).filter(([key]) => !Object.hasOwn(target, key))
22
+ Object.defineProperties(target, Object.fromEntries(entries))
22
23
  }
23
24
 
24
- assignMissing(globalThis, window)
25
- assignMissing(console, window.console)
26
- Object.setPrototypeOf(global, Object.getPrototypeOf(window))
25
+ assignMissing(globalThis, dom.window)
26
+ assignMissing(console, dom.window.console)
27
+ Object.setPrototypeOf(globalThis, Object.getPrototypeOf(dom.window))
28
+ try {
29
+ assignMissing(globalThis, dom.getInternalVMContext())
30
+ } catch {}
27
31
  },
28
32
  },
29
33
 
30
- // Reproduces setup-polly-jest/jest-environment-node ad hacks into 'setup-polly-jest'.pollyJest
34
+ // Reproduces setup-polly-jest/jest-environment-node and hacks into 'setup-polly-jest'.pollyJest
31
35
  'setup-polly-jest/jest-environment-node': {
32
36
  dependencies: ['@pollyjs/core', 'setup-polly-jest', 'setup-polly-jest/lib/common'],
33
37
  setup: async (require, engine) => {
@@ -94,7 +94,10 @@ const snapInline = (obj, inline) => {
94
94
  assert(inline !== undefined, 'Inline Snapshots generation is not supported')
95
95
  assert(typeof inline === 'string')
96
96
  maybeSetupSerializers()
97
- getAssert().strictEqual(serialize(obj).trim(), inline.trim())
97
+ let trimmed = inline.trim()
98
+ const prefix = inline.slice(0, inline.indexOf(trimmed)).split('\n').find(Boolean)
99
+ if (prefix && /^[ \t]+$/u.test(prefix)) trimmed = trimmed.replaceAll(`\n${prefix}`, '\n')
100
+ getAssert().strictEqual(serialize(obj).trim(), trimmed)
98
101
  }
99
102
 
100
103
  const deepMerge = (obj, matcher) => {