Tags: codeceptjs/CodeceptJS
Tags
fix(typescript): unique temp file names to fix run-multiple race (#5642… …) (#5643) Transpiled TypeScript files were written to a fixed "<source>.temp.mjs" path next to the source. Under run-multiple, every forked worker transpiles the same files to the same temp paths and cleans them up independently, so one worker's cleanup deletes files the others still need to import — surfacing as "Cannot find module *.temp.mjs". Include process.pid plus a random suffix in the temp file name so each worker writes (and removes) its own files. The names still end in ".temp.mjs", so stack-trace remapping and fixErrorStack keep working. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
fix(core): load Mocha test files as ES Modules so internal-API import…
…s resolve to the live instance
Test files were loaded with synchronous require(), which under tsx/cjs
created a second CommonJS copy of lib/* modules. A test's
`import { config } from "codeceptjs"` then resolved to a disconnected copy
whose module-level singletons were never populated (#5636).
Load test files through `await import()` instead — the same way the
container already loads helpers — so the whole run shares one ES module
graph and plain imports are honest. New lib/mocha/loadTests.js mirrors
Mocha's loadFiles (lazyLoadFiles + per-file pre-require/require/post-require)
to preserve teardown hooks, the gherkin .feature path, and the
dup/missing-Feature validation.
All synchronous mocha.loadFiles() sites converted: codecept.run(), rerun,
workers (parent grouping + worker threads), dry-run, and check.
TypeScript: tsx/cjs is a require hook and can no longer transpile test
files loaded via import(). requireModules() auto-maps tsx/cjs -> tsx/esm
with a deprecation notice; tsx/esm needs "type": "module" in package.json
(init now writes it, and an ERR_REQUIRE_CYCLE_MODULE guard points users to it).
BREAKING CHANGE: the programmatic Workers grouping API
(createGroupsOfTests, createGroupsOfSuites, addTestFiles, splitTestsByGroups)
is now async. TypeScript projects must set "type": "module" in package.json.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(deps): don't auto-install detox & react-native (#5620) (#5621) @codeceptjs/detox-helper was listed under optionalDependencies, which npm/pnpm install by default. It hard-depends on detox and react-native, so every codeceptjs install pulled in those heavy packages (and the dtrace-provider build script) even though core never requires the Detox helper — it is a user-configured external helper. Move it to devDependencies (still needed for in-repo helper docs generation). Users who need the Detox helper install it separately. Co-authored-by: DavertMik <davert@testomat.io> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
fix(run-multiple): restore plugin loading and per-child reportDir (#5577 ) (#5578) Two regressions introduced during the 3.x → 4.x ESM migration: ## Bug 1 – plugins with runInWorker:false silently skipped in child processes lib/container.js used options.child to detect "running inside a worker thread" and skipped plugins whose runInWorker is false (testomatio defaults to false). But run-multiple also sets --child on every forked child process, so those plugins were incorrectly skipped there too. Fix: replace options.child with !isMainThread (worker_threads). A run-multiple child is a freshly-forked OS process whose isMainThread is true, so the gate no longer fires. An actual run-workers worker thread has isMainThread === false, so the gate still fires as intended. | Context | options.child | isMainThread | before (skipped?) | after | |---------------------------|---------------|--------------|-------------------|--------| | run-workers worker thread | truthy (idx) | false | skipped ✓ | skipped ✓ | | run-multiple child proc | truthy (str) | true | skipped ✗ (bug) | loads ✓ | | normal run / parent proc | falsy | true | loads ✓ | loads ✓ | ## Bug 2 – all children write to the same reportDir, last one wins 3.x run-multiple.js replaced three per-child directory keys before forking: output, reportDir, mochaFile The 4.x port dropped the reportDir line, so every child kept the shared reportDir value from the config (e.g. "output/report") and overwrote each other's HTML file. Fix: restore the missing replaceValueDeep('reportDir', ...) call so each child receives its own directory, matching 3.x behaviour. Regression test added: verifies that a plugin with runInWorker:false is initialised once per child and that each child receives a distinct reportDir. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix retryFailedStep ignoredSteps exact-name matching (#5571) * Fix retryFailedStep ignoredSteps exact-name matching The wildcard check used `ignored.indexOf('*')` as a boolean. `-1` is truthy in JavaScript (only `0` is falsy), so entries without `*` were matched via `startsWith(slice(0, -1))` instead of exact compare, which also chops the last character — broadening the match further. `ignoredSteps: ['see']` silently ignored `seeElement`, `seeInField`, `selectOption`, `sendPostRequest` — anything starting with `se`. Compare against `-1` explicitly so exact-name entries only match themselves, as the docs describe. * fix(retryFailedStep): avoid mutating shared defaultConfig Each call to retryFailedStep mutated the module-level defaultConfig via Object.assign(defaultConfig, config), so config.when from a prior call leaked into the next as customWhen and chained recursively. In tests this made when() return undefined for closures that no longer had a live step.started listener (e.g. after event.cleanDispatcher), causing the new regression test to fail in the full unit suite even though it passed in isolation. Use Object.assign({}, defaultConfig, config) so each registration gets an independent config object. Rewrites the regression test to assert via retryConfig.when() directly, which is now sound. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Michael Bodnarchuk <davert.ua@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
PreviousNext