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
package/lib/locator.js CHANGED
@@ -1,8 +1,14 @@
1
1
  const cssToXPath = require('css-to-xpath');
2
- const xpathLocator = require('./utils').xpathLocator;
3
2
  const sprintf = require('sprintf-js').sprintf;
4
3
 
4
+ const xpathLocator = require('./utils').xpathLocator;
5
+
6
+ /** @class */
5
7
  class Locator {
8
+ /**
9
+ * @param {CodeceptJS.LocatorOrString} locator
10
+ * @param {string} [defaultType]
11
+ */
6
12
  constructor(locator, defaultType = '') {
7
13
  this.type = null;
8
14
  if (!locator) return;
@@ -63,6 +69,9 @@ class Locator {
63
69
  return { [this.type]: this.value };
64
70
  }
65
71
 
72
+ /**
73
+ * @return {string}
74
+ */
66
75
  toString() {
67
76
  return this.output || `{${this.type}: ${this.value}}`;
68
77
  }
@@ -95,6 +104,9 @@ class Locator {
95
104
  return this.isFuzzy() && this.value[0] === '~';
96
105
  }
97
106
 
107
+ /**
108
+ * @return {string}
109
+ */
98
110
  toXPath() {
99
111
  if (this.isXPath()) return this.value;
100
112
  if (this.isCSS()) return cssToXPath(this.value);
@@ -102,6 +114,10 @@ class Locator {
102
114
  }
103
115
 
104
116
  // DSL
117
+ /**
118
+ * @param {CodeceptJS.LocatorOrString} locator
119
+ * @return {Locator}
120
+ */
105
121
  or(locator) {
106
122
  const xpath = xpathLocator.combine([
107
123
  this.toXPath(),
@@ -110,21 +126,37 @@ class Locator {
110
126
  return new Locator({ xpath });
111
127
  }
112
128
 
129
+ /**
130
+ * @param {CodeceptJS.LocatorOrString} locator
131
+ * @return {Locator}
132
+ */
113
133
  find(locator) {
114
134
  const xpath = sprintf('%s//%s', this.toXPath(), convertToSubSelector(locator));
115
135
  return new Locator({ xpath });
116
136
  }
117
137
 
138
+ /**
139
+ * @param {CodeceptJS.LocatorOrString} locator
140
+ * @return {Locator}
141
+ */
118
142
  withChild(locator) {
119
143
  const xpath = sprintf('%s[./child::%s]', this.toXPath(), convertToSubSelector(locator));
120
144
  return new Locator({ xpath });
121
145
  }
122
146
 
147
+ /**
148
+ * @param {CodeceptJS.LocatorOrString} locator
149
+ * @return {Locator}
150
+ */
123
151
  withDescendant(locator) {
124
152
  const xpath = sprintf('%s[./descendant::%s]', this.toXPath(), convertToSubSelector(locator));
125
153
  return new Locator({ xpath });
126
154
  }
127
155
 
156
+ /**
157
+ * @param {number} position
158
+ * @return {Locator}
159
+ */
128
160
  at(position) {
129
161
  if (position < 0) {
130
162
  position++; // -1 points to the last element
@@ -137,20 +169,34 @@ class Locator {
137
169
  return new Locator({ xpath });
138
170
  }
139
171
 
172
+ /**
173
+ * @return {Locator}
174
+ */
140
175
  first() {
141
176
  return this.at(1);
142
177
  }
143
178
 
179
+ /**
180
+ * @return {Locator}
181
+ */
144
182
  last() {
145
183
  return this.at(-1);
146
184
  }
147
185
 
186
+ /**
187
+ * @param {string} text
188
+ * @return {Locator}
189
+ */
148
190
  withText(text) {
149
191
  text = xpathLocator.literal(text);
150
192
  const xpath = sprintf('%s[%s]', this.toXPath(), `contains(., ${text})`);
151
193
  return new Locator({ xpath });
152
194
  }
153
195
 
196
+ /**
197
+ * @param {Object.<string, string>} attrs
198
+ * @return {Locator}
199
+ */
154
200
  withAttr(attrs) {
155
201
  const operands = [];
156
202
  for (const attr of Object.keys(attrs)) {
@@ -160,27 +206,47 @@ class Locator {
160
206
  return new Locator({ xpath });
161
207
  }
162
208
 
209
+ /**
210
+ * @param {string} output
211
+ * @return {Locator}
212
+ */
163
213
  as(output) {
164
214
  this.output = output;
165
215
  return this;
166
216
  }
167
217
 
218
+ /**
219
+ * @param {CodeceptJS.LocatorOrString} locator
220
+ * @return {Locator}
221
+ */
168
222
  inside(locator) {
169
223
  const xpath = sprintf('%s[ancestor::%s]', this.toXPath(), convertToSubSelector(locator));
170
224
  return new Locator({ xpath });
171
225
  }
172
226
 
227
+ /**
228
+ * @param {CodeceptJS.LocatorOrString} locator
229
+ * @return {Locator}
230
+ */
173
231
  after(locator) {
174
232
  const xpath = sprintf('%s[preceding-sibling::%s]', this.toXPath(), convertToSubSelector(locator));
175
233
  return new Locator({ xpath });
176
234
  }
177
235
 
236
+ /**
237
+ * @param {CodeceptJS.LocatorOrString} locator
238
+ * @return {Locator}
239
+ */
178
240
  before(locator) {
179
241
  const xpath = sprintf('%s[following-sibling::%s]', this.toXPath(), convertToSubSelector(locator));
180
242
  return new Locator({ xpath });
181
243
  }
182
244
  }
183
245
 
246
+ /**
247
+ * @param {CodeceptJS.LocatorOrString} locator
248
+ * @returns {Locator}
249
+ */
184
250
  Locator.build = (locator) => {
185
251
  if (!locator) return new Locator({ xpath: '//*' });
186
252
  return new Locator(locator, 'css');
@@ -190,7 +256,6 @@ Locator.filters = [];
190
256
 
191
257
  Locator.addFilter = fn => Locator.filters.push(fn);
192
258
 
193
-
194
259
  Locator.clickable = {
195
260
  narrow: literal => xpathLocator.combine([
196
261
  `.//a[normalize-space(.)=${literal}]`,
package/lib/output.js CHANGED
@@ -15,14 +15,21 @@ let outputLevel = 0;
15
15
  let outputProcess = '';
16
16
  let newline = true;
17
17
 
18
+ /**
19
+ * @alias output
20
+ * @namespace
21
+ */
18
22
  module.exports = {
19
23
  colors,
20
24
  styles,
21
25
  print,
26
+ /** @type {number} */
22
27
  stepShift: 0,
23
28
 
24
29
  /**
25
30
  * Set or return current verbosity level
31
+ * @param {number} level
32
+ * @return {number}
26
33
  */
27
34
  level(level) {
28
35
  if (level !== undefined) outputLevel = level;
@@ -32,6 +39,8 @@ module.exports = {
32
39
  /**
33
40
  * Print information for a process
34
41
  * Used in multiple-run
42
+ * @param {string} process
43
+ * @return {string}
35
44
  */
36
45
  process(process) {
37
46
  if (process === null) return outputProcess = '';
@@ -41,6 +50,7 @@ module.exports = {
41
50
 
42
51
  /**
43
52
  * Print information in --debug mode
53
+ * @param {string} msg
44
54
  */
45
55
  debug(msg) {
46
56
  if (outputLevel >= 2) {
@@ -50,6 +60,7 @@ module.exports = {
50
60
 
51
61
  /**
52
62
  * Print information in --verbose mode
63
+ * @param {string} msg
53
64
  */
54
65
  log(msg) {
55
66
  if (outputLevel >= 3) print(' '.repeat(this.stepShift), styles.log(truncate(` ${msg}`, this.spaceShift)));
@@ -57,6 +68,7 @@ module.exports = {
57
68
 
58
69
  /**
59
70
  * Print error
71
+ * @param {string} msg
60
72
  */
61
73
  error(msg) {
62
74
  print(styles.error(msg));
@@ -64,17 +76,23 @@ module.exports = {
64
76
 
65
77
  /**
66
78
  * Print a successful message
79
+ * @param {string} msg
67
80
  */
68
81
  success(msg) {
69
82
  print(styles.success(msg));
70
83
  },
71
84
 
85
+ /**
86
+ * @param {string} name
87
+ * @param {string} msg
88
+ */
72
89
  plugin(name, msg) {
73
90
  this.debug(`<${name}> ${msg}`);
74
91
  },
75
92
 
76
93
  /**
77
94
  * Print a step
95
+ * @param {CodeceptJS.Step} step
78
96
  */
79
97
  step(step) {
80
98
  if (outputLevel === 0) return;
@@ -98,7 +116,11 @@ module.exports = {
98
116
  print(' '.repeat(this.stepShift), truncate(stepLine, this.spaceShift));
99
117
  },
100
118
 
119
+ /** @namespace */
101
120
  suite: {
121
+ /**
122
+ * @param {Mocha.Suite} suite
123
+ */
102
124
  started: (suite) => {
103
125
  if (!suite.title) return;
104
126
  print(`${colors.bold(suite.title)} --`);
@@ -106,27 +128,50 @@ module.exports = {
106
128
  },
107
129
  },
108
130
 
131
+ /** @namespace */
109
132
  test: {
133
+ /**
134
+ * @param {Mocha.Test} test
135
+ */
110
136
  started(test) {
111
137
  print(` ${colors.magenta.bold(test.title)}`);
112
138
  },
139
+ /**
140
+ * @param {Mocha.Test} test
141
+ */
113
142
  passed(test) {
114
143
  print(` ${colors.green.bold(figures.tick)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`);
115
144
  },
145
+ /**
146
+ * @param {Mocha.Test} test
147
+ */
116
148
  failed(test) {
117
149
  print(` ${colors.red.bold(figures.cross)} ${test.title} ${colors.grey(`in ${test.duration}ms`)}`);
118
150
  },
151
+ /**
152
+ * @param {Mocha.Test} test
153
+ */
119
154
  skipped(test) {
120
155
  print(` ${colors.yellow.bold('S')} ${test.title}`);
121
156
  },
122
157
  },
123
158
 
159
+ /** @namespace */
124
160
  scenario: {
161
+ /**
162
+ * @param {Mocha.Test} test
163
+ */
125
164
  started(test) {},
165
+ /**
166
+ * @param {Mocha.Test} test
167
+ */
126
168
  passed(test) {
127
169
  print(` ${colors.green.bold(`${figures.tick} OK`)} ${colors.grey(`in ${test.duration}ms`)}`);
128
170
  print();
129
171
  },
172
+ /**
173
+ * @param {Mocha.Test} test
174
+ */
130
175
  failed(test) {
131
176
  print(` ${colors.red.bold(`${figures.cross} FAILED`)} ${colors.grey(`in ${test.duration}ms`)}`);
132
177
  print();
@@ -136,11 +181,19 @@ module.exports = {
136
181
  /**
137
182
  *
138
183
  * Print a text in console log
184
+ * @param {string} message
185
+ * @param {string} [color]
139
186
  */
140
187
  say(message, color = 'cyan') {
141
188
  if (outputLevel >= 1) print(` ${colors[color].bold(message)}`);
142
189
  },
143
190
 
191
+ /**
192
+ * @param {number} passed
193
+ * @param {number} failed
194
+ * @param {number} skipped
195
+ * @param {number} duration
196
+ */
144
197
  result(passed, failed, skipped, duration) {
145
198
  let style = colors.bgGreen;
146
199
  let msg = ` ${passed || 0} passed`;
package/lib/parser.js CHANGED
@@ -1,78 +1,10 @@
1
- const parser = require('parse-function')({ ecmaVersion: 2017 });
2
- const { flatTail } = require('./utils');
1
+ function _interopDefault(ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex.default : ex; }
2
+ const parser = _interopDefault(require('parse-function'))({ ecmaVersion: 2017 });
3
3
 
4
4
  module.exports.getParamsToString = function (fn) {
5
5
  return getParams(fn).join(', ');
6
6
  };
7
7
 
8
- module.exports.toTypeDef = function (fn) {
9
- const types = [];
10
- const paramNames = [];
11
- const params = getParams(fn);
12
- for (const key in params) {
13
- let paramName = params[key];
14
- const paramValue = paramName.split('=');
15
- const isOptional = paramValue.length !== 1;
16
- if (isOptional) {
17
- paramName = paramValue[0];
18
- }
19
- paramNames[key] = paramName;
20
- if (isOptional) {
21
- paramNames[key] += '?';
22
- }
23
- types[key] = guessParamTypes(paramName);
24
- }
25
-
26
- let combinedTypes = types[types.length - 1];
27
- if (!combinedTypes) return methodSignature(fn);
28
- if (types.length === 1) {
29
- return combinedTypes.map(type => methodSignature(fn, paramNames, [type])).join('');
30
- }
31
-
32
- for (let i = types.length - 2; i >= 0; i--) {
33
- combinedTypes = flatTail(combinedTypes, types[i]);
34
- }
35
- return combinedTypes.map(type => methodSignature(fn, paramNames, type)).join('');
36
- };
37
-
38
- function methodSignature(fn, paramNames, params) {
39
- if (!fn.name) return;
40
- if (!params) params = [];
41
- params = params.map((p, i) => `${paramNames[i]}: ${p}`).join(', ');
42
- let returnType = 'void';
43
- if (fn.name.indexOf('grab') === 0) {
44
- if (fn.name.indexOf('BrowserLog') > 0 || fn.name.indexOf('ScrollPosition') > 0) {
45
- returnType = 'Promise<object>';
46
- }
47
- if (fn.name.indexOf('Number') > 0) {
48
- returnType = 'Promise<number>';
49
- }
50
- returnType = 'Promise<string>';
51
- }
52
- return ` ${fn.name}(${params}) : ${returnType},\n`;
53
- }
54
-
55
- function guessParamTypes(paramName) {
56
- switch (paramName) {
57
- case 'fn':
58
- return ['Function'];
59
- case 'locator':
60
- case 'field':
61
- case 'context':
62
- case 'select':
63
- return ['LocatorOrString'];
64
- case 'num':
65
- case 'sec':
66
- case 'width':
67
- case 'height':
68
- case 'offset':
69
- case 'offsetX':
70
- case 'offsetY':
71
- return ['number'];
72
- }
73
- return ['string'];
74
- }
75
-
76
8
  function getParams(fn) {
77
9
  if (fn.isSinonProxy) return [];
78
10
  const newFn = fn.toString().replace(/^async/, 'async function');
@@ -91,4 +23,3 @@ function getParams(fn) {
91
23
  console.error(err);
92
24
  }
93
25
  }
94
-
package/lib/pause.js CHANGED
@@ -1,3 +1,6 @@
1
+ const colors = require('chalk');
2
+ const readline = require('readline');
3
+
1
4
  const container = require('./container');
2
5
  const history = require('./history');
3
6
  const store = require('./store');
@@ -6,8 +9,6 @@ const event = require('./event');
6
9
  const output = require('./output');
7
10
  const methodsOfObject = require('./utils').methodsOfObject;
8
11
 
9
- const readline = require('readline');
10
- const colors = require('chalk');
11
12
  // npm install colors
12
13
  let rl;
13
14
  let nextStep;
@@ -1,5 +1,6 @@
1
- const event = require('../event');
2
1
  const Allure = require('allure-js-commons');
2
+
3
+ const event = require('../event');
3
4
  const logger = require('../output');
4
5
  const ansiRegExp = require('../utils').ansiRegExp;
5
6
 
@@ -73,6 +74,8 @@ const defaultConfig = {
73
74
  module.exports = (config) => {
74
75
  config = Object.assign(defaultConfig, config);
75
76
 
77
+ const plugin = {};
78
+
76
79
  const reporter = new Allure();
77
80
  reporter.setOptions({ targetDir: config.outputDir });
78
81
 
@@ -80,15 +83,31 @@ module.exports = (config) => {
80
83
  let currentStep;
81
84
  let isHookSteps = false;
82
85
 
83
- this.addAttachment = (name, buffer, type) => {
86
+ reporter.pendingCase = function (testName, timestamp, opts = {}) {
87
+ reporter.startCase(testName, timestamp);
88
+
89
+ if (opts.description) plugin.setDescription(opts.description);
90
+ if (opts.severity) plugin.severity(opts.severity);
91
+ if (opts.severity) plugin.addLabel('tag', opts.severity);
92
+
93
+ reporter.endCase('pending', { message: opts.message || 'Test ignored' }, timestamp);
94
+ };
95
+
96
+ plugin.addAttachment = (name, buffer, type) => {
84
97
  reporter.addAttachment(name, buffer, type);
85
98
  };
86
99
 
87
- this.setDescription = (description, type) => {
88
- reporter.setDescription(description, type);
100
+ plugin.setDescription = (description, type) => {
101
+ const currentTest = reporter.getCurrentTest();
102
+ if (currentTest) {
103
+ currentTest.setDescription(description, type);
104
+ } else {
105
+ logger.error(`The test is not run. Please use "setDescription" for events:
106
+ "test.start", "test.before", "test.after", "test.passed", "test.failed", "test.finish"`);
107
+ }
89
108
  };
90
109
 
91
- this.createStep = (name, stepFunc = () => {}) => {
110
+ plugin.createStep = (name, stepFunc = () => {}) => {
92
111
  let result;
93
112
  let status = 'passed';
94
113
  reporter.startStep(name);
@@ -110,7 +129,7 @@ module.exports = (config) => {
110
129
  return result;
111
130
  };
112
131
 
113
- this.createAttachment = (name, content, type) => {
132
+ plugin.createAttachment = (name, content, type) => {
114
133
  if (typeof content === 'function') {
115
134
  const attachmentName = name;
116
135
  const buffer = content.apply(this, arguments);
@@ -118,27 +137,27 @@ module.exports = (config) => {
118
137
  } reporter.addAttachment(name, content, type);
119
138
  };
120
139
 
121
- this.severity = (severity) => {
122
- this.addLabel('severity', severity);
140
+ plugin.severity = (severity) => {
141
+ plugin.addLabel('severity', severity);
123
142
  };
124
143
 
125
- this.epic = (epic) => {
126
- this.addLabel('epic', epic);
144
+ plugin.epic = (epic) => {
145
+ plugin.addLabel('epic', epic);
127
146
  };
128
147
 
129
- this.feature = (feature) => {
130
- this.addLabel('feature', feature);
148
+ plugin.feature = (feature) => {
149
+ plugin.addLabel('feature', feature);
131
150
  };
132
151
 
133
- this.story = (story) => {
134
- this.addLabel('story', story);
152
+ plugin.story = (story) => {
153
+ plugin.addLabel('story', story);
135
154
  };
136
155
 
137
- this.issue = (issue) => {
138
- this.addLabel('issue', issue);
156
+ plugin.issue = (issue) => {
157
+ plugin.addLabel('issue', issue);
139
158
  };
140
159
 
141
- this.addLabel = (name, value) => {
160
+ plugin.addLabel = (name, value) => {
142
161
  const currentTest = reporter.getCurrentTest();
143
162
  if (currentTest) {
144
163
  currentTest.addLabel(name, value);
@@ -155,16 +174,16 @@ module.exports = (config) => {
155
174
  event.dispatcher.on(event.suite.before, (suite) => {
156
175
  for (const test of suite.tests) {
157
176
  if (test.pending) {
158
- reporter.pendingCase(test.title);
177
+ reporter.pendingCase(test.title, null, test.opts.skipInfo);
159
178
  }
160
179
  }
161
180
  });
162
181
 
163
- event.dispatcher.on(event.hook.started, (hook) => {
182
+ event.dispatcher.on(event.hook.started, () => {
164
183
  isHookSteps = true;
165
184
  });
166
185
 
167
- event.dispatcher.on(event.hook.passed, (hook) => {
186
+ event.dispatcher.on(event.hook.passed, () => {
168
187
  isHookSteps = false;
169
188
  });
170
189
 
@@ -199,7 +218,7 @@ module.exports = (config) => {
199
218
  reporter.endCase('failed', err);
200
219
  });
201
220
 
202
- event.dispatcher.on(event.test.passed, (test) => {
221
+ event.dispatcher.on(event.test.passed, () => {
203
222
  if (currentStep) reporter.endStep('passed');
204
223
  if (currentMetaStep.length) {
205
224
  currentMetaStep.forEach(() => reporter.endStep('passed'));
@@ -262,5 +281,5 @@ module.exports = (config) => {
262
281
  }
263
282
  }
264
283
 
265
- return this;
284
+ return plugin;
266
285
  };
@@ -217,7 +217,10 @@ const defaultConfig = {
217
217
  */
218
218
  module.exports = function (config) {
219
219
  config = Object.assign(defaultConfig, config);
220
- Object.keys(config.users).map(u => config.users[u] = Object.assign({}, defaultUser, config.users[u]));
220
+ Object.keys(config.users).map(u => config.users[u] = {
221
+ ...defaultUser,
222
+ ...config.users[u],
223
+ });
221
224
 
222
225
  if (config.saveToFile) {
223
226
  // loading from file
@@ -0,0 +1,38 @@
1
+ const event = require('../event');
2
+ const pause = require('../pause');
3
+
4
+ /**
5
+ * Automatically launches [interactive pause](/basics/#pause) when a test fails.
6
+ *
7
+ * Useful for debugging flaky tests on local environment.
8
+ * Add this plugin to config file:
9
+ *
10
+ * ```js
11
+ * plugins: {
12
+ * pauseOnFail: {},
13
+ * }
14
+ * ```
15
+ *
16
+ * Unlike other plugins, `pauseOnFail` is not recommended to be enabled by default.
17
+ * Enable it manually on each run via `-p` option:
18
+ *
19
+ * ```
20
+ * npx codeceptjs run -p pauseOnFail
21
+ * ```
22
+ *
23
+ */
24
+ module.exports = (config) => {
25
+ let failed = false;
26
+
27
+ event.dispatcher.on(event.test.started, (step) => {
28
+ failed = false;
29
+ });
30
+
31
+ event.dispatcher.on(event.step.failed, (step) => {
32
+ failed = true;
33
+ });
34
+
35
+ event.dispatcher.on(event.test.after, (step) => {
36
+ if (failed) pause();
37
+ });
38
+ };
@@ -1,11 +1,12 @@
1
+ const debug = require('debug')('codeceptjs:plugin:puppeteerCoverage');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
1
5
  const Container = require('../container');
2
6
  const recorder = require('../recorder');
3
7
  const event = require('../event');
4
8
  const output = require('../output');
5
- const fs = require('fs');
6
- const path = require('path');
7
9
  const { clearString } = require('../utils');
8
- const debug = require('debug')('codeceptjs:plugin:puppeteerCoverage');
9
10
 
10
11
  const defaultConfig = {
11
12
  coverageDir: 'output/coverage',
@@ -27,10 +28,10 @@ function buildFileName(test, uniqueFileName) {
27
28
  }
28
29
 
29
30
  if (uniqueFileName) {
30
- const uuid =
31
- test.uuid ||
32
- test.ctx.test.uuid ||
33
- Math.floor(new Date().getTime() / 1000);
31
+ const uuid = test.uuid
32
+ || test.ctx.test.uuid
33
+ || Math.floor(new Date().getTime() / 1000);
34
+
34
35
  fileName = `${fileName.substring(0, 10)}_${uuid}.coverage.json`;
35
36
  } else {
36
37
  fileName = `${fileName}.coverage.json`;
@@ -1,9 +1,10 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
1
4
  const Container = require('../container');
2
5
  const recorder = require('../recorder');
3
6
  const event = require('../event');
4
7
  const output = require('../output');
5
- const fs = require('fs');
6
- const path = require('path');
7
8
  const { fileExists, clearString } = require('../utils');
8
9
  const Codeceptjs = require('../index');
9
10
 
@@ -99,7 +100,7 @@ module.exports = function (config) {
99
100
  try {
100
101
  if (options.reportDir) {
101
102
  fileName = path.join(options.reportDir, fileName);
102
- const mochaReportDir = path.join(process.cwd(), options.reportDir);
103
+ const mochaReportDir = path.resolve(process.cwd(), options.reportDir);
103
104
  if (!fileExists(mochaReportDir)) {
104
105
  fs.mkdirSync(mochaReportDir);
105
106
  }
@@ -115,11 +116,15 @@ module.exports = function (config) {
115
116
  allureReporter.addAttachment('Last Seen Screenshot', fs.readFileSync(path.join(global.output_dir, fileName)), 'image/png');
116
117
  }
117
118
  } catch (err) {
118
- if (err &&
119
- err.type &&
120
- err.type === 'RuntimeError' &&
121
- err.message &&
122
- (err.message.indexOf('was terminated due to') > -1 || err.message.indexOf('no such window: target window already closed') > -1)
119
+ if (
120
+ err
121
+ && err.type
122
+ && err.type === 'RuntimeError'
123
+ && err.message
124
+ && (
125
+ err.message.indexOf('was terminated due to') > -1
126
+ || err.message.indexOf('no such window: target window already closed') > -1
127
+ )
123
128
  ) {
124
129
  helper.isRunning = false;
125
130
  }