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.
Files changed (68) hide show
  1. package/CHANGELOG.md +368 -0
  2. package/README.md +0 -2
  3. package/docs/build/Appium.js +48 -7
  4. package/docs/build/GraphQL.js +25 -0
  5. package/docs/build/Nightmare.js +15 -6
  6. package/docs/build/Playwright.js +436 -197
  7. package/docs/build/Protractor.js +17 -8
  8. package/docs/build/Puppeteer.js +37 -20
  9. package/docs/build/TestCafe.js +19 -10
  10. package/docs/build/WebDriver.js +45 -37
  11. package/docs/changelog.md +375 -0
  12. package/docs/community-helpers.md +8 -4
  13. package/docs/examples.md +8 -2
  14. package/docs/helpers/Appium.md +39 -2
  15. package/docs/helpers/GraphQL.md +21 -0
  16. package/docs/helpers/Nightmare.md +1260 -0
  17. package/docs/helpers/Playwright.md +223 -119
  18. package/docs/helpers/Protractor.md +1711 -0
  19. package/docs/helpers/Puppeteer.md +31 -29
  20. package/docs/helpers/TestCafe.md +18 -17
  21. package/docs/helpers/WebDriver.md +34 -32
  22. package/docs/playwright.md +24 -1
  23. package/docs/webapi/dontSeeInField.mustache +1 -1
  24. package/docs/webapi/executeAsyncScript.mustache +2 -0
  25. package/docs/webapi/executeScript.mustache +2 -0
  26. package/docs/webapi/seeInField.mustache +1 -1
  27. package/docs/wiki/Books-&-Posts.md +0 -0
  28. package/docs/wiki/Community-Helpers-&-Plugins.md +8 -4
  29. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +46 -14
  30. package/docs/wiki/Examples.md +8 -2
  31. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -0
  32. package/docs/wiki/Home.md +0 -0
  33. package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +83 -0
  34. package/docs/wiki/Release-Process.md +0 -0
  35. package/docs/wiki/Roadmap.md +0 -0
  36. package/docs/wiki/Tests.md +0 -0
  37. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -0
  38. package/docs/wiki/Videos.md +0 -0
  39. package/lib/codecept.js +1 -0
  40. package/lib/command/definitions.js +2 -7
  41. package/lib/command/init.js +40 -4
  42. package/lib/command/run-multiple/collection.js +17 -5
  43. package/lib/command/run-workers.js +4 -0
  44. package/lib/command/run.js +6 -0
  45. package/lib/helper/Appium.js +46 -5
  46. package/lib/helper/GraphQL.js +25 -0
  47. package/lib/helper/Nightmare.js +1415 -0
  48. package/lib/helper/Playwright.js +336 -62
  49. package/lib/helper/Protractor.js +1837 -0
  50. package/lib/helper/Puppeteer.js +31 -18
  51. package/lib/helper/TestCafe.js +15 -8
  52. package/lib/helper/WebDriver.js +39 -35
  53. package/lib/helper/clientscripts/nightmare.js +213 -0
  54. package/lib/helper/errors/ElementNotFound.js +2 -1
  55. package/lib/helper/scripts/highlightElement.js +1 -1
  56. package/lib/interfaces/bdd.js +1 -1
  57. package/lib/mochaFactory.js +2 -1
  58. package/lib/pause.js +6 -4
  59. package/lib/plugin/heal.js +2 -3
  60. package/lib/plugin/selenoid.js +6 -1
  61. package/lib/step.js +27 -10
  62. package/lib/utils.js +4 -0
  63. package/lib/workers.js +3 -1
  64. package/package.json +87 -87
  65. package/typings/promiseBasedTypes.d.ts +163 -126
  66. package/typings/types.d.ts +183 -144
  67. package/docs/build/Polly.js +0 -42
  68. package/docs/build/SeleniumWebdriver.js +0 -76
@@ -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 {string} value value to check.
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
- return proceedSeeInField.call(this, 'assert', field, value);
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 {string} value value to check.
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
- return proceedSeeInField.call(this, 'negate', field, value);
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, body.offsetHeight,
2462
- html.clientHeight, html.scrollHeight, html.offsetHeight
2467
+ body.scrollHeight,
2468
+ body.offsetHeight,
2469
+ html.clientHeight,
2470
+ html.scrollHeight,
2471
+ html.offsetHeight
2463
2472
  ));
2464
2473
  });
2465
2474
  /* eslint-enable */
@@ -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(locator);
615
- this.withinLocator = new Locator(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, body.offsetHeight,
861
- html.clientHeight, html.scrollHeight, html.offsetHeight,
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.page);
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.page);
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 {string} value value to check.
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
- return proceedSeeInField.call(this, 'assert', field, value);
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 {string} value value to check.
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
- return proceedSeeInField.call(this, 'negate', field, value);
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.page);
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.page);
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()) return locator.value;
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.enableHighlight && !store.debugMode) return;
3813
+ if (!this.options.highlightElement && !store.debugMode) return;
3797
3814
 
3798
3815
  highlightElement(element, context);
3799
3816
  }
@@ -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 {string} value value to check.
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(value)
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 {string} value value to check.
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(value)
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, body.offsetHeight,
1506
- html.clientHeight, html.scrollHeight, html.offsetHeight,
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 => setTimeout(done, 50)));
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
@@ -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 {string} value value to check.
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
- return proceedSeeField.call(this, 'assert', field, value);
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 {string} value value to check.
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
- return proceedSeeField.call(this, 'negate', field, value);
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 => setTimeout(resolve, sec * 1000));
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
- async () => {
3140
- const res = await this.$$(withStrictLocator.call(this, _context));
3141
- if (!res || res.length === 0) return false;
3142
- const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
3143
- if (Array.isArray(selected)) {
3144
- return selected.filter(part => part.indexOf(text) >= 0).length > 0;
3145
- }
3146
- return selected.indexOf(text) >= 0;
3147
- }, {
3148
- timeout: aSec * 1000,
3149
- timeoutMsg: `element (${_context}) is not in DOM or there is no element(${_context}) with text "${text}" after ${aSec} sec`,
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
- async () => {
3173
- const res = await findFields.call(this, field);
3174
- if (!res || res.length === 0) return false;
3175
- const selected = await forEachAsync(res, async el => el.getValue());
3176
- if (Array.isArray(selected)) {
3177
- return selected.filter(part => part.indexOf(value) >= 0).length > 0;
3178
- }
3179
- return selected.indexOf(value) >= 0;
3180
- }, {
3181
- timeout: aSec * 1000,
3182
- timeoutMsg: `element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`,
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, body.offsetHeight,
3529
- html.clientHeight, html.scrollHeight, html.offsetHeight
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.enableHighlight && !store.debugMode) return;
4086
+ if (!this.options.highlightElement && !store.debugMode) return;
4079
4087
 
4080
4088
  highlightElement(element, this.browser);
4081
4089
  }