codeceptjs 3.5.0 → 3.5.1-2.beta.7

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 (273) hide show
  1. package/README.md +24 -25
  2. package/lib/actor.js +6 -3
  3. package/lib/ai.js +12 -3
  4. package/lib/cli.js +12 -2
  5. package/lib/codecept.js +4 -0
  6. package/lib/colorUtils.js +10 -0
  7. package/lib/command/definitions.js +2 -7
  8. package/lib/command/dryRun.js +2 -1
  9. package/lib/command/info.js +24 -0
  10. package/lib/command/init.js +51 -5
  11. package/lib/command/run-multiple/collection.js +17 -5
  12. package/lib/command/run-multiple.js +4 -2
  13. package/lib/command/run-workers.js +66 -4
  14. package/lib/command/run.js +7 -0
  15. package/lib/command/workers/runTests.js +39 -0
  16. package/lib/data/context.js +14 -6
  17. package/lib/event.js +4 -0
  18. package/lib/helper/ApiDataFactory.js +2 -1
  19. package/lib/helper/Appium.js +73 -24
  20. package/lib/helper/Expect.js +422 -0
  21. package/lib/helper/FileSystem.js +1 -1
  22. package/lib/helper/GraphQL.js +25 -0
  23. package/lib/helper/Nightmare.js +9 -4
  24. package/lib/helper/OpenAI.js +14 -10
  25. package/lib/helper/Playwright.js +1205 -288
  26. package/lib/helper/Protractor.js +11 -6
  27. package/lib/helper/Puppeteer.js +173 -61
  28. package/lib/helper/TestCafe.js +44 -9
  29. package/lib/helper/WebDriver.js +231 -82
  30. package/lib/helper/errors/ElementNotFound.js +2 -1
  31. package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
  32. package/lib/helper/scripts/blurElement.js +17 -0
  33. package/lib/helper/scripts/focusElement.js +17 -0
  34. package/lib/helper/scripts/highlightElement.js +2 -2
  35. package/lib/html.js +3 -3
  36. package/lib/interfaces/bdd.js +1 -1
  37. package/lib/interfaces/gherkin.js +37 -3
  38. package/lib/interfaces/scenarioConfig.js +1 -0
  39. package/lib/locator.js +17 -4
  40. package/lib/mochaFactory.js +2 -1
  41. package/lib/output.js +1 -1
  42. package/lib/pause.js +12 -9
  43. package/lib/plugin/autoLogin.js +45 -10
  44. package/lib/plugin/heal.js +47 -17
  45. package/lib/plugin/retryFailedStep.js +10 -1
  46. package/lib/plugin/retryTo.js +2 -4
  47. package/lib/plugin/selenoid.js +6 -1
  48. package/lib/plugin/standardActingHelpers.js +0 -2
  49. package/lib/plugin/stepByStepReport.js +2 -2
  50. package/lib/plugin/tryTo.js +5 -7
  51. package/lib/plugin/wdio.js +0 -1
  52. package/lib/recorder.js +20 -9
  53. package/lib/session.js +1 -1
  54. package/lib/step.js +30 -11
  55. package/lib/ui.js +1 -0
  56. package/lib/utils.js +18 -1
  57. package/lib/workers.js +28 -3
  58. package/package.json +108 -98
  59. package/translations/de-DE.js +5 -0
  60. package/translations/fr-FR.js +14 -1
  61. package/translations/it-IT.js +1 -0
  62. package/translations/ja-JP.js +5 -0
  63. package/translations/pl-PL.js +5 -0
  64. package/translations/pt-BR.js +1 -0
  65. package/translations/ru-RU.js +1 -0
  66. package/translations/zh-CN.js +5 -0
  67. package/translations/zh-TW.js +5 -0
  68. package/typings/index.d.ts +8 -6
  69. package/typings/promiseBasedTypes.d.ts +784 -822
  70. package/typings/types.d.ts +1214 -727
  71. package/CHANGELOG.md +0 -2492
  72. package/docs/advanced.md +0 -351
  73. package/docs/ai.md +0 -246
  74. package/docs/api.md +0 -323
  75. package/docs/basics.md +0 -980
  76. package/docs/bdd.md +0 -535
  77. package/docs/best.md +0 -237
  78. package/docs/books.md +0 -37
  79. package/docs/bootstrap.md +0 -135
  80. package/docs/build/ApiDataFactory.js +0 -409
  81. package/docs/build/Appium.js +0 -1978
  82. package/docs/build/FileSystem.js +0 -228
  83. package/docs/build/GraphQL.js +0 -204
  84. package/docs/build/GraphQLDataFactory.js +0 -309
  85. package/docs/build/JSONResponse.js +0 -338
  86. package/docs/build/Mochawesome.js +0 -71
  87. package/docs/build/Nightmare.js +0 -2147
  88. package/docs/build/OpenAI.js +0 -122
  89. package/docs/build/Playwright.js +0 -4134
  90. package/docs/build/Polly.js +0 -42
  91. package/docs/build/Protractor.js +0 -2701
  92. package/docs/build/Puppeteer.js +0 -3743
  93. package/docs/build/REST.js +0 -344
  94. package/docs/build/SeleniumWebdriver.js +0 -76
  95. package/docs/build/TestCafe.js +0 -2059
  96. package/docs/build/WebDriver.js +0 -4042
  97. package/docs/changelog.md +0 -2501
  98. package/docs/commands.md +0 -254
  99. package/docs/community-helpers.md +0 -58
  100. package/docs/configuration.md +0 -157
  101. package/docs/continuous-integration.md +0 -22
  102. package/docs/custom-helpers.md +0 -306
  103. package/docs/data.md +0 -375
  104. package/docs/detox.md +0 -235
  105. package/docs/docker.md +0 -137
  106. package/docs/email.md +0 -183
  107. package/docs/examples.md +0 -149
  108. package/docs/helpers/ApiDataFactory.md +0 -266
  109. package/docs/helpers/Appium.md +0 -1317
  110. package/docs/helpers/Detox.md +0 -586
  111. package/docs/helpers/FileSystem.md +0 -152
  112. package/docs/helpers/GraphQL.md +0 -130
  113. package/docs/helpers/GraphQLDataFactory.md +0 -226
  114. package/docs/helpers/JSONResponse.md +0 -254
  115. package/docs/helpers/Mochawesome.md +0 -8
  116. package/docs/helpers/MockRequest.md +0 -377
  117. package/docs/helpers/Nightmare.md +0 -1258
  118. package/docs/helpers/OpenAI.md +0 -70
  119. package/docs/helpers/Playwright.md +0 -2250
  120. package/docs/helpers/Polly.md +0 -44
  121. package/docs/helpers/Puppeteer-firefox.md +0 -86
  122. package/docs/helpers/Puppeteer.md +0 -2147
  123. package/docs/helpers/REST.md +0 -218
  124. package/docs/helpers/TestCafe.md +0 -1224
  125. package/docs/helpers/WebDriver.md +0 -2325
  126. package/docs/hooks.md +0 -340
  127. package/docs/index.md +0 -111
  128. package/docs/installation.md +0 -75
  129. package/docs/internal-api.md +0 -265
  130. package/docs/locators.md +0 -331
  131. package/docs/mobile-react-native-locators.md +0 -67
  132. package/docs/mobile.md +0 -344
  133. package/docs/nightmare.md +0 -223
  134. package/docs/pageobjects.md +0 -291
  135. package/docs/parallel.md +0 -288
  136. package/docs/playwright.md +0 -609
  137. package/docs/plugins.md +0 -1225
  138. package/docs/puppeteer.md +0 -316
  139. package/docs/quickstart.md +0 -163
  140. package/docs/react.md +0 -69
  141. package/docs/reports.md +0 -392
  142. package/docs/secrets.md +0 -36
  143. package/docs/shadow.md +0 -68
  144. package/docs/shared/keys.mustache +0 -31
  145. package/docs/shared/react.mustache +0 -1
  146. package/docs/testcafe.md +0 -174
  147. package/docs/translation.md +0 -247
  148. package/docs/tutorial.md +0 -271
  149. package/docs/typescript.md +0 -180
  150. package/docs/ui.md +0 -59
  151. package/docs/videos.md +0 -28
  152. package/docs/visual.md +0 -202
  153. package/docs/vue.md +0 -121
  154. package/docs/webapi/amOnPage.mustache +0 -11
  155. package/docs/webapi/appendField.mustache +0 -11
  156. package/docs/webapi/attachFile.mustache +0 -12
  157. package/docs/webapi/checkOption.mustache +0 -13
  158. package/docs/webapi/clearCookie.mustache +0 -10
  159. package/docs/webapi/clearField.mustache +0 -9
  160. package/docs/webapi/click.mustache +0 -25
  161. package/docs/webapi/clickLink.mustache +0 -8
  162. package/docs/webapi/closeCurrentTab.mustache +0 -7
  163. package/docs/webapi/closeOtherTabs.mustache +0 -8
  164. package/docs/webapi/dontSee.mustache +0 -11
  165. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  166. package/docs/webapi/dontSeeCookie.mustache +0 -8
  167. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  168. package/docs/webapi/dontSeeElement.mustache +0 -8
  169. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  170. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  171. package/docs/webapi/dontSeeInField.mustache +0 -11
  172. package/docs/webapi/dontSeeInSource.mustache +0 -8
  173. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  174. package/docs/webapi/doubleClick.mustache +0 -13
  175. package/docs/webapi/downloadFile.mustache +0 -12
  176. package/docs/webapi/dragAndDrop.mustache +0 -9
  177. package/docs/webapi/dragSlider.mustache +0 -11
  178. package/docs/webapi/executeAsyncScript.mustache +0 -24
  179. package/docs/webapi/executeScript.mustache +0 -26
  180. package/docs/webapi/fillField.mustache +0 -16
  181. package/docs/webapi/forceClick.mustache +0 -28
  182. package/docs/webapi/forceRightClick.mustache +0 -18
  183. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  184. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  185. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  186. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  187. package/docs/webapi/grabCookie.mustache +0 -11
  188. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  189. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  190. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  191. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  192. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  193. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  194. package/docs/webapi/grabGeoLocation.mustache +0 -8
  195. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  196. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  197. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  198. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  199. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  200. package/docs/webapi/grabPopupText.mustache +0 -5
  201. package/docs/webapi/grabSource.mustache +0 -8
  202. package/docs/webapi/grabTextFrom.mustache +0 -10
  203. package/docs/webapi/grabTextFromAll.mustache +0 -9
  204. package/docs/webapi/grabTitle.mustache +0 -8
  205. package/docs/webapi/grabValueFrom.mustache +0 -9
  206. package/docs/webapi/grabValueFromAll.mustache +0 -8
  207. package/docs/webapi/moveCursorTo.mustache +0 -12
  208. package/docs/webapi/openNewTab.mustache +0 -7
  209. package/docs/webapi/pressKey.mustache +0 -12
  210. package/docs/webapi/pressKeyDown.mustache +0 -12
  211. package/docs/webapi/pressKeyUp.mustache +0 -12
  212. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  213. package/docs/webapi/refreshPage.mustache +0 -6
  214. package/docs/webapi/resizeWindow.mustache +0 -6
  215. package/docs/webapi/rightClick.mustache +0 -14
  216. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  217. package/docs/webapi/saveScreenshot.mustache +0 -12
  218. package/docs/webapi/say.mustache +0 -10
  219. package/docs/webapi/scrollIntoView.mustache +0 -11
  220. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  221. package/docs/webapi/scrollPageToTop.mustache +0 -6
  222. package/docs/webapi/scrollTo.mustache +0 -12
  223. package/docs/webapi/see.mustache +0 -11
  224. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  225. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  226. package/docs/webapi/seeCookie.mustache +0 -8
  227. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  228. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  229. package/docs/webapi/seeElement.mustache +0 -8
  230. package/docs/webapi/seeElementInDOM.mustache +0 -8
  231. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  232. package/docs/webapi/seeInField.mustache +0 -12
  233. package/docs/webapi/seeInPopup.mustache +0 -8
  234. package/docs/webapi/seeInSource.mustache +0 -7
  235. package/docs/webapi/seeInTitle.mustache +0 -8
  236. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  237. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  238. package/docs/webapi/seeTextEquals.mustache +0 -9
  239. package/docs/webapi/seeTitleEquals.mustache +0 -8
  240. package/docs/webapi/selectOption.mustache +0 -21
  241. package/docs/webapi/setCookie.mustache +0 -16
  242. package/docs/webapi/setGeoLocation.mustache +0 -12
  243. package/docs/webapi/switchTo.mustache +0 -9
  244. package/docs/webapi/switchToNextTab.mustache +0 -10
  245. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  246. package/docs/webapi/type.mustache +0 -21
  247. package/docs/webapi/uncheckOption.mustache +0 -13
  248. package/docs/webapi/wait.mustache +0 -8
  249. package/docs/webapi/waitForClickable.mustache +0 -11
  250. package/docs/webapi/waitForDetached.mustache +0 -10
  251. package/docs/webapi/waitForElement.mustache +0 -11
  252. package/docs/webapi/waitForEnabled.mustache +0 -6
  253. package/docs/webapi/waitForFunction.mustache +0 -17
  254. package/docs/webapi/waitForInvisible.mustache +0 -10
  255. package/docs/webapi/waitForText.mustache +0 -13
  256. package/docs/webapi/waitForValue.mustache +0 -10
  257. package/docs/webapi/waitForVisible.mustache +0 -10
  258. package/docs/webapi/waitInUrl.mustache +0 -9
  259. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  260. package/docs/webapi/waitToHide.mustache +0 -10
  261. package/docs/webapi/waitUrlEquals.mustache +0 -10
  262. package/docs/webdriver.md +0 -657
  263. package/docs/wiki/Books-&-Posts.md +0 -27
  264. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
  265. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
  266. package/docs/wiki/Examples.md +0 -139
  267. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  268. package/docs/wiki/Home.md +0 -16
  269. package/docs/wiki/Release-Process.md +0 -24
  270. package/docs/wiki/Roadmap.md +0 -23
  271. package/docs/wiki/Tests.md +0 -1393
  272. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  273. package/docs/wiki/Videos.md +0 -19
@@ -89,8 +89,8 @@ module.exports = function (config) {
89
89
  const reportDir = config.output ? path.resolve(global.codecept_dir, config.output) : defaultConfig.output;
90
90
 
91
91
  event.dispatcher.on(event.test.before, (test) => {
92
- const md5hash = crypto.createHash('md5').update(test.file + test.title).digest('hex');
93
- dir = path.join(reportDir, `record_${md5hash}`);
92
+ const sha256hash = crypto.createHash('sha256').update(test.file + test.title).digest('hex');
93
+ dir = path.join(reportDir, `record_${sha256hash}`);
94
94
  mkdirp.sync(dir);
95
95
  stepNum = 0;
96
96
  error = null;
@@ -1,5 +1,4 @@
1
1
  const recorder = require('../recorder');
2
- const store = require('../store');
3
2
  const { debug } = require('../output');
4
3
 
5
4
  const defaultConfig = {
@@ -9,7 +8,7 @@ const defaultConfig = {
9
8
  /**
10
9
  *
11
10
  *
12
- * Adds global `tryTo` function inside of which all failed steps won't fail a test but will return true/false.
11
+ * Adds global `tryTo` function in which all failed steps won't fail a test but will return true/false.
13
12
  *
14
13
  * Enable this plugin in `codecept.conf.js` (enabled by default for new setups):
15
14
  *
@@ -47,7 +46,7 @@ const defaultConfig = {
47
46
  * ```js
48
47
  * const assert = require('assert');
49
48
  * ```
50
- * Then use the assert:
49
+ * Then use the assertion:
51
50
  * const result1 = await tryTo(() => I.see('Hello, user'));
52
51
  * const result2 = await tryTo(() => I.seeElement('.welcome'));
53
52
  * assert.ok(result1 && result2, 'Assertions were not succesful');
@@ -70,7 +69,7 @@ const defaultConfig = {
70
69
  * const tryTo = codeceptjs.container.plugins('tryTo');
71
70
  * ```
72
71
  *
73
- */
72
+ */
74
73
  module.exports = function (config) {
75
74
  config = Object.assign(defaultConfig, config);
76
75
 
@@ -81,11 +80,10 @@ module.exports = function (config) {
81
80
  };
82
81
 
83
82
  function tryTo(callback) {
84
- const mode = store.debugMode;
85
83
  let result = false;
86
84
  return recorder.add('tryTo', () => {
87
- store.debugMode = true;
88
85
  recorder.session.start('tryTo');
86
+ process.env.TRY_TO = 'true';
89
87
  callback();
90
88
  recorder.add(() => {
91
89
  result = true;
@@ -100,7 +98,7 @@ function tryTo(callback) {
100
98
  return result;
101
99
  });
102
100
  return recorder.add('result', () => {
103
- store.debugMode = mode;
101
+ process.env.TRY_TO = undefined;
104
102
  return result;
105
103
  }, true, false);
106
104
  }, false, false);
@@ -51,7 +51,6 @@ let restartsSession;
51
51
  * }
52
52
  * ```
53
53
  *
54
- * Please note, this service can be used with Protractor helper as well!
55
54
  *
56
55
  * #### Sauce Service
57
56
  *
package/lib/recorder.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const debug = require('debug')('codeceptjs:recorder');
2
2
  const promiseRetry = require('promise-retry');
3
-
3
+ const { printObjectProperties } = require('./utils');
4
4
  const { log } = require('./output');
5
5
 
6
6
  const MAX_TASKS = 100;
@@ -11,6 +11,7 @@ let errFn;
11
11
  let queueId = 0;
12
12
  let sessionId = null;
13
13
  let asyncErr = null;
14
+ let ignoredErrs = [];
14
15
 
15
16
  let tasks = [];
16
17
  let oldPromises = [];
@@ -41,6 +42,7 @@ module.exports = {
41
42
  * @inner
42
43
  */
43
44
  start() {
45
+ debug('Starting recording promises');
44
46
  running = true;
45
47
  asyncErr = null;
46
48
  errFn = null;
@@ -92,8 +94,10 @@ module.exports = {
92
94
  promise = Promise.resolve();
93
95
  oldPromises = [];
94
96
  tasks = [];
97
+ ignoredErrs = [];
95
98
  this.session.running = false;
96
- this.retries = [];
99
+ // reset this retries makes the retryFailedStep plugin won't work if there is Before/BeforeSuit block due to retries is undefined on Scenario
100
+ // this.retries = [];
97
101
  },
98
102
 
99
103
  /**
@@ -175,7 +179,7 @@ module.exports = {
175
179
  return;
176
180
  }
177
181
  tasks.push(taskName);
178
- if (process.env.DEBUG) debug(`${currentQueue()}Queued | ${taskName}`);
182
+ debug(`${currentQueue()}Queued | ${taskName}`);
179
183
 
180
184
  return promise = Promise.resolve(promise).then((res) => {
181
185
  // prefer options for non-conditional retries
@@ -224,10 +228,12 @@ module.exports = {
224
228
  * @inner
225
229
  */
226
230
  catch(customErrFn) {
231
+ const fnDescription = customErrFn?.toString()?.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ')?.slice(0, 50);
232
+ debug(`${currentQueue()}Queued | catch with error handler ${fnDescription || ''}`);
227
233
  return promise = promise.catch((err) => {
228
- log(`${currentQueue()}Error | ${err}`);
234
+ log(`${currentQueue()}Error | ${err} ${fnDescription}...`);
229
235
  if (!(err instanceof Error)) { // strange things may happen
230
- err = new Error(`[Wrapped Error] ${JSON.stringify(err)}`); // we should be prepared for them
236
+ err = new Error(`[Wrapped Error] ${printObjectProperties(err)}`); // we should be prepared for them
231
237
  }
232
238
  if (customErrFn) {
233
239
  customErrFn(err);
@@ -244,15 +250,15 @@ module.exports = {
244
250
  * @inner
245
251
  */
246
252
  catchWithoutStop(customErrFn) {
253
+ const fnDescription = customErrFn?.toString()?.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ')?.slice(0, 50);
247
254
  return promise = promise.catch((err) => {
248
- log(`${currentQueue()}Error | ${err}`);
255
+ if (ignoredErrs.includes(err)) return; // already caught
256
+ log(`${currentQueue()}Error (Non-Terminated) | ${err} | ${fnDescription || ''}...`);
249
257
  if (!(err instanceof Error)) { // strange things may happen
250
258
  err = new Error(`[Wrapped Error] ${JSON.stringify(err)}`); // we should be prepared for them
251
259
  }
252
260
  if (customErrFn) {
253
261
  return customErrFn(err);
254
- } if (errFn) {
255
- return errFn(err);
256
262
  }
257
263
  });
258
264
  },
@@ -264,12 +270,17 @@ module.exports = {
264
270
  * @param {*} err
265
271
  * @inner
266
272
  */
273
+
267
274
  throw(err) {
268
- return this.add(`throw error ${err}`, () => {
275
+ return this.add(`throw error: ${err.message}`, () => {
269
276
  throw err;
270
277
  });
271
278
  },
272
279
 
280
+ ignoreErr(err) {
281
+ ignoredErrs.push(err);
282
+ },
283
+
273
284
  /**
274
285
  * @param {*} err
275
286
  * @inner
package/lib/session.js CHANGED
@@ -19,7 +19,7 @@ const savedSessions = {};
19
19
  * @param {CodeceptJS.LocatorOrString} sessionName
20
20
  * @param {Function | Object<string, *>} config
21
21
  * @param {Function} [fn]
22
- * @return {Promise<*> | undefined}
22
+ * @return {any}
23
23
  */
24
24
  function session(sessionName, config, fn) {
25
25
  if (typeof config === 'function') {
package/lib/step.js CHANGED
@@ -119,7 +119,9 @@ class Step {
119
119
  }
120
120
  let result;
121
121
  try {
122
- result = this.helper[this.helperMethod].apply(this.helper, this.args);
122
+ if (this.helperMethod !== 'say') {
123
+ result = this.helper[this.helperMethod].apply(this.helper, this.args);
124
+ }
123
125
  this.setStatus('success');
124
126
  } catch (err) {
125
127
  this.setStatus('failed');
@@ -138,13 +140,7 @@ class Step {
138
140
 
139
141
  /** @return {string} */
140
142
  humanize() {
141
- return this.name
142
- // insert a space before all caps
143
- .replace(/([A-Z])/g, ' $1')
144
- // _ chars to spaces
145
- .replace('_', ' ')
146
- // uppercase the first character
147
- .replace(/^(.)|\s(.)/g, $1 => $1.toLowerCase());
143
+ return humanizeString(this.name);
148
144
  }
149
145
 
150
146
  /** @return {string} */
@@ -247,12 +243,21 @@ class MetaStep extends Step {
247
243
  }
248
244
 
249
245
  toString() {
250
- const actorText = !this.isBDD() && !this.isWithin() ? `${this.actor}:` : this.actor;
251
- return `${this.prefix}${actorText} ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
246
+ const actorText = this.actor;
247
+
248
+ if (this.isBDD() || this.isWithin()) {
249
+ return `${this.prefix}${actorText} ${this.name} "${this.humanizeArgs()}${this.suffix}"`;
250
+ }
251
+
252
+ if (actorText === 'I') {
253
+ return `${this.prefix}${actorText} ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
254
+ }
255
+
256
+ return `On ${this.prefix}${actorText}: ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`;
252
257
  }
253
258
 
254
259
  humanize() {
255
- return this.name;
260
+ return humanizeString(this.name);
256
261
  }
257
262
 
258
263
  setTrace() {
@@ -316,3 +321,17 @@ function dryRunResolver() {
316
321
  },
317
322
  };
318
323
  }
324
+
325
+ function humanizeString(string) {
326
+ // split strings by words, then make them all lowercase
327
+ const _result = string.replace(/([a-z](?=[A-Z]))/g, '$1 ')
328
+ .split(' ')
329
+ .map(word => word.toLowerCase());
330
+
331
+ _result[0] = _result[0] === 'i' ? capitalizeFLetter(_result[0]) : _result[0];
332
+ return _result.join(' ').trim();
333
+ }
334
+
335
+ function capitalizeFLetter(string) {
336
+ return (string[0].toUpperCase() + string.slice(1));
337
+ }
package/lib/ui.js CHANGED
@@ -168,6 +168,7 @@ module.exports = function (suite) {
168
168
  context.Scenario.only = function (title, opts, fn) {
169
169
  const reString = `^${escapeRe(`${suites[0].title}: ${title}`.replace(/( \| {.+})?$/g, ''))}`;
170
170
  mocha.grep(new RegExp(reString));
171
+ process.env.SCENARIO_ONLY = true;
171
172
  return addScenario(title, opts, fn);
172
173
  };
173
174
 
package/lib/utils.js CHANGED
@@ -11,7 +11,7 @@ function deepMerge(target, source) {
11
11
  }
12
12
 
13
13
  module.exports.genTestId = (test) => {
14
- return require('crypto').createHash('md5').update(test.fullTitle()).digest('base64')
14
+ return require('crypto').createHash('sha256').update(test.fullTitle()).digest('base64')
15
15
  .slice(0, -2);
16
16
  };
17
17
 
@@ -459,3 +459,20 @@ module.exports.isNotSet = function (obj) {
459
459
  module.exports.emptyFolder = async (directoryPath) => {
460
460
  require('child_process').execSync(`rm -rf ${directoryPath}/*`);
461
461
  };
462
+
463
+ module.exports.printObjectProperties = (obj) => {
464
+ if (typeof obj !== 'object' || obj === null) {
465
+ return obj;
466
+ }
467
+
468
+ let result = '';
469
+ for (const [key, value] of Object.entries(obj)) {
470
+ result += `${key}: "${value}"; `;
471
+ }
472
+
473
+ return `{${result}}`;
474
+ };
475
+
476
+ module.exports.normalizeSpacesInString = (string) => {
477
+ return string.replace(/\s+/g, ' ');
478
+ };
package/lib/workers.js CHANGED
@@ -94,10 +94,31 @@ const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns
94
94
  });
95
95
  }
96
96
  const workersToExecute = [];
97
+
98
+ const currentOutputFolder = config.output;
99
+ let currentMochawesomeReportDir;
100
+ let currentMochaJunitReporterFile;
101
+
102
+ if (config.mocha && config.mocha.reporterOptions) {
103
+ currentMochawesomeReportDir = config.mocha.reporterOptions?.mochawesome.options.reportDir;
104
+ currentMochaJunitReporterFile = config.mocha.reporterOptions['mocha-junit-reporter'].options.mochaFile;
105
+ }
106
+
97
107
  collection.createRuns(selectedRuns, config).forEach((worker) => {
98
- const workerName = worker.getOriginalName() || worker.getName();
108
+ const separator = path.sep;
109
+ const _config = { ...config };
110
+ let workerName = worker.name.replace(':', '_');
111
+ _config.output = `${currentOutputFolder}${separator}${workerName}`;
112
+ if (config.mocha && config.mocha.reporterOptions) {
113
+ _config.mocha.reporterOptions.mochawesome.options.reportDir = `${currentMochawesomeReportDir}${separator}${workerName}`;
114
+
115
+ const _tempArray = currentMochaJunitReporterFile.split(separator);
116
+ _tempArray.splice(_tempArray.findIndex(item => item.includes('.xml')), 0, workerName);
117
+ _config.mocha.reporterOptions['mocha-junit-reporter'].options.mochaFile = _tempArray.join(separator);
118
+ }
119
+ workerName = worker.getOriginalName() || worker.getName();
99
120
  const workerConfig = worker.getConfig();
100
- workersToExecute.push(getOverridenConfig(workerName, workerConfig, config));
121
+ workersToExecute.push(getOverridenConfig(workerName, workerConfig, _config));
101
122
  });
102
123
  const workers = [];
103
124
  let index = 0;
@@ -338,13 +359,16 @@ class Workers extends EventEmitter {
338
359
  this.stats.start = new Date();
339
360
  recorder.startUnlessRunning();
340
361
  event.dispatcher.emit(event.workers.before);
362
+ process.env.RUNS_WITH_WORKERS = 'true';
341
363
  recorder.add('starting workers', () => {
342
364
  for (const worker of this.workers) {
343
365
  const workerThread = createWorker(worker);
344
366
  this._listenWorkerEvents(workerThread);
345
367
  }
346
368
  });
347
- return new Promise(resolve => this.on('end', resolve));
369
+ return new Promise(resolve => {
370
+ this.on('end', resolve);
371
+ });
348
372
  }
349
373
 
350
374
  /**
@@ -469,6 +493,7 @@ class Workers extends EventEmitter {
469
493
  }
470
494
 
471
495
  output.result(this.stats.passes, this.stats.failures, this.stats.pending, ms(this.stats.duration));
496
+ process.env.RUNS_WITH_WORKERS = 'false';
472
497
  }
473
498
  }
474
499
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "3.5.0",
3
+ "version": "3.5.12.beta.7",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -23,7 +23,6 @@
23
23
  },
24
24
  "files": [
25
25
  "bin",
26
- "docs",
27
26
  "lib",
28
27
  "translations",
29
28
  "typings/**/*.d.ts"
@@ -40,118 +39,129 @@
40
39
  "lint": "eslint bin/ examples/ lib/ test/ translations/ runok.js",
41
40
  "lint-fix": "eslint bin/ examples/ lib/ test/ translations/ runok.js --fix",
42
41
  "docs": "./runok.js docs",
43
- "test:unit": "mocha test/unit --recursive",
44
- "test:runner": "mocha test/runner --recursive --timeout 5000",
42
+ "test:unit": "mocha test/unit --recursive --timeout 10000",
43
+ "test:runner": "mocha test/runner --recursive --timeout 10000",
45
44
  "test": "npm run test:unit && npm run test:runner",
46
- "test:appium-quick": "mocha test/helper/Appium_test.js --grep 'quick'",
47
- "test:appium-other": "mocha test/helper/Appium_test.js --grep 'second'",
45
+ "test:appium-quick": "mocha test/helper/AppiumV2_test.js --grep 'quick'",
46
+ "test:appium-other": "mocha test/helper/AppiumV2_test.js --grep 'second'",
47
+ "test:ios:appium-quick": "mocha test/helper/AppiumV2_ios_test.js --grep 'quick'",
48
+ "test:ios:appium-other": "mocha test/helper/AppiumV2_ios_test.js --grep 'second'",
48
49
  "test-app:start": "php -S 127.0.0.1:8000 -t test/data/app",
49
50
  "test-app:stop": "kill -9 $(lsof -t -i:8000)",
50
51
  "test:unit:webbapi:playwright": "mocha test/helper/Playwright_test.js",
51
52
  "test:unit:webbapi:puppeteer": "mocha test/helper/Puppeteer_test.js",
52
53
  "test:unit:webbapi:webDriver": "mocha test/helper/WebDriver_test.js",
54
+ "test:unit:webbapi:webDriver:noSeleniumServer": "mocha test/helper/WebDriver.noSeleniumServer_test.js",
55
+ "test:unit:webbapi:webDriver:devtools": "mocha test/helper/WebDriver_devtools_test.js --exit",
53
56
  "test:unit:webbapi:testCafe": "mocha test/helper/TestCafe_test.js",
57
+ "test:unit:expect": "mocha test/helper/Expect_test.js",
58
+ "test:plugin": "mocha test/plugin/plugin_test.js",
54
59
  "def": "./runok.js def",
55
60
  "dev:graphql": "node test/data/graphql/index.js",
56
61
  "publish:site": "./runok.js publish:site",
57
- "update-contributor-faces": "contributor-faces .",
62
+ "update-contributor-faces": "./runok.js contributor:faces",
58
63
  "dtslint": "dtslint typings --localTs './node_modules/typescript/lib'",
59
- "prepare": "husky install"
64
+ "prepare": "husky install",
65
+ "prepare-release": "./runok.js versioning && ./runok.js get:commit-log"
60
66
  },
61
67
  "dependencies": {
62
- "@codeceptjs/configure": "^0.8.0",
63
- "@codeceptjs/helper": "^1.0.2",
64
- "@cucumber/cucumber-expressions": "^16",
65
- "@cucumber/gherkin": "^26",
66
- "@cucumber/messages": "^21.0.1",
67
- "@xmldom/xmldom": "^0.7.9",
68
- "acorn": "^7.4.1",
69
- "arrify": "^2.0.1",
70
- "axios": "^1.3.3",
71
- "chai": "^4.3.6",
72
- "chai-deep-match": "^1.2.1",
73
- "chalk": "^4.1.2",
74
- "commander": "^11.0.0",
75
- "cross-spawn": "^7.0.3",
76
- "css-to-xpath": "^0.1.0",
77
- "envinfo": "^7.8.1",
78
- "escape-string-regexp": "^1.0.3",
79
- "figures": "^3.2.0",
80
- "fn-args": "^4.0.0",
81
- "fs-extra": "^8.1.0",
82
- "glob": "^6.0.1",
83
- "html-minifier": "^4.0.0",
84
- "i": "^0.3.7",
85
- "inquirer": "^6.5.2",
86
- "joi": "^17.6.0",
87
- "js-beautify": "^1.14.0",
88
- "lodash.clonedeep": "^4.5.0",
89
- "lodash.merge": "^4.6.2",
90
- "mkdirp": "^1.0.4",
91
- "mocha": "^10.2.0",
92
- "mocha-junit-reporter": "^1.23.3",
93
- "ms": "^2.1.3",
94
- "npm": "^9.6.7",
95
- "openai": "^3.2.1",
96
- "ora-classic": "^5.4.2",
97
- "parse-function": "^5.6.4",
98
- "parse5": "^7.1.2",
99
- "promise-retry": "^1.1.1",
100
- "resq": "^1.10.2",
101
- "sprintf-js": "^1.1.1",
102
- "uuid": "^9.0"
68
+ "@codeceptjs/configure": "0.10.0",
69
+ "@codeceptjs/helper": "2.0.1",
70
+ "@cucumber/cucumber-expressions": "17",
71
+ "@cucumber/gherkin": "26",
72
+ "@cucumber/messages": "24.0.1",
73
+ "@xmldom/xmldom": "0.8.10",
74
+ "acorn": "8.11.2",
75
+ "arrify": "2.0.1",
76
+ "axios": "1.6.3",
77
+ "chai": "4.3.8",
78
+ "chai-deep-match": "1.2.1",
79
+ "chai-exclude": "^2.1.0",
80
+ "chai-json-schema": "^1.5.1",
81
+ "chai-json-schema-ajv": "^5.2.4",
82
+ "chai-match-pattern": "^1.3.0",
83
+ "chai-string": "^1.5.0",
84
+ "chalk": "4.1.2",
85
+ "commander": "11.1.0",
86
+ "cross-spawn": "7.0.3",
87
+ "csstoxpath": "1.6.0",
88
+ "devtools": "8.27.2",
89
+ "envinfo": "7.11.0",
90
+ "escape-string-regexp": "4.0.0",
91
+ "figures": "3.2.0",
92
+ "fn-args": "4.0.0",
93
+ "fs-extra": "11.2.0",
94
+ "glob": "6.0.1",
95
+ "html-minifier-terser": "^7.2.0",
96
+ "inquirer": "6.5.2",
97
+ "joi": "17.11.0",
98
+ "js-beautify": "1.14.11",
99
+ "lodash.clonedeep": "4.5.0",
100
+ "lodash.merge": "4.6.2",
101
+ "mkdirp": "1.0.4",
102
+ "mocha": "10.2.0",
103
+ "ms": "2.1.3",
104
+ "openai": "3.2.1",
105
+ "ora-classic": "5.4.2",
106
+ "parse-function": "5.6.4",
107
+ "parse5": "7.1.2",
108
+ "promise-retry": "1.1.1",
109
+ "resq": "1.11.0",
110
+ "sprintf-js": "1.1.1",
111
+ "uuid": "9.0"
112
+ },
113
+ "optionalDependencies": {
114
+ "@codeceptjs/detox-helper": "1.0.2"
103
115
  },
104
116
  "devDependencies": {
105
- "@codeceptjs/detox-helper": "^1.0.2",
106
- "@codeceptjs/mock-request": "^0.3.1",
107
- "@faker-js/faker": "^7.6.0",
108
- "@pollyjs/adapter-puppeteer": "^6.0.5",
109
- "@pollyjs/core": "^5.1.0",
110
- "@types/inquirer": "^0.0.35",
111
- "@types/node": "^8.10.66",
112
- "@wdio/sauce-service": "^8.3.8",
113
- "@wdio/selenium-standalone-service": "^8.3.2",
114
- "@wdio/utils": "^8.3.0",
117
+ "@codeceptjs/mock-request": "0.3.1",
118
+ "@faker-js/faker": "7.6.0",
119
+ "@pollyjs/adapter-puppeteer": "6.0.6",
120
+ "@pollyjs/core": "5.1.0",
121
+ "@types/chai": "^4.3.7",
122
+ "@types/inquirer": "9.0.3",
123
+ "@types/node": "20.10.7",
124
+ "@wdio/sauce-service": "8.27.0",
125
+ "@wdio/selenium-standalone-service": "8.3.2",
126
+ "@wdio/utils": "8.27.2",
127
+ "@xmldom/xmldom": "0.8.10",
115
128
  "apollo-server-express": "2.25.3",
116
- "chai-as-promised": "^7.1.1",
117
- "chai-subset": "^1.6.0",
118
- "contributor-faces": "^1.0.3",
119
- "documentation": "^12.3.0",
120
- "dtslint": "^4.1.6",
121
- "electron": "^12.2.3",
122
- "eslint": "^6.8.0",
123
- "eslint-config-airbnb-base": "^14.2.1",
124
- "eslint-plugin-import": "^2.25.4",
125
- "eslint-plugin-mocha": "^6.3.0",
126
- "expect": "^26.6.2",
127
- "express": "^4.17.2",
128
- "form-data": "^3.0.1",
129
- "graphql": "^14.6.0",
130
- "husky": "^8.0.1",
131
- "inquirer-test": "^2.0.1",
132
- "jsdoc": "^3.6.10",
133
- "jsdoc-typeof-plugin": "^1.0.0",
134
- "json-server": "^0.10.1",
135
- "nightmare": "^3.0.2",
136
- "playwright": "^1.35.1",
137
- "puppeteer": "^10.4.0",
138
- "qrcode-terminal": "^0.12.0",
139
- "rosie": "^2.1.0",
140
- "runok": "^0.9.2",
141
- "sinon": "^9.2.4",
142
- "sinon-chai": "^3.7.0",
143
- "testcafe": "^2.1.0",
144
- "ts-morph": "^3.1.3",
145
- "ts-node": "^10.9.1",
146
- "tsd-jsdoc": "^2.5.0",
147
- "typedoc": "^0.23.10",
148
- "typedoc-plugin-markdown": "^3.13.4",
149
- "typescript": "^4.8.4",
150
- "wdio-docker-service": "^1.5.0",
151
- "webdriverio": "^8.3.8",
152
- "xml2js": "^0.4.23",
153
- "xmldom": "^0.5.0",
154
- "xpath": "0.0.27"
129
+ "chai-as-promised": "7.1.1",
130
+ "chai-subset": "1.6.0",
131
+ "contributor-faces": "1.1.0",
132
+ "documentation": "12.3.0",
133
+ "dtslint": "4.2.1",
134
+ "electron": "28.0.0",
135
+ "eslint": "8.56.0",
136
+ "eslint-config-airbnb-base": "15.0.0",
137
+ "eslint-plugin-import": "2.29.1",
138
+ "eslint-plugin-mocha": "6.3.0",
139
+ "expect": "29.7.0",
140
+ "express": "4.18.2",
141
+ "graphql": "14.6.0",
142
+ "husky": "8.0.3",
143
+ "inquirer-test": "2.0.1",
144
+ "jsdoc": "3.6.11",
145
+ "jsdoc-typeof-plugin": "1.0.0",
146
+ "json-server": "0.10.1",
147
+ "playwright": "1.40.1",
148
+ "puppeteer": "21.1.1",
149
+ "qrcode-terminal": "0.12.0",
150
+ "rosie": "2.1.1",
151
+ "runok": "0.9.3",
152
+ "sinon": "17.0.1",
153
+ "sinon-chai": "3.7.0",
154
+ "testcafe": "3.3.0",
155
+ "ts-morph": "21.0.1",
156
+ "ts-node": "10.9.2",
157
+ "tsd-jsdoc": "2.5.0",
158
+ "typedoc": "0.25.7",
159
+ "typedoc-plugin-markdown": "3.17.1",
160
+ "typescript": "5.3.3",
161
+ "wdio-docker-service": "1.5.0",
162
+ "webdriverio": "8.27.2",
163
+ "xml2js": "0.6.2",
164
+ "xpath": "0.0.34"
155
165
  },
156
166
  "engines": {
157
167
  "node": ">=16.0",
@@ -1,5 +1,10 @@
1
1
  module.exports = {
2
2
  I: 'Ich',
3
+ contexts: {
4
+ Feature: 'Funktionalität',
5
+ Scenario: 'Szenario',
6
+ ScenarioOutline: 'Szenariogrundriss',
7
+ },
3
8
  actions: {
4
9
  amOutsideAngularApp: 'befinde_mich_außerhalb_der_angular_app',
5
10
  amInsideAngularApp: 'bedinde_mich_innerhalb_der_angular_app',
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Fonctionnalité',
5
5
  Scenario: 'Scénario',
6
+ ScenarioOutline: 'Plan du scénario',
6
7
  Before: 'Avant',
7
8
  After: 'Après',
8
9
  BeforeSuite: 'AvantLaSuite',
@@ -12,11 +13,15 @@ module.exports = {
12
13
  amOutsideAngularApp: 'suisALExtérieurDeLApplicationAngular',
13
14
  amInsideAngularApp: 'suisALIntérieurDeLApplicationAngular',
14
15
  waitForElement: 'attendsLElément',
15
- waitForClickable: 'attends',
16
+ waitForClickable: 'attendsDeCliquer',
16
17
  waitForVisible: 'attendsPourVoir',
18
+ waitForEnabled: 'attendsLActivationDe',
19
+ waitForInvisible: 'attendsLInvisibilitéDe',
20
+ waitInUrl: 'attendsDansLUrl',
17
21
  waitForText: 'attendsLeTexte',
18
22
  moveTo: 'vaisSur',
19
23
  refresh: 'rafraîchis',
24
+ refreshPage: 'rafraîchisLaPage',
20
25
  haveModule: 'ajouteLeModule',
21
26
  resetModule: 'réinitialiseLeModule',
22
27
  amOnPage: 'suisSurLaPage',
@@ -59,5 +64,13 @@ module.exports = {
59
64
  grabCookie: 'prendsLeCookie',
60
65
  resizeWindow: 'redimensionneLaFenêtre',
61
66
  wait: 'attends',
67
+ clearField: 'effaceLeChamp',
68
+ dontSeeElementInDOM: 'neVoisPasDansLeDOM',
69
+ moveCursorTo: 'bougeLeCurseurSur',
70
+ scrollTo: 'défileVers',
71
+ sendGetRequest: 'envoieLaRequêteGet',
72
+ sendPutRequest: 'envoieLaRequêtePut',
73
+ sendDeleteRequest: 'envoieLaRequêteDelete',
74
+ sendPostRequest: 'envoieLaRequêtePost',
62
75
  },
63
76
  };
@@ -3,6 +3,7 @@ module.exports = {
3
3
  contexts: {
4
4
  Feature: 'Caratteristica',
5
5
  Scenario: 'lo_scenario',
6
+ ScenarioOutline: 'Schema dello scenario',
6
7
  Before: 'Prima',
7
8
  After: 'Dopo',
8
9
  BeforeSuite: 'Prima_della_suite',