codeceptjs 3.5.4-beta.1 → 3.5.5
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 +368 -0
- package/README.md +0 -2
- package/docs/build/Appium.js +48 -7
- package/docs/build/GraphQL.js +25 -0
- package/docs/build/Nightmare.js +15 -6
- package/docs/build/Playwright.js +436 -197
- package/docs/build/Protractor.js +17 -8
- package/docs/build/Puppeteer.js +37 -20
- package/docs/build/TestCafe.js +19 -10
- package/docs/build/WebDriver.js +45 -37
- package/docs/changelog.md +375 -0
- package/docs/community-helpers.md +8 -4
- package/docs/examples.md +8 -2
- package/docs/helpers/Appium.md +39 -2
- package/docs/helpers/GraphQL.md +21 -0
- package/docs/helpers/Nightmare.md +1260 -0
- package/docs/helpers/Playwright.md +223 -119
- package/docs/helpers/Protractor.md +1711 -0
- package/docs/helpers/Puppeteer.md +31 -29
- package/docs/helpers/TestCafe.md +18 -17
- package/docs/helpers/WebDriver.md +34 -32
- package/docs/playwright.md +24 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +2 -0
- package/docs/webapi/executeScript.mustache +2 -0
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/wiki/Books-&-Posts.md +0 -0
- package/docs/wiki/Community-Helpers-&-Plugins.md +8 -4
- package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +46 -14
- package/docs/wiki/Examples.md +8 -2
- package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -0
- package/docs/wiki/Home.md +0 -0
- package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +83 -0
- package/docs/wiki/Release-Process.md +0 -0
- package/docs/wiki/Roadmap.md +0 -0
- package/docs/wiki/Tests.md +0 -0
- package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -0
- package/docs/wiki/Videos.md +0 -0
- package/lib/codecept.js +1 -0
- package/lib/command/definitions.js +2 -7
- package/lib/command/init.js +40 -4
- package/lib/command/run-multiple/collection.js +17 -5
- package/lib/command/run-workers.js +4 -0
- package/lib/command/run.js +6 -0
- package/lib/helper/Appium.js +46 -5
- package/lib/helper/GraphQL.js +25 -0
- package/lib/helper/Nightmare.js +1415 -0
- package/lib/helper/Playwright.js +336 -62
- package/lib/helper/Protractor.js +1837 -0
- package/lib/helper/Puppeteer.js +31 -18
- package/lib/helper/TestCafe.js +15 -8
- package/lib/helper/WebDriver.js +39 -35
- package/lib/helper/clientscripts/nightmare.js +213 -0
- package/lib/helper/errors/ElementNotFound.js +2 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/interfaces/bdd.js +1 -1
- package/lib/mochaFactory.js +2 -1
- package/lib/pause.js +6 -4
- package/lib/plugin/heal.js +2 -3
- package/lib/plugin/selenoid.js +6 -1
- package/lib/step.js +27 -10
- package/lib/utils.js +4 -0
- package/lib/workers.js +3 -1
- package/package.json +87 -87
- package/typings/promiseBasedTypes.d.ts +163 -126
- package/typings/types.d.ts +183 -144
- package/docs/build/Polly.js +0 -42
- package/docs/build/SeleniumWebdriver.js +0 -76
package/docs/build/Protractor.js
CHANGED
|
@@ -821,12 +821,13 @@ class Protractor extends Helper {
|
|
|
821
821
|
* I.seeInField('#searchform input','Search');
|
|
822
822
|
* ```
|
|
823
823
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
824
|
-
* @param {
|
|
824
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
825
825
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
826
826
|
*
|
|
827
827
|
*/
|
|
828
828
|
async seeInField(field, value) {
|
|
829
|
-
|
|
829
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
830
|
+
return proceedSeeInField.call(this, 'assert', field, _value);
|
|
830
831
|
}
|
|
831
832
|
|
|
832
833
|
/**
|
|
@@ -839,12 +840,13 @@ class Protractor extends Helper {
|
|
|
839
840
|
* ```
|
|
840
841
|
*
|
|
841
842
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
842
|
-
* @param {
|
|
843
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
843
844
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
844
845
|
*
|
|
845
846
|
*/
|
|
846
847
|
async dontSeeInField(field, value) {
|
|
847
|
-
|
|
848
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
849
|
+
return proceedSeeInField.call(this, 'negate', field, _value);
|
|
848
850
|
}
|
|
849
851
|
|
|
850
852
|
/**
|
|
@@ -1523,6 +1525,8 @@ class Protractor extends Helper {
|
|
|
1523
1525
|
*
|
|
1524
1526
|
* @param {string|function} fn function to be executed in browser context.
|
|
1525
1527
|
* @param {...any} args to be passed to function.
|
|
1528
|
+
* @returns {Promise<any>} script return value
|
|
1529
|
+
*
|
|
1526
1530
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1527
1531
|
*
|
|
1528
1532
|
*/
|
|
@@ -1554,6 +1558,8 @@ class Protractor extends Helper {
|
|
|
1554
1558
|
*
|
|
1555
1559
|
* @param {string|function} fn function to be executed in browser context.
|
|
1556
1560
|
* @param {...any} args to be passed to function.
|
|
1561
|
+
* @returns {Promise<any>} script return value
|
|
1562
|
+
*
|
|
1557
1563
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1558
1564
|
*
|
|
1559
1565
|
*/
|
|
@@ -1645,7 +1651,7 @@ class Protractor extends Helper {
|
|
|
1645
1651
|
const stream = fs.createWriteStream(outputFile);
|
|
1646
1652
|
stream.write(Buffer.from(png, 'base64'));
|
|
1647
1653
|
stream.end();
|
|
1648
|
-
return new Promise(resolve => stream.on('finish', resolve));
|
|
1654
|
+
return new Promise(resolve => stream.on('finish', resolve)); // eslint-disable-line no-promise-executor-return
|
|
1649
1655
|
};
|
|
1650
1656
|
|
|
1651
1657
|
const res = await this._locate(locator);
|
|
@@ -1680,7 +1686,7 @@ class Protractor extends Helper {
|
|
|
1680
1686
|
const stream = fs.createWriteStream(outputFile);
|
|
1681
1687
|
stream.write(Buffer.from(png, 'base64'));
|
|
1682
1688
|
stream.end();
|
|
1683
|
-
return new Promise(resolve => stream.on('finish', resolve));
|
|
1689
|
+
return new Promise(resolve => stream.on('finish', resolve)); // eslint-disable-line no-promise-executor-return
|
|
1684
1690
|
};
|
|
1685
1691
|
|
|
1686
1692
|
if (!fullPage) {
|
|
@@ -2458,8 +2464,11 @@ class Protractor extends Helper {
|
|
|
2458
2464
|
const body = document.body;
|
|
2459
2465
|
const html = document.documentElement;
|
|
2460
2466
|
window.scrollTo(0, Math.max(
|
|
2461
|
-
body.scrollHeight,
|
|
2462
|
-
|
|
2467
|
+
body.scrollHeight,
|
|
2468
|
+
body.offsetHeight,
|
|
2469
|
+
html.clientHeight,
|
|
2470
|
+
html.scrollHeight,
|
|
2471
|
+
html.offsetHeight
|
|
2463
2472
|
));
|
|
2464
2473
|
});
|
|
2465
2474
|
/* eslint-enable */
|
package/docs/build/Puppeteer.js
CHANGED
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
screenshotOutputFolder,
|
|
24
24
|
getNormalizedKeyAttributeValue,
|
|
25
25
|
isModifierKey,
|
|
26
|
-
requireWithFallback,
|
|
26
|
+
requireWithFallback, normalizeSpacesInString,
|
|
27
27
|
} = require('../utils');
|
|
28
28
|
const {
|
|
29
29
|
isColorProperty,
|
|
@@ -69,7 +69,7 @@ const consoleLogStore = new Console();
|
|
|
69
69
|
* @prop {boolean} [manualStart=false] - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
|
|
70
70
|
* @prop {string} [browser=chrome] - can be changed to `firefox` when using [puppeteer-firefox](https://codecept.io/helpers/Puppeteer-firefox).
|
|
71
71
|
* @prop {object} [chrome] - pass additional [Puppeteer run options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions).
|
|
72
|
-
* @prop {boolean} [highlightElement] - highlight the interacting elements
|
|
72
|
+
* @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false
|
|
73
73
|
*/
|
|
74
74
|
const config = {};
|
|
75
75
|
|
|
@@ -231,6 +231,7 @@ class Puppeteer extends Helper {
|
|
|
231
231
|
keepBrowserState: false,
|
|
232
232
|
show: false,
|
|
233
233
|
defaultPopupAction: 'accept',
|
|
234
|
+
highlightElement: false,
|
|
234
235
|
};
|
|
235
236
|
|
|
236
237
|
return Object.assign(defaults, config);
|
|
@@ -611,8 +612,8 @@ class Puppeteer extends Helper {
|
|
|
611
612
|
return this.switchTo(null)
|
|
612
613
|
.then(() => frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve()));
|
|
613
614
|
}
|
|
614
|
-
await this.switchTo(
|
|
615
|
-
this.withinLocator = new Locator(
|
|
615
|
+
await this.switchTo(frame);
|
|
616
|
+
this.withinLocator = new Locator(frame);
|
|
616
617
|
return;
|
|
617
618
|
}
|
|
618
619
|
|
|
@@ -857,8 +858,11 @@ class Puppeteer extends Helper {
|
|
|
857
858
|
const body = document.body;
|
|
858
859
|
const html = document.documentElement;
|
|
859
860
|
window.scrollTo(0, Math.max(
|
|
860
|
-
body.scrollHeight,
|
|
861
|
-
|
|
861
|
+
body.scrollHeight,
|
|
862
|
+
body.offsetHeight,
|
|
863
|
+
html.clientHeight,
|
|
864
|
+
html.scrollHeight,
|
|
865
|
+
html.offsetHeight,
|
|
862
866
|
));
|
|
863
867
|
});
|
|
864
868
|
}
|
|
@@ -1756,7 +1760,7 @@ class Puppeteer extends Helper {
|
|
|
1756
1760
|
await this._evaluateHandeInContext(el => el.innerHTML = '', el);
|
|
1757
1761
|
}
|
|
1758
1762
|
|
|
1759
|
-
highlightActiveElement.call(this, el, this.
|
|
1763
|
+
highlightActiveElement.call(this, el, await this._getContext());
|
|
1760
1764
|
await el.type(value.toString(), { delay: this.options.pressKeyDelay });
|
|
1761
1765
|
|
|
1762
1766
|
return this._waitForAction();
|
|
@@ -1797,7 +1801,7 @@ class Puppeteer extends Helper {
|
|
|
1797
1801
|
async appendField(field, value) {
|
|
1798
1802
|
const els = await findVisibleFields.call(this, field);
|
|
1799
1803
|
assertElementExists(els, field, 'Field');
|
|
1800
|
-
highlightActiveElement.call(this, els[0], this.
|
|
1804
|
+
highlightActiveElement.call(this, els[0], await this._getContext());
|
|
1801
1805
|
await els[0].press('End');
|
|
1802
1806
|
await els[0].type(value.toString(), { delay: this.options.pressKeyDelay });
|
|
1803
1807
|
return this._waitForAction();
|
|
@@ -1814,12 +1818,13 @@ class Puppeteer extends Helper {
|
|
|
1814
1818
|
* I.seeInField('#searchform input','Search');
|
|
1815
1819
|
* ```
|
|
1816
1820
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1817
|
-
* @param {
|
|
1821
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1818
1822
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1819
1823
|
*
|
|
1820
1824
|
*/
|
|
1821
1825
|
async seeInField(field, value) {
|
|
1822
|
-
|
|
1826
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1827
|
+
return proceedSeeInField.call(this, 'assert', field, _value);
|
|
1823
1828
|
}
|
|
1824
1829
|
|
|
1825
1830
|
/**
|
|
@@ -1832,12 +1837,13 @@ class Puppeteer extends Helper {
|
|
|
1832
1837
|
* ```
|
|
1833
1838
|
*
|
|
1834
1839
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1835
|
-
* @param {
|
|
1840
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1836
1841
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1837
1842
|
*
|
|
1838
1843
|
*/
|
|
1839
1844
|
async dontSeeInField(field, value) {
|
|
1840
|
-
|
|
1845
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1846
|
+
return proceedSeeInField.call(this, 'negate', field, _value);
|
|
1841
1847
|
}
|
|
1842
1848
|
|
|
1843
1849
|
/**
|
|
@@ -1900,7 +1906,7 @@ class Puppeteer extends Helper {
|
|
|
1900
1906
|
if (await el.getProperty('tagName').then(t => t.jsonValue()) !== 'SELECT') {
|
|
1901
1907
|
throw new Error('Element is not <select>');
|
|
1902
1908
|
}
|
|
1903
|
-
highlightActiveElement.call(this, els[0], this.
|
|
1909
|
+
highlightActiveElement.call(this, els[0], await this._getContext());
|
|
1904
1910
|
if (!Array.isArray(option)) option = [option];
|
|
1905
1911
|
|
|
1906
1912
|
for (const key in option) {
|
|
@@ -2308,6 +2314,8 @@ class Puppeteer extends Helper {
|
|
|
2308
2314
|
*
|
|
2309
2315
|
* @param {string|function} fn function to be executed in browser context.
|
|
2310
2316
|
* @param {...any} args to be passed to function.
|
|
2317
|
+
* @returns {Promise<any>} script return value
|
|
2318
|
+
*
|
|
2311
2319
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2312
2320
|
*
|
|
2313
2321
|
*
|
|
@@ -2345,6 +2353,8 @@ class Puppeteer extends Helper {
|
|
|
2345
2353
|
*
|
|
2346
2354
|
* @param {string|function} fn function to be executed in browser context.
|
|
2347
2355
|
* @param {...any} args to be passed to function.
|
|
2356
|
+
* @returns {Promise<any>} script return value
|
|
2357
|
+
*
|
|
2348
2358
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2349
2359
|
*
|
|
2350
2360
|
*
|
|
@@ -2936,7 +2946,7 @@ class Puppeteer extends Helper {
|
|
|
2936
2946
|
assertElementExists(els, locator);
|
|
2937
2947
|
|
|
2938
2948
|
return this.waitForFunction(isElementClickable, [els[0]], waitTimeout).catch(async (e) => {
|
|
2939
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
2949
|
+
if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
2940
2950
|
throw new Error(`element ${new Locator(locator).toString()} still not clickable after ${waitTimeout || this.options.waitForTimeout / 1000} sec`);
|
|
2941
2951
|
} else {
|
|
2942
2952
|
throw e;
|
|
@@ -3090,7 +3100,7 @@ class Puppeteer extends Helper {
|
|
|
3090
3100
|
return currUrl.indexOf(urlPart) > -1;
|
|
3091
3101
|
}, { timeout: waitTimeout }, urlPart).catch(async (e) => {
|
|
3092
3102
|
const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
|
|
3093
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
3103
|
+
if (/Waiting failed:/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
3094
3104
|
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
|
|
3095
3105
|
} else {
|
|
3096
3106
|
throw e;
|
|
@@ -3124,7 +3134,7 @@ class Puppeteer extends Helper {
|
|
|
3124
3134
|
return currUrl.indexOf(urlPart) > -1;
|
|
3125
3135
|
}, { timeout: waitTimeout }, urlPart).catch(async (e) => {
|
|
3126
3136
|
const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
|
|
3127
|
-
if (/failed: timeout/i.test(e.message)) {
|
|
3137
|
+
if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
|
|
3128
3138
|
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
|
|
3129
3139
|
} else {
|
|
3130
3140
|
throw e;
|
|
@@ -3421,6 +3431,10 @@ async function findElements(matcher, locator) {
|
|
|
3421
3431
|
if (locator.react) return findReact(matcher.executionContext(), locator);
|
|
3422
3432
|
locator = new Locator(locator, 'css');
|
|
3423
3433
|
if (!locator.isXPath()) return matcher.$$(locator.simplify());
|
|
3434
|
+
// puppeteer version < 19.4.0 is no longer supported. This one is backward support.
|
|
3435
|
+
if (puppeteer.default?.defaultBrowserRevision) {
|
|
3436
|
+
return matcher.$$(`xpath/${locator.value}`);
|
|
3437
|
+
}
|
|
3424
3438
|
return matcher.$x(locator.value);
|
|
3425
3439
|
}
|
|
3426
3440
|
|
|
@@ -3438,7 +3452,7 @@ async function proceedClick(locator, context = null, options = {}) {
|
|
|
3438
3452
|
assertElementExists(els, locator, 'Clickable element');
|
|
3439
3453
|
}
|
|
3440
3454
|
|
|
3441
|
-
highlightActiveElement.call(this, els[0], this.
|
|
3455
|
+
highlightActiveElement.call(this, els[0], await this._getContext());
|
|
3442
3456
|
|
|
3443
3457
|
await els[0].click(options);
|
|
3444
3458
|
const promises = [];
|
|
@@ -3498,7 +3512,7 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
3498
3512
|
if (strict) {
|
|
3499
3513
|
return allText.map(elText => equals(description)[assertType](text, elText));
|
|
3500
3514
|
}
|
|
3501
|
-
return stringIncludes(description)[assertType](text, allText.join(' | '));
|
|
3515
|
+
return stringIncludes(description)[assertType](normalizeSpacesInString(text), normalizeSpacesInString(allText.join(' | ')));
|
|
3502
3516
|
}
|
|
3503
3517
|
|
|
3504
3518
|
async function findCheckable(locator, context) {
|
|
@@ -3675,7 +3689,10 @@ async function elementSelected(element) {
|
|
|
3675
3689
|
|
|
3676
3690
|
function isFrameLocator(locator) {
|
|
3677
3691
|
locator = new Locator(locator);
|
|
3678
|
-
if (locator.isFrame())
|
|
3692
|
+
if (locator.isFrame()) {
|
|
3693
|
+
const _locator = new Locator(locator);
|
|
3694
|
+
return _locator.value;
|
|
3695
|
+
}
|
|
3679
3696
|
return false;
|
|
3680
3697
|
}
|
|
3681
3698
|
|
|
@@ -3793,7 +3810,7 @@ function getNormalizedKey(key) {
|
|
|
3793
3810
|
}
|
|
3794
3811
|
|
|
3795
3812
|
function highlightActiveElement(element, context) {
|
|
3796
|
-
if (!this.options.
|
|
3813
|
+
if (!this.options.highlightElement && !store.debugMode) return;
|
|
3797
3814
|
|
|
3798
3815
|
highlightElement(element, context);
|
|
3799
3816
|
}
|
package/docs/build/TestCafe.js
CHANGED
|
@@ -20,7 +20,7 @@ const { urlEquals } = require('../assert/equal');
|
|
|
20
20
|
const { empty } = require('../assert/empty');
|
|
21
21
|
const { truth } = require('../assert/truth');
|
|
22
22
|
const {
|
|
23
|
-
xpathLocator,
|
|
23
|
+
xpathLocator, normalizeSpacesInString,
|
|
24
24
|
} = require('../utils');
|
|
25
25
|
const Locator = require('../locator');
|
|
26
26
|
|
|
@@ -933,9 +933,9 @@ class TestCafe extends Helper {
|
|
|
933
933
|
async see(text, context = null) {
|
|
934
934
|
let els;
|
|
935
935
|
if (context) {
|
|
936
|
-
els = (await findElements.call(this, this.context, context)).withText(text);
|
|
936
|
+
els = (await findElements.call(this, this.context, context)).withText(normalizeSpacesInString(text));
|
|
937
937
|
} else {
|
|
938
|
-
els = (await findElements.call(this, this.context, '*')).withText(text);
|
|
938
|
+
els = (await findElements.call(this, this.context, '*')).withText(normalizeSpacesInString(text));
|
|
939
939
|
}
|
|
940
940
|
|
|
941
941
|
return this.t
|
|
@@ -1091,18 +1091,19 @@ class TestCafe extends Helper {
|
|
|
1091
1091
|
* I.seeInField('#searchform input','Search');
|
|
1092
1092
|
* ```
|
|
1093
1093
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1094
|
-
* @param {
|
|
1094
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1095
1095
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1096
1096
|
*
|
|
1097
1097
|
*/
|
|
1098
1098
|
async seeInField(field, value) {
|
|
1099
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1099
1100
|
// const expectedValue = findElements.call(this, this.context, field).value;
|
|
1100
1101
|
const els = await findFields.call(this, field);
|
|
1101
1102
|
assertElementExists(els, field, 'Field');
|
|
1102
1103
|
const el = await els.nth(0);
|
|
1103
1104
|
|
|
1104
1105
|
return this.t
|
|
1105
|
-
.expect(await el.value).eql(
|
|
1106
|
+
.expect(await el.value).eql(_value)
|
|
1106
1107
|
.catch(mapError);
|
|
1107
1108
|
}
|
|
1108
1109
|
|
|
@@ -1116,18 +1117,19 @@ class TestCafe extends Helper {
|
|
|
1116
1117
|
* ```
|
|
1117
1118
|
*
|
|
1118
1119
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1119
|
-
* @param {
|
|
1120
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1120
1121
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1121
1122
|
*
|
|
1122
1123
|
*/
|
|
1123
1124
|
async dontSeeInField(field, value) {
|
|
1125
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1124
1126
|
// const expectedValue = findElements.call(this, this.context, field).value;
|
|
1125
1127
|
const els = await findFields.call(this, field);
|
|
1126
1128
|
assertElementExists(els, field, 'Field');
|
|
1127
1129
|
const el = await els.nth(0);
|
|
1128
1130
|
|
|
1129
1131
|
return this.t
|
|
1130
|
-
.expect(el.value).notEql(
|
|
1132
|
+
.expect(el.value).notEql(_value)
|
|
1131
1133
|
.catch(mapError);
|
|
1132
1134
|
}
|
|
1133
1135
|
|
|
@@ -1268,6 +1270,8 @@ class TestCafe extends Helper {
|
|
|
1268
1270
|
*
|
|
1269
1271
|
* @param {string|function} fn function to be executed in browser context.
|
|
1270
1272
|
* @param {...any} args to be passed to function.
|
|
1273
|
+
* @returns {Promise<any>} script return value
|
|
1274
|
+
*
|
|
1271
1275
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1272
1276
|
*
|
|
1273
1277
|
*
|
|
@@ -1502,8 +1506,11 @@ class TestCafe extends Helper {
|
|
|
1502
1506
|
const body = document.body;
|
|
1503
1507
|
const html = document.documentElement;
|
|
1504
1508
|
window.scrollTo(0, Math.max(
|
|
1505
|
-
body.scrollHeight,
|
|
1506
|
-
|
|
1509
|
+
body.scrollHeight,
|
|
1510
|
+
body.offsetHeight,
|
|
1511
|
+
html.clientHeight,
|
|
1512
|
+
html.scrollHeight,
|
|
1513
|
+
html.offsetHeight,
|
|
1507
1514
|
));
|
|
1508
1515
|
}).with({ boundTestRun: this.t })().catch(mapError);
|
|
1509
1516
|
}
|
|
@@ -1926,7 +1933,9 @@ class TestCafe extends Helper {
|
|
|
1926
1933
|
}
|
|
1927
1934
|
|
|
1928
1935
|
async function waitForFunction(browserFn, waitTimeout) {
|
|
1929
|
-
const pause = () => new Promise((done =>
|
|
1936
|
+
const pause = () => new Promise((done => {
|
|
1937
|
+
setTimeout(done, 50);
|
|
1938
|
+
}));
|
|
1930
1939
|
|
|
1931
1940
|
const start = Date.now();
|
|
1932
1941
|
// eslint-disable-next-line no-constant-condition
|
package/docs/build/WebDriver.js
CHANGED
|
@@ -62,7 +62,7 @@ const webRoot = 'body';
|
|
|
62
62
|
* @prop {object} [desiredCapabilities] Selenium's [desired capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities).
|
|
63
63
|
* @prop {boolean} [manualStart=false] - do not start browser before a test, start it manually inside a helper with `this.helpers["WebDriver"]._startBrowser()`.
|
|
64
64
|
* @prop {object} [timeouts] [WebDriver timeouts](http://webdriver.io/docs/timeouts.html) defined as hash.
|
|
65
|
-
* @prop {boolean} [highlightElement] - highlight the interacting elements
|
|
65
|
+
* @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false
|
|
66
66
|
*/
|
|
67
67
|
const config = {};
|
|
68
68
|
|
|
@@ -429,6 +429,7 @@ class WebDriver extends Helper {
|
|
|
429
429
|
keepCookies: false,
|
|
430
430
|
keepBrowserState: false,
|
|
431
431
|
deprecationWarnings: false,
|
|
432
|
+
highlightElement: false,
|
|
432
433
|
};
|
|
433
434
|
|
|
434
435
|
// override defaults with config
|
|
@@ -1713,13 +1714,14 @@ class WebDriver extends Helper {
|
|
|
1713
1714
|
* I.seeInField('#searchform input','Search');
|
|
1714
1715
|
* ```
|
|
1715
1716
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1716
|
-
* @param {
|
|
1717
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1717
1718
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1718
1719
|
*
|
|
1719
1720
|
*
|
|
1720
1721
|
*/
|
|
1721
1722
|
async seeInField(field, value) {
|
|
1722
|
-
|
|
1723
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1724
|
+
return proceedSeeField.call(this, 'assert', field, _value);
|
|
1723
1725
|
}
|
|
1724
1726
|
|
|
1725
1727
|
/**
|
|
@@ -1732,13 +1734,14 @@ class WebDriver extends Helper {
|
|
|
1732
1734
|
* ```
|
|
1733
1735
|
*
|
|
1734
1736
|
* @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
|
|
1735
|
-
* @param {
|
|
1737
|
+
* @param {CodeceptJS.StringOrSecret} value value to check.
|
|
1736
1738
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
1737
1739
|
*
|
|
1738
1740
|
*
|
|
1739
1741
|
*/
|
|
1740
1742
|
async dontSeeInField(field, value) {
|
|
1741
|
-
|
|
1743
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1744
|
+
return proceedSeeField.call(this, 'negate', field, _value);
|
|
1742
1745
|
}
|
|
1743
1746
|
|
|
1744
1747
|
/**
|
|
@@ -2170,6 +2173,8 @@ class WebDriver extends Helper {
|
|
|
2170
2173
|
*
|
|
2171
2174
|
* @param {string|function} fn function to be executed in browser context.
|
|
2172
2175
|
* @param {...any} args to be passed to function.
|
|
2176
|
+
* @returns {Promise<any>} script return value
|
|
2177
|
+
*
|
|
2173
2178
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2174
2179
|
*
|
|
2175
2180
|
*
|
|
@@ -2204,6 +2209,8 @@ class WebDriver extends Helper {
|
|
|
2204
2209
|
*
|
|
2205
2210
|
* @param {string|function} fn function to be executed in browser context.
|
|
2206
2211
|
* @param {...any} args to be passed to function.
|
|
2212
|
+
* @returns {Promise<any>} script return value
|
|
2213
|
+
*
|
|
2207
2214
|
* ⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
2208
2215
|
*
|
|
2209
2216
|
*
|
|
@@ -2970,7 +2977,9 @@ class WebDriver extends Helper {
|
|
|
2970
2977
|
*
|
|
2971
2978
|
*/
|
|
2972
2979
|
async wait(sec) {
|
|
2973
|
-
return new Promise(resolve =>
|
|
2980
|
+
return new Promise(resolve => {
|
|
2981
|
+
setTimeout(resolve, sec * 1000);
|
|
2982
|
+
});
|
|
2974
2983
|
}
|
|
2975
2984
|
|
|
2976
2985
|
/**
|
|
@@ -3135,20 +3144,18 @@ class WebDriver extends Helper {
|
|
|
3135
3144
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
3136
3145
|
const _context = context || this.root;
|
|
3137
3146
|
|
|
3138
|
-
return this.browser.waitUntil(
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
},
|
|
3151
|
-
);
|
|
3147
|
+
return this.browser.waitUntil(async () => {
|
|
3148
|
+
const res = await this.$$(withStrictLocator.call(this, _context));
|
|
3149
|
+
if (!res || res.length === 0) return false;
|
|
3150
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
|
|
3151
|
+
if (Array.isArray(selected)) {
|
|
3152
|
+
return selected.filter(part => part.indexOf(text) >= 0).length > 0;
|
|
3153
|
+
}
|
|
3154
|
+
return selected.indexOf(text) >= 0;
|
|
3155
|
+
}, {
|
|
3156
|
+
timeout: aSec * 1000,
|
|
3157
|
+
timeoutMsg: `element (${_context}) is not in DOM or there is no element(${_context}) with text "${text}" after ${aSec} sec`,
|
|
3158
|
+
});
|
|
3152
3159
|
}
|
|
3153
3160
|
|
|
3154
3161
|
/**
|
|
@@ -3168,20 +3175,18 @@ class WebDriver extends Helper {
|
|
|
3168
3175
|
const client = this.browser;
|
|
3169
3176
|
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
3170
3177
|
|
|
3171
|
-
return client.waitUntil(
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
},
|
|
3184
|
-
);
|
|
3178
|
+
return client.waitUntil(async () => {
|
|
3179
|
+
const res = await findFields.call(this, field);
|
|
3180
|
+
if (!res || res.length === 0) return false;
|
|
3181
|
+
const selected = await forEachAsync(res, async el => el.getValue());
|
|
3182
|
+
if (Array.isArray(selected)) {
|
|
3183
|
+
return selected.filter(part => part.indexOf(value) >= 0).length > 0;
|
|
3184
|
+
}
|
|
3185
|
+
return selected.indexOf(value) >= 0;
|
|
3186
|
+
}, {
|
|
3187
|
+
timeout: aSec * 1000,
|
|
3188
|
+
timeoutMsg: `element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`,
|
|
3189
|
+
});
|
|
3185
3190
|
}
|
|
3186
3191
|
|
|
3187
3192
|
/**
|
|
@@ -3525,8 +3530,11 @@ class WebDriver extends Helper {
|
|
|
3525
3530
|
const body = document.body;
|
|
3526
3531
|
const html = document.documentElement;
|
|
3527
3532
|
window.scrollTo(0, Math.max(
|
|
3528
|
-
body.scrollHeight,
|
|
3529
|
-
|
|
3533
|
+
body.scrollHeight,
|
|
3534
|
+
body.offsetHeight,
|
|
3535
|
+
html.clientHeight,
|
|
3536
|
+
html.scrollHeight,
|
|
3537
|
+
html.offsetHeight
|
|
3530
3538
|
));
|
|
3531
3539
|
});
|
|
3532
3540
|
/* eslint-enable */
|
|
@@ -4075,7 +4083,7 @@ function isModifierKey(key) {
|
|
|
4075
4083
|
}
|
|
4076
4084
|
|
|
4077
4085
|
function highlightActiveElement(element) {
|
|
4078
|
-
if (!this.options.
|
|
4086
|
+
if (!this.options.highlightElement && !store.debugMode) return;
|
|
4079
4087
|
|
|
4080
4088
|
highlightElement(element, this.browser);
|
|
4081
4089
|
}
|