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);
@@ -701,6 +723,14 @@ class WebDriver extends Helper {
701
723
  *
702
724
  */
703
725
  amOnPage(url) {
726
+ let split_url;
727
+ if (this.config.basicAuth) {
728
+ if (url.startsWith('/')) {
729
+ url = this.config.url + url;
730
+ }
731
+ split_url = url.split('//');
732
+ url = `${split_url[0]}//${this.config.basicAuth.username}:${this.config.basicAuth.password}@${split_url[1]}`;
733
+ }
704
734
  return this.browser.url(url);
705
735
  }
706
736
 
@@ -983,7 +1013,7 @@ class WebDriver extends Helper {
983
1013
  * I.seeTitleEquals('Test title.');
984
1014
  * ```
985
1015
  *
986
- * @param text value to check.
1016
+ * @param {string} text value to check.
987
1017
  */
988
1018
  async seeTitleEquals(text) {
989
1019
  const title = await this.browser.getTitle();
@@ -1019,14 +1049,7 @@ class WebDriver extends Helper {
1019
1049
  }
1020
1050
 
1021
1051
  /**
1022
- * Checks that text is equal to provided one.
1023
- *
1024
- * ```js
1025
- * I.seeTextEquals('text', 'h1');
1026
- * ```
1027
- *
1028
- * @param text element value to check.
1029
- * @param context (optional) element located by CSS|XPath|strict locator.
1052
+ * {{> seeTextEquals }}
1030
1053
  */
1031
1054
  async seeTextEquals(text, context = null) {
1032
1055
  return proceedSee.call(this, 'assert', text, context, true);
@@ -1140,6 +1163,7 @@ class WebDriver extends Helper {
1140
1163
  * let logs = await I.grabBrowserLogs();
1141
1164
  * console.log(JSON.stringify(logs))
1142
1165
  * ```
1166
+ * @returns {Promise<string|undefined>}
1143
1167
  */
1144
1168
  async grabBrowserLogs() {
1145
1169
  if (this.browser.isW3C) {
@@ -1312,6 +1336,17 @@ class WebDriver extends Helper {
1312
1336
  return this.browser.executeAsync.apply(this.browser, arguments);
1313
1337
  }
1314
1338
 
1339
+ /**
1340
+ * {{> scrollIntoView }}
1341
+ *
1342
+ */
1343
+ async scrollIntoView(locator, scrollIntoViewOptions) {
1344
+ const res = await this._locate(withStrictLocator(locator), true);
1345
+ assertElementExists(res);
1346
+ const elem = usingFirstElement(res);
1347
+ return elem.scrollIntoView(scrollIntoViewOptions);
1348
+ }
1349
+
1315
1350
  /**
1316
1351
  * {{> scrollTo }}
1317
1352
  *
@@ -1464,7 +1499,7 @@ class WebDriver extends Helper {
1464
1499
  * Checks that the active JavaScript popup, as created by `window.alert|window.confirm|window.prompt`, contains the
1465
1500
  * given string.
1466
1501
  *
1467
- * @param text value to check.
1502
+ * @param {string} text value to check.
1468
1503
  */
1469
1504
  async seeInPopup(text) {
1470
1505
  return this.browser.getAlertText().then((res) => {
@@ -1737,6 +1772,21 @@ class WebDriver extends Helper {
1737
1772
  }, aSec * 1000, `element (${locator}) still not present on page after ${aSec} sec`);
1738
1773
  }
1739
1774
 
1775
+ /**
1776
+ * {{> waitForClickable }}
1777
+ */
1778
+ async waitForClickable(locator, waitTimeout) {
1779
+ waitTimeout = waitTimeout || this.options.waitForTimeout;
1780
+ let res = await this._locate(locator);
1781
+ res = usingFirstElement(res);
1782
+ assertElementExists(res, locator);
1783
+
1784
+ return res.waitForClickable({
1785
+ timeout: waitTimeout,
1786
+ timeoutMsg: `element ${res.selector} still not clickable after ${waitTimeout} sec`,
1787
+ });
1788
+ }
1789
+
1740
1790
  async waitUntilExists(locator, sec = null) {
1741
1791
  console.log(`waitUntilExists deprecated:
1742
1792
  * use 'waitForElement' to wait for element to be attached
@@ -1940,9 +1990,11 @@ class WebDriver extends Helper {
1940
1990
  this.browser.isInsideFrame = true;
1941
1991
  if (Number.isInteger(locator)) {
1942
1992
  return this.browser.switchToFrame(locator);
1943
- } else if (!locator) {
1993
+ }
1994
+ if (!locator) {
1944
1995
  return this.browser.switchToFrame(null);
1945
1996
  }
1997
+
1946
1998
  let res = await this._locate(locator, true);
1947
1999
  assertElementExists(res, locator);
1948
2000
  res = usingFirstElement(res);
@@ -1957,8 +2009,8 @@ class WebDriver extends Helper {
1957
2009
  * I.switchToNextTab(2);
1958
2010
  * ```
1959
2011
  *
1960
- * @param num (optional) number of tabs to switch forward, default: 1.
1961
- * @param sec (optional) time in seconds to wait.
2012
+ * @param {number} [num] (optional) number of tabs to switch forward, default: 1.
2013
+ * @param {number | null} [sec] (optional) time in seconds to wait.
1962
2014
  */
1963
2015
  async switchToNextTab(num = 1, sec = null) {
1964
2016
  const aSec = sec || this.options.waitForTimeout;
@@ -1983,8 +2035,8 @@ class WebDriver extends Helper {
1983
2035
  * I.switchToPreviousTab(2);
1984
2036
  * ```
1985
2037
  *
1986
- * @param num (optional) number of tabs to switch backward, default: 1.
1987
- * @param sec (optional) time in seconds to wait.
2038
+ * @param {number} [num] (optional) number of tabs to switch backward, default: 1.
2039
+ * @param {number?} [sec] (optional) time in seconds to wait.
1988
2040
  */
1989
2041
  async switchToPreviousTab(num = 1, sec = null) {
1990
2042
  const aSec = sec || this.options.waitForTimeout;
@@ -2118,7 +2170,10 @@ class WebDriver extends Helper {
2118
2170
  assertElementExists(res, locator);
2119
2171
  const el = usingFirstElement(res);
2120
2172
 
2121
- const rect = Object.assign({}, await el.getLocation(), await el.getSize());
2173
+ const rect = {
2174
+ ...await el.getLocation(),
2175
+ ...await el.getSize(),
2176
+ };
2122
2177
  if (prop) return rect[prop];
2123
2178
  return rect;
2124
2179
  }
@@ -2173,58 +2228,57 @@ async function proceedSee(assertType, text, context, strict = false) {
2173
2228
  return stringIncludes(description)[assertType](text, selected);
2174
2229
  }
2175
2230
 
2176
- // Mimic Array.forEach() API, but with an async callback function.
2177
- // Execute each callback on each array item serially. Useful when using WebDriver API.
2178
- //
2179
- // Added due because of problem with chrome driver when too many requests
2180
- // are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
2181
- //
2182
- // @param {object[]} array Input array items to iterate over
2183
- // @param {function} callback Async function to excute on each array item
2184
- // @return Array
2185
- async function forEachAsync(array, callback, option = {}) {
2231
+ /**
2232
+ * Mimic Array.forEach() API, but with an async callback function.
2233
+ * Execute each callback on each array item serially. Useful when using WebDriver API.
2234
+ *
2235
+ * Added due because of problem with chrome driver when too many requests
2236
+ * are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
2237
+ * @private
2238
+ * @param {Array} array Input array items to iterate over.
2239
+ * @param {Function} callback - Async function to excute on each array item.
2240
+ * @param {object} [options] - Configurable options.
2241
+ * @param {boolean} [options.expandArrayResults=true] - Flag to flat one dimension array results.
2242
+ * @return {Promise<Array>} - Array of values.
2243
+ */
2244
+ async function forEachAsync(array, callback, options = { expandArrayResults: true }) {
2186
2245
  const {
2187
2246
  expandArrayResults = true,
2188
- } = option;
2247
+ } = options;
2189
2248
  const inputArray = Array.isArray(array) ? array : [array];
2190
2249
  const values = [];
2191
2250
  for (let index = 0; index < inputArray.length; index++) {
2192
- let res;
2193
- try {
2194
- res = await callback(inputArray[index], index, inputArray);
2195
- if (Array.isArray(res) && expandArrayResults) {
2196
- res.forEach(val => values.push(val));
2197
- } else if (res) {
2198
- values.push(res);
2199
- }
2200
- } catch (err) {
2201
- throw err;
2251
+ const res = await callback(inputArray[index], index, inputArray);
2252
+
2253
+ if (Array.isArray(res) && expandArrayResults) {
2254
+ res.forEach(val => values.push(val));
2255
+ } else if (res) {
2256
+ values.push(res);
2202
2257
  }
2203
2258
  }
2204
2259
  return values;
2205
2260
  }
2206
2261
 
2207
- // Mimic Array.filter() API, but with an async callback function.
2208
- // Execute each callback on each array item serially. Useful when using WebDriver API.
2209
- // Added due because of problem with chrome driver when too many requests
2210
- // are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
2211
- // @param {object[]} array Input array items to iterate over
2212
- // @param {function} callback Async functin to excute on each array item
2213
- // @param {object} option Additional options. 'extractValue' will extract the .value object from a WebdriverIO
2214
- //
2262
+ /**
2263
+ * Mimic Array.filter() API, but with an async callback function.
2264
+ * Execute each callback on each array item serially. Useful when using WebDriver API.
2265
+ *
2266
+ * Added due because of problem with chrome driver when too many requests
2267
+ * are made simultaneously. https://bugs.chromium.org/p/chromedriver/issues/detail?id=2152#c9
2268
+ * @private
2269
+ * @param {Array} array - Input array items to iterate over.
2270
+ * @param {Function} callback - Async functin to excute on each array item.
2271
+ * @return {Promise<Array>} - Array of values.
2272
+ */
2215
2273
  async function filterAsync(array, callback) {
2216
2274
  const inputArray = Array.isArray(array) ? array : [array];
2217
2275
  const values = [];
2218
2276
  for (let index = 0; index < inputArray.length; index++) {
2219
- try {
2220
- const res = await callback(inputArray[index], index, inputArray);
2221
- const value = Array.isArray(res) ? res[0] : res;
2277
+ const res = await callback(inputArray[index], index, inputArray);
2278
+ const value = Array.isArray(res) ? res[0] : res;
2222
2279
 
2223
- if (value) {
2224
- values.push(inputArray[index]);
2225
- }
2226
- } catch (err) {
2227
- throw err;
2280
+ if (value) {
2281
+ values.push(inputArray[index]);
2228
2282
  }
2229
2283
  }
2230
2284
  return values;
@@ -1,5 +1,9 @@
1
1
  let webdriverio;
2
+
3
+ const assert = require('assert');
4
+ const path = require('path');
2
5
  const requireg = require('requireg');
6
+
3
7
  const Helper = require('../helper');
4
8
  const stringIncludes = require('../assert/include').includes;
5
9
  const { urlEquals, equals } = require('../assert/equal');
@@ -21,8 +25,6 @@ const {
21
25
  const ElementNotFound = require('./errors/ElementNotFound');
22
26
  const ConnectionRefused = require('./errors/ConnectionRefused');
23
27
 
24
- const assert = require('assert');
25
- const path = require('path');
26
28
 
27
29
  const webRoot = 'body';
28
30
  const Locator = require('../locator');
@@ -92,7 +94,7 @@ let withinStore = {};
92
94
  * "browser": "chrome",
93
95
  * "desiredCapabilities": {
94
96
  * "chromeOptions": {
95
- * "args": [ "--headless", "--disable-gpu", "--window-size=800,600" ]
97
+ * "args": [ "--headless", "--disable-gpu", "--no-sandbox" ]
96
98
  * }
97
99
  * }
98
100
  * }
@@ -446,7 +448,7 @@ class WebDriverIO extends Helper {
446
448
  * this.helpers['WebDriverIO']._locate({name: 'password'}).then //...
447
449
  * ```
448
450
  *
449
- * @param locator element located by CSS|XPath|strict locator.
451
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
450
452
  */
451
453
  async _locate(locator, smartWait = false) {
452
454
  if (!this.options.smartWait || !smartWait) return this.browser.elements(withStrictLocator.call(this, locator));
@@ -465,7 +467,7 @@ class WebDriverIO extends Helper {
465
467
  * this.helpers['WebDriverIO']._locateCheckable('I agree with terms and conditions').then // ...
466
468
  * ```
467
469
  *
468
- * @param locator element located by CSS|XPath|strict locator.
470
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
469
471
  */
470
472
  async _locateCheckable(locator) {
471
473
  return findCheckable.call(this, locator, this.browser.elements.bind(this)).then(res => res.value);
@@ -478,7 +480,7 @@ class WebDriverIO extends Helper {
478
480
  * this.helpers['WebDriverIO']._locateClickable('Next page').then // ...
479
481
  * ```
480
482
  *
481
- * @param locator element located by CSS|XPath|strict locator.
483
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
482
484
  */
483
485
  async _locateClickable(locator) {
484
486
  return findClickable.call(this, locator, this.browser.elements.bind(this)).then(res => res.value);
@@ -491,7 +493,7 @@ class WebDriverIO extends Helper {
491
493
  * this.helpers['WebDriverIO']._locateFields('Your email').then // ...
492
494
  * ```
493
495
  *
494
- * @param locator element located by CSS|XPath|strict locator.
496
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
495
497
  */
496
498
  async _locateFields(locator) {
497
499
  return findFields.call(this, locator).then(res => res.value);
@@ -507,7 +509,7 @@ class WebDriverIO extends Helper {
507
509
  * I.defineTimeout({ implicit: 10000, pageLoad: 10000, script: 5000 });
508
510
  * ```
509
511
  *
510
- * @param timeouts WebDriver timeouts object.
512
+ * @param {WebdriverIO.Timeouts} timeouts WebDriver timeouts object.
511
513
  */
512
514
  async defineTimeout(timeouts) {
513
515
  try {
@@ -780,7 +782,7 @@ class WebDriverIO extends Helper {
780
782
  * I.seeTitleEquals('Test title.');
781
783
  * ```
782
784
  *
783
- * @param text value to check.
785
+ * @param {string} text value to check.
784
786
  */
785
787
  async seeTitleEquals(text) {
786
788
  const title = await this.browser.getTitle();
@@ -821,8 +823,8 @@ class WebDriverIO extends Helper {
821
823
  * I.seeTextEquals('text', 'h1');
822
824
  * ```
823
825
  *
824
- * @param text element value to check.
825
- * @param context (optional) element located by CSS|XPath|strict locator.
826
+ * @param {string} text element value to check.
827
+ * @param {CodeceptJS.LocatorOrString?} [context] (optional) element located by CSS|XPath|strict locator.
826
828
  */
827
829
  async seeTextEquals(text, context = null) {
828
830
  return proceedSee.call(this, 'assert', text, context, true);
@@ -974,8 +976,8 @@ class WebDriverIO extends Helper {
974
976
  * I.seeNumberOfElements('#submitBtn', 1);
975
977
  * ```
976
978
  *
977
- * @param locator element located by CSS|XPath|strict locator.
978
- * @param num number of elements.
979
+ * @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
980
+ * @param {number} [num] number of elements.
979
981
  */
980
982
  async seeNumberOfElements(locator, num) {
981
983
  const res = await this._locate(withStrictLocator.call(this, locator));
@@ -1127,9 +1129,9 @@ class WebDriverIO extends Helper {
1127
1129
  * I.scrollTo('#submit', 5, 5);
1128
1130
  * ```
1129
1131
  *
1130
- * @param locator located by CSS|XPath|strict locator.
1131
- * @param offsetX (optional) X-axis offset.
1132
- * @param offsetY (optional) Y-axis offset.
1132
+ * @param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
1133
+ * @param {number} [offsetX=0] (optional) X-axis offset.
1134
+ * @param {number} [offsetY=0] (optional) Y-axis offset.
1133
1135
  */
1134
1136
 
1135
1137
  /**
@@ -1165,7 +1167,7 @@ class WebDriverIO extends Helper {
1165
1167
  }
1166
1168
 
1167
1169
  /**
1168
- * {{> moveCursorTo}}
1170
+ * {{> moveCursorTo }}
1169
1171
  * Appium: support only web testing
1170
1172
  */
1171
1173
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
@@ -1239,7 +1241,7 @@ class WebDriverIO extends Helper {
1239
1241
  }
1240
1242
 
1241
1243
  /**
1242
- * {{> clearCookie}}
1244
+ * {{> clearCookie }}
1243
1245
  * Appium: support only web testing
1244
1246
  */
1245
1247
  async clearCookie(cookie) {
@@ -1247,7 +1249,7 @@ class WebDriverIO extends Helper {
1247
1249
  }
1248
1250
 
1249
1251
  /**
1250
- * {{> seeCookie}}
1252
+ * {{> seeCookie }}
1251
1253
  * Appium: support only web testing
1252
1254
  */
1253
1255
  async seeCookie(name) {
@@ -1256,7 +1258,7 @@ class WebDriverIO extends Helper {
1256
1258
  }
1257
1259
 
1258
1260
  /**
1259
- * {{> dontSeeCookie}}
1261
+ * {{> dontSeeCookie }}
1260
1262
  * Appium: support only web testing
1261
1263
  */
1262
1264
  async dontSeeCookie(name) {
@@ -1265,7 +1267,7 @@ class WebDriverIO extends Helper {
1265
1267
  }
1266
1268
 
1267
1269
  /**
1268
- * {{> grabCookie}}
1270
+ * {{> grabCookie }}
1269
1271
  * Appium: support only web testing
1270
1272
  */
1271
1273
  async grabCookie(name) {
@@ -1301,7 +1303,7 @@ class WebDriverIO extends Helper {
1301
1303
  * Checks that the active JavaScript popup, as created by `window.alert|window.confirm|window.prompt`, contains the
1302
1304
  * given string. Appium: support only web testing
1303
1305
  *
1304
- * @param text value to check.
1306
+ * @param {string} text value to check.
1305
1307
  */
1306
1308
  async seeInPopup(text) {
1307
1309
  return this.browser.alertText().then((res) => {
@@ -1325,17 +1327,7 @@ class WebDriverIO extends Helper {
1325
1327
  }
1326
1328
 
1327
1329
  /**
1328
- * {{> pressKey }}
1329
- * {{> _keys }}
1330
- *
1331
- * To make combinations with modifier and mouse clicks (like Ctrl+Click) press a modifier, click, then release it.
1332
- * Appium: support, but clear field before pressing in apps:
1333
- *
1334
- * ```js
1335
- * I.pressKey('Control');
1336
- * I.click('#someelement');
1337
- * I.pressKey('Control');
1338
- * ```
1330
+ * {{> pressKeyWithKeyNormalization }}
1339
1331
  */
1340
1332
  async pressKey(key) {
1341
1333
  let modifier;
@@ -1661,7 +1653,6 @@ class WebDriverIO extends Helper {
1661
1653
 
1662
1654
  /**
1663
1655
  * {{> waitUntil }}
1664
- * @param interval (optional) time in seconds between condition checks.
1665
1656
  * * *Appium*: supported
1666
1657
  */
1667
1658
  async waitUntil(fn, sec = null, timeoutMsg = null, interval = null) {
@@ -1677,9 +1668,11 @@ class WebDriverIO extends Helper {
1677
1668
  async switchTo(locator) {
1678
1669
  if (Number.isInteger(locator)) {
1679
1670
  return this.browser.frame(locator);
1680
- } else if (!locator) {
1671
+ }
1672
+ if (!locator) {
1681
1673
  return this.browser.frame(null);
1682
1674
  }
1675
+
1683
1676
  const res = await this._locate(withStrictLocator.call(this, locator), true);
1684
1677
  assertElementExists(res, locator);
1685
1678
  return this.browser.frame(res.value[0]);
@@ -1693,8 +1686,8 @@ class WebDriverIO extends Helper {
1693
1686
  * I.switchToNextTab(2);
1694
1687
  * ```
1695
1688
  *
1696
- * @param num (optional) number of tabs to switch forward, default: 1.
1697
- * @param sec (optional) time in seconds to wait.
1689
+ * @param {number} [num=1] (optional) number of tabs to switch forward, default: 1.
1690
+ * @param {?number} [sec=null] (optional) time in seconds to wait.
1698
1691
  */
1699
1692
  async switchToNextTab(num = 1, sec = null) {
1700
1693
  const aSec = sec || this.options.waitForTimeout;
@@ -1719,8 +1712,8 @@ class WebDriverIO extends Helper {
1719
1712
  * I.switchToPreviousTab(2);
1720
1713
  * ```
1721
1714
  *
1722
- * @param num (optional) number of tabs to switch backward, default: 1.
1723
- * @param sec (optional) time in seconds to wait.
1715
+ * @param {number} [num=1] (optional) number of tabs to switch backward, default: 1.
1716
+ * @param {?number} [sec] (optional) time in seconds to wait.
1724
1717
  */
1725
1718
  async switchToPreviousTab(num = 1, sec = null) {
1726
1719
  const aSec = sec || this.options.waitForTimeout;
@@ -1888,16 +1881,11 @@ async function forEachAsync(array, callback, option = {}) {
1888
1881
  const inputArray = Array.isArray(array) ? array : [array];
1889
1882
  const values = [];
1890
1883
  for (let index = 0; index < inputArray.length; index++) {
1891
- let res;
1892
- try {
1893
- res = await callback(inputArray[index], index, inputArray);
1894
- if (Array.isArray(res) && expandArrayResults) {
1895
- res.forEach(val => values.push(val));
1896
- } else if (res) {
1897
- values.push(res);
1898
- }
1899
- } catch (err) {
1900
- throw err;
1884
+ const res = await callback(inputArray[index], index, inputArray);
1885
+ if (Array.isArray(res) && expandArrayResults) {
1886
+ res.forEach(val => values.push(val));
1887
+ } else if (res) {
1888
+ values.push(res);
1901
1889
  }
1902
1890
  }
1903
1891
  if (unifyResults) {
@@ -1921,15 +1909,11 @@ async function filterAsync(array, callback, option = {}) {
1921
1909
  const inputArray = Array.isArray(array) ? array : [array];
1922
1910
  const values = [];
1923
1911
  for (let index = 0; index < inputArray.length; index++) {
1924
- try {
1925
- const res = unify(await callback(inputArray[index], index, inputArray), { extractValue });
1926
- const value = Array.isArray(res) ? res[0] : res;
1912
+ const res = unify(await callback(inputArray[index], index, inputArray), { extractValue });
1913
+ const value = Array.isArray(res) ? res[0] : res;
1927
1914
 
1928
- if (value) {
1929
- values.push(inputArray[index]);
1930
- }
1931
- } catch (err) {
1932
- throw err;
1915
+ if (value) {
1916
+ values.push(inputArray[index]);
1933
1917
  }
1934
1918
  }
1935
1919
  return values;
@@ -1939,8 +1923,8 @@ async function filterAsync(array, callback, option = {}) {
1939
1923
  // Internal helper method to handle command results (similar behaviour as the unify function from WebDriverIO
1940
1924
  // except it does not resolve promises)
1941
1925
  //
1942
- // @param {object[]} items list of items
1943
- // @param {object} [option] extractValue: set to try to return the .value property of the input items
1926
+ // @param {object[]} items list of items
1927
+ // @param {object} [option] extractValue: set to try to return the .value property of the input items
1944
1928
  function unify(items, option = {}) {
1945
1929
  const { extractValue = false } = option;
1946
1930