@@ -13,7 +13,7 @@ import Codecept from './codecept.js'
1313import MochaFactory from './mocha/factory.js'
1414import Container from './container.js'
1515import { getTestRoot } from './command/utils.js'
16- import { isFunction , fileExists , replaceValueDeep , deepClone } from './utils.js'
16+ import { isFunction , fileExists } from './utils.js'
1717import mainConfig from './config.js'
1818import output from './output.js'
1919import event from './event.js'
@@ -117,34 +117,11 @@ const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns
117117 }
118118 const workersToExecute = [ ]
119119
120- const currentOutputFolder = config . output
121- let currentMochawesomeReportDir
122- let currentMochaJunitReporterFile
123-
124- if ( config . mocha && config . mocha . reporterOptions ) {
125- currentMochawesomeReportDir = config . mocha . reporterOptions ?. mochawesome . options . reportDir
126- currentMochaJunitReporterFile = config . mocha . reporterOptions [ 'mocha-junit-reporter' ] . options . mochaFile
127- }
128-
129120 createRuns ( selectedRuns , config ) . forEach ( worker => {
130- const separator = path . sep
131- const _config = { ...config }
132- let workerName = worker . name . replace ( ':' , '_' )
133- _config . output = `${ currentOutputFolder } ${ separator } ${ workerName } `
134- if ( config . mocha && config . mocha . reporterOptions ) {
135- _config . mocha . reporterOptions . mochawesome . options . reportDir = `${ currentMochawesomeReportDir } ${ separator } ${ workerName } `
136-
137- const _tempArray = currentMochaJunitReporterFile . split ( separator )
138- _tempArray . splice (
139- _tempArray . findIndex ( item => item . includes ( '.xml' ) ) ,
140- 0 ,
141- workerName ,
142- )
143- _config . mocha . reporterOptions [ 'mocha-junit-reporter' ] . options . mochaFile = _tempArray . join ( separator )
144- }
145- workerName = worker . getOriginalName ( ) || worker . getName ( )
146- const workerConfig = worker . getConfig ( )
147- workersToExecute . push ( getOverridenConfig ( workerName , workerConfig , _config ) )
121+ const workerName = worker . name . replace ( ':' , '_' )
122+ const _config = mainConfig . applyRunConfig ( config , worker . getConfig ( ) )
123+ _config . output = path . join ( config . output , workerName )
124+ workersToExecute . push ( _config )
148125 } )
149126 const workers = [ ]
150127 let index = 0
@@ -188,27 +165,6 @@ const convertToMochaTests = testGroup => {
188165 return group
189166}
190167
191- const getOverridenConfig = ( workerName , workerConfig , config ) => {
192- // clone config
193- const overriddenConfig = deepClone ( config )
194-
195- // get configuration
196- const browserConfig = workerConfig . browser
197-
198- for ( const key in browserConfig ) {
199- overriddenConfig . helpers = replaceValueDeep ( overriddenConfig . helpers , key , browserConfig [ key ] )
200- }
201-
202- // override tests configuration
203- if ( overriddenConfig . tests ) {
204- overriddenConfig . tests = workerConfig . tests
205- }
206-
207- if ( overriddenConfig . gherkin && workerConfig . gherkin && workerConfig . gherkin . features ) {
208- overriddenConfig . gherkin . features = workerConfig . gherkin . features
209- }
210- return overriddenConfig
211- }
212168
213169class WorkerObject {
214170 /**
@@ -224,17 +180,11 @@ class WorkerObject {
224180 addConfig ( config ) {
225181 const oldConfig = JSON . parse ( this . options . override || '{}' )
226182
227- // Remove customLocatorStrategies from both old and new config before JSON serialization
228- // since functions cannot be serialized and will be lost, causing workers to have empty strategies.
229- // Note: Only WebDriver helper supports customLocatorStrategies
230- const configWithoutFunctions = { ...config }
231-
232- // Clean both old and new config
233183 const cleanConfig = cfg => {
234184 if ( cfg . helpers ) {
235185 cfg . helpers = { ...cfg . helpers }
236186 Object . keys ( cfg . helpers ) . forEach ( helperName => {
237- if ( cfg . helpers [ helperName ] && cfg . helpers [ helperName ] . customLocatorStrategies !== undefined ) {
187+ if ( cfg . helpers [ helperName ] ? .customLocatorStrategies !== undefined ) {
238188 cfg . helpers [ helperName ] = { ...cfg . helpers [ helperName ] }
239189 delete cfg . helpers [ helperName ] . customLocatorStrategies
240190 }
@@ -243,11 +193,7 @@ class WorkerObject {
243193 return cfg
244194 }
245195
246- const cleanedOldConfig = cleanConfig ( oldConfig )
247- const cleanedNewConfig = cleanConfig ( configWithoutFunctions )
248-
249- // Deep merge configurations to preserve all helpers from base config
250- const newConfig = merge ( { } , cleanedOldConfig , cleanedNewConfig )
196+ const newConfig = merge ( { } , cleanConfig ( oldConfig ) , cleanConfig ( config ) )
251197 this . options . override = JSON . stringify ( newConfig )
252198 }
253199
@@ -292,8 +238,6 @@ class Workers extends EventEmitter {
292238 this . testPool = [ ]
293239 this . testPoolInitialized = false
294240 this . isPoolMode = config . by === 'pool'
295- this . activeWorkers = new Map ( )
296- this . maxWorkers = numberOfWorkers // Track original worker count for pool mode
297241
298242 createOutputDir ( config . testConfig )
299243 // Defer worker initialization until codecept is ready
@@ -395,36 +339,11 @@ class Workers extends EventEmitter {
395339 this . testGroups = populateGroups ( numberOfWorkers )
396340 }
397341
398- /**
399- * Initialize the test pool if not already done
400- * This is called lazily to avoid state pollution issues during construction
401- */
402342 _initializeTestPool ( ) {
403- if ( this . testPoolInitialized ) {
404- return
405- }
406-
407- // Ensure codecept is initialized
408- if ( ! this . codecept ) {
409- output . log ( 'Warning: codecept not initialized when initializing test pool' )
410- this . testPoolInitialized = true
411- return
412- }
413-
414- const files = this . codecept . testFiles
415- if ( ! files || files . length === 0 ) {
416- this . testPoolInitialized = true
417- return
418- }
419-
420- // In ESM, test UIDs are not stable across different mocha instances
421- // So instead of using UIDs, we distribute test FILES
422- // Each file may contain multiple tests
423- for ( const file of files ) {
424- this . testPool . push ( file )
425- }
426-
343+ if ( this . testPoolInitialized ) return
427344 this . testPoolInitialized = true
345+ if ( ! this . codecept ) return
346+ this . testPool = [ ...this . codecept . testFiles ]
428347 }
429348
430349 /**
@@ -493,10 +412,6 @@ class Workers extends EventEmitter {
493412 workerThreads . push ( workerThread )
494413 }
495414
496- recorder . add ( 'workers started' , ( ) => {
497- // Workers are already running, this is just a placeholder step
498- } )
499-
500415 // Add overall timeout to prevent infinite hanging
501416 const overallTimeout = setTimeout ( ( ) => {
502417 console . error ( '[Main] Overall timeout reached (10 minutes). Force terminating remaining workers...' )
@@ -533,11 +448,6 @@ class Workers extends EventEmitter {
533448 }
534449
535450 _listenWorkerEvents ( worker ) {
536- // Track worker thread for pool mode
537- if ( this . isPoolMode ) {
538- this . activeWorkers . set ( worker , { available : true , workerIndex : null } )
539- }
540-
541451 // Track last activity time to detect hanging workers
542452 let lastActivity = Date . now ( )
543453 let currentTest = null
0 commit comments