Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 19, 2025

Motivation/Description of the PR

In CodeceptJS 4.x, custom helpers use ESM export default syntax. The codeceptjs def command generated incorrect TypeScript definitions that caused TypeScript to fail resolving helper methods on the I object:

// Generated (incorrect)
type MyHelper = import('./myhelper_helper.js');

// TypeScript error: Property 'openPage' does not exist on type 'I'. ts(2339)
I.openPage("http://codecept.io");

The generated type referenced the module object instead of the exported class instance type.

Fix: Generate InstanceType<typeof import(...).default> for .js and .ts helper files to correctly resolve the class instance type from ESM default exports.

Applicable helpers:

  • Playwright
  • Puppeteer
  • WebDriver
  • REST
  • FileHelper
  • Appium

Applicable plugins: N/A

Type of change

  • 🔥 Breaking changes
  • 🚀 New functionality
  • 🐛 Bug fix
  • 🧹 Chore
  • 📋 Documentation changes/updates
  • ♨️ Hot fix
  • 🔨 Markdown files fix - not related to source code
  • 💅 Polish code

Checklist:

  • Tests have been added
  • Documentation has been added (Run npm run docs)
  • Lint checking (Run npm run lint)
  • Local tests are passed (Run npm test)

Changes

lib/command/definitions.js

  • Modified getImportString() to check original file extension before generating type imports
  • For .js/.ts files: emit InstanceType<typeof import(...).default>
  • For other files: maintain existing behavior for backward compatibility

Test coverage

  • Added test case validating ESM default export type generation
  • Created test fixtures for .js and .ts custom helpers
  • All 11 definition tests pass

Example

Custom helper with ESM syntax:

class MyHelper extends Helper {
  openPage(url: string): Promise<void> { ... }
}
export default MyHelper;

Generated type definition (after fix):

type MyHelper = InstanceType<typeof import('./myhelper_helper.js').default>;

TypeScript now correctly resolves I.openPage() with full IntelliSense.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • google.com
    • Triggering command: node /home/REDACTED/work/CodeceptJS/CodeceptJS/bin/codecept.js run --config /home/REDACTED/work/CodeceptJS/CodeceptJS/test/data/sandbox/codecept.bdd.js --grep @fail --steps (dns block)
  • googlechromelabs.github.io
    • Triggering command: node install.mjs (dns block)
  • https://storage.googleapis.com/chrome-for-testing-public/138.0.7204.168/linux64/chrome-headless-shell-linux64.zip
    • Triggering command: node install.mjs (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>CodeceptJS 4.x: Custom helper type definition created by codeceptjs def doesn't work (Property does not exist on type 'I')</issue_title>
<issue_description>The problem started with CodeceptJS 4.x because a helper in CodeceptJS needs to be exported with export default MyHelper (ESM) instead of export = MyHelper (CommonJS)

config codecept.conf.ts:

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"],
};

myhelper_helper.ts:

import Helper from "@codeceptjs/helper";

class MyHelper extends Helper {
  openPage(url: string): Promise<void> {
    return this.helpers.Playwright.amOnPage(url);
  }
}

export default MyHelper;

steps.d.ts (created by codeceptjs def after adding of the MyHelper config into codecept.conf.ts)

/// <reference types='codeceptjs' />
type MyHelper = import("./myhelper_helper");

declare namespace CodeceptJS {
  interface SupportObject { I: I, current: any }
  interface Methods extends Playwright, MyHelper {}
  interface I extends WithTranslation<Methods> {}
  namespace Translation {
    interface Actions {}
  }
}

test

Feature("My");

const {I} = inject();

Scenario("test something",  () => {
    I.openPage("http://codecept.io");
});

Expected result:

  • TS check and IDE IntelliSense works well

Actual result:

  • It fails
Image
mirao@rog:~/workspace/codeceptjs/esm$ npx tsc --noEmit
My_test.ts:6:7 - error TS2339: Property 'openPage' does not exist on type 'I'.

6     I.openPage("http://codecept.io");
        ~~~~~~~~


Found 1 error in My_test.ts:6

Note that the test passes because tsx doesn't do a TS check. But if you run it with require: ["ts-node/esm"] it fails (ts-node does a TS check).

AI suggested me this fix (and it works).

type MyHelper = InstanceType<typeof import("./myhelper_helper").default>;

instead of

type MyHelper = import("./myhelper_helper");

Used SW:

  • CodeceptJS 4.0.1-beta.12
  • Playwright 1.56.1</issue_description>

<agent_instructions>- investigate the issue with typescript definitions

  • fix issue
  • all tests passed </agent_instructions>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 5 commits November 19, 2025 14:51
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix custom helper type definition for CodeceptJS 4.x Fix type definitions for custom helpers with ESM default exports Nov 19, 2025
Copilot AI requested a review from kobenguyent November 19, 2025 15:12
Copilot finished work on behalf of kobenguyent November 19, 2025 15:12
@kobenguyent
Copy link
Collaborator

Verified it worked

After running def

npx codeceptjs def             
TypeScript Definitions provide autocompletion in Visual Studio Code and other IDEs
Definitions were generated in steps.d.ts
Screenshot 2

In test file
Screenshot 1

@kobenguyent kobenguyent marked this pull request as ready for review November 19, 2025 16:15
@kobenguyent kobenguyent merged commit 90d53c2 into 4.x Nov 19, 2025
10 checks passed
@kobenguyent kobenguyent deleted the copilot/fix-custom-helper-type-definition branch November 19, 2025 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants