Skip to content

Commit a07f5ca

Browse files
authored
Fix defenitions generation error (#2707)
* fix LocatorOrString definitions generation * chore: fix formating * refactor: make definitions.js more unerstandable, fix lint errors * fix: turn on doc generation for defenitions
1 parent 866fdb7 commit a07f5ca

File tree

7 files changed

+125
-31
lines changed

7 files changed

+125
-31
lines changed

docs/helpers/Appium.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ I.seeTextEquals('text', 'h1');
14811481
#### Parameters
14821482

14831483
- `text` **[string][4]** element value to check.
1484-
- `context` **([string][4] \| [object][6]?)** element located by CSS|XPath|strict locator. (optional, default `null`)
1484+
- `context` **([string][4] \| [object][6])?** element located by CSS|XPath|strict locator. (optional, default `null`)
14851485

14861486
### seeElementInDOM
14871487

docs/helpers/Playwright.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,7 @@ I.seeTextEquals('text', 'h1');
14541454
#### Parameters
14551455

14561456
- `text` **[string][7]** element value to check.
1457-
- `context` **([string][7] | [object][5]?)** element located by CSS|XPath|strict locator.
1457+
- `context` **([string][7] | [object][5])?** element located by CSS|XPath|strict locator.
14581458

14591459
### seeTitleEquals
14601460

docs/helpers/Protractor.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ I.seeTextEquals('text', 'h1');
12611261
#### Parameters
12621262
12631263
- `text` **[string][9]** element value to check.
1264-
- `context` **([string][9] | [object][10]?)** element located by CSS|XPath|strict locator.
1264+
- `context` **([string][9] | [object][10])?** element located by CSS|XPath|strict locator.
12651265
12661266
### seeTitleEquals
12671267

docs/helpers/Puppeteer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@ I.seeTextEquals('text', 'h1');
15861586
#### Parameters
15871587
15881588
- `text` **[string][8]** element value to check.
1589-
- `context` **([string][8] | [object][6]?)** element located by CSS|XPath|strict locator.
1589+
- `context` **([string][8] | [object][6])?** element located by CSS|XPath|strict locator.
15901590
15911591
### seeTitleEquals
15921592

docs/helpers/WebDriver.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,7 @@ I.seeTextEquals('text', 'h1');
17681768
#### Parameters
17691769
17701770
- `text` **[string][19]** element value to check.
1771-
- `context` **([string][19] | [object][18]?)** element located by CSS|XPath|strict locator.
1771+
- `context` **([string][19] | [object][18])?** element located by CSS|XPath|strict locator.
17721772
17731773
### seeTitleEquals
17741774

lib/command/definitions.js

Lines changed: 115 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,112 @@ const { getConfig, getTestRoot } = require('./utils');
55
const Codecept = require('../codecept');
66
const container = require('../container');
77
const output = require('../output');
8-
const actingHelpers = [...require('../../lib/plugin/standardActingHelpers'), 'REST'];
8+
const actingHelpers = [...require('../plugin/standardActingHelpers'), 'REST'];
99

10-
const template = ({
11-
helperNames, supportObject, importPaths, translations, hasCustomStepsFile, hasCustomHelper, customHelpers,
12-
}) => `/// <reference types='codeceptjs' />
13-
${importPaths.join('\n')}
10+
/**
11+
* Prepare data and generate content of definitions file
12+
* @private
13+
*
14+
* @param {Object} params
15+
* @param {boolean} params.hasCustomStepsFile
16+
* @param {boolean} params.hasCustomHelper
17+
* @param {Map} params.supportObject
18+
* @param {Array<string>} params.helperNames
19+
* @param {Array<string>} params.importPaths
20+
* @param {Array<string>} params.customHelpers
21+
* @param params.translations
22+
*
23+
* @returns {string}
24+
*/
25+
const getDefinitionsFileContent = ({
26+
hasCustomHelper,
27+
hasCustomStepsFile,
28+
helperNames,
29+
supportObject,
30+
importPaths,
31+
translations,
32+
customHelpers,
33+
}) => {
34+
const getHelperListFragment = ({
35+
hasCustomHelper,
36+
hasCustomStepsFile,
37+
customHelpers,
38+
}) => {
39+
if (hasCustomHelper && hasCustomStepsFile) {
40+
return `${['ReturnType<steps_file>', ...customHelpers].join(', ')}`;
41+
}
42+
43+
if (hasCustomStepsFile) {
44+
return 'ReturnType<steps_file>';
45+
}
46+
47+
return 'WithTranslation<Methods>';
48+
};
49+
50+
const helpersListFragment = getHelperListFragment({
51+
hasCustomHelper,
52+
hasCustomStepsFile,
53+
customHelpers,
54+
});
55+
56+
const importPathsFragment = importPaths.join('\n');
57+
const supportObjectsTypeFragment = convertMapToType(supportObject);
58+
const methodsTypeFragment = helperNames.length > 0
59+
? `interface Methods extends ${helperNames.join(', ')} {}`
60+
: '';
61+
const translatedActionsFragment = JSON.stringify(translations.vocabulary.actions, null, 2);
62+
63+
return generateDefinitionsContent({
64+
helpersListFragment,
65+
importPathsFragment,
66+
supportObjectsTypeFragment,
67+
methodsTypeFragment,
68+
translatedActionsFragment,
69+
});
70+
};
71+
72+
/**
73+
* Generate content for definitions file from fragments
74+
* @private
75+
*
76+
* @param {Object} fragments - parts for template
77+
* @param {string} fragments.importPathsFragment
78+
* @param {string} fragments.supportObjectsTypeFragment
79+
* @param {string} fragments.methodsTypeFragment
80+
* @param {string} fragments.helpersListFragment
81+
* @param {string} fragments.translatedActionsFragment
82+
*
83+
* @returns {string}
84+
*/
85+
const generateDefinitionsContent = ({
86+
importPathsFragment,
87+
supportObjectsTypeFragment,
88+
methodsTypeFragment,
89+
helpersListFragment,
90+
translatedActionsFragment,
91+
}) => {
92+
return `/// <reference types='codeceptjs' />
93+
${importPathsFragment}
1494
1595
declare namespace CodeceptJS {
16-
interface SupportObject ${convertMapToType(supportObject)}
17-
${helperNames.length > 0 ? `interface Methods extends ${helperNames.join(', ')} {}` : ''}
18-
interface I extends ${hasCustomStepsFile && hasCustomStepsFile ? `${['ReturnType<steps_file>', ...customHelpers].join(', ')}` : hasCustomStepsFile ? 'ReturnType<steps_file>' : 'WithTranslation<Methods>'} {}
96+
interface SupportObject ${supportObjectsTypeFragment}
97+
${methodsTypeFragment}
98+
interface I extends ${helpersListFragment} {}
1999
namespace Translation {
20-
interface Actions ${JSON.stringify(translations.vocabulary.actions, null, 2)}
100+
interface Actions ${translatedActionsFragment}
21101
}
22102
}
23103
`;
104+
};
24105

106+
/** @type {Array<string>} */
25107
const helperNames = [];
108+
/** @type {Array<string>} */
26109
const customHelpers = [];
27110

28111
module.exports = function (genPath, options) {
29112
const configFile = options.config || genPath;
113+
/** @type {string} */
30114
const testsPath = getTestRoot(configFile);
31115
const config = getConfig(configFile);
32116
if (!config) return;
@@ -35,9 +119,12 @@ module.exports = function (genPath, options) {
35119
const helperPaths = {};
36120
/** @type {Object<string, string>} */
37121
const supportPaths = {};
122+
/** @type {boolean} */
38123
let hasCustomStepsFile = false;
39-
let hasCustomerHelper = false;
124+
/** @type {boolean} */
125+
let hasCustomHelper = false;
40126

127+
/** @type {string} */
41128
const targetFolderPath = options.output && getTestRoot(options.output) || testsPath;
42129

43130
const codecept = new Codecept(config, {});
@@ -46,13 +133,13 @@ module.exports = function (genPath, options) {
46133
const helpers = container.helpers();
47134
const translations = container.translation();
48135
for (const name in helpers) {
49-
const require = codecept.config.helpers[name].require;
50-
if (require) {
51-
helperPaths[name] = require;
52-
helperNames.push(name);
53-
} else {
54-
helperNames.push(name);
55-
}
136+
const require = codecept.config.helpers[name].require;
137+
if (require) {
138+
helperPaths[name] = require;
139+
helperNames.push(name);
140+
} else {
141+
helperNames.push(name);
142+
}
56143

57144
if (!actingHelpers.includes(name)) {
58145
customHelpers.push(`WithTranslation<${name}>`);
@@ -64,7 +151,7 @@ module.exports = function (genPath, options) {
64151
supportObject.set('current', 'any');
65152

66153
if (customHelpers.length > 0) {
67-
hasCustomerHelper = true;
154+
hasCustomHelper = true;
68155
}
69156

70157
for (const name in codecept.config.include) {
@@ -78,26 +165,26 @@ module.exports = function (genPath, options) {
78165
supportObject.set(name, name);
79166
}
80167

81-
const definitionsTemplate = template({
168+
const definitionsFileContent = getDefinitionsFileContent({
82169
helperNames,
83170
supportObject,
84171
importPaths: getImportString(testsPath, targetFolderPath, supportPaths, helperPaths),
85172
translations,
86173
hasCustomStepsFile,
87-
hasCustomerHelper,
88-
customHelpers
174+
hasCustomHelper,
175+
customHelpers,
89176
});
90177

91-
fs.writeFileSync(path.join(targetFolderPath, 'steps.d.ts'), definitionsTemplate);
178+
fs.writeFileSync(path.join(targetFolderPath, 'steps.d.ts'), definitionsFileContent);
92179
output.print('TypeScript Definitions provide autocompletion in Visual Studio Code and other IDEs');
93180
output.print('Definitions were generated in steps.d.ts');
94181
};
95182

96183
/**
97184
* Returns the relative path from the to the targeted folder.
98185
* @param {string} originalPath
99-
* @param { string} targetFolderPath
100-
* @param { string} testsPath
186+
* @param {string} targetFolderPath
187+
* @param {string} testsPath
101188
*/
102189
function getPath(originalPath, targetFolderPath, testsPath) {
103190
const parsedPath = path.parse(originalPath);
@@ -119,7 +206,8 @@ function getPath(originalPath, targetFolderPath, testsPath) {
119206
* @param {string} targetFolderPath
120207
* @param {Object<string, string>} pathsToType
121208
* @param {Object<string, string>} pathsToValue
122-
* @returns
209+
*
210+
* @returns {Array<string>}
123211
*/
124212
function getImportString(testsPath, targetFolderPath, pathsToType, pathsToValue) {
125213
const importStrings = [];
@@ -139,6 +227,8 @@ function getImportString(testsPath, targetFolderPath, pathsToType, pathsToValue)
139227

140228
/**
141229
* @param {Map} map
230+
*
231+
* @returns {string}
142232
*/
143233
function convertMapToType(map) {
144234
return `{ ${Array.from(map).map(([key, value]) => `${key}: ${value}`).join(', ')} }`;

runok.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = {
2323

2424
async def() {
2525
await Promise.all([
26-
// this.buildLibWithDocs(true),
26+
this.buildLibWithDocs(true),
2727
this.docsPlugins(),
2828
this.docsExternalHelpers(),
2929
]);
@@ -156,6 +156,8 @@ Our community prepared some valuable recipes for setting up CI systems with Code
156156
cfg.replace(placeholders[i], templates[i]);
157157
}
158158
if (!forTypings) {
159+
cfg.replace(/CodeceptJS.LocatorOrString\?/g, '(string | object)?');
160+
cfg.replace(/LocatorOrString\?/g, '(string | object)?');
159161
cfg.replace(/CodeceptJS.LocatorOrString/g, 'string | object');
160162
cfg.replace(/LocatorOrString/g, 'string | object');
161163
}
@@ -190,6 +192,8 @@ Our community prepared some valuable recipes for setting up CI systems with Code
190192
for (const i in placeholders) {
191193
cfg.replace(placeholders[i], templates[i]);
192194
}
195+
cfg.replace(/CodeceptJS.LocatorOrString\?/g, '(string | object)?');
196+
cfg.replace(/LocatorOrString\?/g, '(string | object)?');
193197
cfg.replace(/CodeceptJS.LocatorOrString/g, 'string | object');
194198
cfg.replace(/LocatorOrString/g, 'string | object');
195199
});

0 commit comments

Comments
 (0)