codeceptjs 4.0.2-beta.3 → 4.0.2-beta.5

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.
@@ -19,6 +19,18 @@ const stderr = ''
19
19
 
20
20
  const { options, tests, testRoot, workerIndex, poolMode } = workerData
21
21
 
22
+ // Global error handlers to prevent worker from hanging
23
+ process.on('uncaughtException', (err) => {
24
+ console.error(`[Worker ${workerIndex}] Uncaught exception:`, err.message)
25
+ console.error(err.stack)
26
+ process.exit(1)
27
+ })
28
+
29
+ process.on('unhandledRejection', (reason, promise) => {
30
+ console.error(`[Worker ${workerIndex}] Unhandled rejection:`, reason)
31
+ process.exit(1)
32
+ })
33
+
22
34
  // hide worker output
23
35
  // In pool mode, only suppress output if debug is NOT enabled
24
36
  // In regular mode, hide result output but allow step output in verbose/debug
@@ -116,7 +128,10 @@ initPromise = (async function () {
116
128
  // We'll reload test files fresh for each test request
117
129
  } else {
118
130
  // Legacy mode - filter tests upfront
131
+ console.log(`[Worker ${workerIndex}] Starting test filtering. Assigned ${tests.length} test UIDs`)
119
132
  filterTests()
133
+ const finalCount = mocha.suite.total()
134
+ console.log(`[Worker ${workerIndex}] After filtering: ${finalCount} tests to run`)
120
135
  }
121
136
 
122
137
  // run tests
@@ -126,6 +141,7 @@ initPromise = (async function () {
126
141
  await runTests()
127
142
  } else {
128
143
  // No tests to run, close the worker
144
+ console.error(`[Worker ${workerIndex}] ERROR: No tests found after filtering! Assigned ${tests.length} UIDs but none matched.`)
129
145
  parentPort?.close()
130
146
  }
131
147
  } catch (err) {
@@ -140,6 +156,7 @@ async function runTests() {
140
156
  try {
141
157
  await codecept.bootstrap()
142
158
  } catch (err) {
159
+ console.error(`[Worker ${workerIndex}] Bootstrap error:`, err.message)
143
160
  throw new Error(`Error while running bootstrap file :${err}`)
144
161
  }
145
162
  listenToParentThread()
@@ -147,8 +164,15 @@ async function runTests() {
147
164
  disablePause()
148
165
  try {
149
166
  await codecept.run()
167
+ } catch (err) {
168
+ console.error(`[Worker ${workerIndex}] Runtime error:`, err.message)
169
+ throw err
150
170
  } finally {
151
- await codecept.teardown()
171
+ try {
172
+ await codecept.teardown()
173
+ } catch (err) {
174
+ console.error(`[Worker ${workerIndex}] Teardown error:`, err.message)
175
+ }
152
176
  }
153
177
  }
154
178
 
@@ -336,24 +360,24 @@ function filterTests() {
336
360
  mocha.files = files
337
361
  mocha.loadFiles()
338
362
 
339
- // Debug logging to help diagnose test filtering issues
340
- if (options.debug || options.verbose) {
341
- const allLoadedTests = [];
342
- mocha.suite.eachTest(test => {
343
- if (test) {
344
- allLoadedTests.push({ uid: test.uid, title: test.fullTitle() });
345
- }
346
- });
347
-
348
- console.log(`[Worker ${workerIndex}] Loaded ${allLoadedTests.length} tests, expecting ${tests.length} tests`);
349
-
350
- const loadedUids = new Set(allLoadedTests.map(t => t.uid));
351
- const missingTests = tests.filter(uid => !loadedUids.has(uid));
352
-
353
- if (missingTests.length > 0) {
354
- console.log(`[Worker ${workerIndex}] WARNING: ${missingTests.length} assigned tests not found in loaded files`);
355
- console.log(`[Worker ${workerIndex}] Missing UIDs:`, missingTests);
363
+ // Collect all loaded tests for debugging
364
+ const allLoadedTests = [];
365
+ mocha.suite.eachTest(test => {
366
+ if (test) {
367
+ allLoadedTests.push({ uid: test.uid, title: test.fullTitle() });
356
368
  }
369
+ });
370
+
371
+ console.log(`[Worker ${workerIndex}] Loaded ${allLoadedTests.length} tests from ${files.length} files`);
372
+ console.log(`[Worker ${workerIndex}] Expecting ${tests.length} test UIDs`);
373
+
374
+ const loadedUids = new Set(allLoadedTests.map(t => t.uid));
375
+ const missingTests = tests.filter(uid => !loadedUids.has(uid));
376
+
377
+ if (missingTests.length > 0) {
378
+ console.error(`[Worker ${workerIndex}] ERROR: ${missingTests.length} assigned tests NOT FOUND in loaded files!`);
379
+ console.error(`[Worker ${workerIndex}] Missing UIDs:`, missingTests);
380
+ console.error(`[Worker ${workerIndex}] Available UIDs:`, Array.from(loadedUids).slice(0, 5), '...');
357
381
  }
358
382
 
359
383
  // Recursively filter tests in all suites (including nested ones)
@@ -367,13 +391,6 @@ function filterTests() {
367
391
  for (const suite of mocha.suite.suites) {
368
392
  filterSuiteTests(suite)
369
393
  }
370
-
371
- // Verify final test count
372
- if (options.debug || options.verbose) {
373
- let finalCount = 0;
374
- mocha.suite.eachTest(() => finalCount++);
375
- console.log(`[Worker ${workerIndex}] After filtering: ${finalCount} tests will run`);
376
- }
377
394
  }
378
395
 
379
396
  function initializeListeners() {
package/lib/workers.js CHANGED
@@ -542,8 +542,22 @@ class Workers extends EventEmitter {
542
542
  if (this.isPoolMode) {
543
543
  this.activeWorkers.set(worker, { available: true, workerIndex: null })
544
544
  }
545
+
546
+ // Track last activity time to detect hanging workers
547
+ let lastActivity = Date.now()
548
+ const workerTimeout = 300000 // 5 minutes
549
+
550
+ const timeoutChecker = setInterval(() => {
551
+ const elapsed = Date.now() - lastActivity
552
+ if (elapsed > workerTimeout) {
553
+ console.error(`[Main] Worker appears to be hanging (no activity for ${Math.floor(elapsed/1000)}s). Terminating...`)
554
+ clearInterval(timeoutChecker)
555
+ worker.terminate()
556
+ }
557
+ }, 30000) // Check every 30 seconds
545
558
 
546
559
  worker.on('message', message => {
560
+ lastActivity = Date.now() // Update activity timestamp
547
561
  output.process(message.workerIndex)
548
562
 
549
563
  // Handle test requests for pool mode
@@ -660,11 +674,17 @@ class Workers extends EventEmitter {
660
674
  })
661
675
 
662
676
  worker.on('error', err => {
677
+ console.error(`[Main] Worker error:`, err.message || err)
663
678
  this.errors.push(err)
664
679
  })
665
680
 
666
- worker.on('exit', () => {
681
+ worker.on('exit', (code) => {
682
+ clearInterval(timeoutChecker)
667
683
  this.closedWorkers += 1
684
+
685
+ if (code !== 0) {
686
+ console.error(`[Main] Worker exited with code ${code}`)
687
+ }
668
688
 
669
689
  if (this.isPoolMode) {
670
690
  // Pool mode: finish when all workers have exited and no more tests
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "4.0.2-beta.3",
3
+ "version": "4.0.2-beta.5",
4
4
  "type": "module",
5
5
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
6
6
  "keywords": [