CodeceptJS icon indicating copy to clipboard operation
CodeceptJS copied to clipboard

CodeceptJS 4.x: Can't import container from codeceptjs (Module '"codeceptjs"' has no exported member 'container')

Open mirao opened this issue 2 months ago • 3 comments

In CodeceptJS 3.x if you use "module": "commonjs" in compilerOptions in tsconfig.json (it's a default), you are able to import the CodeceptJS container in a TS test ✔️

import { container } from "codeceptjs";

But if you try it in CodeceptJS 4.x, with ts-node/esm or tsx/esm requirement in CodeceptJS config, it fails :x:. I tried "module": "esnext" with "moduleResolution": "node" to add to tsconfig.json, but it didn't help.

Or is there another way how to import container?

This is my CodeceptJS 4.x setup:

tsconfig.json

{
  "ts-node": {
    "files": true,
    "esm": true,
    "experimentalSpecifierResolution": "node"
  },
  "compilerOptions": {
    "target": "es2022",
    "lib": ["es2022", "DOM"],
    "esModuleInterop": true,
    "strictNullChecks": false,
    "types": ["codeceptjs", "node"],
    "declaration": true,
    "skipLibCheck": true
  },
  "exclude": ["node_modules"]
}

codecept.conf.ts

export const config: CodeceptJS.MainConfig = {
  tests: "./*_test.ts",
  output: "./output",
  helpers: {
    Playwright: {
      browser: "chromium",
      url: "http://localhost",
      show: true,
    },
  },
  name: "esm",
  require: ["ts-node/esm"]
};

test

import { container } from "codeceptjs";

Feature("My");

const {I} = inject();

Scenario("test something",  () => {
    I.say(container.helpers("Playwright").config.url);
});

output:

$ codeceptjs run --verbose
***************************************
nodeInfo:  20.19.5
osInfo:  Linux 6.14 Ubuntu 24.04.3 LTS 24.04.3 LTS (Noble Numbat)
cpuInfo:  (16) x64 AMD Ryzen 7 9700X 8-Core Processor
chromeInfo:  142.0.7444.175
edgeInfo:  "N/A"
firefoxInfo:  145.0
safariInfo:  N/A
playwrightBrowsers:  "chromium: 141.0.7390.37, firefox: 142.0.1, webkit: 26.0"
If you need more detailed info, just run this: npx codeceptjs info
***************************************
TSError: ⨯ Unable to compile TypeScript:
My_test.ts:1:10 - error TS2614: Module '"codeceptjs"' has no exported member 'container'. Did you mean to use 'import container from "codeceptjs"' instead?

1 import { container } from "codeceptjs";
           ~~~~~~~~~

    at createTSError (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:859:12)
    at reportTSError (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:863:19)
    at getOutput (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1077:36)
    at Object.compile (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1433:41)
    at Module.m._compile (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1617:30)
    at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
    at Object.require.extensions.<computed> [as .ts] (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1621:12)
    at Module.load (node:internal/modules/cjs/loader:1266:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1091:12)
    at Module.require (node:internal/modules/cjs/loader:1289:19)

⨯ Unable to compile TypeScript:
My_test.ts:1:10 - error TS2614: Module '"codeceptjs"' has no exported member 'container'. Did you mean to use 'import container from "codeceptjs"' instead?

1 import { container } from "codeceptjs";
           ~~~~~~~~~


TSError: 
    at createTSError (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:859:12)
    at reportTSError (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:863:19)
    at getOutput (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1077:36)
    at Object.compile (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1433:41)
    at Module.m._compile (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1617:30)
    at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
    at Object.require.extensions.<computed> [as .ts] (/home/mirao/workspace/esm/node_modules/ts-node/src/index.ts:1621:12)
    at Module.load (node:internal/modules/cjs/loader:1266:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1091:12)
    at Module.require (node:internal/modules/cjs/loader:1289:19)

As a workaround (suggested by AI) I can use declare const container: any; instead of import container from "codeceptjs";. But it works for the requirements "ts-node/esm" and "tsx/cjs" only. It doesn't work for "tsx/esm" (it fails on SyntaxError: Unexpected token 'const')

Used SW:

  • CodeceptJS 4.0.1-beta.12
  • Playwright 1.56.1

mirao avatar Nov 19 '25 11:11 mirao

@mirao this works for me but not sure if any better way to handle this nicely

my conf

export const config: CodeceptJS.MainConfig = {
  tests: "./*_test.ts",
  output: "./output",
  helpers: {
    Playwright: {
      browser: "chromium",
      url: "http://localhost",
      show: true,
    },
    MyHelper: {
      require: "./myhelper_helper.ts",
    },
  },
  name: "esm",
  require: ["tsx/esm"],
};
import container from "codeceptjs/lib/container";

Feature("My");

const {I} = inject();

Scenario("test something",  () => {
    I.say(container.helpers("Playwright").config.url);
});
Nov 19 17:19:35     [1]  Starting recording promises
Nov 19 17:19:35     Timeouts: 
Nov 19 17:19:35  › [Session] Starting singleton browser session
Nov 19 17:19:36   test something
Nov 19 17:19:36  › [New Session] {"ignoreHTTPSErrors":false,"acceptDownloads":true}
Nov 19 17:19:36   Scenario()
Nov 19 17:19:36     I say "http://localhost"
Nov 19 17:19:36    http://localhost
Nov 19 17:19:36   ✔ OK in 6ms

kobenguyent avatar Nov 19 '25 16:11 kobenguyent

@kobenguyent Yes, import container from "codeceptjs/lib/container"; works for me, with both "tsx/esm" and "ts-node/esm", thanks. It works even in 3.7.5

I minor issue is that no TS definition exists for the container

Image Image
Could not find a declaration file for module 'codeceptjs/lib/container'. '/home/mirao/workspace/esm/node_modules/codeceptjs/lib/container.js' implicitly has an 'any' type.
  If the 'codeceptjs' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'codeceptjs/lib/container';`

In 3.7.5 if I use the original internal API import {container} from "codeceptjs", the TS resolving works nicely (see below). So I guess the original API TS types isn't present in 4.x anymore?

Image Image

mirao avatar Nov 19 '25 17:11 mirao

The same issue is with import { config } from "codeceptjs" (https://codecept.io/internal-api/#config) It's the API I'm using for getting of the current CodeceptJS configuration, e.g. const { env } = config.get() (env is a custom property of the exported config).

error TS2614: Module '"codeceptjs"' has no exported member 'config'. Did you mean to use 'import config from "codeceptjs"' instead?

3 import {config} from "codeceptjs";

mirao avatar Nov 25 '25 11:11 mirao