codeceptjs 3.3.8-beta.1 → 3.4.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/README.md +31 -32
- package/docs/advanced.md +48 -24
- package/docs/basics.md +115 -40
- package/docs/best.md +2 -2
- package/docs/build/ApiDataFactory.js +6 -6
- package/docs/build/Appium.js +2 -19
- package/docs/build/FileSystem.js +2 -2
- package/docs/build/GraphQLDataFactory.js +2 -2
- package/docs/build/Playwright.js +3 -2
- package/docs/build/TestCafe.js +4 -4
- package/docs/build/WebDriver.js +29 -164
- package/docs/helpers/ApiDataFactory.md +6 -6
- package/docs/helpers/FileSystem.md +2 -2
- package/docs/helpers/GraphQLDataFactory.md +2 -2
- package/docs/helpers/Playwright.md +2 -1
- package/docs/index.md +1 -1
- package/docs/plugins.md +73 -48
- package/docs/reports.md +0 -56
- package/docs/typescript.md +2 -8
- package/lib/actor.js +2 -1
- package/lib/cli.js +3 -3
- package/lib/codecept.js +2 -1
- package/lib/command/generate.js +3 -1
- package/lib/command/gherkin/snippets.js +8 -4
- package/lib/command/init.js +0 -8
- package/lib/command/run-workers.js +3 -6
- package/lib/command/utils.js +0 -10
- package/lib/command/workers/runTests.js +2 -2
- package/lib/config.js +5 -1
- package/lib/helper/ApiDataFactory.js +7 -7
- package/lib/helper/Appium.js +2 -19
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQL.js +1 -1
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +1 -1
- package/lib/helper/Mochawesome.js +1 -1
- package/lib/helper/Nightmare.js +1 -1
- package/lib/helper/Playwright.js +4 -3
- package/lib/helper/Protractor.js +1 -1
- package/lib/helper/Puppeteer.js +1 -1
- package/lib/helper/REST.js +1 -1
- package/lib/helper/TestCafe.js +5 -5
- package/lib/helper/WebDriver.js +30 -165
- package/lib/helper.js +0 -2
- package/lib/interfaces/bdd.js +1 -1
- package/lib/interfaces/featureConfig.js +1 -0
- package/lib/interfaces/gherkin.js +38 -25
- package/lib/listener/exit.js +2 -2
- package/lib/listener/retry.js +67 -0
- package/lib/listener/steps.js +1 -1
- package/lib/listener/timeout.js +47 -10
- package/lib/mochaFactory.js +3 -3
- package/lib/plugin/allure.js +14 -323
- package/lib/plugin/fakerTransform.js +2 -2
- package/lib/recorder.js +1 -1
- package/lib/scenario.js +25 -18
- package/lib/utils.js +6 -0
- package/lib/workers.js +4 -7
- package/package.json +13 -17
- package/typings/index.d.ts +66 -1
- package/typings/promiseBasedTypes.d.ts +12 -12
- package/typings/types.d.ts +95 -262
package/lib/helper/Appium.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
let webdriverio;
|
|
2
|
-
let wdioV4;
|
|
3
2
|
|
|
4
3
|
const fs = require('fs');
|
|
5
4
|
const axios = require('axios').default;
|
|
@@ -131,6 +130,7 @@ class Appium extends Webdriver {
|
|
|
131
130
|
* @augments WebDriver
|
|
132
131
|
*/
|
|
133
132
|
|
|
133
|
+
// @ts-ignore
|
|
134
134
|
constructor(config) {
|
|
135
135
|
super(config);
|
|
136
136
|
|
|
@@ -138,7 +138,6 @@ class Appium extends Webdriver {
|
|
|
138
138
|
this.axios = axios.create();
|
|
139
139
|
|
|
140
140
|
webdriverio = require('webdriverio');
|
|
141
|
-
(!webdriverio.VERSION || webdriverio.VERSION.indexOf('4') !== 0) ? wdioV4 = false : wdioV4 = true;
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
_validateConfig(config) {
|
|
@@ -516,10 +515,6 @@ class Appium extends Webdriver {
|
|
|
516
515
|
async removeApp(appId, bundleId) {
|
|
517
516
|
onlyForApps.call(this, supportedPlatform.android);
|
|
518
517
|
|
|
519
|
-
if (wdioV4) {
|
|
520
|
-
return this.browser.removeApp(bundleId);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
518
|
return this.axios({
|
|
524
519
|
method: 'post',
|
|
525
520
|
url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
|
|
@@ -610,19 +605,13 @@ class Appium extends Webdriver {
|
|
|
610
605
|
*/
|
|
611
606
|
async seeOrientationIs(orientation) {
|
|
612
607
|
onlyForApps.call(this);
|
|
613
|
-
let currentOrientation;
|
|
614
|
-
|
|
615
|
-
if (wdioV4) {
|
|
616
|
-
const res = await this.browser.orientation();
|
|
617
|
-
currentOrientation = res;
|
|
618
|
-
}
|
|
619
608
|
|
|
620
609
|
const res = await this.axios({
|
|
621
610
|
method: 'get',
|
|
622
611
|
url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
|
|
623
612
|
});
|
|
624
613
|
|
|
625
|
-
currentOrientation = res.data.value;
|
|
614
|
+
const currentOrientation = res.data.value;
|
|
626
615
|
return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation);
|
|
627
616
|
}
|
|
628
617
|
|
|
@@ -640,9 +629,6 @@ class Appium extends Webdriver {
|
|
|
640
629
|
*/
|
|
641
630
|
async setOrientation(orientation) {
|
|
642
631
|
onlyForApps.call(this);
|
|
643
|
-
if (wdioV4) {
|
|
644
|
-
return this.browser.setOrientation(orientation);
|
|
645
|
-
}
|
|
646
632
|
|
|
647
633
|
return this.axios({
|
|
648
634
|
method: 'post',
|
|
@@ -916,9 +902,6 @@ class Appium extends Webdriver {
|
|
|
916
902
|
*/
|
|
917
903
|
async sendDeviceKeyEvent(keyValue) {
|
|
918
904
|
onlyForApps.call(this, supportedPlatform.android);
|
|
919
|
-
if (wdioV4) {
|
|
920
|
-
return this.browser.sendKeyEvent(keyValue);
|
|
921
|
-
}
|
|
922
905
|
return this.browser.pressKeyCode(keyValue);
|
|
923
906
|
}
|
|
924
907
|
|
package/lib/helper/FileSystem.js
CHANGED
|
@@ -2,7 +2,7 @@ const assert = require('assert');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
|
|
5
|
-
const Helper = require('
|
|
5
|
+
const Helper = require('@codeceptjs/helper');
|
|
6
6
|
const { fileExists } = require('../utils');
|
|
7
7
|
const { fileIncludes } = require('../assert/include');
|
|
8
8
|
const { fileEquals } = require('../assert/equal');
|
|
@@ -71,10 +71,10 @@ class FileSystem extends Helper {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
* Waits for file to be present in current directory.
|
|
74
|
+
* Waits for the file to be present in the current directory.
|
|
75
75
|
*
|
|
76
76
|
* ```js
|
|
77
|
-
* I.handleDownloads();
|
|
77
|
+
* I.handleDownloads('downloads/largeFilesName.txt');
|
|
78
78
|
* I.click('Download large File');
|
|
79
79
|
* I.amInPath('output/downloads');
|
|
80
80
|
* I.waitForFile('largeFilesName.txt', 10); // wait 10 seconds for file
|
package/lib/helper/GraphQL.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
-
const Helper = require('
|
|
3
|
+
const Helper = require('@codeceptjs/helper');
|
|
4
4
|
const GraphQL = require('./GraphQL');
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -46,8 +46,8 @@ const GraphQL = require('./GraphQL');
|
|
|
46
46
|
* ```js
|
|
47
47
|
* // tests/factories/users.js
|
|
48
48
|
*
|
|
49
|
-
* const Factory = require('rosie').Factory;
|
|
50
|
-
* const faker = require('@faker-js/faker');
|
|
49
|
+
* const { Factory } = require('rosie').Factory;
|
|
50
|
+
* const { faker } = require('@faker-js/faker');
|
|
51
51
|
*
|
|
52
52
|
* // Used with a constructor function passed to Factory, so that the final build
|
|
53
53
|
* // object matches the necessary pattern to be sent as the variables object.
|
package/lib/helper/Nightmare.js
CHANGED
|
@@ -2,7 +2,7 @@ const path = require('path');
|
|
|
2
2
|
|
|
3
3
|
const urlResolve = require('url').resolve;
|
|
4
4
|
|
|
5
|
-
const Helper = require('
|
|
5
|
+
const Helper = require('@codeceptjs/helper');
|
|
6
6
|
const { includes: stringIncludes } = require('../assert/include');
|
|
7
7
|
const { urlEquals } = require('../assert/equal');
|
|
8
8
|
const { equals } = require('../assert/equal');
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
|
|
4
|
-
const Helper = require('
|
|
4
|
+
const Helper = require('@codeceptjs/helper');
|
|
5
5
|
const Locator = require('../locator');
|
|
6
6
|
const recorder = require('../recorder');
|
|
7
7
|
const stringIncludes = require('../assert/include').includes;
|
|
@@ -66,6 +66,7 @@ const pathSeparator = path.sep;
|
|
|
66
66
|
* @prop {boolean} [video=false] - enables video recording for failed tests; videos are saved into `output/videos` folder
|
|
67
67
|
* @prop {boolean} [keepVideoForPassedTests=false] - save videos for passed tests; videos are saved into `output/videos` folder
|
|
68
68
|
* @prop {boolean} [trace=false] - record [tracing information](https://playwright.dev/docs/trace-viewer) with screenshots and snapshots.
|
|
69
|
+
* @prop {boolean} [keepTraceForPassedTests=false] - save trace for passed tests.
|
|
69
70
|
* @prop {boolean} [fullPageScreenshots=false] - make full page screenshots on failure.
|
|
70
71
|
* @prop {boolean} [uniqueScreenshotNames=false] - option to prevent screenshot override if you have scenarios with the same name in different suites.
|
|
71
72
|
* @prop {boolean} [keepBrowserState=false] - keep browser state between tests when `restart` is set to 'session'.
|
|
@@ -1259,7 +1260,7 @@ class Playwright extends Helper {
|
|
|
1259
1260
|
*
|
|
1260
1261
|
* ```
|
|
1261
1262
|
*
|
|
1262
|
-
* @param {string}
|
|
1263
|
+
* @param {string} fileName set filename for downloaded file
|
|
1263
1264
|
* @return {Promise<void>}
|
|
1264
1265
|
*/
|
|
1265
1266
|
async handleDownloads(fileName) {
|
|
@@ -2981,7 +2982,7 @@ async function refreshContextSession() {
|
|
|
2981
2982
|
|
|
2982
2983
|
async function saveVideoForPage(page, name) {
|
|
2983
2984
|
if (!page.video()) return null;
|
|
2984
|
-
const fileName = `${global.output_dir}${pathSeparator}videos${pathSeparator}${Date.now()}_${clearString(name)
|
|
2985
|
+
const fileName = `${`${global.output_dir}${pathSeparator}videos${pathSeparator}${Date.now()}_${clearString(name)}`.slice(0, 245)}.webm`;
|
|
2985
2986
|
page.video().saveAs(fileName).then(() => {
|
|
2986
2987
|
if (!page) return;
|
|
2987
2988
|
page.video().delete().catch(e => {});
|
package/lib/helper/Protractor.js
CHANGED
|
@@ -6,7 +6,7 @@ let ProtractorExpectedConditions;
|
|
|
6
6
|
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
|
-
const Helper = require('
|
|
9
|
+
const Helper = require('@codeceptjs/helper');
|
|
10
10
|
const stringIncludes = require('../assert/include').includes;
|
|
11
11
|
const { urlEquals, equals } = require('../assert/equal');
|
|
12
12
|
const { empty } = require('../assert/empty');
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -3,7 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const fsExtra = require('fs-extra');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
-
const Helper = require('
|
|
6
|
+
const Helper = require('@codeceptjs/helper');
|
|
7
7
|
const Locator = require('../locator');
|
|
8
8
|
const recorder = require('../recorder');
|
|
9
9
|
const stringIncludes = require('../assert/include').includes;
|
package/lib/helper/REST.js
CHANGED
package/lib/helper/TestCafe.js
CHANGED
|
@@ -6,6 +6,7 @@ const qrcode = require('qrcode-terminal');
|
|
|
6
6
|
const createTestCafe = require('testcafe');
|
|
7
7
|
const { Selector, ClientFunction } = require('testcafe');
|
|
8
8
|
|
|
9
|
+
const Helper = require('@codeceptjs/helper');
|
|
9
10
|
const ElementNotFound = require('./errors/ElementNotFound');
|
|
10
11
|
const testControllerHolder = require('./testcafe/testControllerHolder');
|
|
11
12
|
const {
|
|
@@ -22,7 +23,6 @@ const {
|
|
|
22
23
|
xpathLocator,
|
|
23
24
|
} = require('../utils');
|
|
24
25
|
const Locator = require('../locator');
|
|
25
|
-
const Helper = require('../helper');
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Client Functions
|
|
@@ -545,8 +545,8 @@ class TestCafe extends Helper {
|
|
|
545
545
|
|
|
546
546
|
// TODO As far as I understand the testcafe docs this should do a multi-select
|
|
547
547
|
// but it does not work
|
|
548
|
-
const clickOpts = { ctrl: option.length > 1 };
|
|
549
|
-
await this.t.click(el
|
|
548
|
+
// const clickOpts = { ctrl: option.length > 1 };
|
|
549
|
+
await this.t.click(el).catch(mapError);
|
|
550
550
|
|
|
551
551
|
for (const key of option) {
|
|
552
552
|
const opt = key;
|
|
@@ -555,7 +555,7 @@ class TestCafe extends Helper {
|
|
|
555
555
|
try {
|
|
556
556
|
optEl = el.child('option').withText(opt);
|
|
557
557
|
if (await optEl.count) {
|
|
558
|
-
await this.t.click(optEl
|
|
558
|
+
await this.t.click(optEl).catch(mapError);
|
|
559
559
|
continue;
|
|
560
560
|
}
|
|
561
561
|
// eslint-disable-next-line no-empty
|
|
@@ -566,7 +566,7 @@ class TestCafe extends Helper {
|
|
|
566
566
|
const sel = `[value="${opt}"]`;
|
|
567
567
|
optEl = el.find(sel);
|
|
568
568
|
if (await optEl.count) {
|
|
569
|
-
await this.t.click(optEl
|
|
569
|
+
await this.t.click(optEl).catch(mapError);
|
|
570
570
|
}
|
|
571
571
|
// eslint-disable-next-line no-empty
|
|
572
572
|
} catch (err) {
|
package/lib/helper/WebDriver.js
CHANGED
|
@@ -4,12 +4,12 @@ const assert = require('assert');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
|
|
7
|
-
const Helper = require('
|
|
7
|
+
const Helper = require('@codeceptjs/helper');
|
|
8
8
|
const stringIncludes = require('../assert/include').includes;
|
|
9
9
|
const { urlEquals, equals } = require('../assert/equal');
|
|
10
10
|
const { debug } = require('../output');
|
|
11
|
-
const empty = require('../assert/empty')
|
|
12
|
-
const truth = require('../assert/truth')
|
|
11
|
+
const { empty } = require('../assert/empty');
|
|
12
|
+
const { truth } = require('../assert/truth');
|
|
13
13
|
const {
|
|
14
14
|
xpathLocator,
|
|
15
15
|
fileExists,
|
|
@@ -31,8 +31,6 @@ const Locator = require('../locator');
|
|
|
31
31
|
const SHADOW = 'shadow';
|
|
32
32
|
const webRoot = 'body';
|
|
33
33
|
|
|
34
|
-
let version;
|
|
35
|
-
|
|
36
34
|
/**
|
|
37
35
|
* ## Configuration
|
|
38
36
|
*
|
|
@@ -266,7 +264,7 @@ const config = {};
|
|
|
266
264
|
* ```js
|
|
267
265
|
* plugins: {
|
|
268
266
|
* wdio: {
|
|
269
|
-
|
|
267
|
+
* enabled: true,
|
|
270
268
|
* services: ['sauce'],
|
|
271
269
|
* user: ... ,// saucelabs username
|
|
272
270
|
* key: ... // saucelabs api key
|
|
@@ -294,7 +292,7 @@ const config = {};
|
|
|
294
292
|
* ```js
|
|
295
293
|
* plugins: {
|
|
296
294
|
* wdio: {
|
|
297
|
-
|
|
295
|
+
* enabled: true,
|
|
298
296
|
* services: ['browserstack'],
|
|
299
297
|
* user: ... ,// browserstack username
|
|
300
298
|
* key: ... // browserstack api key
|
|
@@ -386,16 +384,6 @@ class WebDriver extends Helper {
|
|
|
386
384
|
super(config);
|
|
387
385
|
webdriverio = require('webdriverio');
|
|
388
386
|
|
|
389
|
-
try {
|
|
390
|
-
version = JSON.parse(fs.readFileSync(path.join(require.resolve('webdriverio'), '/../../', 'package.json')).toString()).version;
|
|
391
|
-
} catch (err) {
|
|
392
|
-
this.debug('Can\'t detect webdriverio version, assuming webdriverio v6 is used');
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (isWebDriver5()) {
|
|
396
|
-
console.log('DEPRECATION NOTICE:');
|
|
397
|
-
console.log('You are using webdriverio v5. It is recommended to update to webdriverio@6.\nSupport of webdriverio v5 is deprecated and will be removed in CodeceptJS 3.0\n');
|
|
398
|
-
}
|
|
399
387
|
// set defaults
|
|
400
388
|
this.root = webRoot;
|
|
401
389
|
this.isWeb = true;
|
|
@@ -661,23 +649,23 @@ class WebDriver extends Helper {
|
|
|
661
649
|
}
|
|
662
650
|
|
|
663
651
|
/**
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
652
|
+
* Use [webdriverio](https://webdriver.io/docs/api.html) API inside a test.
|
|
653
|
+
*
|
|
654
|
+
* First argument is a description of an action.
|
|
655
|
+
* Second argument is async function that gets this helper as parameter.
|
|
656
|
+
*
|
|
657
|
+
* { [`browser`](https://webdriver.io/docs/api.html)) } object from WebDriver API is available.
|
|
658
|
+
*
|
|
659
|
+
* ```js
|
|
660
|
+
* I.useWebDriverTo('open multiple windows', async ({ browser }) {
|
|
661
|
+
* // create new window
|
|
662
|
+
* await browser.newWindow('https://webdriver.io');
|
|
663
|
+
* });
|
|
664
|
+
* ```
|
|
665
|
+
*
|
|
666
|
+
* @param {string} description used to show in logs.
|
|
667
|
+
* @param {function} fn async functuion that executed with WebDriver helper as argument
|
|
668
|
+
*/
|
|
681
669
|
useWebDriverTo(description, fn) {
|
|
682
670
|
return this._useTo(...arguments);
|
|
683
671
|
}
|
|
@@ -1654,7 +1642,6 @@ class WebDriver extends Helper {
|
|
|
1654
1642
|
const res = await this._locate(withStrictLocator(locator), true);
|
|
1655
1643
|
assertElementExists(res, locator);
|
|
1656
1644
|
const elem = usingFirstElement(res);
|
|
1657
|
-
if (isWebDriver5()) return elem.moveTo(xOffset, yOffset);
|
|
1658
1645
|
return elem.moveTo({ xOffset, yOffset });
|
|
1659
1646
|
}
|
|
1660
1647
|
|
|
@@ -2043,19 +2030,7 @@ class WebDriver extends Helper {
|
|
|
2043
2030
|
*/
|
|
2044
2031
|
async waitForEnabled(locator, sec = null) {
|
|
2045
2032
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2046
|
-
|
|
2047
|
-
return this.browser.waitUntil(async () => {
|
|
2048
|
-
const res = await this.$$(withStrictLocator(locator));
|
|
2049
|
-
if (!res || res.length === 0) {
|
|
2050
|
-
return false;
|
|
2051
|
-
}
|
|
2052
|
-
const selected = await forEachAsync(res, async el => this.browser.isElementEnabled(getElementId(el)));
|
|
2053
|
-
if (Array.isArray(selected)) {
|
|
2054
|
-
return selected.filter(val => val === true).length > 0;
|
|
2055
|
-
}
|
|
2056
|
-
return selected;
|
|
2057
|
-
}, aSec * 1000, `element (${new Locator(locator)}) still not enabled after ${aSec} sec`);
|
|
2058
|
-
}
|
|
2033
|
+
|
|
2059
2034
|
return this.browser.waitUntil(async () => {
|
|
2060
2035
|
const res = await this._res(locator);
|
|
2061
2036
|
if (!res || res.length === 0) {
|
|
@@ -2077,12 +2052,7 @@ class WebDriver extends Helper {
|
|
|
2077
2052
|
*/
|
|
2078
2053
|
async waitForElement(locator, sec = null) {
|
|
2079
2054
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2080
|
-
|
|
2081
|
-
return this.browser.waitUntil(async () => {
|
|
2082
|
-
const res = await this.$$(withStrictLocator(locator));
|
|
2083
|
-
return res && res.length;
|
|
2084
|
-
}, aSec * 1000, `element (${(new Locator(locator))}) still not present on page after ${aSec} sec`);
|
|
2085
|
-
}
|
|
2055
|
+
|
|
2086
2056
|
return this.browser.waitUntil(async () => {
|
|
2087
2057
|
const res = await this._res(locator);
|
|
2088
2058
|
return res && res.length;
|
|
@@ -2111,20 +2081,7 @@ class WebDriver extends Helper {
|
|
|
2111
2081
|
const client = this.browser;
|
|
2112
2082
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2113
2083
|
let currUrl = '';
|
|
2114
|
-
|
|
2115
|
-
return client
|
|
2116
|
-
.waitUntil(function () {
|
|
2117
|
-
return this.getUrl().then((res) => {
|
|
2118
|
-
currUrl = decodeUrl(res);
|
|
2119
|
-
return currUrl.indexOf(urlPart) > -1;
|
|
2120
|
-
});
|
|
2121
|
-
}, aSec * 1000).catch((e) => {
|
|
2122
|
-
if (e.message.indexOf('timeout')) {
|
|
2123
|
-
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
|
|
2124
|
-
}
|
|
2125
|
-
throw e;
|
|
2126
|
-
});
|
|
2127
|
-
}
|
|
2084
|
+
|
|
2128
2085
|
return client
|
|
2129
2086
|
.waitUntil(function () {
|
|
2130
2087
|
return this.getUrl().then((res) => {
|
|
@@ -2169,20 +2126,6 @@ class WebDriver extends Helper {
|
|
|
2169
2126
|
async waitForText(text, sec = null, context = null) {
|
|
2170
2127
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2171
2128
|
const _context = context || this.root;
|
|
2172
|
-
if (isWebDriver5()) {
|
|
2173
|
-
return this.browser.waitUntil(
|
|
2174
|
-
async () => {
|
|
2175
|
-
const res = await this.$$(withStrictLocator.call(this, _context));
|
|
2176
|
-
if (!res || res.length === 0) return false;
|
|
2177
|
-
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
|
|
2178
|
-
if (Array.isArray(selected)) {
|
|
2179
|
-
return selected.filter(part => part.indexOf(text) >= 0).length > 0;
|
|
2180
|
-
}
|
|
2181
|
-
return selected.indexOf(text) >= 0;
|
|
2182
|
-
}, aSec * 1000,
|
|
2183
|
-
`element (${_context}) is not in DOM or there is no element(${_context}) with text "${text}" after ${aSec} sec`,
|
|
2184
|
-
);
|
|
2185
|
-
}
|
|
2186
2129
|
|
|
2187
2130
|
return this.browser.waitUntil(
|
|
2188
2131
|
async () => {
|
|
@@ -2206,20 +2149,7 @@ class WebDriver extends Helper {
|
|
|
2206
2149
|
async waitForValue(field, value, sec = null) {
|
|
2207
2150
|
const client = this.browser;
|
|
2208
2151
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2209
|
-
|
|
2210
|
-
return client.waitUntil(
|
|
2211
|
-
async () => {
|
|
2212
|
-
const res = await findFields.call(this, field);
|
|
2213
|
-
if (!res || res.length === 0) return false;
|
|
2214
|
-
const selected = await forEachAsync(res, async el => el.getValue());
|
|
2215
|
-
if (Array.isArray(selected)) {
|
|
2216
|
-
return selected.filter(part => part.indexOf(value) >= 0).length > 0;
|
|
2217
|
-
}
|
|
2218
|
-
return selected.indexOf(value) >= 0;
|
|
2219
|
-
}, aSec * 1000,
|
|
2220
|
-
`element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`,
|
|
2221
|
-
);
|
|
2222
|
-
}
|
|
2152
|
+
|
|
2223
2153
|
return client.waitUntil(
|
|
2224
2154
|
async () => {
|
|
2225
2155
|
const res = await findFields.call(this, field);
|
|
@@ -2242,17 +2172,7 @@ class WebDriver extends Helper {
|
|
|
2242
2172
|
*/
|
|
2243
2173
|
async waitForVisible(locator, sec = null) {
|
|
2244
2174
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2245
|
-
|
|
2246
|
-
return this.browser.waitUntil(async () => {
|
|
2247
|
-
const res = await this.$$(withStrictLocator(locator));
|
|
2248
|
-
if (!res || res.length === 0) return false;
|
|
2249
|
-
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2250
|
-
if (Array.isArray(selected)) {
|
|
2251
|
-
return selected.filter(val => val === true).length > 0;
|
|
2252
|
-
}
|
|
2253
|
-
return selected;
|
|
2254
|
-
}, aSec * 1000, `element (${new Locator(locator)}) still not visible after ${aSec} sec`);
|
|
2255
|
-
}
|
|
2175
|
+
|
|
2256
2176
|
return this.browser.waitUntil(async () => {
|
|
2257
2177
|
const res = await this._res(locator);
|
|
2258
2178
|
if (!res || res.length === 0) return false;
|
|
@@ -2269,17 +2189,7 @@ class WebDriver extends Helper {
|
|
|
2269
2189
|
*/
|
|
2270
2190
|
async waitNumberOfVisibleElements(locator, num, sec = null) {
|
|
2271
2191
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2272
|
-
if (isWebDriver5()) {
|
|
2273
|
-
return this.browser.waitUntil(async () => {
|
|
2274
|
-
const res = await this.$$(withStrictLocator(locator));
|
|
2275
|
-
if (!res || res.length === 0) return false;
|
|
2276
|
-
let selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2277
2192
|
|
|
2278
|
-
if (!Array.isArray(selected)) selected = [selected];
|
|
2279
|
-
selected = selected.filter(val => val === true);
|
|
2280
|
-
return selected.length === num;
|
|
2281
|
-
}, aSec * 1000, `The number of elements (${new Locator(locator)}) is not ${num} after ${aSec} sec`);
|
|
2282
|
-
}
|
|
2283
2193
|
return this.browser.waitUntil(async () => {
|
|
2284
2194
|
const res = await this._res(locator);
|
|
2285
2195
|
if (!res || res.length === 0) return false;
|
|
@@ -2296,14 +2206,7 @@ class WebDriver extends Helper {
|
|
|
2296
2206
|
*/
|
|
2297
2207
|
async waitForInvisible(locator, sec = null) {
|
|
2298
2208
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2299
|
-
|
|
2300
|
-
return this.browser.waitUntil(async () => {
|
|
2301
|
-
const res = await this.$$(withStrictLocator(locator));
|
|
2302
|
-
if (!res || res.length === 0) return true;
|
|
2303
|
-
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2304
|
-
return !selected.length;
|
|
2305
|
-
}, aSec * 1000, `element (${new Locator(locator)}) still visible after ${aSec} sec`);
|
|
2306
|
-
}
|
|
2209
|
+
|
|
2307
2210
|
return this.browser.waitUntil(async () => {
|
|
2308
2211
|
const res = await this._res(locator);
|
|
2309
2212
|
if (!res || res.length === 0) return true;
|
|
@@ -2324,15 +2227,7 @@ class WebDriver extends Helper {
|
|
|
2324
2227
|
*/
|
|
2325
2228
|
async waitForDetached(locator, sec = null) {
|
|
2326
2229
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2327
|
-
|
|
2328
|
-
return this.browser.waitUntil(async () => {
|
|
2329
|
-
const res = await this._res(locator);
|
|
2330
|
-
if (!res || res.length === 0) {
|
|
2331
|
-
return true;
|
|
2332
|
-
}
|
|
2333
|
-
return false;
|
|
2334
|
-
}, aSec * 1000, `element (${new Locator(locator)}) still on page after ${aSec} sec`);
|
|
2335
|
-
}
|
|
2230
|
+
|
|
2336
2231
|
return this.browser.waitUntil(async () => {
|
|
2337
2232
|
const res = await this._res(locator);
|
|
2338
2233
|
if (!res || res.length === 0) {
|
|
@@ -2356,9 +2251,7 @@ class WebDriver extends Helper {
|
|
|
2356
2251
|
}
|
|
2357
2252
|
|
|
2358
2253
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2359
|
-
|
|
2360
|
-
return this.browser.waitUntil(async () => this.browser.execute(fn, ...args), aSec * 1000, '');
|
|
2361
|
-
}
|
|
2254
|
+
|
|
2362
2255
|
return this.browser.waitUntil(async () => this.browser.execute(fn, ...args), { timeout: aSec * 1000, timeoutMsg: '' });
|
|
2363
2256
|
}
|
|
2364
2257
|
|
|
@@ -2388,18 +2281,6 @@ class WebDriver extends Helper {
|
|
|
2388
2281
|
let target;
|
|
2389
2282
|
const current = await this.browser.getWindowHandle();
|
|
2390
2283
|
|
|
2391
|
-
if (isWebDriver5()) {
|
|
2392
|
-
await this.browser.waitUntil(async () => {
|
|
2393
|
-
await this.browser.getWindowHandles().then((handles) => {
|
|
2394
|
-
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
2395
|
-
target = handles[handles.indexOf(current) + num];
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
return target;
|
|
2399
|
-
}, aSec * 1000, `There is no ability to switch to next tab with offset ${num}`);
|
|
2400
|
-
return this.browser.switchToWindow(target);
|
|
2401
|
-
}
|
|
2402
|
-
|
|
2403
2284
|
await this.browser.waitUntil(async () => {
|
|
2404
2285
|
await this.browser.getWindowHandles().then((handles) => {
|
|
2405
2286
|
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
@@ -2419,18 +2300,6 @@ class WebDriver extends Helper {
|
|
|
2419
2300
|
const current = await this.browser.getWindowHandle();
|
|
2420
2301
|
let target;
|
|
2421
2302
|
|
|
2422
|
-
if (isWebDriver5()) {
|
|
2423
|
-
await this.browser.waitUntil(async () => {
|
|
2424
|
-
await this.browser.getWindowHandles().then((handles) => {
|
|
2425
|
-
if (handles.indexOf(current) - num > -1) {
|
|
2426
|
-
target = handles[handles.indexOf(current) - num];
|
|
2427
|
-
}
|
|
2428
|
-
});
|
|
2429
|
-
return target;
|
|
2430
|
-
}, aSec * 1000, `There is no ability to switch to previous tab with offset ${num}`);
|
|
2431
|
-
return this.browser.switchToWindow(target);
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
2303
|
await this.browser.waitUntil(async () => {
|
|
2435
2304
|
await this.browser.getWindowHandles().then((handles) => {
|
|
2436
2305
|
if (handles.indexOf(current) - num > -1) {
|
|
@@ -3018,8 +2887,4 @@ function prepareLocateFn(context) {
|
|
|
3018
2887
|
};
|
|
3019
2888
|
}
|
|
3020
2889
|
|
|
3021
|
-
function isWebDriver5() {
|
|
3022
|
-
return version && version.indexOf('5') === 0;
|
|
3023
|
-
}
|
|
3024
|
-
|
|
3025
2890
|
module.exports = WebDriver;
|
package/lib/helper.js
CHANGED
package/lib/interfaces/bdd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { CucumberExpression, ParameterTypeRegistry, ParameterType } = require('cucumber-expressions');
|
|
1
|
+
const { CucumberExpression, ParameterTypeRegistry, ParameterType } = require('@cucumber/cucumber-expressions');
|
|
2
2
|
const Config = require('../config');
|
|
3
3
|
|
|
4
4
|
let steps = {};
|