Skip to content

4.x: The test in the mode "run-multiple" sometimes fails: "Cannot find module *.temp.mjs" #5642

@mirao

Description

@mirao

I hit it once after migration of my 3.x project to 4.x.
A problem is that the customhelper.temp.mjs is shared during the transpilation in "run-multiple" and when it's deleted by one of the processes the others are missing it.

Here is the setup and script (prepared by AI) how to reproduce the issue reliably:

repro/tests/a_test.ts

Feature('A');

Scenario('a noop', ({ I }) => {
  I.noop();
});

repro/tests/b_test.ts

Feature('B');

Scenario('b noop', ({ I }) => {
  I.noop();
});

repro/tests/c_test.ts

Feature('C');

Scenario('c noop', ({ I }) => {
  I.noop();
});

repro/codecept.conf.ts

import { WORKERS } from './shared';

// Minimal, browser-free CodeceptJS config that reproduces the run-multiple
// "Cannot find module *.temp.mjs" race in CodeceptJS 4.x.
//
// Every .ts file referenced here (this config, ./shared.ts, ./CustomHelper.ts,
// ./steps_file.ts and each tests/*_test.ts) is transpiled by the built-in
// TypeScript transpiler into a FIXED "<name>.temp.mjs" file next to the source,
// imported, then deleted on cleanup. run-multiple forks one OS process per
// "browser" entry, all at once, so the workers fight over the same temp paths.
export const config: CodeceptJS.MainConfig = {
  tests: './tests/*_test.ts',
  output: './output',
  helpers: {
    Custom: { require: './CustomHelper.ts' },
  },
  include: {
    I: './steps_file.ts',
  },
  multiple: {
    // One named run expanded into WORKERS.length concurrent forked processes.
    parallel: {
      browsers: WORKERS,
    },
  },
  name: 'repro',
  // Matches the real project. Note: this loader only affects *test* files.
  // codecept.conf.ts / helpers / include files are still transpiled by the
  // built-in transpiler into "*.temp.mjs" (it runs before any loader exists),
  // which is exactly what races under run-multiple.
  require: ['tsx/cjs'],
};

repro/CustomHelper.ts

// A browser-free helper so the repro needs no Playwright / network.
import Helper from '@codeceptjs/helper';

class CustomHelper extends Helper {
  async noop() {
    return true;
  }
}

export default CustomHelper;

repro/shared.ts

// Imported by codecept.conf.ts so the config itself transpiles into TWO temp
// files (codecept.conf.temp.mjs + shared.temp.mjs), widening the race window.
export const WORKERS: string[] = Array.from({ length: 12 }, (_, i) => `w${i + 1}`);

output

mirao@rog:~/workspace/my$ cd repro
for i in $(seq 1 40); do
  if node ../node_modules/codeceptjs/bin/codecept.js run-multiple --all -c . 2>&1 \
       | grep -qi "temp.mjs\|Cannot find module\|ENOENT"; then
    echo "iter $i FAILED"
  else
    echo "iter $i ok"
  fi
done
iter 1 FAILED
iter 2 FAILED
iter 3 FAILED
iter 4 FAILED
iter 5 FAILED
iter 6 FAILED
iter 7 FAILED
iter 8 FAILED
iter 9 ok
iter 10 FAILED
iter 11 ok
iter 12 FAILED
iter 13 FAILED
iter 14 FAILED
iter 15 ok
iter 16 FAILED
iter 17 FAILED
iter 18 ok
iter 19 FAILED
iter 20 FAILED
iter 21 FAILED
iter 22 FAILED
iter 23 FAILED
iter 24 FAILED
iter 25 FAILED
iter 26 ok
iter 27 FAILED
iter 28 FAILED
iter 29 FAILED
iter 30 FAILED
iter 31 FAILED
iter 32 FAILED
iter 33 FAILED
iter 34 FAILED
iter 35 FAILED
iter 36 FAILED
iter 37 ok
iter 38 FAILED
iter 39 FAILED
iter 40 ok

Used SW:

  • CodeceptJS 4.0.7
  • NodeJS 24

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions