Skip to content

Commit 7f80cfa

Browse files
authored
Promise based helper methods (#3465)
* generate both regular and promise-based helper definitions * load types according to feature 'fullBasedPromised' running npm def * fix runner-related tests * review documentation + add code comments * make the generations of TS definition clearer * fix unit tests related to Init Command
1 parent 8d27e08 commit 7f80cfa

20 files changed

+590
-247
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ testpullfilecache*
2121
package-lock.json
2222
yarn.lock
2323
/.vs
24-
typings/types.d.ts
24+
typings/types.d.ts
25+
typings/promiseBasedTypes.d.ts

docs/typescript.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,15 @@ declare namespace CodeceptJS {
138138
}
139139
}
140140
```
141+
142+
## Full promise-based methods <Badge text="Since 3.3.6" type="warning"/>
143+
144+
All CodeceptJS methods return a promise; however, some of its are not typed as accordingly.
145+
This feature, which is enabled by [configuration](https://codecept.io/configuration/), refers to alternative typescript definitions transforming all methods to asynchronous actions.
146+
147+
How to enable it?
148+
- Add required configuration
149+
```ts
150+
fullPromiseBased: true;
151+
```
152+
- Refresh internal TypeScript definitions by running following command: `npx codeceptjs def`

lib/command/definitions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ module.exports = function (genPath, options) {
138138
helperPaths[name] = require;
139139
helperNames.push(name);
140140
} else {
141-
helperNames.push(name);
141+
const fullBasedPromised = codecept.config.fullPromiseBased;
142+
helperNames.push(fullBasedPromised === true ? `${name}Ts` : name);
142143
}
143144

144145
if (!actingHelpers.includes(name)) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"lint-fix": "eslint bin/ examples/ lib/ test/ translations/ runok.js --fix",
4343
"docs": "./runok.js docs",
4444
"test:unit": "mocha test/unit --recursive",
45-
"test:runner": "mocha test/runner --recursive",
45+
"test:runner": "mocha test/runner --recursive --timeout 5000",
4646
"test": "npm run test:unit && npm run test:runner",
4747
"test:appium-quick": "mocha test/helper/Appium_test.js --grep 'quick'",
4848
"test:appium-other": "mocha test/helper/Appium_test.js --grep 'second'",

runok.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ module.exports = {
3737

3838
async defTypings() {
3939
console.log('Generate TypeScript definition');
40+
// Generate definitions for promised-based helper methods
41+
await npx('jsdoc -c typings/jsdocPromiseBased.conf.js');
42+
fs.renameSync('typings/types.d.ts', 'typings/promiseBasedTypes.d.ts');
43+
// Generate all other regular definitions
4044
await npx('jsdoc -c typings/jsdoc.conf.js');
4145
},
4246

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
exports.config = {
2+
tests: './*_test.js',
3+
timeout: 10000,
4+
output: './output',
5+
helpers: {
6+
FileSystem: {},
7+
},
8+
include: {},
9+
bootstrap: false,
10+
mocha: {},
11+
name: 'sandbox',
12+
fullPromiseBased: true,
13+
};

test/runner/bdd_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ describe('BDD Gherkin', () => {
193193
});
194194

195195
it('should show all available steps', (done) => {
196-
exec(`${runner} gherkin:steps --config ${codecept_dir}/codecept.bdd.json`, (err, stdout, stderr) => { //eslint-disable-line
196+
exec(`${runner} gherkin:steps --config ${codecept_dir}/codecept.bdd.js`, (err, stdout, stderr) => { //eslint-disable-line
197197
stdout.should.include('Gherkin');
198198
stdout.should.include('/I have product with \\$(\\d+) price/');
199199
stdout.should.include('step_definitions/my_steps.js:3:1');
@@ -206,7 +206,7 @@ describe('BDD Gherkin', () => {
206206
});
207207

208208
it('should generate snippets for missing steps', (done) => {
209-
exec(`${runner} gherkin:snippets --dry-run --config ${codecept_dir}/codecept.dummy.bdd.json`, (err, stdout, stderr) => { //eslint-disable-line
209+
exec(`${runner} gherkin:snippets --dry-run --config ${codecept_dir}/codecept.dummy.bdd.js`, (err, stdout, stderr) => { //eslint-disable-line
210210
stdout.should.include(`Given('I open a browser on a site', () => {
211211
// From "support/dummy.feature" {"line":4,"column":5}
212212
throw new Error('Not implemented yet');
@@ -277,7 +277,7 @@ When(/^I define a step with a \\( paren and a "(.*?)" string$/, () => {
277277
});
278278

279279
it('should not generate duplicated steps', (done) => {
280-
exec(`${runner} gherkin:snippets --dry-run --config ${codecept_dir}/codecept.duplicate.bdd.json`, (err, stdout, stderr) => { //eslint-disable-line
280+
exec(`${runner} gherkin:snippets --dry-run --config ${codecept_dir}/codecept.duplicate.bdd.js`, (err, stdout, stderr) => { //eslint-disable-line
281281
assert.equal(stdout.match(/I open a browser on a site/g).length, 1);
282282
assert(!err);
283283
done();

test/runner/before_failure_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const exec = require('child_process').exec;
33

44
const runner = path.join(__dirname, '/../../bin/codecept.js');
55
const codecept_dir = path.join(__dirname, '/../data/sandbox');
6-
const codecept_run = `${runner} run --config ${codecept_dir}/codecept.beforetest.failure.json `;
6+
const codecept_run = `${runner} run --config ${codecept_dir}/codecept.beforetest.failure.js `;
77

88
describe('Failure in before', function () {
99
this.timeout(5000);

test/runner/definitions_test.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('Definitions', function () {
3434

3535
describe('Static files', () => {
3636
it('should have internal object that is available as variable codeceptjs', (done) => {
37-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, () => {
37+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, () => {
3838
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
3939
types.should.be.valid;
4040

@@ -79,7 +79,7 @@ describe('Definitions', function () {
7979
});
8080

8181
it('def should create definition file with correct page def', (done) => {
82-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, (err, stdout) => {
82+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, (err, stdout) => {
8383
stdout.should.include('Definitions were generated in steps.d.ts');
8484
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
8585
types.should.be.valid;
@@ -94,7 +94,7 @@ describe('Definitions', function () {
9494
});
9595

9696
it('def should create definition file given a config file', (done) => {
97-
exec(`${runner} def --config ${codecept_dir}/../../codecept.ddt.json`, (err, stdout) => {
97+
exec(`${runner} def --config ${codecept_dir}/../../codecept.ddt.js`, (err, stdout) => {
9898
stdout.should.include('Definitions were generated in steps.d.ts');
9999
const types = typesFrom(`${codecept_dir}/../../steps.d.ts`);
100100
types.should.be.valid;
@@ -104,7 +104,7 @@ describe('Definitions', function () {
104104
});
105105

106106
it('def should create definition file with support object', (done) => {
107-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, () => {
107+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, () => {
108108
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
109109
types.should.be.valid;
110110

@@ -128,7 +128,7 @@ describe('Definitions', function () {
128128
});
129129

130130
it('def should create definition file with inject which contains support objects', (done) => {
131-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, () => {
131+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, () => {
132132
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
133133
types.should.be.valid;
134134

@@ -145,7 +145,7 @@ describe('Definitions', function () {
145145
});
146146

147147
it('def should create definition file with inject which contains I object', (done) => {
148-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, (err) => {
148+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, (err) => {
149149
assert(!err);
150150
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
151151
types.should.be.valid;
@@ -165,7 +165,7 @@ describe('Definitions', function () {
165165
});
166166

167167
it('def should create definition file with inject which contains I object from helpers', (done) => {
168-
exec(`${runner} def --config ${codecept_dir}//codecept.inject.powi.json`, () => {
168+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.powi.js`, () => {
169169
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
170170
types.should.be.valid;
171171

@@ -179,7 +179,7 @@ describe('Definitions', function () {
179179
});
180180

181181
it('def should create definition file with callback params', (done) => {
182-
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.json`, () => {
182+
exec(`${runner} def --config ${codecept_dir}/codecept.inject.po.js`, () => {
183183
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
184184
types.should.be.valid;
185185

@@ -193,6 +193,30 @@ describe('Definitions', function () {
193193
done();
194194
});
195195
});
196+
197+
it('def should create definition file with promise-based feature', (done) => {
198+
exec(`${runner} def --config ${codecept_dir}/codecept.promise.based.js`, (err, stdout) => {
199+
stdout.should.include('Definitions were generated in steps.d.ts');
200+
const types = typesFrom(`${codecept_dir}/steps.d.ts`);
201+
types.should.be.valid;
202+
203+
const definitionFile = types.getSourceFileOrThrow(`${codecept_dir}/steps.d.ts`);
204+
const extend = getExtends(definitionFile.getNamespaceOrThrow('CodeceptJS').getInterfaceOrThrow('I'));
205+
extend.should.containSubset([{
206+
methods: [{
207+
name: 'amInPath',
208+
returnType: 'Promise<any>',
209+
parameters: [{ name: 'openPath', type: 'string' }],
210+
}, {
211+
name: 'seeFile',
212+
returnType: 'Promise<any>',
213+
parameters: [{ name: 'name', type: 'string' }],
214+
}],
215+
}]);
216+
assert(!err);
217+
done();
218+
});
219+
});
196220
});
197221

198222
/** @type {Chai.ChaiPlugin */

test/runner/init_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ describe('Init Command', function () {
3535
});
3636

3737
it('init - Where should logs, screenshots, and reports to be stored? (./output)', async () => {
38-
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER]);
38+
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER, ENTER]);
3939
result.should.include('? What helpers do you want to use? REST');
4040
result.should.include('Where should logs, screenshots, and reports to be stored? (./output)');
4141
});
4242

4343
it('init - Do you want localization for tests? (See https://codecept.io/translation/)', async () => {
44-
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER, ENTER]);
44+
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER, ENTER, ENTER]);
4545
result.should.include('? Do you want localization for tests? (See https://codecept.io/translation/)');
4646
result.should.include('❯ English (no localization)');
4747
for (const item of ['de-DE', 'it-IT', 'fr-FR', 'ja-JP', 'pl-PL', 'pt-BR']) {
@@ -51,7 +51,7 @@ describe('Init Command', function () {
5151
});
5252

5353
it('init - [REST] Endpoint of API you are going to test (http://localhost:3000/api)', async () => {
54-
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER, ENTER, ENTER]);
54+
const result = await run([runner, 'init'], ['Y', ENTER, ENTER, DOWN, DOWN, DOWN, ENTER, ENTER, ENTER, ENTER]);
5555
result.should.include('Do you want localization for tests? (See https://codecept.io/translation/) Eng');
5656
result.should.include('Configure helpers...');
5757
result.should.include('? [REST] Endpoint of API you are going to test (http://localhost:3000/api)');

0 commit comments

Comments
 (0)