@@ -4,6 +4,7 @@ import { specialEnvironments } from './jest.environment.js'
44
55const skipPreset = new Set ( [ 'ts-jest' ] )
66const EXTS = `.?([cm])[jt]s?(x)` // we differ from jest, allowing [cm] before everything
7+ const needPreset = ( { preset } = { } ) => preset && ! skipPreset . has ( preset )
78const normalizeJestConfig = ( config ) => ( {
89 testMatch : [ `**/__tests__/**/*${ EXTS } ` , `**/?(*.)+(spec|test)${ EXTS } ` ] ,
910 testEnvironment : 'node' ,
@@ -65,6 +66,67 @@ export const jestConfig = () => {
6566
6667// Methods loadJestConfig() and installJestEnvironment() below are for --jest flag
6768
69+ // Optimized out in 'bundle' env
70+ async function loadConfigParts ( rawConfig ) {
71+ const presetExtension = / \. ( [ c m ] ? j s | j s o n ) $ / u
72+ const suffixes = [ '/jest-preset.json' , '/jest-preset.js' , '/jest-preset.cjs' , '/jest-preset.mjs' ]
73+ const resolveGlobalSetup = ( config , req ) => {
74+ if ( config . globalSetup ) config . globalSetup = req . resolve ( config . globalSetup ) // eslint-disable-line @exodus/mutable/no-param-reassign-prop-only
75+ if ( config . globalTeardown ) config . globalTeardown = req . resolve ( config . globalTeardown ) // eslint-disable-line @exodus/mutable/no-param-reassign-prop-only
76+ }
77+
78+ assert ( rawConfig . rootDir )
79+ const { resolve } = await import ( 'node:path' )
80+ const { createRequire } = await import ( 'node:module' )
81+ const { pathToFileURL } = await import ( 'node:url' )
82+ let requireConfig = createRequire ( resolve ( rawConfig . rootDir , 'package.json' ) )
83+ resolveGlobalSetup ( rawConfig , requireConfig )
84+ while ( needPreset ( rawConfig ) ) {
85+ let baseConfig
86+
87+ const attemptLoad = async ( file ) => {
88+ try {
89+ const resolved = requireConfig . resolve ( file )
90+ // FIXME: fix linter to allow this
91+ // const meta = resolved.toLowerCase().endsWith('.json') ? { with: { type: 'json' } } : undefined
92+ // const presetModule = await import(pathToFileURL(resolved), meta)
93+ const presetModule = await import ( pathToFileURL ( resolved ) )
94+ requireConfig = createRequire ( resolved )
95+ baseConfig = presetModule . default
96+ } catch { }
97+ }
98+
99+ // Even if it is relative, it could be a path to module
100+ for ( const suffix of suffixes ) {
101+ if ( ! baseConfig ) await attemptLoad ( `${ rawConfig . preset } ${ suffix } ` )
102+ }
103+
104+ // If it's a path to a file
105+ if ( ! baseConfig && rawConfig . preset [ 0 ] === '.' && presetExtension . test ( rawConfig . preset ) ) {
106+ const { statSync } = await import ( 'node:fs' )
107+ if ( statSync ( rawConfig . preset ) . isFile ( ) ) await attemptLoad ( rawConfig . preset )
108+ }
109+
110+ assert ( baseConfig , `Could not load preset: ${ rawConfig . preset } ` )
111+ resolveGlobalSetup ( baseConfig , requireConfig )
112+ rawConfig = {
113+ ...baseConfig ,
114+ ...rawConfig ,
115+ preset : baseConfig . preset ,
116+ setupFiles : [
117+ ...( baseConfig . setupFiles || [ ] ) . map ( ( file ) => requireConfig . resolve ( file ) ) ,
118+ ...( rawConfig . setupFiles || [ ] ) ,
119+ ] ,
120+ setupFilesAfterEnv : [
121+ ...( baseConfig . setupFilesAfterEnv || [ ] ) . map ( ( file ) => requireConfig . resolve ( file ) ) ,
122+ ...( rawConfig . setupFilesAfterEnv || [ ] ) ,
123+ ] ,
124+ }
125+ }
126+
127+ return rawConfig
128+ }
129+
68130export async function loadJestConfig ( ...args ) {
69131 let rawConfig
70132 if ( process . env . EXODUS_TEST_JEST_CONFIG === undefined ) {
@@ -75,67 +137,12 @@ export async function loadJestConfig(...args) {
75137 }
76138
77139 const cleanFile = ( file ) => file . replace ( / ^ < r o o t D i r > \/ / g, './' ) // require is already relative to rootDir
78- const needPreset = ( { preset } = { } ) => preset && ! skipPreset . has ( preset )
79- const resolveGlobalSetup = ( config , req ) => {
80- if ( config . globalSetup ) config . globalSetup = req . resolve ( config . globalSetup ) // eslint-disable-line @exodus/mutable/no-param-reassign-prop-only
81- if ( config . globalTeardown ) config . globalTeardown = req . resolve ( config . globalTeardown ) // eslint-disable-line @exodus/mutable/no-param-reassign-prop-only
82- }
83-
84- const presetExtension = / \. ( [ c m ] ? j s | j s o n ) $ / u
85- const suffixes = [ '/jest-preset.json' , '/jest-preset.js' , '/jest-preset.cjs' , '/jest-preset.mjs' ]
86140 if ( needPreset ( rawConfig ) || rawConfig ?. globalSetup || rawConfig ?. globalTeardown ) {
87141 rawConfig . preset = cleanFile ( rawConfig . preset ) // relative to root dir only at top level, presets shouldn't use <rootDir>
88142 if ( process . env . EXODUS_TEST_ENVIRONMENT === 'bundle' ) {
89143 throw new Error ( 'jest preset and globalSetup/Teardown not yet supported in bundles' )
90144 } else {
91- assert ( rawConfig . rootDir )
92- const { resolve } = await import ( 'node:path' )
93- const { createRequire } = await import ( 'node:module' )
94- const { pathToFileURL } = await import ( 'node:url' )
95- let requireConfig = createRequire ( resolve ( rawConfig . rootDir , 'package.json' ) )
96- resolveGlobalSetup ( rawConfig , requireConfig )
97- while ( needPreset ( rawConfig ) ) {
98- let baseConfig
99-
100- const attemptLoad = async ( file ) => {
101- try {
102- const resolved = requireConfig . resolve ( file )
103- // FIXME: fix linter to allow this
104- // const meta = resolved.toLowerCase().endsWith('.json') ? { with: { type: 'json' } } : undefined
105- // const presetModule = await import(pathToFileURL(resolved), meta)
106- const presetModule = await import ( pathToFileURL ( resolved ) )
107- requireConfig = createRequire ( resolved )
108- baseConfig = presetModule . default
109- } catch { }
110- }
111-
112- // Even if it is relative, it could be a path to module
113- for ( const suffix of suffixes ) {
114- if ( ! baseConfig ) await attemptLoad ( `${ rawConfig . preset } ${ suffix } ` )
115- }
116-
117- // If it's a path to a file
118- if ( ! baseConfig && rawConfig . preset [ 0 ] === '.' && presetExtension . test ( rawConfig . preset ) ) {
119- const { statSync } = await import ( 'node:fs' )
120- if ( statSync ( rawConfig . preset ) . isFile ( ) ) await attemptLoad ( rawConfig . preset )
121- }
122-
123- assert ( baseConfig , `Could not load preset: ${ rawConfig . preset } ` )
124- resolveGlobalSetup ( baseConfig , requireConfig )
125- rawConfig = {
126- ...baseConfig ,
127- ...rawConfig ,
128- preset : baseConfig . preset ,
129- setupFiles : [
130- ...( baseConfig . setupFiles || [ ] ) . map ( ( file ) => requireConfig . resolve ( file ) ) ,
131- ...( rawConfig . setupFiles || [ ] ) ,
132- ] ,
133- setupFilesAfterEnv : [
134- ...( baseConfig . setupFilesAfterEnv || [ ] ) . map ( ( file ) => requireConfig . resolve ( file ) ) ,
135- ...( rawConfig . setupFilesAfterEnv || [ ] ) ,
136- ] ,
137- }
138- }
145+ await loadConfigParts ( rawConfig )
139146 }
140147 }
141148
@@ -148,6 +155,15 @@ export async function loadJestConfig(...args) {
148155 return config
149156}
150157
158+ // Optimized out in 'bundle' env
159+ async function makeDynamicImport ( rootDir ) {
160+ const { resolve } = await import ( 'node:path' )
161+ const { createRequire } = await import ( 'node:module' )
162+ const { pathToFileURL } = await import ( 'node:url' )
163+ const require = createRequire ( resolve ( rootDir , 'package.json' ) )
164+ return ( path ) => import ( pathToFileURL ( require . resolve ( path ) ) ) // does not need json imports
165+ }
166+
151167export async function installJestEnvironment ( jestGlobals ) {
152168 const engine = await import ( './engine.js' )
153169
@@ -173,11 +189,7 @@ export async function installJestEnvironment(jestGlobals) {
173189 assert . fail ( 'Requiring non-bundled plugins from bundle is unsupported' )
174190 }
175191 } else if ( config . rootDir ) {
176- const { resolve } = await import ( 'node:path' )
177- const { createRequire } = await import ( 'node:module' )
178- const { pathToFileURL } = await import ( 'node:url' )
179- const require = createRequire ( resolve ( config . rootDir , 'package.json' ) )
180- dynamicImport = ( path ) => import ( pathToFileURL ( require . resolve ( path ) ) ) // does not need json imports
192+ dynamicImport = makeDynamicImport ( config . rootDir )
181193 } else {
182194 dynamicImport = async ( ) => assert . fail ( 'Unreachable: importing plugins without a rootDir' )
183195 }
0 commit comments