codeceptjs 2.3.4 → 2.4.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.
Files changed (269) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +28 -6
  3. package/bin/codecept.js +42 -0
  4. package/docs/advanced.md +45 -1
  5. package/docs/angular.md +3 -3
  6. package/docs/basics.md +162 -118
  7. package/docs/bdd.md +30 -5
  8. package/docs/best.md +8 -6
  9. package/docs/books.md +6 -1
  10. package/docs/build/Appium.js +95 -85
  11. package/docs/build/FileSystem.js +48 -3
  12. package/docs/build/GraphQL.js +3 -2
  13. package/docs/build/GraphQLDataFactory.js +1 -0
  14. package/docs/build/Mochawesome.js +3 -2
  15. package/docs/build/MockRequest.js +23 -5
  16. package/docs/build/Nightmare.js +87 -128
  17. package/docs/build/Protractor.js +107 -155
  18. package/docs/build/Puppeteer.js +190 -174
  19. package/docs/build/REST.js +13 -9
  20. package/docs/build/SeleniumWebdriver.js +0 -17
  21. package/docs/build/TestCafe.js +164 -158
  22. package/docs/build/WebDriver.js +236 -211
  23. package/docs/build/WebDriverIO.js +218 -187
  24. package/docs/changelog.md +57 -1
  25. package/docs/commands.md +41 -2
  26. package/docs/community-helpers.md +12 -1
  27. package/docs/configuration.md +5 -2
  28. package/docs/continuous-integration.md +22 -0
  29. package/docs/{helpers.md → custom-helpers.md} +16 -10
  30. package/docs/data.md +7 -6
  31. package/docs/detox.md +6 -6
  32. package/docs/email.md +4 -2
  33. package/docs/examples.md +22 -3
  34. package/docs/helpers/ApiDataFactory.md +15 -13
  35. package/docs/helpers/Appium.md +1011 -468
  36. package/docs/helpers/Detox.md +33 -26
  37. package/docs/helpers/FileSystem.md +43 -13
  38. package/docs/helpers/GraphQL.md +17 -15
  39. package/docs/helpers/GraphQLDataFactory.md +15 -13
  40. package/docs/helpers/Mochawesome.md +3 -1
  41. package/docs/helpers/MockRequest.md +37 -19
  42. package/docs/helpers/Nightmare.md +129 -240
  43. package/docs/helpers/Polly.md +1 -1
  44. package/docs/helpers/Protractor.md +157 -298
  45. package/docs/helpers/Puppeteer.md +216 -335
  46. package/docs/helpers/REST.md +29 -24
  47. package/docs/helpers/TestCafe.md +137 -235
  48. package/docs/helpers/WebDriver.md +250 -347
  49. package/docs/hooks.md +14 -10
  50. package/docs/index.md +112 -0
  51. package/docs/installation.md +3 -1
  52. package/docs/locators.md +19 -8
  53. package/docs/mobile-react-native-locators.md +2 -2
  54. package/docs/mobile.md +5 -3
  55. package/docs/nightmare.md +2 -1
  56. package/docs/pageobjects.md +4 -2
  57. package/docs/parallel.md +4 -2
  58. package/docs/plugins.md +41 -15
  59. package/docs/puppeteer.md +8 -6
  60. package/docs/quickstart.md +130 -0
  61. package/docs/react.md +4 -2
  62. package/docs/reports.md +6 -4
  63. package/docs/testcafe.md +10 -8
  64. package/docs/translation.md +4 -2
  65. package/docs/ui.md +56 -0
  66. package/docs/videos.md +11 -2
  67. package/docs/visual.md +7 -5
  68. package/docs/vue.md +121 -0
  69. package/docs/webapi/appendField.mustache +1 -1
  70. package/docs/webapi/attachFile.mustache +1 -1
  71. package/docs/webapi/checkOption.mustache +2 -2
  72. package/docs/webapi/clearCookie.mustache +1 -1
  73. package/docs/webapi/click.mustache +2 -2
  74. package/docs/webapi/clickLink.mustache +2 -2
  75. package/docs/webapi/dontSee.mustache +1 -2
  76. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
  77. package/docs/webapi/dontSeeElement.mustache +1 -1
  78. package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
  79. package/docs/webapi/dontSeeInField.mustache +1 -1
  80. package/docs/webapi/doubleClick.mustache +2 -2
  81. package/docs/webapi/downloadFile.mustache +1 -1
  82. package/docs/webapi/dragSlider.mustache +1 -1
  83. package/docs/webapi/executeAsyncScript.mustache +2 -1
  84. package/docs/webapi/executeScript.mustache +2 -1
  85. package/docs/webapi/fillField.mustache +1 -1
  86. package/docs/webapi/grabAttributeFrom.mustache +1 -1
  87. package/docs/webapi/grabBrowserLogs.mustache +1 -1
  88. package/docs/webapi/grabCookie.mustache +2 -2
  89. package/docs/webapi/grabCssPropertyFrom.mustache +1 -1
  90. package/docs/webapi/grabHTMLFrom.mustache +1 -1
  91. package/docs/webapi/grabNumberOfVisibleElements.mustache +1 -1
  92. package/docs/webapi/grabPageScrollPosition.mustache +1 -1
  93. package/docs/webapi/grabTextFrom.mustache +2 -2
  94. package/docs/webapi/grabValueFrom.mustache +1 -1
  95. package/docs/webapi/moveCursorTo.mustache +3 -3
  96. package/docs/webapi/pressKey.mustache +1 -1
  97. package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
  98. package/docs/webapi/rightClick.mustache +2 -2
  99. package/docs/webapi/saveScreenshot.mustache +1 -1
  100. package/docs/webapi/scrollIntoView.mustache +10 -0
  101. package/docs/webapi/scrollTo.mustache +3 -3
  102. package/docs/webapi/see.mustache +1 -1
  103. package/docs/webapi/seeAttributesOnElements.mustache +1 -1
  104. package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
  105. package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
  106. package/docs/webapi/seeElement.mustache +1 -1
  107. package/docs/webapi/seeElementInDOM.mustache +1 -1
  108. package/docs/webapi/seeInField.mustache +1 -1
  109. package/docs/webapi/seeNumberOfElements.mustache +1 -1
  110. package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
  111. package/docs/webapi/seeTextEquals.mustache +8 -0
  112. package/docs/webapi/selectOption.mustache +2 -2
  113. package/docs/webapi/switchTo.mustache +1 -1
  114. package/docs/webapi/uncheckOption.mustache +2 -2
  115. package/docs/webapi/waitForClickable.mustache +10 -0
  116. package/docs/webapi/waitForDetached.mustache +2 -2
  117. package/docs/webapi/waitForElement.mustache +2 -2
  118. package/docs/webapi/waitForEnabled.mustache +2 -2
  119. package/docs/webapi/waitForFunction.mustache +2 -2
  120. package/docs/webapi/waitForInvisible.mustache +2 -2
  121. package/docs/webapi/waitForText.mustache +2 -2
  122. package/docs/webapi/waitForValue.mustache +1 -1
  123. package/docs/webapi/waitForVisible.mustache +2 -2
  124. package/docs/webapi/waitInUrl.mustache +1 -1
  125. package/docs/webapi/waitNumberOfVisibleElements.mustache +2 -2
  126. package/docs/webapi/waitToHide.mustache +2 -2
  127. package/docs/webapi/waitUntil.mustache +3 -2
  128. package/docs/webapi/waitUrlEquals.mustache +1 -1
  129. package/docs/webdriver.md +20 -18
  130. package/docs/wiki/.git/FETCH_HEAD +1 -0
  131. package/docs/wiki/.git/HEAD +1 -0
  132. package/docs/wiki/.git/ORIG_HEAD +1 -0
  133. package/docs/wiki/.git/config +11 -0
  134. package/docs/wiki/.git/description +1 -0
  135. package/docs/wiki/.git/hooks/applypatch-msg.sample +15 -0
  136. package/docs/wiki/.git/hooks/commit-msg.sample +24 -0
  137. package/docs/wiki/.git/hooks/fsmonitor-watchman.sample +114 -0
  138. package/docs/wiki/.git/hooks/post-update.sample +8 -0
  139. package/docs/wiki/.git/hooks/pre-applypatch.sample +14 -0
  140. package/docs/wiki/.git/hooks/pre-commit.sample +49 -0
  141. package/docs/wiki/.git/hooks/pre-push.sample +53 -0
  142. package/docs/wiki/.git/hooks/pre-rebase.sample +169 -0
  143. package/docs/wiki/.git/hooks/pre-receive.sample +24 -0
  144. package/docs/wiki/.git/hooks/prepare-commit-msg.sample +42 -0
  145. package/docs/wiki/.git/hooks/update.sample +128 -0
  146. package/docs/wiki/.git/index +0 -0
  147. package/docs/wiki/.git/info/exclude +6 -0
  148. package/docs/wiki/.git/logs/HEAD +4 -0
  149. package/docs/wiki/.git/logs/refs/heads/master +4 -0
  150. package/docs/wiki/.git/logs/refs/remotes/origin/HEAD +1 -0
  151. package/docs/wiki/.git/logs/refs/remotes/origin/master +3 -0
  152. package/docs/wiki/.git/objects/00/d216b0774d15db2d0a2a0d4ce249b5251acc55 +3 -0
  153. package/docs/wiki/.git/objects/09/01d87c5241905fdfe3493cfe8f04df4a2685ea +0 -0
  154. package/docs/wiki/.git/objects/0d/bdd0c20c4deb6a8cc81dbbf32ecf8c09238983 +2 -0
  155. package/docs/wiki/.git/objects/1a/c29e4fa82422c52392f22f0f2b8d1a759535bf +0 -0
  156. package/docs/wiki/.git/objects/27/12f92898d3e8f68e229b6cda76570d6c66d781 +0 -0
  157. package/docs/wiki/.git/objects/2d/dbe22c257166b648928eeb9460ecfb71ba702d +0 -0
  158. package/docs/wiki/.git/objects/2f/c942ec3773efd2678d9ff98035c61fcded81a1 +0 -0
  159. package/docs/wiki/.git/objects/40/a2856342c67796b48911a256b764fb06888b94 +5 -0
  160. package/docs/wiki/.git/objects/47/53181844fc4dc563cf3aa5e80462243cb58d38 +0 -0
  161. package/docs/wiki/.git/objects/4e/24a95fb2e4f8ffef51f19b694451a205c06f10 +3 -0
  162. package/docs/wiki/.git/objects/73/31ebd96f3c7e08a9f63f05a25f939afa0d4de1 +0 -0
  163. package/docs/wiki/.git/objects/86/19cbb2289caa502e33fccf0ed14eecf6ba2ba0 +0 -0
  164. package/docs/wiki/.git/objects/a4/72f797d9d74b87c9f71a2b1539d75bb07d1e35 +0 -0
  165. package/docs/wiki/.git/objects/c9/9f3e4bd227d6b050b2e416f9876df49583dbf6 +0 -0
  166. package/docs/wiki/.git/objects/ca/e609b4ef3e0ef85fcbe0d68d1a58246584b915 +0 -0
  167. package/docs/wiki/.git/objects/d5/8386ca72f6d550548f3d71d74e3ac73d5ad488 +0 -0
  168. package/docs/wiki/.git/objects/d9/c6874a6de524bdafeb563a20d847f4fdd59a86 +0 -0
  169. package/docs/wiki/.git/objects/f1/c944675bb38b40ae553b0be36c14674c79af54 +0 -0
  170. package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.idx +0 -0
  171. package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.pack +0 -0
  172. package/docs/wiki/.git/packed-refs +2 -0
  173. package/docs/wiki/.git/refs/heads/master +1 -0
  174. package/docs/wiki/.git/refs/remotes/origin/HEAD +1 -0
  175. package/docs/wiki/.git/refs/remotes/origin/master +1 -0
  176. package/docs/wiki/Books-&-Posts.md +27 -0
  177. package/docs/wiki/Community-Helpers.md +41 -0
  178. package/docs/wiki/Examples.md +138 -0
  179. package/docs/wiki/Home.md +11 -0
  180. package/docs/wiki/Release-process.md +25 -0
  181. package/docs/wiki/Roadmap.md +23 -0
  182. package/docs/wiki/Videos.md +19 -0
  183. package/lib/actor.js +18 -1
  184. package/lib/assert/error.js +3 -3
  185. package/lib/codecept.js +9 -6
  186. package/lib/command/configMigrate.js +7 -6
  187. package/lib/command/definitions.js +98 -350
  188. package/lib/command/generate.js +22 -17
  189. package/lib/command/gherkin/init.js +2 -1
  190. package/lib/command/gherkin/snippets.js +6 -6
  191. package/lib/command/gherkin/steps.js +0 -1
  192. package/lib/command/info.js +40 -0
  193. package/lib/command/init.js +54 -41
  194. package/lib/command/run-multiple.js +5 -4
  195. package/lib/command/run-rerun.js +39 -0
  196. package/lib/command/run-workers.js +4 -6
  197. package/lib/command/run.js +8 -18
  198. package/lib/command/utils.js +23 -2
  199. package/lib/command/workers/runTests.js +1 -2
  200. package/lib/config.js +10 -4
  201. package/lib/container.js +31 -6
  202. package/lib/data/dataTableArgument.js +31 -0
  203. package/lib/data/table.js +4 -0
  204. package/lib/event.js +65 -1
  205. package/lib/helper/Appium.js +52 -38
  206. package/lib/helper/FileSystem.js +48 -3
  207. package/lib/helper/GraphQL.js +3 -2
  208. package/lib/helper/GraphQLDataFactory.js +1 -0
  209. package/lib/helper/Mochawesome.js +3 -2
  210. package/lib/helper/MockRequest.js +23 -5
  211. package/lib/helper/Nightmare.js +5 -6
  212. package/lib/helper/Protractor.js +7 -8
  213. package/lib/helper/Puppeteer.js +76 -20
  214. package/lib/helper/REST.js +13 -9
  215. package/lib/helper/SeleniumWebdriver.js +0 -17
  216. package/lib/helper/TestCafe.js +84 -36
  217. package/lib/helper/WebDriver.js +113 -59
  218. package/lib/helper/WebDriverIO.js +43 -59
  219. package/lib/helper/clientscripts/nightmare.js +66 -4
  220. package/lib/helper/scripts/isElementClickable.js +24 -0
  221. package/lib/helper.js +34 -10
  222. package/lib/history.js +1 -1
  223. package/lib/hooks.js +2 -1
  224. package/lib/index.js +19 -0
  225. package/lib/interfaces/bdd.js +4 -0
  226. package/lib/interfaces/featureConfig.js +10 -3
  227. package/lib/interfaces/gherkin.js +6 -2
  228. package/lib/interfaces/scenarioConfig.js +17 -6
  229. package/lib/listener/config.js +1 -1
  230. package/lib/listener/exit.js +6 -0
  231. package/lib/listener/steps.js +0 -1
  232. package/lib/listener/trace.js +0 -1
  233. package/lib/locator.js +67 -2
  234. package/lib/output.js +53 -0
  235. package/lib/parser.js +2 -71
  236. package/lib/pause.js +3 -2
  237. package/lib/plugin/allure.js +41 -22
  238. package/lib/plugin/autoLogin.js +4 -1
  239. package/lib/plugin/pauseOnFail.js +38 -0
  240. package/lib/plugin/puppeteerCoverage.js +8 -7
  241. package/lib/plugin/screenshotOnFail.js +13 -8
  242. package/lib/plugin/stepByStepReport.js +7 -6
  243. package/lib/plugin/wdio.js +2 -1
  244. package/lib/recorder.js +85 -7
  245. package/lib/rerun.js +81 -0
  246. package/lib/secret.js +6 -0
  247. package/lib/session.js +9 -2
  248. package/lib/step.js +37 -2
  249. package/lib/store.js +5 -1
  250. package/lib/ui.js +34 -8
  251. package/lib/utils.js +6 -13
  252. package/lib/within.js +5 -0
  253. package/package.json +49 -29
  254. package/typings/Mocha.d.ts +21 -0
  255. package/typings/Protractor.d.ts +16 -0
  256. package/typings/index.d.ts +169 -0
  257. package/typings/jsdoc.conf.js +34 -0
  258. package/typings/jsdoc.namespace.js +29 -0
  259. package/typings/types.d.ts +9827 -0
  260. package/typings/utils.d.ts +7 -0
  261. package/docs/acceptance.md +0 -409
  262. package/docs/api/codecept.md +0 -75
  263. package/docs/api/config.md +0 -49
  264. package/docs/api/container.md +0 -66
  265. package/docs/api/helper.md +0 -116
  266. package/docs/api/output.md +0 -67
  267. package/docs/api/recorder.md +0 -63
  268. package/docs/helpers/SeleniumWebdriver.md +0 -92
  269. package/docs/helpers/WebDriverIO.md +0 -1671
@@ -1,7 +1,9 @@
1
1
  let webdriverio;
2
+
2
3
  const assert = require('assert');
3
4
  const path = require('path');
4
5
  const requireg = require('requireg');
6
+
5
7
  const Helper = require('../helper');
6
8
  const stringIncludes = require('../assert/include').includes;
7
9
  const { urlEquals, equals } = require('../assert/equal');
@@ -39,6 +41,7 @@ const webRoot = 'body';
39
41
  * This helper should be configured in codecept.json or codecept.conf.js
40
42
  *
41
43
  * * `url`: base url of website to be tested.
44
+ * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'}
42
45
  * * `browser`: browser in which to perform testing.
43
46
  * * `host`: (optional, default: localhost) - WebDriver host to connect.
44
47
  * * `port`: (optional, default: 4444) - WebDriver port to connect.
@@ -78,6 +81,25 @@ const webRoot = 'body';
78
81
  * }
79
82
  * ```
80
83
  *
84
+ * Example with basic authentication
85
+ * ```js
86
+ * {
87
+ * helpers: {
88
+ * WebDriver : {
89
+ * smartWait: 5000,
90
+ * browser: "chrome",
91
+ * basicAuth: {username: 'username', password: 'password'},
92
+ * restart: false,
93
+ * windowSize: "maximize",
94
+ * timeouts: {
95
+ * "script": 60000,
96
+ * "page load": 10000
97
+ * }
98
+ * }
99
+ * }
100
+ * }
101
+ * ```
102
+ *
81
103
  * Additional configuration params can be used from [webdriverio
82
104
  * website](http://webdriver.io/guide/getstarted/configuration.html).
83
105
  *
@@ -91,7 +113,7 @@ const webRoot = 'body';
91
113
  * browser: "chrome",
92
114
  * desiredCapabilities: {
93
115
  * chromeOptions: {
94
- * args: [ "--headless", "--disable-gpu", "--window-size=800,600" ]
116
+ * args: [ "--headless", "--disable-gpu", "--no-sandbox" ]
95
117
  * }
96
118
  * }
97
119
  * }
@@ -613,7 +635,7 @@ class WebDriver extends Helper {
613
635
  * ```
614
636
  *
615
637
  *
616
- * @param locator element located by CSS|XPath|strict locator.
638
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
617
639
  */
618
640
  async _locate(locator, smartWait = false) {
619
641
  if (require('../store').debugMode) smartWait = false;
@@ -644,7 +666,7 @@ class WebDriver extends Helper {
644
666
  * this.helpers['WebDriver']._locateCheckable('I agree with terms and conditions').then // ...
645
667
  * ```
646
668
  *
647
- * @param locator element located by CSS|XPath|strict locator.
669
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
648
670
  */
649
671
  async _locateCheckable(locator) {
650
672
  return findCheckable.call(this, locator, this.$$.bind(this)).then(res => res);
@@ -657,7 +679,7 @@ class WebDriver extends Helper {
657
679
  * this.helpers['WebDriver']._locateClickable('Next page').then // ...
658
680
  * ```
659
681
  *
660
- * @param locator element located by CSS|XPath|strict locator.
682
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
661
683
  */
662
684
  async _locateClickable(locator) {
663
685
  return findClickable.call(this, locator, this.$$.bind(this)).then(res => res);
@@ -670,7 +692,7 @@ class WebDriver extends Helper {
670
692
  * this.helpers['WebDriver']._locateFields('Your email').then // ...
671
693
  * ```
672
694
  *
673
- * @param locator element located by CSS|XPath|strict locator.
695
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
674
696
  */
675
697
  async _locateFields(locator) {
676
698
  return findFields.call(this, locator).then(res => res);
@@ -686,7 +708,7 @@ class WebDriver extends Helper {
686
708
  * I.defineTimeout({ implicit: 10000, pageLoad: 10000, script: 5000 });
687
709
  * ```
688
710
  *
689
- * @param timeouts WebDriver timeouts object.
711
+ * @param {WebdriverIO.Timeouts} timeouts WebDriver timeouts object.
690
712
  */
691
713
  defineTimeout(timeouts) {
692
714
  return this._defineBrowserTimeout(this.browser, timeouts);
@@ -707,10 +729,17 @@ class WebDriver extends Helper {
707
729
  * ```
708
730
  *
709
731
  * @param {string} url url path or global url.
710
- * {--end--}
711
732
  *
712
733
  */
713
734
  amOnPage(url) {
735
+ let split_url;
736
+ if (this.config.basicAuth) {
737
+ if (url.startsWith('/')) {
738
+ url = this.config.url + url;
739
+ }
740
+ split_url = url.split('//');
741
+ url = `${split_url[0]}//${this.config.basicAuth.username}:${this.config.basicAuth.password}@${split_url[1]}`;
742
+ }
714
743
  return this.browser.url(url);
715
744
  }
716
745
 
@@ -737,9 +766,9 @@ class WebDriver extends Helper {
737
766
  * I.click({css: 'nav a.login'});
738
767
  * ```
739
768
  *
740
- * @param {string|object} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
741
- * @param {string|object} context (optional, `null` by default) element to search in CSS|XPath|Strict locator.
742
- * {--end--}
769
+ * @param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
770
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
771
+ *
743
772
  *
744
773
  * {{ react }}
745
774
  */
@@ -768,9 +797,9 @@ class WebDriver extends Helper {
768
797
  * I.doubleClick('.btn.edit');
769
798
  * ```
770
799
  *
771
- * @param {string|object} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
772
- * @param {string|object} context (optional, `null` by default) element to search in CSS|XPath|Strict locator.
773
- * {--end--}
800
+ * @param {CodeceptJS.LocatorOrString} locator clickable link or button located by text, or any element located by CSS|XPath|strict locator.
801
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element to search in CSS|XPath|Strict locator.
802
+ *
774
803
  *
775
804
  * {{ react }}
776
805
  */
@@ -800,9 +829,9 @@ class WebDriver extends Helper {
800
829
  * I.rightClick('Click me', '.context');
801
830
  * ```
802
831
  *
803
- * @param {string|object} locator clickable element located by CSS|XPath|strict locator.
804
- * @param {string|object} context (optional, `null` by default) element located by CSS|XPath|strict locator.
805
- * {--end--}
832
+ * @param {CodeceptJS.LocatorOrString} locator clickable element located by CSS|XPath|strict locator.
833
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
834
+ *
806
835
  *
807
836
  * {{ react }}
808
837
  */
@@ -844,9 +873,9 @@ class WebDriver extends Helper {
844
873
  * // or by strict locator
845
874
  * I.fillField({css: 'form#login input[name=username]'}, 'John');
846
875
  * ```
847
- * @param {string|object} field located by label|name|CSS|XPath|strict locator.
876
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
848
877
  * @param {string} value text value to fill.
849
- * {--end--}
878
+ *
850
879
  * {{ react }}
851
880
  *
852
881
  */
@@ -864,9 +893,8 @@ class WebDriver extends Helper {
864
893
  * ```js
865
894
  * I.appendField('#myTextField', 'appended');
866
895
  * ```
867
- * @param {string|object} field located by label|name|CSS|XPath|strict locator
896
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator
868
897
  * @param {string} value text value to append.
869
- * {--end--}
870
898
  * {{ react }}
871
899
  */
872
900
  async appendField(field, value) {
@@ -886,7 +914,6 @@ class WebDriver extends Helper {
886
914
  * I.clearField('#email');
887
915
  * ```
888
916
  * @param {string|object} editable field located by label|name|CSS|XPath|strict locator.
889
- * {--end--}
890
917
  *
891
918
  */
892
919
  async clearField(field) {
@@ -916,9 +943,8 @@ class WebDriver extends Helper {
916
943
  * ```js
917
944
  * I.selectOption('Which OS do you use?', ['Android', 'iOS']);
918
945
  * ```
919
- * @param {string|object} select field located by label|name|CSS|XPath|strict locator.
920
- * @param {string|array} option visible text or value of option.
921
- * {--end--}
946
+ * @param {CodeceptJS.LocatorOrString} select field located by label|name|CSS|XPath|strict locator.
947
+ * @param {string|Array<*>} option visible text or value of option.
922
948
  */
923
949
  async selectOption(select, option) {
924
950
  const res = await findFields.call(this, select);
@@ -959,9 +985,8 @@ class WebDriver extends Helper {
959
985
  * I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
960
986
  * ```
961
987
  *
962
- * @param {string|object} locator field located by label|name|CSS|XPath|strict locator.
988
+ * @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
963
989
  * @param {string} pathToFile local file path relative to codecept.json config file.
964
- * {--end--}
965
990
  * Appium: not tested
966
991
  */
967
992
  async attachFile(locator, pathToFile) {
@@ -999,9 +1024,8 @@ class WebDriver extends Helper {
999
1024
  * I.checkOption('I Agree to Terms and Conditions');
1000
1025
  * I.checkOption('agree', '//form');
1001
1026
  * ```
1002
- * @param {string|object} field checkbox located by label | name | CSS | XPath | strict locator.
1003
- * @param {string} context (optional, `null` by default) element located by CSS | XPath | strict locator.
1004
- * {--end--}
1027
+ * @param {CodeceptJS.LocatorOrString} field checkbox located by label | name | CSS | XPath | strict locator.
1028
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
1005
1029
  * Appium: not tested
1006
1030
  */
1007
1031
  async checkOption(field, context = null) {
@@ -1030,9 +1054,8 @@ class WebDriver extends Helper {
1030
1054
  * I.uncheckOption('I Agree to Terms and Conditions');
1031
1055
  * I.uncheckOption('agree', '//form');
1032
1056
  * ```
1033
- * @param {string|object} field checkbox located by label | name | CSS | XPath | strict locator.
1034
- * @param {string} context (optional, `null` by default) element located by CSS | XPath | strict locator.
1035
- * {--end--}
1057
+ * @param {CodeceptJS.LocatorOrString} field checkbox located by label | name | CSS | XPath | strict locator.
1058
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
1036
1059
  * Appium: not tested
1037
1060
  */
1038
1061
  async uncheckOption(field, context = null) {
@@ -1059,9 +1082,8 @@ class WebDriver extends Helper {
1059
1082
  * ```
1060
1083
  * If multiple elements found returns an array of texts.
1061
1084
  *
1062
- * @param locator element located by CSS|XPath|strict locator.
1063
- * @returns {Promise<string>} attribute value
1064
- * {--end--}
1085
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1086
+ * @returns {Promise<string|string[]>} attribute value
1065
1087
  *
1066
1088
  */
1067
1089
  async grabTextFrom(locator) {
@@ -1086,9 +1108,8 @@ class WebDriver extends Helper {
1086
1108
  * let postHTML = await I.grabHTMLFrom('#post');
1087
1109
  * ```
1088
1110
  *
1089
- * @param locator element located by CSS|XPath|strict locator.
1111
+ * @param {CodeceptJS.LocatorOrString} element located by CSS|XPath|strict locator.
1090
1112
  * @returns {Promise<string>} HTML code for an element
1091
- * {--end--}
1092
1113
  *
1093
1114
  */
1094
1115
  async grabHTMLFrom(locator) {
@@ -1109,9 +1130,8 @@ class WebDriver extends Helper {
1109
1130
  * ```js
1110
1131
  * let email = await I.grabValueFrom('input[name=email]');
1111
1132
  * ```
1112
- * @param {string|object} locator field located by label|name|CSS|XPath|strict locator.
1133
+ * @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
1113
1134
  * @returns {Promise<string>} attribute value
1114
- * {--end--}
1115
1135
  *
1116
1136
  */
1117
1137
  async grabValueFrom(locator) {
@@ -1129,10 +1149,9 @@ class WebDriver extends Helper {
1129
1149
  * const value = await I.grabCssPropertyFrom('h3', 'font-weight');
1130
1150
  * ```
1131
1151
  *
1132
- * @param {string|object} locator element located by CSS|XPath|strict locator.
1152
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1133
1153
  * @param {string} cssProperty CSS property name.
1134
1154
  * @returns {Promise<string>} CSS value
1135
- * {--end--}
1136
1155
  */
1137
1156
  async grabCssPropertyFrom(locator, cssProperty) {
1138
1157
  const res = await this._locate(locator, true);
@@ -1148,10 +1167,9 @@ class WebDriver extends Helper {
1148
1167
  * ```js
1149
1168
  * let hint = await I.grabAttributeFrom('#tooltip', 'title');
1150
1169
  * ```
1151
- * @param {string|object} locator element located by CSS|XPath|strict locator.
1170
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1152
1171
  * @param {string} attr attribute name.
1153
1172
  * @returns {Promise<string>} attribute value
1154
- * {--end--}
1155
1173
  * Appium: can be used for apps only with several values ("contentDescription", "text", "className", "resourceId")
1156
1174
  */
1157
1175
  async grabAttributeFrom(locator, attr) {
@@ -1168,7 +1186,6 @@ class WebDriver extends Helper {
1168
1186
  * ```
1169
1187
  *
1170
1188
  * @param {string} text text value to check.
1171
- * {--end--}
1172
1189
  *
1173
1190
  */
1174
1191
  async seeInTitle(text) {
@@ -1183,7 +1200,7 @@ class WebDriver extends Helper {
1183
1200
  * I.seeTitleEquals('Test title.');
1184
1201
  * ```
1185
1202
  *
1186
- * @param text value to check.
1203
+ * @param {string} text value to check.
1187
1204
  */
1188
1205
  async seeTitleEquals(text) {
1189
1206
  const title = await this.browser.getTitle();
@@ -1198,7 +1215,6 @@ class WebDriver extends Helper {
1198
1215
  * ```
1199
1216
  *
1200
1217
  * @param {string} text value to check.
1201
- * {--end--}
1202
1218
  *
1203
1219
  */
1204
1220
  async dontSeeInTitle(text) {
@@ -1215,7 +1231,6 @@ class WebDriver extends Helper {
1215
1231
  * ```
1216
1232
  *
1217
1233
  * @returns {Promise<string>} title
1218
- * {--end--}
1219
1234
  *
1220
1235
  */
1221
1236
  async grabTitle() {
@@ -1234,8 +1249,7 @@ class WebDriver extends Helper {
1234
1249
  * I.see('Register', {css: 'form.register'}); // use strict locator
1235
1250
  * ```
1236
1251
  * @param {string} text expected on page.
1237
- * @param {string|object} context (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
1238
- * {--end--}
1252
+ * @param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text.
1239
1253
  *
1240
1254
  * {{ react }}
1241
1255
  */
@@ -1245,13 +1259,13 @@ class WebDriver extends Helper {
1245
1259
 
1246
1260
  /**
1247
1261
  * Checks that text is equal to provided one.
1248
- *
1262
+ *
1249
1263
  * ```js
1250
1264
  * I.seeTextEquals('text', 'h1');
1251
1265
  * ```
1252
- *
1253
- * @param text element value to check.
1254
- * @param context (optional) element located by CSS|XPath|strict locator.
1266
+ *
1267
+ * @param {string} text element value to check.
1268
+ * @param {CodeceptJS.LocatorOrString?} [context=null] element located by CSS|XPath|strict locator.
1255
1269
  */
1256
1270
  async seeTextEquals(text, context = null) {
1257
1271
  return proceedSee.call(this, 'assert', text, context, true);
@@ -1267,9 +1281,8 @@ class WebDriver extends Helper {
1267
1281
  * ```
1268
1282
  *
1269
1283
  * @param {string} text which is not present.
1270
- * @param {string|object} context (optional) element located by CSS|XPath|strict locator in which to perfrom search.
1271
- *
1272
- * {--end--}
1284
+ * @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator in which to perfrom search.
1285
+ *
1273
1286
  *
1274
1287
  * {{ react }}
1275
1288
  */
@@ -1287,9 +1300,9 @@ class WebDriver extends Helper {
1287
1300
  * I.seeInField('form input[type=hidden]','hidden_value');
1288
1301
  * I.seeInField('#searchform input','Search');
1289
1302
  * ```
1290
- * @param {string|object} field located by label|name|CSS|XPath|strict locator.
1303
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
1291
1304
  * @param {string} value value to check.
1292
- * {--end--}
1305
+ *
1293
1306
  *
1294
1307
  */
1295
1308
  async seeInField(field, value) {
@@ -1305,9 +1318,8 @@ class WebDriver extends Helper {
1305
1318
  * I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
1306
1319
  * ```
1307
1320
  *
1308
- * @param {string|object} field located by label|name|CSS|XPath|strict locator.
1321
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
1309
1322
  * @param {string} value value to check.
1310
- * {--end--}
1311
1323
  *
1312
1324
  */
1313
1325
  async dontSeeInField(field, value) {
@@ -1323,8 +1335,8 @@ class WebDriver extends Helper {
1323
1335
  * I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'});
1324
1336
  * ```
1325
1337
  *
1326
- * @param {string|object} field located by label|name|CSS|XPath|strict locator.
1327
- * {--end--}
1338
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
1339
+ *
1328
1340
  * Appium: not tested
1329
1341
  */
1330
1342
  async seeCheckboxIsChecked(field) {
@@ -1340,8 +1352,8 @@ class WebDriver extends Helper {
1340
1352
  * I.dontSeeCheckboxIsChecked('agree'); // located by name
1341
1353
  * ```
1342
1354
  *
1343
- * @param {string|object} field located by label|name|CSS|XPath|strict locator.
1344
- * {--end--}
1355
+ * @param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
1356
+ *
1345
1357
  * Appium: not tested
1346
1358
  */
1347
1359
  async dontSeeCheckboxIsChecked(field) {
@@ -1355,8 +1367,7 @@ class WebDriver extends Helper {
1355
1367
  * ```js
1356
1368
  * I.seeElement('#modal');
1357
1369
  * ```
1358
- * @param {string|object} locator located by CSS|XPath|strict locator.
1359
- * {--end--}
1370
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1360
1371
  * {{ react }}
1361
1372
  *
1362
1373
  */
@@ -1374,8 +1385,7 @@ class WebDriver extends Helper {
1374
1385
  * I.dontSeeElement('.modal'); // modal is not shown
1375
1386
  * ```
1376
1387
  *
1377
- * @param {string|object} locator located by CSS|XPath|Strict locator.
1378
- * {--end--}
1388
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|Strict locator.
1379
1389
  * {{ react }}
1380
1390
  */
1381
1391
  async dontSeeElement(locator) {
@@ -1394,8 +1404,8 @@ class WebDriver extends Helper {
1394
1404
  * ```js
1395
1405
  * I.seeElementInDOM('#modal');
1396
1406
  * ```
1397
- * @param {string|object} locator element located by CSS|XPath|strict locator.
1398
- * {--end--}
1407
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1408
+ *
1399
1409
  *
1400
1410
  */
1401
1411
  async seeElementInDOM(locator) {
@@ -1410,8 +1420,7 @@ class WebDriver extends Helper {
1410
1420
  * I.dontSeeElementInDOM('.nav'); // checks that element is not on page visible or not
1411
1421
  * ```
1412
1422
  *
1413
- * @param {string|object} locator located by CSS|XPath|Strict locator.
1414
- * {--end--}
1423
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|Strict locator.
1415
1424
  *
1416
1425
  */
1417
1426
  async dontSeeElementInDOM(locator) {
@@ -1426,7 +1435,6 @@ class WebDriver extends Helper {
1426
1435
  * I.seeInSource('<h1>Green eggs &amp; ham</h1>');
1427
1436
  * ```
1428
1437
  * @param {string} text value to check.
1429
- * {--end--}
1430
1438
  *
1431
1439
  */
1432
1440
  async seeInSource(text) {
@@ -1443,7 +1451,6 @@ class WebDriver extends Helper {
1443
1451
  * ```
1444
1452
  *
1445
1453
  * @returns {Promise<string>} source code
1446
- * {--end--}
1447
1454
  *
1448
1455
  */
1449
1456
  async grabSource() {
@@ -1457,6 +1464,7 @@ class WebDriver extends Helper {
1457
1464
  * let logs = await I.grabBrowserLogs();
1458
1465
  * console.log(JSON.stringify(logs))
1459
1466
  * ```
1467
+ * @returns {Promise<string|undefined>}
1460
1468
  */
1461
1469
  async grabBrowserLogs() {
1462
1470
  if (this.browser.isW3C) {
@@ -1476,7 +1484,6 @@ class WebDriver extends Helper {
1476
1484
  * ```
1477
1485
  *
1478
1486
  * @returns {Promise<string>} current URL
1479
- * {--end--}
1480
1487
  */
1481
1488
  async grabCurrentUrl() {
1482
1489
  const res = await this.browser.getUrl();
@@ -1492,7 +1499,7 @@ class WebDriver extends Helper {
1492
1499
  * ```
1493
1500
  *
1494
1501
  * @param {string} value to check.
1495
- * {--end--}
1502
+ *
1496
1503
  */
1497
1504
  async dontSeeInSource(text) {
1498
1505
  const source = await this.browser.getPageSource();
@@ -1508,9 +1515,9 @@ class WebDriver extends Helper {
1508
1515
  * I.seeNumberOfElements('#submitBtn', 1);
1509
1516
  * ```
1510
1517
  *
1511
- * @param {string|object} locator element located by CSS|XPath|strict locator.
1518
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1512
1519
  * @param {number} num number of elements.
1513
- * {--end--}
1520
+ *
1514
1521
  * {{ react }}
1515
1522
  */
1516
1523
  async seeNumberOfElements(locator, num) {
@@ -1526,9 +1533,9 @@ class WebDriver extends Helper {
1526
1533
  * I.seeNumberOfVisibleElements('.buttons', 3);
1527
1534
  * ```
1528
1535
  *
1529
- * @param {string|object} locator element located by CSS|XPath|strict locator.
1536
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
1530
1537
  * @param {number} num number of elements.
1531
- * {--end--}
1538
+ *
1532
1539
  * {{ react }}
1533
1540
  */
1534
1541
  async seeNumberOfVisibleElements(locator, num) {
@@ -1543,9 +1550,8 @@ class WebDriver extends Helper {
1543
1550
  * I.seeCssPropertiesOnElements('h3', { 'font-weight': "bold"});
1544
1551
  * ```
1545
1552
  *
1546
- * @param {string|object} locator located by CSS|XPath|strict locator.
1553
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1547
1554
  * @param {object} cssProperties object with CSS properties and their values to check.
1548
- * {--end--}
1549
1555
  */
1550
1556
  async seeCssPropertiesOnElements(locator, cssProperties) {
1551
1557
  const res = await this._locate(locator);
@@ -1586,9 +1592,8 @@ class WebDriver extends Helper {
1586
1592
  * I.seeAttributesOnElements('//form', { method: "post"});
1587
1593
  * ```
1588
1594
  *
1589
- * @param {string|object} locator located by CSS|XPath|strict locator.
1595
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1590
1596
  * @param {object} attributes attributes and their values to check.
1591
- * {--end--}
1592
1597
  */
1593
1598
  async seeAttributesOnElements(locator, attributes) {
1594
1599
  const res = await this._locate(locator);
@@ -1621,9 +1626,8 @@ class WebDriver extends Helper {
1621
1626
  * let numOfElements = await I.grabNumberOfVisibleElements('p');
1622
1627
  * ```
1623
1628
  *
1624
- * @param {string|object} locator located by CSS|XPath|strict locator.
1629
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1625
1630
  * @returns {Promise<number>} number of visible elements
1626
- * {--end--}
1627
1631
  */
1628
1632
  async grabNumberOfVisibleElements(locator) {
1629
1633
  const res = await this._locate(locator);
@@ -1642,7 +1646,6 @@ class WebDriver extends Helper {
1642
1646
  * ```
1643
1647
  *
1644
1648
  * @param {string} url a fragment to check
1645
- * {--end--}
1646
1649
  *
1647
1650
  */
1648
1651
  async seeInCurrentUrl(url) {
@@ -1654,7 +1657,6 @@ class WebDriver extends Helper {
1654
1657
  * Checks that current url does not contain a provided fragment.
1655
1658
  *
1656
1659
  * @param {string} url value to check.
1657
- * {--end--}
1658
1660
  *
1659
1661
  */
1660
1662
  async dontSeeInCurrentUrl(url) {
@@ -1673,7 +1675,6 @@ class WebDriver extends Helper {
1673
1675
  * ```
1674
1676
  *
1675
1677
  * @param {string} url value to check.
1676
- * {--end--}
1677
1678
  *
1678
1679
  */
1679
1680
  async seeCurrentUrlEquals(url) {
@@ -1691,7 +1692,6 @@ class WebDriver extends Helper {
1691
1692
  * ```
1692
1693
  *
1693
1694
  * @param {string} url value to check.
1694
- * {--end--}
1695
1695
  *
1696
1696
  */
1697
1697
  async dontSeeCurrentUrlEquals(url) {
@@ -1724,8 +1724,9 @@ class WebDriver extends Helper {
1724
1724
  * ```
1725
1725
  *
1726
1726
  * @param {string|function} fn function to be executed in browser context.
1727
- * @param ...args args to be passed to function.
1728
- * {--end--}
1727
+ * @param {...any} args to be passed to function.
1728
+ * @return {Promise<any>}
1729
+ *
1729
1730
  *
1730
1731
  *
1731
1732
  * Wraps [execute](http://webdriver.io/api/protocol/execute.html) command.
@@ -1757,14 +1758,36 @@ class WebDriver extends Helper {
1757
1758
  * ```
1758
1759
  *
1759
1760
  * @param {string|function} fn function to be executed in browser context.
1760
- * @param ...args args to be passed to function.
1761
- * {--end--}
1761
+ * @param {...any} args to be passed to function.
1762
+ * @return {Promise<any>}
1763
+ *
1762
1764
  *
1763
1765
  */
1764
1766
  executeAsyncScript(fn) {
1765
1767
  return this.browser.executeAsync.apply(this.browser, arguments);
1766
1768
  }
1767
1769
 
1770
+ /**
1771
+ * Scroll element into viewport.
1772
+ *
1773
+ * ```js
1774
+ * I.scrollIntoView('#submit');
1775
+ * I.scrollIntoView('#submit', true);
1776
+ * I.scrollIntoView('#submit', { behavior: "smooth", block: "center", inline: "center" });
1777
+ * ```
1778
+ *
1779
+ * @param {string|object} locator located by CSS|XPath|strict locator.
1780
+ * @param {boolean|object} alignToTop (optional) or scrollIntoViewOptions (optional), see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView.
1781
+ *
1782
+ *
1783
+ */
1784
+ async scrollIntoView(locator, scrollIntoViewOptions) {
1785
+ const res = await this._locate(withStrictLocator(locator), true);
1786
+ assertElementExists(res);
1787
+ const elem = usingFirstElement(res);
1788
+ return elem.scrollIntoView(scrollIntoViewOptions);
1789
+ }
1790
+
1768
1791
  /**
1769
1792
  * Scrolls to element matched by locator.
1770
1793
  * Extra shift can be set with offsetX and offsetY options.
@@ -1774,10 +1797,9 @@ class WebDriver extends Helper {
1774
1797
  * I.scrollTo('#submit', 5, 5);
1775
1798
  * ```
1776
1799
  *
1777
- * @param {string|object} locator located by CSS|XPath|strict locator.
1778
- * @param {number} offsetX (optional, `0` by default) X-axis offset.
1779
- * @param {number} offsetY (optional, `0` by default) Y-axis offset.
1780
- * {--end--}
1800
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1801
+ * @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
1802
+ * @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
1781
1803
  *
1782
1804
  */
1783
1805
  async scrollTo(locator, offsetX = 0, offsetY = 0) {
@@ -1816,10 +1838,10 @@ class WebDriver extends Helper {
1816
1838
  * I.moveCursorTo('#submit', 5,5);
1817
1839
  * ```
1818
1840
  *
1819
- * @param {string|object} locator located by CSS|XPath|strict locator.
1820
- * @param {number} offsetX (optional, `0` by default) X-axis offset.
1821
- * @param {number} offsetY (optional, `0` by default) Y-axis offset.
1822
- * {--end--}
1841
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1842
+ * @param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
1843
+ * @param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
1844
+ *
1823
1845
  *
1824
1846
  */
1825
1847
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
@@ -1840,8 +1862,7 @@ class WebDriver extends Helper {
1840
1862
  * ```
1841
1863
  *
1842
1864
  * @param {string} fileName file name to save.
1843
- * @param {boolean} fullPage (optional, `false` by default) flag to enable fullscreen screenshot mode.
1844
- * {--end--}
1865
+ * @param {boolean} [fullPage=false] (optional, `false` by default) flag to enable fullscreen screenshot mode.
1845
1866
  *
1846
1867
  */
1847
1868
  async saveScreenshot(fileName, fullPage = false) {
@@ -1881,7 +1902,6 @@ class WebDriver extends Helper {
1881
1902
  * ```
1882
1903
  *
1883
1904
  * @param {object} cookie a cookie object.
1884
- * {--end--}
1885
1905
  *
1886
1906
  *
1887
1907
  * Uses Selenium's JSON [cookie
@@ -1900,8 +1920,7 @@ class WebDriver extends Helper {
1900
1920
  * I.clearCookie('test');
1901
1921
  * ```
1902
1922
  *
1903
- * @param {string} cookie (optional, `null` by default) cookie name
1904
- * {--end--}
1923
+ * @param {?string} [cookie=null] (optional, `null` by default) cookie name
1905
1924
  *
1906
1925
  */
1907
1926
  async clearCookie(cookie) {
@@ -1916,7 +1935,7 @@ class WebDriver extends Helper {
1916
1935
  * ```
1917
1936
  *
1918
1937
  * @param {string} name cookie name.
1919
- * {--end--}
1938
+ *
1920
1939
  *
1921
1940
  */
1922
1941
  async seeCookie(name) {
@@ -1932,7 +1951,6 @@ class WebDriver extends Helper {
1932
1951
  * ```
1933
1952
  *
1934
1953
  * @param {string} name cookie name.
1935
- * {--end--}
1936
1954
  *
1937
1955
  */
1938
1956
  async dontSeeCookie(name) {
@@ -1943,16 +1961,15 @@ class WebDriver extends Helper {
1943
1961
  /**
1944
1962
  * Gets a cookie object by name.
1945
1963
  * If none provided gets all cookies.
1946
- * * Resumes test execution, so **should be used inside async with `await`** operator.
1964
+ * Resumes test execution, so **should be used inside async with `await`** operator.
1947
1965
  *
1948
1966
  * ```js
1949
1967
  * let cookie = await I.grabCookie('auth');
1950
1968
  * assert(cookie.value, '123456');
1951
1969
  * ```
1952
1970
  *
1953
- * @param [name=null] cookie name.
1971
+ * @param {?string} [name=null] cookie name.
1954
1972
  * @returns {Promise<string>} attribute value
1955
- * {--end--}
1956
1973
  *
1957
1974
  */
1958
1975
  async grabCookie(name) {
@@ -1991,7 +2008,7 @@ class WebDriver extends Helper {
1991
2008
  * Checks that the active JavaScript popup, as created by `window.alert|window.confirm|window.prompt`, contains the
1992
2009
  * given string.
1993
2010
  *
1994
- * @param text value to check.
2011
+ * @param {string} text value to check.
1995
2012
  */
1996
2013
  async seeInPopup(text) {
1997
2014
  return this.browser.getAlertText().then((res) => {
@@ -2029,7 +2046,7 @@ class WebDriver extends Helper {
2029
2046
  * ```
2030
2047
  *
2031
2048
  * @param {string} key name of key to press down.
2032
- * {--end--}
2049
+ *
2033
2050
  */
2034
2051
  async pressKeyDown(key) {
2035
2052
  key = getNormalizedKey.call(this, key);
@@ -2058,7 +2075,7 @@ class WebDriver extends Helper {
2058
2075
  * ```
2059
2076
  *
2060
2077
  * @param {string} key name of key to release.
2061
- * {--end--}
2078
+ *
2062
2079
  */
2063
2080
  async pressKeyUp(key) {
2064
2081
  key = getNormalizedKey.call(this, key);
@@ -2134,8 +2151,8 @@ class WebDriver extends Helper {
2134
2151
  * - `'Space'`
2135
2152
  * - `'Tab'`
2136
2153
  *
2137
- * @param {string|array} key key or array of keys to press.
2138
- * {--end--}
2154
+ * @param {string|string[]} key key or array of keys to press.
2155
+ *
2139
2156
  *
2140
2157
  * _Note:_ In case a text field or textarea is focused be aware that some browsers do not respect active modifier when combining modifier keys with other keys.
2141
2158
  */
@@ -2183,7 +2200,6 @@ class WebDriver extends Helper {
2183
2200
  *
2184
2201
  * @param {number} width width in pixels or `maximize`.
2185
2202
  * @param {number} height height in pixels.
2186
- * {--end--}
2187
2203
  * Appium: not tested in web, in apps doesn't work
2188
2204
  */
2189
2205
  async resizeWindow(width, height) {
@@ -2220,7 +2236,6 @@ class WebDriver extends Helper {
2220
2236
  *
2221
2237
  * @param {string|object} srcElement located by CSS|XPath|strict locator.
2222
2238
  * @param {string|object} destElement located by CSS|XPath|strict locator.
2223
- * {--end--}
2224
2239
  * Appium: not tested
2225
2240
  */
2226
2241
  async dragAndDrop(srcElement, destElement) {
@@ -2244,9 +2259,8 @@ class WebDriver extends Helper {
2244
2259
  * I.dragSlider('#slider', -70);
2245
2260
  * ```
2246
2261
  *
2247
- * @param {string|object} locator located by label|name|CSS|XPath|strict locator.
2262
+ * @param {CodeceptJS.LocatorOrString} locator located by label|name|CSS|XPath|strict locator.
2248
2263
  * @param {number} offsetX position to drag.
2249
- * {--end--}
2250
2264
  */
2251
2265
  async dragSlider(locator, offsetX = 0) {
2252
2266
  const browser = this.browser;
@@ -2338,7 +2352,6 @@ class WebDriver extends Helper {
2338
2352
  * ```
2339
2353
  *
2340
2354
  * @param {number} sec number of second to wait.
2341
- * {--end--}
2342
2355
  *
2343
2356
  */
2344
2357
  async wait(sec) {
@@ -2349,9 +2362,8 @@ class WebDriver extends Helper {
2349
2362
  * Waits for element to become enabled (by default waits for 1sec).
2350
2363
  * Element can be located by CSS or XPath.
2351
2364
  *
2352
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2353
- * @param sec (optional) time in seconds to wait, 1 by default.
2354
- * {--end--}
2365
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2366
+ * @param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
2355
2367
  *
2356
2368
  */
2357
2369
  async waitForEnabled(locator, sec = null) {
@@ -2378,9 +2390,8 @@ class WebDriver extends Helper {
2378
2390
  * I.waitForElement('.btn.continue', 5); // wait for 5 secs
2379
2391
  * ```
2380
2392
  *
2381
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2382
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2383
- * {--end--}
2393
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2394
+ * @param {number} [sec] (optional, `1` by default) time in seconds to wait
2384
2395
  */
2385
2396
  async waitForElement(locator, sec = null) {
2386
2397
  const aSec = sec || this.options.waitForTimeout;
@@ -2390,6 +2401,30 @@ class WebDriver extends Helper {
2390
2401
  }, aSec * 1000, `element (${locator}) still not present on page after ${aSec} sec`);
2391
2402
  }
2392
2403
 
2404
+ /**
2405
+ * Waits for element to be clickable (by default waits for 1sec).
2406
+ * Element can be located by CSS or XPath.
2407
+ *
2408
+ * ```js
2409
+ * I.waitForClickable('.btn.continue');
2410
+ * I.waitForClickable('.btn.continue', 5); // wait for 5 secs
2411
+ * ```
2412
+ *
2413
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2414
+ * @param {number} [sec] (optional, `1` by default) time in seconds to wait
2415
+ */
2416
+ async waitForClickable(locator, waitTimeout) {
2417
+ waitTimeout = waitTimeout || this.options.waitForTimeout;
2418
+ let res = await this._locate(locator);
2419
+ res = usingFirstElement(res);
2420
+ assertElementExists(res, locator);
2421
+
2422
+ return res.waitForClickable({
2423
+ timeout: waitTimeout,
2424
+ timeoutMsg: `element ${res.selector} still not clickable after ${waitTimeout} sec`,
2425
+ });
2426
+ }
2427
+
2393
2428
  async waitUntilExists(locator, sec = null) {
2394
2429
  console.log(`waitUntilExists deprecated:
2395
2430
  * use 'waitForElement' to wait for element to be attached
@@ -2406,8 +2441,7 @@ class WebDriver extends Helper {
2406
2441
  * ```
2407
2442
  *
2408
2443
  * @param {string} urlPart value to check.
2409
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2410
- * {--end--}
2444
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2411
2445
  */
2412
2446
  async waitInUrl(urlPart, sec = null) {
2413
2447
  const client = this.browser;
@@ -2436,8 +2470,7 @@ class WebDriver extends Helper {
2436
2470
  * ```
2437
2471
  *
2438
2472
  * @param {string} urlPart value to check.
2439
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2440
- * {--end--}
2473
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2441
2474
  */
2442
2475
  async waitUrlEquals(urlPart, sec = null) {
2443
2476
  const aSec = sec || this.options.waitForTimeout;
@@ -2470,9 +2503,8 @@ class WebDriver extends Helper {
2470
2503
  * ```
2471
2504
  *
2472
2505
  * @param {string }text to wait for.
2473
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2474
- * @param {string|object} context (optional) element located by CSS|XPath|strict locator.
2475
- * {--end--}
2506
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2507
+ * @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator.
2476
2508
  *
2477
2509
  */
2478
2510
  async waitForText(text, sec = null, context = null) {
@@ -2501,8 +2533,7 @@ class WebDriver extends Helper {
2501
2533
  *
2502
2534
  * @param {string|object} field input field.
2503
2535
  * @param {string }value expected value.
2504
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2505
- * {--end--}
2536
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2506
2537
  */
2507
2538
  async waitForValue(field, value, sec = null) {
2508
2539
  const client = this.browser;
@@ -2529,9 +2560,8 @@ class WebDriver extends Helper {
2529
2560
  * I.waitForVisible('#popup');
2530
2561
  * ```
2531
2562
  *
2532
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2533
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2534
- * {--end--}
2563
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2564
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2535
2565
  *
2536
2566
  */
2537
2567
  async waitForVisible(locator, sec = null) {
@@ -2554,10 +2584,9 @@ class WebDriver extends Helper {
2554
2584
  * I.waitNumberOfVisibleElements('a', 3);
2555
2585
  * ```
2556
2586
  *
2557
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2587
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2558
2588
  * @param {number} num number of elements.
2559
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2560
- * {--end--}
2589
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2561
2590
  */
2562
2591
  async waitNumberOfVisibleElements(locator, num, sec = null) {
2563
2592
  const aSec = sec || this.options.waitForTimeout;
@@ -2579,9 +2608,8 @@ class WebDriver extends Helper {
2579
2608
  * I.waitForInvisible('#popup');
2580
2609
  * ```
2581
2610
  *
2582
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2583
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2584
- * {--end--}
2611
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2612
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2585
2613
  *
2586
2614
  */
2587
2615
  async waitForInvisible(locator, sec = null) {
@@ -2602,9 +2630,8 @@ class WebDriver extends Helper {
2602
2630
  * I.waitToHide('#popup');
2603
2631
  * ```
2604
2632
  *
2605
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2606
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2607
- * {--end--}
2633
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2634
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2608
2635
  *
2609
2636
  */
2610
2637
  async waitToHide(locator, sec = null) {
@@ -2624,9 +2651,8 @@ class WebDriver extends Helper {
2624
2651
  * I.waitForDetached('#popup');
2625
2652
  * ```
2626
2653
  *
2627
- * @param {string|object} locator element located by CSS|XPath|strict locator.
2628
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2629
- * {--end--}
2654
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
2655
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2630
2656
  *
2631
2657
  */
2632
2658
  async waitForDetached(locator, sec = null) {
@@ -2655,9 +2681,9 @@ class WebDriver extends Helper {
2655
2681
  * ```
2656
2682
  *
2657
2683
  * @param {string|function} fn to be executed in browser context.
2658
- * @param {array|number} argsOrSec (optional, `1` by default) arguments for function or seconds.
2659
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2660
- * {--end--}
2684
+ * @param {any[]|number} [argsOrSec] (optional, `1` by default) arguments for function or seconds.
2685
+ * @param {number} [sec] (optional, `1` by default) time in seconds to wait
2686
+ *
2661
2687
  *
2662
2688
  */
2663
2689
  async waitForFunction(fn, argsOrSec = null, sec = null) {
@@ -2683,9 +2709,9 @@ class WebDriver extends Helper {
2683
2709
  * ```
2684
2710
  *
2685
2711
  * @param {function|string} fn function which is executed in browser context.
2686
- * @param {number} sec (optional, `1` by default) time in seconds to wait
2712
+ * @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
2687
2713
  * @param {string} [timeoutMsg=''] message to show in case of timeout fail.
2688
- * {--end--}
2714
+ * @param {?number} [interval=null]
2689
2715
  *
2690
2716
  */
2691
2717
  async waitUntil(fn, sec = null, timeoutMsg = null, interval = null) {
@@ -2702,17 +2728,18 @@ class WebDriver extends Helper {
2702
2728
  * I.switchTo(); // switch back to main page
2703
2729
  * ```
2704
2730
  *
2705
- * @param {string|object} locator (optional, `null` by default) element located by CSS|XPath|strict locator.
2706
- * {--end--}
2731
+ * @param {?CodeceptJS.LocatorOrString} [locator=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
2707
2732
  *
2708
2733
  */
2709
2734
  async switchTo(locator) {
2710
2735
  this.browser.isInsideFrame = true;
2711
2736
  if (Number.isInteger(locator)) {
2712
2737
  return this.browser.switchToFrame(locator);
2713
- } else if (!locator) {
2738
+ }
2739
+ if (!locator) {
2714
2740
  return this.browser.switchToFrame(null);
2715
2741
  }
2742
+
2716
2743
  let res = await this._locate(locator, true);
2717
2744
  assertElementExists(res, locator);
2718
2745
  res = usingFirstElement(res);
@@ -2727,8 +2754,8 @@ class WebDriver extends Helper {
2727
2754
  * I.switchToNextTab(2);
2728
2755
  * ```
2729
2756
  *
2730
- * @param num (optional) number of tabs to switch forward, default: 1.
2731
- * @param sec (optional) time in seconds to wait.
2757
+ * @param {number} [num] (optional) number of tabs to switch forward, default: 1.
2758
+ * @param {number | null} [sec] (optional) time in seconds to wait.
2732
2759
  */
2733
2760
  async switchToNextTab(num = 1, sec = null) {
2734
2761
  const aSec = sec || this.options.waitForTimeout;
@@ -2753,8 +2780,8 @@ class WebDriver extends Helper {
2753
2780
  * I.switchToPreviousTab(2);
2754
2781
  * ```
2755
2782
  *
2756
- * @param num (optional) number of tabs to switch backward, default: 1.
2757
- * @param sec (optional) time in seconds to wait.
2783
+ * @param {number} [num] (optional) number of tabs to switch backward, default: 1.
2784
+ * @param {number?} [sec] (optional) time in seconds to wait.
2758
2785
  */
2759
2786
  async switchToPreviousTab(num = 1, sec = null) {
2760
2787
  const aSec = sec || this.options.waitForTimeout;
@@ -2808,7 +2835,6 @@ class WebDriver extends Helper {
2808
2835
  * ```
2809
2836
  *
2810
2837
  * @returns {Promise<number>} number of open tabs
2811
- * {--end--}
2812
2838
  */
2813
2839
  async grabNumberOfOpenTabs() {
2814
2840
  const pages = await this.browser.getWindowHandles();
@@ -2822,7 +2848,7 @@ class WebDriver extends Helper {
2822
2848
  * ```js
2823
2849
  * I.refreshPage();
2824
2850
  * ```
2825
- * {--end--}
2851
+ *
2826
2852
  */
2827
2853
  async refreshPage() {
2828
2854
  const client = this.browser;
@@ -2835,7 +2861,7 @@ class WebDriver extends Helper {
2835
2861
  * ```js
2836
2862
  * I.scrollPageToTop();
2837
2863
  * ```
2838
- * {--end--}
2864
+ *
2839
2865
  */
2840
2866
  scrollPageToTop() {
2841
2867
  const client = this.browser;
@@ -2852,7 +2878,7 @@ class WebDriver extends Helper {
2852
2878
  * ```js
2853
2879
  * I.scrollPageToBottom();
2854
2880
  * ```
2855
- * {--end--}
2881
+ *
2856
2882
  */
2857
2883
  scrollPageToBottom() {
2858
2884
  const client = this.browser;
@@ -2876,8 +2902,7 @@ class WebDriver extends Helper {
2876
2902
  * let { x, y } = await I.grabPageScrollPosition();
2877
2903
  * ```
2878
2904
  *
2879
- * @returns {Promise<object>} scroll position
2880
- * {--end--}
2905
+ * @returns {Promise<Object<string, *>>} scroll position
2881
2906
  */
2882
2907
  async grabPageScrollPosition() {
2883
2908
  /* eslint-disable comma-dangle */
@@ -2903,7 +2928,6 @@ class WebDriver extends Helper {
2903
2928
  * @param {number} latitude to set.
2904
2929
  * @param {number} longitude to set
2905
2930
  * @param {number} altitude (optional, null by default) to set
2906
- * {--end--}
2907
2931
  *
2908
2932
  */
2909
2933
  async setGeoLocation(latitude, longitude, altitude = null) {
@@ -2920,7 +2944,7 @@ class WebDriver extends Helper {
2920
2944
  * ```js
2921
2945
  * let geoLocation = await I.grabGeoLocation();
2922
2946
  * ```
2923
- * {--end--}
2947
+ *
2924
2948
  *
2925
2949
  */
2926
2950
  async grabGeoLocation() {
@@ -2948,14 +2972,16 @@ class WebDriver extends Helper {
2948
2972
  * @param {string|object} locator element located by CSS|XPath|strict locator.
2949
2973
  * @param {string} elementSize x, y, width or height of the given element.
2950
2974
  * @returns {object} Element bounding rectangle
2951
- * {--end--}
2952
2975
  */
2953
2976
  async grabElementBoundingRect(locator, prop) {
2954
2977
  const res = await this._locate(locator, true);
2955
2978
  assertElementExists(res, locator);
2956
2979
  const el = usingFirstElement(res);
2957
2980
 
2958
- const rect = Object.assign({}, await el.getLocation(), await el.getSize());
2981
+ const rect = {
2982
+ ...await el.getLocation(),
2983
+ ...await el.getSize(),
2984
+ };
2959
2985
  if (prop) return rect[prop];
2960
2986
  return rect;
2961
2987
  }
@@ -3010,58 +3036,57 @@ async function proceedSee(assertType, text, context, strict = false) {
3010
3036
  return stringIncludes(description)[assertType](text, selected);
3011
3037
  }
3012
3038
 
3013
- // Mimic Array.forEach() API, but with an async callback function.
3014
- // Execute each callback on each array item serially. Useful when using WebDriver API.
3015
- //
3016
- // Added due because of problem with chrome driver when too many requests
3017
- // are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
3018
- //
3019
- // @param {object[]} array Input array items to iterate over
3020
- // @param {function} callback Async function to excute on each array item
3021
- // @return Array
3022
- async function forEachAsync(array, callback, option = {}) {
3039
+ /**
3040
+ * Mimic Array.forEach() API, but with an async callback function.
3041
+ * Execute each callback on each array item serially. Useful when using WebDriver API.
3042
+ *
3043
+ * Added due because of problem with chrome driver when too many requests
3044
+ * are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
3045
+ * @private
3046
+ * @param {Array} array Input array items to iterate over.
3047
+ * @param {Function} callback - Async function to excute on each array item.
3048
+ * @param {object} [options] - Configurable options.
3049
+ * @param {boolean} [options.expandArrayResults=true] - Flag to flat one dimension array results.
3050
+ * @return {Promise<Array>} - Array of values.
3051
+ */
3052
+ async function forEachAsync(array, callback, options = { expandArrayResults: true }) {
3023
3053
  const {
3024
3054
  expandArrayResults = true,
3025
- } = option;
3055
+ } = options;
3026
3056
  const inputArray = Array.isArray(array) ? array : [array];
3027
3057
  const values = [];
3028
3058
  for (let index = 0; index < inputArray.length; index++) {
3029
- let res;
3030
- try {
3031
- res = await callback(inputArray[index], index, inputArray);
3032
- if (Array.isArray(res) && expandArrayResults) {
3033
- res.forEach(val => values.push(val));
3034
- } else if (res) {
3035
- values.push(res);
3036
- }
3037
- } catch (err) {
3038
- throw err;
3059
+ const res = await callback(inputArray[index], index, inputArray);
3060
+
3061
+ if (Array.isArray(res) && expandArrayResults) {
3062
+ res.forEach(val => values.push(val));
3063
+ } else if (res) {
3064
+ values.push(res);
3039
3065
  }
3040
3066
  }
3041
3067
  return values;
3042
3068
  }
3043
3069
 
3044
- // Mimic Array.filter() API, but with an async callback function.
3045
- // Execute each callback on each array item serially. Useful when using WebDriver API.
3046
- // Added due because of problem with chrome driver when too many requests
3047
- // are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
3048
- // @param {object[]} array Input array items to iterate over
3049
- // @param {function} callback Async functin to excute on each array item
3050
- // @param {object} option Additional options. 'extractValue' will extract the .value object from a WebdriverIO
3051
- //
3070
+ /**
3071
+ * Mimic Array.filter() API, but with an async callback function.
3072
+ * Execute each callback on each array item serially. Useful when using WebDriver API.
3073
+ *
3074
+ * Added due because of problem with chrome driver when too many requests
3075
+ * are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
3076
+ * @private
3077
+ * @param {Array} array - Input array items to iterate over.
3078
+ * @param {Function} callback - Async functin to excute on each array item.
3079
+ * @return {Promise<Array>} - Array of values.
3080
+ */
3052
3081
  async function filterAsync(array, callback) {
3053
3082
  const inputArray = Array.isArray(array) ? array : [array];
3054
3083
  const values = [];
3055
3084
  for (let index = 0; index < inputArray.length; index++) {
3056
- try {
3057
- const res = await callback(inputArray[index], index, inputArray);
3058
- const value = Array.isArray(res) ? res[0] : res;
3085
+ const res = await callback(inputArray[index], index, inputArray);
3086
+ const value = Array.isArray(res) ? res[0] : res;
3059
3087
 
3060
- if (value) {
3061
- values.push(inputArray[index]);
3062
- }
3063
- } catch (err) {
3064
- throw err;
3088
+ if (value) {
3089
+ values.push(inputArray[index]);
3065
3090
  }
3066
3091
  }
3067
3092
  return values;