From b948f1898707ef82360ad5426cd2da798a81ffd5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 20 Nov 2025 16:02:44 +0000
Subject: [PATCH 1/3] Initial plan
From 432430691a3996943bbd8f1bf92bb795ad252055 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 20 Nov 2025 16:10:25 +0000
Subject: [PATCH 2/3] Initial investigation complete
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
---
example-esm/steps.d.ts | 8 +++-----
examples/steps.d.ts | 15 +++++++++++++++
2 files changed, 18 insertions(+), 5 deletions(-)
create mode 100644 examples/steps.d.ts
diff --git a/example-esm/steps.d.ts b/example-esm/steps.d.ts
index d5d62ecc0..d544e62d8 100644
--- a/example-esm/steps.d.ts
+++ b/example-esm/steps.d.ts
@@ -1,11 +1,9 @@
///
+type CustomHelper = InstanceType;
declare namespace CodeceptJS {
- interface SupportObject {
- I: I
- current: any
- }
-
+ interface SupportObject { I: I, current: any }
+ interface Methods extends CustomHelper, FileSystem, REST {}
interface I extends WithTranslation {}
namespace Translation {
interface Actions {}
diff --git a/examples/steps.d.ts b/examples/steps.d.ts
new file mode 100644
index 000000000..8c779b85e
--- /dev/null
+++ b/examples/steps.d.ts
@@ -0,0 +1,15 @@
+///
+type steps_file = typeof import('./custom_steps.js')['default'];
+type Smth = typeof import('./pages/Smth.js')['default'];
+type loginPage = typeof import('./pages/Login.js')['default'];
+type signinFragment = typeof import('./fragments/Signin.js')['default'];
+type User = InstanceType;
+
+declare namespace CodeceptJS {
+ interface SupportObject { I: I, current: any, Smth: Smth, loginPage: loginPage, signinFragment: signinFragment }
+ interface Methods extends Playwright, REST, User {}
+ interface I extends ReturnType, WithTranslation {}
+ namespace Translation {
+ interface Actions {}
+ }
+}
From 664de16b1a594874006e15970215cf3dd9e86f35 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 20 Nov 2025 16:17:37 +0000
Subject: [PATCH 3/3] Fix auto-suggestion issue for I actor when no helpers
configured
When no helpers are configured, the Methods interface was not being generated,
causing TypeScript to fail resolving the type referenced in interface I.
This broke auto-completion for the I actor methods.
The fix ensures that the Methods interface is always generated, even when
empty, so that 'interface I extends WithTranslation' always
references a valid type.
Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
---
lib/command/definitions.js | 2 +-
.../sandbox/configs/custom-helper-esm/steps.d.ts | 11 +++++++++++
.../configs/definitions/codecept.no-helpers.js | 10 ++++++++++
test/runner/definitions_test.js | 16 ++++++++++++++++
4 files changed, 38 insertions(+), 1 deletion(-)
create mode 100644 test/data/sandbox/configs/custom-helper-esm/steps.d.ts
create mode 100644 test/data/sandbox/configs/definitions/codecept.no-helpers.js
diff --git a/lib/command/definitions.js b/lib/command/definitions.js
index db76bcde2..ade5c2535 100644
--- a/lib/command/definitions.js
+++ b/lib/command/definitions.js
@@ -41,7 +41,7 @@ const getDefinitionsFileContent = ({ hasCustomHelper, hasCustomStepsFile, helper
const importPathsFragment = importPaths.join('\n')
const supportObjectsTypeFragment = convertMapToType(supportObject)
- const methodsTypeFragment = helperNames.length > 0 ? `interface Methods extends ${helperNames.join(', ')} {}` : ''
+ const methodsTypeFragment = helperNames.length > 0 ? `interface Methods extends ${helperNames.join(', ')} {}` : 'interface Methods {}'
const translatedActionsFragment = JSON.stringify(translations.vocabulary.actions, null, 2)
return generateDefinitionsContent({
diff --git a/test/data/sandbox/configs/custom-helper-esm/steps.d.ts b/test/data/sandbox/configs/custom-helper-esm/steps.d.ts
new file mode 100644
index 000000000..edb27382a
--- /dev/null
+++ b/test/data/sandbox/configs/custom-helper-esm/steps.d.ts
@@ -0,0 +1,11 @@
+///
+type MyHelper = InstanceType;
+
+declare namespace CodeceptJS {
+ interface SupportObject { I: I, current: any }
+ interface Methods extends FileSystem, MyHelper {}
+ interface I extends WithTranslation {}
+ namespace Translation {
+ interface Actions {}
+ }
+}
diff --git a/test/data/sandbox/configs/definitions/codecept.no-helpers.js b/test/data/sandbox/configs/definitions/codecept.no-helpers.js
new file mode 100644
index 000000000..3625377cd
--- /dev/null
+++ b/test/data/sandbox/configs/definitions/codecept.no-helpers.js
@@ -0,0 +1,10 @@
+export const config = {
+ tests: './*_test.js',
+ timeout: 10000,
+ output: './output',
+ helpers: {},
+ include: {},
+ bootstrap: false,
+ mocha: {},
+ name: 'sandbox-no-helpers',
+};
diff --git a/test/runner/definitions_test.js b/test/runner/definitions_test.js
index 0fd6f25d8..ea10085ba 100644
--- a/test/runner/definitions_test.js
+++ b/test/runner/definitions_test.js
@@ -283,6 +283,22 @@ describe('Definitions', function () {
done()
})
})
+
+ it('def should create definition file with empty Methods interface when no helpers configured', done => {
+ exec(`${runner} def --config ${codecept_dir}/codecept.no-helpers.js`, (err, stdout) => {
+ stdout.should.include('Definitions were generated in steps.d.ts')
+ const types = typesFrom(`${codecept_dir}/steps.d.ts`)
+ types.should.be.valid
+
+ const definitionFile = types.getSourceFileOrThrow(`${codecept_dir}/steps.d.ts`)
+ const fileContent = definitionFile.getFullText()
+ fileContent.should.include('interface Methods {}')
+ fileContent.should.include('interface I extends WithTranslation')
+
+ assert(!err)
+ done()
+ })
+ })
})
/**