From e53acd1f6da01156389841a66d7542087c2cc64d Mon Sep 17 00:00:00 2001 From: Denys Kuchma Date: Tue, 13 Jan 2026 16:57:40 +0200 Subject: [PATCH 1/5] export container as named export for ESM TypeScript --- typings/index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/typings/index.d.ts b/typings/index.d.ts index 50e3fcc95..7ac78782a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -637,6 +637,7 @@ declare namespace Mocha { declare module 'codeceptjs' { export default codeceptjs + export const container: any } declare module '@codeceptjs/helper' { From ccc7bbb82325c9c555f31d6c8087cf483385b634 Mon Sep 17 00:00:00 2001 From: Denys Kuchma Date: Thu, 15 Jan 2026 16:20:40 +0200 Subject: [PATCH 2/5] add all export from codeceptjs and add tests --- .../typescript-esm-exports/codecept.conf.ts | 9 + test/data/typescript-esm-exports/package.json | 5 + .../test-all-exports.ts | 107 +++++++++++ test/data/typescript-esm-exports/test.ts | 12 ++ typings/index.d.ts | 178 +++++++++++++++++- 5 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 test/data/typescript-esm-exports/codecept.conf.ts create mode 100644 test/data/typescript-esm-exports/package.json create mode 100644 test/data/typescript-esm-exports/test-all-exports.ts create mode 100644 test/data/typescript-esm-exports/test.ts diff --git a/test/data/typescript-esm-exports/codecept.conf.ts b/test/data/typescript-esm-exports/codecept.conf.ts new file mode 100644 index 000000000..76a21e55c --- /dev/null +++ b/test/data/typescript-esm-exports/codecept.conf.ts @@ -0,0 +1,9 @@ +export const config: CodeceptJS.MainConfig = { + tests: "./*.ts", + output: "./output", + helpers: { + FileSystem: {}, + }, + name: "container-esm", + require: ["tsx/cjs"], +}; diff --git a/test/data/typescript-esm-exports/package.json b/test/data/typescript-esm-exports/package.json new file mode 100644 index 000000000..e160f5318 --- /dev/null +++ b/test/data/typescript-esm-exports/package.json @@ -0,0 +1,5 @@ +{ + "name": "container-esm", + "version": "1.0.0", + "private": true +} diff --git a/test/data/typescript-esm-exports/test-all-exports.ts b/test/data/typescript-esm-exports/test-all-exports.ts new file mode 100644 index 000000000..3a56a9331 --- /dev/null +++ b/test/data/typescript-esm-exports/test-all-exports.ts @@ -0,0 +1,107 @@ +import { + container, + codecept, + output, + event, + recorder, + config, + actor, + helper, + pause, + within, + dataTable, + dataTableArgument, + store, + locator, + // Secret, + // secret, +} from "codeceptjs"; +import { expect } from "chai"; + +Feature("Import all exports from codeceptjs"); + +Scenario("container should be importable as named export", () => { + expect(container).to.exist; + expect(container.helpers).to.be.a("function"); + + const helpers = container.helpers(); + console.log("Available helpers:", Object.keys(helpers)); +}); + +Scenario("codecept should be importable", () => { + expect(codecept).to.exist; +}); + +Scenario("output should be importable", () => { + expect(output).to.exist; + expect(output.print).to.be.a("function"); + output.print("Testing output.print"); +}); + +Scenario("event should be importable", () => { + expect(event).to.exist; + expect(event).to.be.an("object"); + expect(event.dispatcher).to.exist; +}); + +Scenario("recorder should be importable", () => { + expect(recorder).to.exist; + expect(recorder).to.be.an("object"); + expect(recorder.start).to.be.a("function"); +}); + +Scenario("config should be importable", () => { + expect(config).to.exist; + expect(config.get).to.be.a("function"); +}); + +Scenario("actor should be importable", () => { + expect(actor).to.exist; + expect(actor).to.be.a("function"); +}); + +Scenario("helper should be importable", () => { + expect(helper).to.exist; +}); + +Scenario("pause should be importable", () => { + expect(pause).to.exist; +}); + +Scenario("within should be importable", () => { + expect(within).to.exist; + expect(within).to.be.a("function"); +}); + +Scenario("dataTable should be importable", () => { + expect(dataTable).to.exist; +}); + +Scenario("dataTableArgument should be importable", () => { + expect(dataTableArgument).to.exist; +}); + +Scenario("store should be importable", () => { + expect(store).to.exist; + expect(store).to.be.an("object"); + expect(store.debugMode).to.exist; +}); + +Scenario("locator should be importable", () => { + expect(locator).to.exist; + expect(locator.build).to.be.a("function"); +}); + +// Secret and secret are not exported from lib/index.js in older versions, so skip them +// Scenario("Secret should be importable", () => { +// expect(Secret).to.exist; +// expect(Secret.secret).to.be.a("function"); +// }); + +// Scenario("secret should be importable", () => { +// expect(secret).to.exist; +// expect(secret).to.be.a("function"); +// +// const mySecret = secret("my-password"); +// expect(mySecret.toString()).to.equal("my-password"); +// }); diff --git a/test/data/typescript-esm-exports/test.ts b/test/data/typescript-esm-exports/test.ts new file mode 100644 index 000000000..971d55613 --- /dev/null +++ b/test/data/typescript-esm-exports/test.ts @@ -0,0 +1,12 @@ +import { container } from "codeceptjs"; +import { expect } from "chai"; + +Feature("Import container as named export"); + +Scenario("container should be importable as named export", () => { + expect(container).to.exist; + expect(container.helpers).to.be.a("function"); + + const helpers = container.helpers(); + console.log("Available helpers:", Object.keys(helpers)); +}); diff --git a/typings/index.d.ts b/typings/index.d.ts index 7ac78782a..341c98803 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -520,6 +520,86 @@ declare namespace CodeceptJS { } function addStep(step: string | RegExp, fn: Function): Promise + + // Internal API types + class Container { + static create(config: any, opts?: any): Promise + static actor(): any + static plugins(name?: string): any + static support(name?: string): any + static helpers(name?: string): any + static translation(): any + static mocha(): any + } + + class Codecept { + // Codecept class methods - to be filled from JSDoc + } + + class Config { + static get(): any + static set(key: string, value: any): void + } + + namespace output { + function print(message: string): void + function log(message: string): void + function debug(message: string): void + function error(message: string): void + function info(message: string): void + function success(message: string): void + function warn(message: string): void + } + + type event = { + dispatcher: any + on: (event: string, handler: Function) => void + once: (event: string, handler: Function) => void + removeListener: (event: string, handler: Function) => void + removeAllListeners: (event?: string) => void + emit: (event: string, ...args: any[]) => void + } + + type recorder = { + (fn: () => Promise | void): void + start: () => void + stop: () => void + add: (fn: Function) => void + retry: any[] + catch: (fn: Function) => void + schedule: (fn: Function) => any + promiseStack: any[] + running: boolean + } + + type store = { + debugMode: boolean + timeouts: boolean + autoRetries: boolean + dryRun: boolean + } + + class Secret { + static secret(value: string | number): Secret + toString(): string + getMasked(): string + } + + type pause = () => void + + type within = (locator: LocatorOrString) => void + + class DataTable { + static (data: any[] | any[][]): any + } + + class DataTableArgument { + static (data: any): any + } + + class Locator { + static build(locator: ILocator | string): any + } } type TryTo = (fn: () => Promise | T) => Promise @@ -635,9 +715,105 @@ declare namespace Mocha { } } +// Internal API types declare module 'codeceptjs' { export default codeceptjs - export const container: any + + /** + * Dependency Injection Container + * Provides access to helpers, support objects, plugins, and translation + */ + export const container: typeof CodeceptJS.Container + + /** + * Test runner class + */ + export const codecept: typeof CodeceptJS.Codecept + + /** + * Output module for printing messages + */ + export const output: typeof CodeceptJS.output + + /** + * Event dispatcher for listening to CodeceptJS events + */ + export const event: CodeceptJS.event + + /** + * Global promise chain recorder + */ + export const recorder: CodeceptJS.recorder + + /** + * Configuration module + */ + export const config: typeof CodeceptJS.Config + + /** + * Actor (I) constructor + */ + export const actor: CodeceptJS.actor + + /** + * Base Helper class + */ + export const helper: typeof CodeceptJS.Helper + + /** + * Pause execution until user input + */ + export const pause: CodeceptJS.pause + + /** + * Execute steps within specific context + */ + export const within: CodeceptJS.within + + /** + * Create data tables for data-driven tests + */ + export const dataTable: typeof CodeceptJS.DataTable + + /** + * Create data table arguments + */ + export const dataTableArgument: typeof CodeceptJS.DataTableArgument + + /** + * Shared store for test data + */ + export const store: CodeceptJS.store + + /** + * Locator builder + */ + export const locator: typeof CodeceptJS.Locator + + /** + * Auto-healing module + */ + export const heal: any + + /** + * AI assistant module + */ + export const ai: any + + /** + * Workers for parallel execution + */ + export const Workers: any + + /** + * Secret value type for sensitive data + */ + export const Secret: typeof CodeceptJS.Secret + + /** + * Create a secret value + */ + export const secret: typeof CodeceptJS.secret } declare module '@codeceptjs/helper' { From fc51b981d44556b913bdde70e5e7db30892db606 Mon Sep 17 00:00:00 2001 From: Denys Kuchma Date: Thu, 15 Jan 2026 18:36:19 +0200 Subject: [PATCH 3/5] export all internal API objects from codeceptjs module --- typings/index.d.ts | 82 +--------------------------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 341c98803..0667ad57b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -520,86 +520,6 @@ declare namespace CodeceptJS { } function addStep(step: string | RegExp, fn: Function): Promise - - // Internal API types - class Container { - static create(config: any, opts?: any): Promise - static actor(): any - static plugins(name?: string): any - static support(name?: string): any - static helpers(name?: string): any - static translation(): any - static mocha(): any - } - - class Codecept { - // Codecept class methods - to be filled from JSDoc - } - - class Config { - static get(): any - static set(key: string, value: any): void - } - - namespace output { - function print(message: string): void - function log(message: string): void - function debug(message: string): void - function error(message: string): void - function info(message: string): void - function success(message: string): void - function warn(message: string): void - } - - type event = { - dispatcher: any - on: (event: string, handler: Function) => void - once: (event: string, handler: Function) => void - removeListener: (event: string, handler: Function) => void - removeAllListeners: (event?: string) => void - emit: (event: string, ...args: any[]) => void - } - - type recorder = { - (fn: () => Promise | void): void - start: () => void - stop: () => void - add: (fn: Function) => void - retry: any[] - catch: (fn: Function) => void - schedule: (fn: Function) => any - promiseStack: any[] - running: boolean - } - - type store = { - debugMode: boolean - timeouts: boolean - autoRetries: boolean - dryRun: boolean - } - - class Secret { - static secret(value: string | number): Secret - toString(): string - getMasked(): string - } - - type pause = () => void - - type within = (locator: LocatorOrString) => void - - class DataTable { - static (data: any[] | any[][]): any - } - - class DataTableArgument { - static (data: any): any - } - - class Locator { - static build(locator: ILocator | string): any - } } type TryTo = (fn: () => Promise | T) => Promise @@ -813,7 +733,7 @@ declare module 'codeceptjs' { /** * Create a secret value */ - export const secret: typeof CodeceptJS.secret + export const secret: typeof CodeceptJS.Secret.secret } declare module '@codeceptjs/helper' { From 0af1f37f51ac14149b95afffc16b5833dc56f712 Mon Sep 17 00:00:00 2001 From: Denys Kuchma Date: Thu, 15 Jan 2026 19:06:48 +0200 Subject: [PATCH 4/5] export all internal API objects from codeceptjs module --- typings/index.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 0667ad57b..72ee780d9 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -658,12 +658,12 @@ declare module 'codeceptjs' { /** * Event dispatcher for listening to CodeceptJS events */ - export const event: CodeceptJS.event + export const event: typeof CodeceptJS.event /** * Global promise chain recorder */ - export const recorder: CodeceptJS.recorder + export const recorder: typeof CodeceptJS.recorder /** * Configuration module @@ -683,12 +683,12 @@ declare module 'codeceptjs' { /** * Pause execution until user input */ - export const pause: CodeceptJS.pause + export const pause: typeof CodeceptJS.pause /** * Execute steps within specific context */ - export const within: CodeceptJS.within + export const within: typeof CodeceptJS.within /** * Create data tables for data-driven tests @@ -703,7 +703,7 @@ declare module 'codeceptjs' { /** * Shared store for test data */ - export const store: CodeceptJS.store + export const store: typeof CodeceptJS.store /** * Locator builder From 54b6b6b33ef539bed40246c03af42284a1d6193e Mon Sep 17 00:00:00 2001 From: Denys Kuchma Date: Thu, 15 Jan 2026 19:24:43 +0200 Subject: [PATCH 5/5] remove typeof --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 72ee780d9..7406dadba 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -663,7 +663,7 @@ declare module 'codeceptjs' { /** * Global promise chain recorder */ - export const recorder: typeof CodeceptJS.recorder + export const recorder: CodeceptJS.recorder /** * Configuration module