codeceptjs 3.3.0-beta.4 → 3.3.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 (137) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/README.md +26 -0
  3. package/docs/api.md +45 -30
  4. package/docs/bdd.md +1 -0
  5. package/docs/best.md +1 -1
  6. package/docs/build/ApiDataFactory.js +4 -3
  7. package/docs/build/Appium.js +58 -43
  8. package/docs/build/GraphQL.js +4 -2
  9. package/docs/build/GraphQLDataFactory.js +3 -3
  10. package/docs/build/JSONResponse.js +1 -1
  11. package/docs/build/Nightmare.js +99 -70
  12. package/docs/build/Playwright.js +187 -109
  13. package/docs/build/Protractor.js +70 -32
  14. package/docs/build/Puppeteer.js +141 -98
  15. package/docs/build/REST.js +4 -1
  16. package/docs/build/TestCafe.js +96 -65
  17. package/docs/build/WebDriver.js +183 -133
  18. package/docs/changelog.md +92 -0
  19. package/docs/custom-helpers.md +1 -1
  20. package/docs/data.md +2 -2
  21. package/docs/email.md +5 -0
  22. package/docs/helpers/ApiDataFactory.md +7 -3
  23. package/docs/helpers/Appium.md +113 -15
  24. package/docs/helpers/GraphQL.md +6 -0
  25. package/docs/helpers/GraphQLDataFactory.md +3 -3
  26. package/docs/helpers/JSONResponse.md +1 -1
  27. package/docs/helpers/MockRequest.md +8 -6
  28. package/docs/helpers/Nightmare.md +131 -29
  29. package/docs/helpers/Playwright.md +424 -215
  30. package/docs/helpers/Puppeteer.md +229 -92
  31. package/docs/helpers/REST.md +1 -1
  32. package/docs/helpers/TestCafe.md +166 -62
  33. package/docs/helpers/WebDriver.md +254 -103
  34. package/docs/index.md +1 -1
  35. package/docs/locators.md +1 -1
  36. package/docs/videos.md +2 -2
  37. package/docs/webapi/amOnPage.mustache +2 -1
  38. package/docs/webapi/appendField.mustache +2 -1
  39. package/docs/webapi/attachFile.mustache +2 -1
  40. package/docs/webapi/checkOption.mustache +2 -1
  41. package/docs/webapi/clearCookie.mustache +2 -1
  42. package/docs/webapi/clearField.mustache +1 -0
  43. package/docs/webapi/click.mustache +2 -1
  44. package/docs/webapi/clickLink.mustache +2 -1
  45. package/docs/webapi/closeCurrentTab.mustache +6 -4
  46. package/docs/webapi/closeOtherTabs.mustache +6 -4
  47. package/docs/webapi/dontSee.mustache +1 -0
  48. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -0
  49. package/docs/webapi/dontSeeCookie.mustache +2 -1
  50. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +2 -1
  51. package/docs/webapi/dontSeeElement.mustache +2 -1
  52. package/docs/webapi/dontSeeElementInDOM.mustache +2 -1
  53. package/docs/webapi/dontSeeInCurrentUrl.mustache +2 -1
  54. package/docs/webapi/dontSeeInField.mustache +2 -1
  55. package/docs/webapi/dontSeeInSource.mustache +1 -0
  56. package/docs/webapi/dontSeeInTitle.mustache +2 -1
  57. package/docs/webapi/doubleClick.mustache +1 -0
  58. package/docs/webapi/downloadFile.mustache +2 -1
  59. package/docs/webapi/dragAndDrop.mustache +1 -0
  60. package/docs/webapi/dragSlider.mustache +2 -1
  61. package/docs/webapi/fillField.mustache +1 -0
  62. package/docs/webapi/forceClick.mustache +1 -0
  63. package/docs/webapi/forceRightClick.mustache +1 -0
  64. package/docs/webapi/grabDataFromPerformanceTiming.mustache +2 -1
  65. package/docs/webapi/moveCursorTo.mustache +1 -0
  66. package/docs/webapi/openNewTab.mustache +6 -4
  67. package/docs/webapi/pressKey.mustache +2 -1
  68. package/docs/webapi/pressKeyDown.mustache +1 -0
  69. package/docs/webapi/pressKeyUp.mustache +1 -0
  70. package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -0
  71. package/docs/webapi/refreshPage.mustache +1 -0
  72. package/docs/webapi/resizeWindow.mustache +2 -1
  73. package/docs/webapi/rightClick.mustache +1 -0
  74. package/docs/webapi/saveElementScreenshot.mustache +1 -0
  75. package/docs/webapi/saveScreenshot.mustache +2 -1
  76. package/docs/webapi/say.mustache +2 -1
  77. package/docs/webapi/scrollIntoView.mustache +1 -0
  78. package/docs/webapi/scrollPageToBottom.mustache +1 -0
  79. package/docs/webapi/scrollPageToTop.mustache +1 -0
  80. package/docs/webapi/scrollTo.mustache +2 -1
  81. package/docs/webapi/see.mustache +2 -1
  82. package/docs/webapi/seeAttributesOnElements.mustache +2 -1
  83. package/docs/webapi/seeCheckboxIsChecked.mustache +1 -0
  84. package/docs/webapi/seeCookie.mustache +1 -0
  85. package/docs/webapi/seeCssPropertiesOnElements.mustache +2 -1
  86. package/docs/webapi/seeCurrentUrlEquals.mustache +2 -1
  87. package/docs/webapi/seeElement.mustache +2 -1
  88. package/docs/webapi/seeElementInDOM.mustache +1 -0
  89. package/docs/webapi/seeInCurrentUrl.mustache +2 -1
  90. package/docs/webapi/seeInField.mustache +1 -0
  91. package/docs/webapi/seeInPopup.mustache +1 -0
  92. package/docs/webapi/seeInSource.mustache +2 -1
  93. package/docs/webapi/seeInTitle.mustache +2 -1
  94. package/docs/webapi/seeNumberOfElements.mustache +1 -0
  95. package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -0
  96. package/docs/webapi/seeTextEquals.mustache +2 -1
  97. package/docs/webapi/seeTitleEquals.mustache +6 -5
  98. package/docs/webapi/selectOption.mustache +1 -0
  99. package/docs/webapi/setCookie.mustache +1 -0
  100. package/docs/webapi/setGeoLocation.mustache +1 -0
  101. package/docs/webapi/switchTo.mustache +2 -1
  102. package/docs/webapi/switchToNextTab.mustache +8 -7
  103. package/docs/webapi/switchToPreviousTab.mustache +8 -7
  104. package/docs/webapi/type.mustache +1 -0
  105. package/docs/webapi/uncheckOption.mustache +2 -1
  106. package/docs/webapi/wait.mustache +2 -1
  107. package/docs/webapi/waitForClickable.mustache +2 -1
  108. package/docs/webapi/waitForDetached.mustache +2 -1
  109. package/docs/webapi/waitForElement.mustache +2 -1
  110. package/docs/webapi/waitForEnabled.mustache +2 -1
  111. package/docs/webapi/waitForFunction.mustache +1 -0
  112. package/docs/webapi/waitForInvisible.mustache +2 -1
  113. package/docs/webapi/waitForText.mustache +2 -1
  114. package/docs/webapi/waitForValue.mustache +1 -0
  115. package/docs/webapi/waitForVisible.mustache +1 -0
  116. package/docs/webapi/waitInUrl.mustache +2 -1
  117. package/docs/webapi/waitNumberOfVisibleElements.mustache +2 -1
  118. package/docs/webapi/waitToHide.mustache +2 -1
  119. package/docs/webapi/waitUrlEquals.mustache +2 -1
  120. package/lib/command/definitions.js +9 -0
  121. package/lib/command/run.js +2 -2
  122. package/lib/command/workers/runTests.js +40 -0
  123. package/lib/helper/ApiDataFactory.js +4 -3
  124. package/lib/helper/Appium.js +7 -2
  125. package/lib/helper/GraphQL.js +4 -2
  126. package/lib/helper/GraphQLDataFactory.js +3 -3
  127. package/lib/helper/JSONResponse.js +1 -1
  128. package/lib/helper/Playwright.js +49 -13
  129. package/lib/helper/REST.js +4 -1
  130. package/lib/helper/WebDriver.js +6 -0
  131. package/lib/interfaces/bdd.js +5 -0
  132. package/lib/listener/steps.js +1 -0
  133. package/lib/plugin/fakerTransform.js +1 -1
  134. package/lib/plugin/stepByStepReport.js +8 -6
  135. package/lib/workers.js +12 -0
  136. package/package.json +4 -3
  137. package/typings/types.d.ts +598 -600
@@ -7,4 +7,5 @@ I.waitForElement('.btn.continue', 5); // wait for 5 secs
7
7
  ```
8
8
 
9
9
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
10
- @param {number} [sec] (optional, `1` by default) time in seconds to wait
10
+ @param {number} [sec] (optional, `1` by default) time in seconds to wait
11
+ @return {Promise<any>}
@@ -2,4 +2,5 @@ Waits for element to become enabled (by default waits for 1sec).
2
2
  Element can be located by CSS or XPath.
3
3
 
4
4
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
5
- @param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
5
+ @param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
6
+ @return {Promise<any>}
@@ -14,3 +14,4 @@ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and
14
14
  @param {string|function} fn to be executed in browser context.
15
15
  @param {any[]|number} [argsOrSec] (optional, `1` by default) arguments for function or seconds.
16
16
  @param {number} [sec] (optional, `1` by default) time in seconds to wait
17
+ @return {Promise<any>}
@@ -6,4 +6,5 @@ I.waitForInvisible('#popup');
6
6
  ```
7
7
 
8
8
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
9
- @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
9
+ @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -9,4 +9,5 @@ I.waitForText('Thank you, form has been submitted', 5, '#modal');
9
9
 
10
10
  @param {string }text to wait for.
11
11
  @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
12
- @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator.
12
+ @param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator.
13
+ @return {Promise<any>}
@@ -7,3 +7,4 @@ I.waitForValue('//input', "GoodValue");
7
7
  @param {LocatorOrString} field input field.
8
8
  @param {string }value expected value.
9
9
  @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -7,3 +7,4 @@ I.waitForVisible('#popup');
7
7
 
8
8
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
9
9
  @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -5,4 +5,5 @@ I.waitInUrl('/info', 2);
5
5
  ```
6
6
 
7
7
  @param {string} urlPart value to check.
8
- @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
8
+ @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
9
+ @return {Promise<any>}
@@ -6,4 +6,5 @@ I.waitNumberOfVisibleElements('a', 3);
6
6
 
7
7
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
8
8
  @param {number} num number of elements.
9
- @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
9
+ @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -6,4 +6,5 @@ I.waitToHide('#popup');
6
6
  ```
7
7
 
8
8
  @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
9
- @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
9
+ @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -6,4 +6,5 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
6
6
  ```
7
7
 
8
8
  @param {string} urlPart value to check.
9
- @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
9
+ @param {number} [sec=1] (optional, `1` by default) time in seconds to wait
10
+ @return {Promise<any>}
@@ -146,10 +146,19 @@ module.exports = function (genPath, options) {
146
146
  }
147
147
  }
148
148
 
149
+ let autoLogin;
150
+ if (config.plugins.autoLogin) {
151
+ autoLogin = config.plugins.autoLogin.inject;
152
+ }
153
+
149
154
  const supportObject = new Map();
150
155
  supportObject.set('I', 'I');
151
156
  supportObject.set('current', 'any');
152
157
 
158
+ if (autoLogin) {
159
+ supportObject.set(autoLogin, 'any');
160
+ }
161
+
153
162
  if (customHelpers.length > 0) {
154
163
  hasCustomHelper = true;
155
164
  }
@@ -23,8 +23,8 @@ module.exports = async function (test, options) {
23
23
  try {
24
24
  codecept.init(testRoot);
25
25
  await codecept.bootstrap();
26
- codecept.loadTests();
27
- await codecept.run(test);
26
+ codecept.loadTests(test);
27
+ await codecept.run();
28
28
  } catch (err) {
29
29
  printError(err);
30
30
  process.exitCode = 1;
@@ -115,6 +115,8 @@ function initializeListeners() {
115
115
  }
116
116
 
117
117
  return {
118
+ opts: test.opts || {},
119
+ tags: test.tags || [],
118
120
  id: test.id,
119
121
  workerIndex,
120
122
  retries: test._retries,
@@ -126,6 +128,38 @@ function initializeListeners() {
126
128
  };
127
129
  }
128
130
 
131
+ function simplifyStep(step, err = null) {
132
+ step = { ...step };
133
+
134
+ if (step.startTime && !step.duration) {
135
+ const end = new Date();
136
+ step.duration = end - step.startTime;
137
+ }
138
+
139
+ if (step.err) {
140
+ err = simplifyError(step.err);
141
+ step.status = 'failed';
142
+ } else if (err) {
143
+ err = simplifyError(err);
144
+ step.status = 'failed';
145
+ }
146
+
147
+ const parent = {};
148
+ if (step.metaStep) {
149
+ parent.title = step.metaStep.actor;
150
+ }
151
+ return {
152
+ opts: step.opts || {},
153
+ workerIndex,
154
+ title: step.name,
155
+ status: step.status,
156
+ duration: step.duration || 0,
157
+ err,
158
+ parent,
159
+ test: simplifyTest(step.test),
160
+ };
161
+ }
162
+
129
163
  collectStats();
130
164
  // suite
131
165
  event.dispatcher.on(event.suite.before, suite => sendToParentThread({ event: event.suite.before, workerIndex, data: simplifyTest(suite) }));
@@ -144,6 +178,12 @@ function initializeListeners() {
144
178
  event.dispatcher.on(event.test.started, test => sendToParentThread({ event: event.test.started, workerIndex, data: simplifyTest(test) }));
145
179
  event.dispatcher.on(event.test.skipped, test => sendToParentThread({ event: event.test.skipped, workerIndex, data: simplifyTest(test) }));
146
180
 
181
+ // steps
182
+ event.dispatcher.on(event.step.finished, step => sendToParentThread({ event: event.step.finished, workerIndex, data: simplifyStep(step) }));
183
+ event.dispatcher.on(event.step.started, step => sendToParentThread({ event: event.step.started, workerIndex, data: simplifyStep(step) }));
184
+ event.dispatcher.on(event.step.passed, step => sendToParentThread({ event: event.step.passed, workerIndex, data: simplifyStep(step) }));
185
+ event.dispatcher.on(event.step.failed, step => sendToParentThread({ event: event.step.failed, workerIndex, data: simplifyStep(step) }));
186
+
147
187
  event.dispatcher.on(event.hook.failed, (test, err) => sendToParentThread({ event: event.hook.failed, workerIndex, data: simplifyTest(test, err) }));
148
188
  event.dispatcher.on(event.hook.passed, (test, err) => sendToParentThread({ event: event.hook.passed, workerIndex, data: simplifyTest(test, err) }));
149
189
  event.dispatcher.on(event.all.failures, (data) => sendToParentThread({ event: event.all.failures, workerIndex, data }));
@@ -36,7 +36,7 @@ const REST = require('./REST');
36
36
  * Install [Rosie](https://github.com/rosiejs/rosie) and [Faker](https://www.npmjs.com/package/faker) libraries.
37
37
  *
38
38
  * ```sh
39
- * npm i rosie faker --save-dev
39
+ * npm i rosie @faker-js/faker --save-dev
40
40
  * ```
41
41
  *
42
42
  * Create a factory file for a resource.
@@ -46,8 +46,8 @@ const REST = require('./REST');
46
46
  * ```js
47
47
  * // tests/factories/posts.js
48
48
  *
49
- * var Factory = require('rosie').Factory;
50
- * var faker = require('faker');
49
+ * const Factory = require('rosie').Factory;
50
+ * const faker = require('@faker-js/faker');
51
51
  *
52
52
  * module.exports = new Factory()
53
53
  * // no need to set id, it will be set by REST API
@@ -264,6 +264,7 @@ class ApiDataFactory extends Helper {
264
264
  * @param {*} factory factory to use
265
265
  * @param {*} params predefined parameters
266
266
  * @param {*} options options for programmatically generate the attributes
267
+ * @returns {Promise<*>}
267
268
  */
268
269
  have(factory, params, options) {
269
270
  const item = this._createItem(factory, params, options);
@@ -124,6 +124,7 @@ const webRoot = 'body';
124
124
  class Appium extends Webdriver {
125
125
  /**
126
126
  * Appium Special Methods for Mobile only
127
+ * @augments WebDriver
127
128
  */
128
129
 
129
130
  constructor(config) {
@@ -492,6 +493,7 @@ class Appium extends Webdriver {
492
493
  *
493
494
  * @param {string} appId
494
495
  * @param {string} [bundleId] ID of bundle
496
+ * @return {Promise<any>}
495
497
  */
496
498
  async removeApp(appId, bundleId) {
497
499
  onlyForApps.call(this, 'Android');
@@ -728,7 +730,7 @@ class Appium extends Webdriver {
728
730
  * Switch to the specified context.
729
731
  *
730
732
  * @param {*} context the context to switch to
731
-
733
+ * @return {Promise<any>}
732
734
  */
733
735
  async _switchToContext(context) {
734
736
  return this.browser.switchContext(context);
@@ -774,7 +776,7 @@ class Appium extends Webdriver {
774
776
  * // or set context explicitly
775
777
  * I.switchToNative('SOME_OTHER_CONTEXT');
776
778
  * ```
777
- * @param {*} context
779
+ * @param {*} [context]
778
780
  * @return {Promise<void>}
779
781
  */
780
782
  async switchToNative(context = null) {
@@ -859,6 +861,7 @@ class Appium extends Webdriver {
859
861
  *
860
862
  * @param {'tapOutside' | 'pressKey'} [strategy] Desired strategy to close keyboard (‘tapOutside’ or ‘pressKey’)
861
863
  * @param {string} [key] Optional key
864
+ * @return {Promise<any>}
862
865
  */
863
866
  async hideDeviceKeyboard(strategy, key) {
864
867
  onlyForApps.call(this);
@@ -981,6 +984,7 @@ class Appium extends Webdriver {
981
984
  *
982
985
  * @param {object} from
983
986
  * @param {object} to
987
+ * @return {Promise<any>}
984
988
  *
985
989
  * Appium: support Android and iOS
986
990
  */
@@ -1213,6 +1217,7 @@ class Appium extends Webdriver {
1213
1217
  * Appium: support Android and iOS
1214
1218
  *
1215
1219
  * @param {Array} actions Array of touch actions
1220
+ * @return {Promise<any>}
1216
1221
  */
1217
1222
  async touchPerform(actions) {
1218
1223
  onlyForApps.call(this);
@@ -112,15 +112,15 @@ class GraphQL extends Helper {
112
112
  *
113
113
  * @param {object} operation
114
114
  * @param {object} headers
115
+ * @return {object} graphQLRequest
115
116
  */
116
117
  _prepareGraphQLRequest(operation, headers) {
117
- const request = {
118
+ return {
118
119
  baseURL: this.options.endpoint,
119
120
  method: 'POST',
120
121
  data: operation,
121
122
  headers,
122
123
  };
123
- return request;
124
124
  }
125
125
 
126
126
  /**
@@ -142,6 +142,7 @@ class GraphQL extends Helper {
142
142
  * @param {object} variables that may go along with the query
143
143
  * @param {object} options are additional query options
144
144
  * @param {object} headers
145
+ * @return Promise<any>
145
146
  */
146
147
  async sendQuery(query, variables, options = {}, headers = {}) {
147
148
  if (typeof query !== 'string') {
@@ -181,6 +182,7 @@ class GraphQL extends Helper {
181
182
  * @param {object} variables that may go along with the mutation
182
183
  * @param {object} options are additional query options
183
184
  * @param {object} headers
185
+ * @return Promise<any>
184
186
  */
185
187
  async sendMutation(mutation, variables, options = {}, headers = {}) {
186
188
  if (typeof mutation !== 'string') {
@@ -36,7 +36,7 @@ const GraphQL = require('./GraphQL');
36
36
  * Install [Rosie](https://github.com/rosiejs/rosie) and [Faker](https://www.npmjs.com/package/faker) libraries.
37
37
  *
38
38
  * ```sh
39
- * npm i rosie faker --save-dev
39
+ * npm i rosie @faker-js/faker --save-dev
40
40
  * ```
41
41
  *
42
42
  * Create a factory file for a resource.
@@ -46,8 +46,8 @@ const GraphQL = require('./GraphQL');
46
46
  * ```js
47
47
  * // tests/factories/users.js
48
48
  *
49
- * var Factory = require('rosie').Factory;
50
- * var faker = require('faker');
49
+ * const Factory = require('rosie').Factory;
50
+ * const faker = require('@faker-js/faker');
51
51
  *
52
52
  * // Used with a constructor function passed to Factory, so that the final build
53
53
  * // object matches the necessary pattern to be sent as the variables object.
@@ -218,7 +218,7 @@ class JSONResponse extends Helper {
218
218
  * Use it to perform custom checks of response data
219
219
  *
220
220
  * ```js
221
- * I.seeResponseValidByCallback({ data, status, expect } => {
221
+ * I.seeResponseValidByCallback(({ data, status, expect }) => {
222
222
  * expect(status).to.eql(200);
223
223
  * expect(data).keys.to.include(['user', 'company']);
224
224
  * });
@@ -92,6 +92,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
92
92
  * * `waitForTimeout`: (optional) default wait* timeout in ms. Default: 1000.
93
93
  * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'}
94
94
  * * `windowSize`: (optional) default window size. Set a dimension like `640x480`.
95
+ * * `colorScheme`: (optional) default color scheme. Possible values: `dark` | `light` | `no-preference`.
95
96
  * * `userAgent`: (optional) user-agent string.
96
97
  * * `locale`: (optional) locale string. Example: 'en-GB', 'de-DE', 'fr-FR', ...
97
98
  * * `manualStart`: (optional, default: false) - do not start browser before a test, start it manually inside a helper with `this.helpers["Playwright"]._startBrowser()`.
@@ -212,7 +213,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
212
213
  * }
213
214
  * ```
214
215
  *
215
- * #### Example #7: Launch test with a specifc user locale
216
+ * #### Example #7: Launch test with a specific user locale
216
217
  *
217
218
  * ```js
218
219
  * {
@@ -225,6 +226,19 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
225
226
  * }
226
227
  * ```
227
228
  *
229
+ * * #### Example #8: Launch test with a specific color scheme
230
+ *
231
+ * ```js
232
+ * {
233
+ * helpers: {
234
+ * Playwright : {
235
+ * url: "http://localhost",
236
+ * colorScheme: "dark",
237
+ * }
238
+ * }
239
+ * }
240
+ * ```
241
+ *
228
242
  * Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored.
229
243
  *
230
244
  * ## Access From Helpers
@@ -273,7 +287,7 @@ class Playwright extends Helper {
273
287
  waitForAction: 100,
274
288
  waitForTimeout: 1000,
275
289
  pressKeyDelay: 10,
276
- timeout: 1000,
290
+ timeout: 5000,
277
291
  fullPageScreenshots: false,
278
292
  disableScreenshots: false,
279
293
  ignoreLog: ['warning', 'log'],
@@ -411,6 +425,7 @@ class Playwright extends Helper {
411
425
  if (this.storageState) contextOptions.storageState = this.storageState;
412
426
  if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent;
413
427
  if (this.options.locale) contextOptions.locale = this.options.locale;
428
+ if (this.options.colorScheme) contextOptions.colorScheme = this.options.colorScheme;
414
429
  if (!this.browserContext || !restartsSession()) {
415
430
  this.browserContext = await this.browser.newContext(contextOptions); // Adding the HTTPSError ignore in the context so that we can ignore those errors
416
431
  }
@@ -539,6 +554,7 @@ class Playwright extends Helper {
539
554
  *
540
555
  * @param {string} description used to show in logs.
541
556
  * @param {function} fn async function that executed with Playwright helper as argument
557
+ * @return {Promise<any>}
542
558
  */
543
559
  usePlaywrightTo(description, fn) {
544
560
  return this._useTo(...arguments);
@@ -553,6 +569,7 @@ class Playwright extends Helper {
553
569
  * I.click('#triggerPopup');
554
570
  * I.acceptPopup();
555
571
  * ```
572
+ * @return {Promise<any>}
556
573
  */
557
574
  amAcceptingPopups() {
558
575
  popupStore.actionType = 'accept';
@@ -562,6 +579,7 @@ class Playwright extends Helper {
562
579
  * Accepts the active JavaScript native popup window, as created by window.alert|window.confirm|window.prompt.
563
580
  * Don't confuse popups with modal windows, as created by [various
564
581
  * libraries](http://jster.net/category/windows-modals-popups).
582
+ * @return {Promise<any>}
565
583
  */
566
584
  acceptPopup() {
567
585
  popupStore.assertPopupActionType('accept');
@@ -576,6 +594,7 @@ class Playwright extends Helper {
576
594
  * I.click('#triggerPopup');
577
595
  * I.cancelPopup();
578
596
  * ```
597
+ * @return {Promise<any>}
579
598
  */
580
599
  amCancellingPopups() {
581
600
  popupStore.actionType = 'cancel';
@@ -583,6 +602,7 @@ class Playwright extends Helper {
583
602
 
584
603
  /**
585
604
  * Dismisses the active JavaScript popup, as created by window.alert|window.confirm|window.prompt.
605
+ * @return {Promise<any>}
586
606
  */
587
607
  cancelPopup() {
588
608
  popupStore.assertPopupActionType('cancel');
@@ -600,6 +620,7 @@ class Playwright extends Helper {
600
620
  /**
601
621
  * Set current page
602
622
  * @param {object} page page to set
623
+ * @return {Promise<any>}
603
624
  */
604
625
  async _setPage(page) {
605
626
  page = await page;
@@ -624,6 +645,7 @@ class Playwright extends Helper {
624
645
  /**
625
646
  * Add the 'dialog' event listener to a page
626
647
  * @page {playwright.Page}
648
+ * @return {Promise<any>}
627
649
  *
628
650
  * The popup listener handles the dialog with the predefined action when it appears on the page.
629
651
  * It also saves a reference to the object which is used in seeInPopup.
@@ -654,6 +676,7 @@ class Playwright extends Helper {
654
676
 
655
677
  /**
656
678
  * Gets page URL including hash.
679
+ * @return {Promise<any>}
657
680
  */
658
681
  async _getPageUrl() {
659
682
  return this.executeScript(() => window.location.href);
@@ -826,6 +849,7 @@ class Playwright extends Helper {
826
849
  * ```
827
850
  *
828
851
  * @param {object} customHeaders headers to set
852
+ * @return {Promise<any>}
829
853
  */
830
854
  async haveRequestHeaders(customHeaders) {
831
855
  if (!customHeaders) {
@@ -851,7 +875,7 @@ class Playwright extends Helper {
851
875
  /**
852
876
  * {{> dragAndDrop }}
853
877
  *
854
- * [Additional options](https://playwright.dev/docs/api/class-page#page-drag-and-drop) can be passed as 3rd argument.
878
+ * @param {any} [options] [Additional options](https://playwright.dev/docs/api/class-page#page-drag-and-drop) can be passed as 3rd argument.
855
879
  *
856
880
  * ```js
857
881
  * // specify coordinates for source position
@@ -886,7 +910,7 @@ class Playwright extends Helper {
886
910
  /**
887
911
  * {{> scrollPageToBottom }}
888
912
  */
889
- scrollPageToBottom() {
913
+ async scrollPageToBottom() {
890
914
  return this.executeScript(() => {
891
915
  const body = document.body;
892
916
  const html = document.documentElement;
@@ -972,8 +996,7 @@ class Playwright extends Helper {
972
996
  * ```js
973
997
  * const elements = await this.helpers['Playwright']._locate({name: 'password'});
974
998
  * ```
975
- *
976
- *
999
+ * @return {Promise<any>}
977
1000
  */
978
1001
  async _locate(locator) {
979
1002
  const context = await this.context || await this._getContext();
@@ -987,6 +1010,7 @@ class Playwright extends Helper {
987
1010
  * ```js
988
1011
  * this.helpers['Playwright']._locateCheckable('I agree with terms and conditions').then // ...
989
1012
  * ```
1013
+ * @return {Promise<any>}
990
1014
  */
991
1015
  async _locateCheckable(locator, providedContext = null) {
992
1016
  const context = providedContext || await this._getContext();
@@ -1001,6 +1025,7 @@ class Playwright extends Helper {
1001
1025
  * ```js
1002
1026
  * this.helpers['Playwright']._locateClickable('Next page').then // ...
1003
1027
  * ```
1028
+ * @return {Promise<any>}
1004
1029
  */
1005
1030
  async _locateClickable(locator) {
1006
1031
  const context = await this._getContext();
@@ -1013,6 +1038,7 @@ class Playwright extends Helper {
1013
1038
  * ```js
1014
1039
  * this.helpers['Playwright']._locateFields('Your email').then // ...
1015
1040
  * ```
1041
+ * @return {Promise<any>}
1016
1042
  */
1017
1043
  async _locateFields(locator) {
1018
1044
  return findFields.call(this, locator);
@@ -1027,6 +1053,7 @@ class Playwright extends Helper {
1027
1053
  * ```
1028
1054
  *
1029
1055
  * @param {number} [num=1]
1056
+ * @return {Promise<any>}
1030
1057
  */
1031
1058
  async switchToNextTab(num = 1) {
1032
1059
  if (this.isElectron) {
@@ -1053,6 +1080,7 @@ class Playwright extends Helper {
1053
1080
  * I.switchToPreviousTab(2);
1054
1081
  * ```
1055
1082
  * @param {number} [num=1]
1083
+ * @return {Promise<any>}
1056
1084
  */
1057
1085
  async switchToPreviousTab(num = 1) {
1058
1086
  if (this.isElectron) {
@@ -1077,6 +1105,7 @@ class Playwright extends Helper {
1077
1105
  * ```js
1078
1106
  * I.closeCurrentTab();
1079
1107
  * ```
1108
+ * @return {Promise<any>}
1080
1109
  */
1081
1110
  async closeCurrentTab() {
1082
1111
  if (this.isElectron) {
@@ -1094,6 +1123,7 @@ class Playwright extends Helper {
1094
1123
  * ```js
1095
1124
  * I.closeOtherTabs();
1096
1125
  * ```
1126
+ * @return {Promise<any>}
1097
1127
  */
1098
1128
  async closeOtherTabs() {
1099
1129
  const pages = await this.browserContext.pages();
@@ -1118,6 +1148,7 @@ class Playwright extends Helper {
1118
1148
  * // enable mobile
1119
1149
  * I.openNewTab({ isMobile: true });
1120
1150
  * ```
1151
+ * @return {Promise<any>}
1121
1152
  */
1122
1153
  async openNewTab(options) {
1123
1154
  if (this.isElectron) {
@@ -1186,6 +1217,7 @@ class Playwright extends Helper {
1186
1217
  * ```
1187
1218
  *
1188
1219
  * @param {string} [fileName] set filename for downloaded file
1220
+ * @return {Promise<void>}
1189
1221
  */
1190
1222
  async handleDownloads(fileName = 'downloads') {
1191
1223
  this.page.waitForEvent('download').then(async (download) => {
@@ -1204,7 +1236,7 @@ class Playwright extends Helper {
1204
1236
  /**
1205
1237
  * {{> click }}
1206
1238
  *
1207
- * [Additional options](https://playwright.dev/docs/api/class-page#page-click) for click available as 3rd argument.
1239
+ * @param {any} [opts] [Additional options](https://playwright.dev/docs/api/class-page#page-click) for click available as 3rd argument.
1208
1240
  *
1209
1241
  * Examples:
1210
1242
  *
@@ -1223,6 +1255,7 @@ class Playwright extends Helper {
1223
1255
 
1224
1256
  /**
1225
1257
  * Clicks link and waits for navigation (deprecated)
1258
+ * @return {Promise<any>}
1226
1259
  */
1227
1260
  async clickLink(locator, context = null) {
1228
1261
  console.log('clickLink deprecated: Playwright automatically waits for navigation to happen.');
@@ -1992,7 +2025,7 @@ class Playwright extends Helper {
1992
2025
  test.artifacts = {};
1993
2026
  }
1994
2027
 
1995
- if (this.options.recordVideo && this.page.video()) {
2028
+ if (this.options.recordVideo && this.page && this.page.video()) {
1996
2029
  test.artifacts.video = await this.page.video().path();
1997
2030
  }
1998
2031
 
@@ -2004,7 +2037,7 @@ class Playwright extends Helper {
2004
2037
  }
2005
2038
 
2006
2039
  async _passed(test) {
2007
- if (this.options.recordVideo && this.page.video()) {
2040
+ if (this.options.recordVideo && this.page && this.page.video()) {
2008
2041
  if (this.options.keepVideoForPassedTests) {
2009
2042
  test.artifacts.video = await this.page.video().path();
2010
2043
  } else {
@@ -2270,6 +2303,7 @@ class Playwright extends Helper {
2270
2303
  *
2271
2304
  * @param {string|function} urlOrPredicate
2272
2305
  * @param {?number} [sec=null] seconds to wait
2306
+ * @return {Promise<any>}
2273
2307
  */
2274
2308
  async waitForRequest(urlOrPredicate, sec = null) {
2275
2309
  const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
@@ -2286,6 +2320,7 @@ class Playwright extends Helper {
2286
2320
  *
2287
2321
  * @param {string|function} urlOrPredicate
2288
2322
  * @param {?number} [sec=null] number of seconds to wait
2323
+ * @return {Promise<any>}
2289
2324
  */
2290
2325
  async waitForResponse(urlOrPredicate, sec = null) {
2291
2326
  const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
@@ -2357,6 +2392,7 @@ class Playwright extends Helper {
2357
2392
  * See [Playwright's reference](https://playwright.dev/docs/api/class-page?_highlight=waitfornavi#pagewaitfornavigationoptions)
2358
2393
  *
2359
2394
  * @param {*} opts
2395
+ * @return {Promise<any>}
2360
2396
  */
2361
2397
  async waitForNavigation(opts = {}) {
2362
2398
  opts = {
@@ -2427,9 +2463,9 @@ class Playwright extends Helper {
2427
2463
  * ```
2428
2464
  * This method allows intercepting and mocking requests & responses. [Learn more about it](https://playwright.dev/docs/network#handle-requests)
2429
2465
  *
2430
- * @param {string} [url] URL, regex or pattern for to match URL
2466
+ * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2431
2467
  * @param {function} [handler] a function to process request
2432
- *
2468
+ * @return {Promise<any>}
2433
2469
  */
2434
2470
  async mockRoute(url, handler) {
2435
2471
  return this.browserContext.route(...arguments);
@@ -2444,9 +2480,9 @@ class Playwright extends Helper {
2444
2480
  * ```
2445
2481
  * If no handler is passed, all mock requests for the rote are disabled.
2446
2482
  *
2447
- * @param {string} [url] URL, regex or pattern for to match URL
2483
+ * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2448
2484
  * @param {function} [handler] a function to process request
2449
- *
2485
+ * @return {Promise<any>}
2450
2486
  */
2451
2487
  async stopMockingRoute(url, handler) {
2452
2488
  return this.browserContext.unroute(...arguments);
@@ -98,7 +98,7 @@ class REST extends Helper {
98
98
  * I.amBearerAuthenticated(secret('heregoestoken'))
99
99
  * ```
100
100
  *
101
- * @param {string} accessToken Bearer access token
101
+ * @param {string | CodeceptJS.Secret} accessToken Bearer access token
102
102
  */
103
103
  amBearerAuthenticated(accessToken) {
104
104
  this.haveRequestHeaders({ Authorization: `Bearer ${accessToken}` });
@@ -112,6 +112,9 @@ class REST extends Helper {
112
112
  * @returns {Promise<*>} response
113
113
  */
114
114
  async _executeRequest(request) {
115
+ // Add custom headers. They can be set by amBearerAuthenticated() or haveRequestHeaders()
116
+ request.headers = { ...request.headers, ...this.headers };
117
+
115
118
  const _debugRequest = { ...request };
116
119
  this.axios.defaults.timeout = request.timeout || this.options.timeout;
117
120
 
@@ -2551,6 +2551,9 @@ class WebDriver extends Helper {
2551
2551
 
2552
2552
  /**
2553
2553
  * Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
2554
+ * @param {*} caps
2555
+ * @param {*} fn
2556
+ * @return {Promise<any>}
2554
2557
  */
2555
2558
  /* eslint-disable */
2556
2559
  runOnIOS(caps, fn) {
@@ -2558,6 +2561,9 @@ class WebDriver extends Helper {
2558
2561
 
2559
2562
  /**
2560
2563
  * Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
2564
+ * @param {*} caps
2565
+ * @param {*} fn
2566
+ * @return {Promise<any>}
2561
2567
  */
2562
2568
  runOnAndroid(caps, fn) {
2563
2569
  }