codeceptjs 3.6.10 → 3.7.0-beta.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 (105) hide show
  1. package/README.md +81 -110
  2. package/bin/codecept.js +2 -2
  3. package/docs/webapi/clearCookie.mustache +1 -1
  4. package/lib/actor.js +46 -36
  5. package/lib/assert/empty.js +3 -5
  6. package/lib/assert/equal.js +4 -7
  7. package/lib/assert/include.js +4 -6
  8. package/lib/assert/throws.js +2 -4
  9. package/lib/assert/truth.js +2 -2
  10. package/lib/codecept.js +87 -83
  11. package/lib/command/configMigrate.js +2 -4
  12. package/lib/command/definitions.js +5 -25
  13. package/lib/command/generate.js +10 -14
  14. package/lib/command/gherkin/snippets.js +10 -8
  15. package/lib/command/gherkin/steps.js +1 -1
  16. package/lib/command/info.js +1 -3
  17. package/lib/command/init.js +8 -12
  18. package/lib/command/interactive.js +1 -1
  19. package/lib/command/list.js +1 -1
  20. package/lib/command/run-multiple.js +12 -35
  21. package/lib/command/run-workers.js +10 -10
  22. package/lib/command/utils.js +5 -6
  23. package/lib/command/workers/runTests.js +14 -17
  24. package/lib/container.js +327 -237
  25. package/lib/data/context.js +10 -13
  26. package/lib/data/dataScenarioConfig.js +8 -8
  27. package/lib/data/dataTableArgument.js +6 -6
  28. package/lib/data/table.js +5 -11
  29. package/lib/els.js +177 -0
  30. package/lib/event.js +1 -0
  31. package/lib/heal.js +78 -80
  32. package/lib/helper/ApiDataFactory.js +3 -6
  33. package/lib/helper/Appium.js +15 -30
  34. package/lib/helper/FileSystem.js +3 -3
  35. package/lib/helper/GraphQLDataFactory.js +3 -3
  36. package/lib/helper/JSONResponse.js +57 -37
  37. package/lib/helper/Nightmare.js +35 -53
  38. package/lib/helper/Playwright.js +189 -251
  39. package/lib/helper/Protractor.js +54 -77
  40. package/lib/helper/Puppeteer.js +134 -232
  41. package/lib/helper/REST.js +5 -17
  42. package/lib/helper/TestCafe.js +21 -44
  43. package/lib/helper/WebDriver.js +103 -162
  44. package/lib/helper/testcafe/testcafe-utils.js +26 -27
  45. package/lib/listener/artifacts.js +2 -2
  46. package/lib/listener/emptyRun.js +58 -0
  47. package/lib/listener/exit.js +4 -4
  48. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  49. package/lib/listener/{timeout.js → globalTimeout.js} +8 -8
  50. package/lib/listener/helpers.js +15 -15
  51. package/lib/listener/mocha.js +1 -1
  52. package/lib/listener/steps.js +17 -12
  53. package/lib/listener/store.js +12 -0
  54. package/lib/mocha/asyncWrapper.js +204 -0
  55. package/lib/{interfaces → mocha}/bdd.js +3 -3
  56. package/lib/mocha/cli.js +257 -0
  57. package/lib/mocha/factory.js +104 -0
  58. package/lib/{interfaces → mocha}/featureConfig.js +11 -12
  59. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  60. package/lib/mocha/hooks.js +83 -0
  61. package/lib/mocha/index.js +12 -0
  62. package/lib/mocha/inject.js +24 -0
  63. package/lib/{interfaces → mocha}/scenarioConfig.js +10 -6
  64. package/lib/mocha/suite.js +55 -0
  65. package/lib/mocha/test.js +60 -0
  66. package/lib/mocha/types.d.ts +31 -0
  67. package/lib/mocha/ui.js +219 -0
  68. package/lib/output.js +28 -10
  69. package/lib/pause.js +159 -135
  70. package/lib/plugin/autoDelay.js +4 -4
  71. package/lib/plugin/autoLogin.js +6 -7
  72. package/lib/plugin/commentStep.js +1 -1
  73. package/lib/plugin/coverage.js +10 -19
  74. package/lib/plugin/customLocator.js +3 -3
  75. package/lib/plugin/debugErrors.js +2 -2
  76. package/lib/plugin/eachElement.js +1 -1
  77. package/lib/plugin/fakerTransform.js +1 -1
  78. package/lib/plugin/heal.js +6 -9
  79. package/lib/plugin/retryFailedStep.js +4 -4
  80. package/lib/plugin/retryTo.js +2 -2
  81. package/lib/plugin/screenshotOnFail.js +9 -36
  82. package/lib/plugin/selenoid.js +15 -35
  83. package/lib/plugin/stepByStepReport.js +51 -13
  84. package/lib/plugin/stepTimeout.js +4 -11
  85. package/lib/plugin/subtitles.js +4 -4
  86. package/lib/plugin/tryTo.js +1 -1
  87. package/lib/plugin/wdio.js +8 -10
  88. package/lib/recorder.js +142 -121
  89. package/lib/secret.js +1 -1
  90. package/lib/step.js +160 -144
  91. package/lib/store.js +6 -2
  92. package/lib/template/heal.js +2 -11
  93. package/lib/utils.js +224 -216
  94. package/lib/within.js +73 -55
  95. package/lib/workers.js +265 -261
  96. package/package.json +46 -47
  97. package/typings/index.d.ts +172 -184
  98. package/typings/promiseBasedTypes.d.ts +53 -516
  99. package/typings/types.d.ts +127 -587
  100. package/lib/cli.js +0 -256
  101. package/lib/helper/ExpectHelper.js +0 -391
  102. package/lib/helper/SoftExpectHelper.js +0 -381
  103. package/lib/mochaFactory.js +0 -113
  104. package/lib/scenario.js +0 -224
  105. package/lib/ui.js +0 -236
@@ -185,9 +185,7 @@ class Appium extends Webdriver {
185
185
 
186
186
  webdriverio = require('webdriverio')
187
187
  if (!config.appiumV2) {
188
- console.log(
189
- 'The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Please migrating to Appium 2.x by adding appiumV2: true to your config.',
190
- )
188
+ console.log('The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Please migrating to Appium 2.x by adding appiumV2: true to your config.')
191
189
  console.log('More info: https://bit.ly/appium-v2-migration')
192
190
  console.log('This Appium 1.x support will be removed in next major release.')
193
191
  }
@@ -234,20 +232,14 @@ class Appium extends Webdriver {
234
232
 
235
233
  config.baseUrl = config.url || config.baseUrl
236
234
  if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
237
- config.capabilities =
238
- this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities
235
+ config.capabilities = this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities
239
236
  }
240
237
 
241
238
  if (this.appiumV2) {
242
- config.capabilities[`${vendorPrefix.appium}:deviceName`] =
243
- config[`${vendorPrefix.appium}:device`] || config.capabilities[`${vendorPrefix.appium}:deviceName`]
244
- config.capabilities[`${vendorPrefix.appium}:browserName`] =
245
- config[`${vendorPrefix.appium}:browser`] || config.capabilities[`${vendorPrefix.appium}:browserName`]
246
- config.capabilities[`${vendorPrefix.appium}:app`] =
247
- config[`${vendorPrefix.appium}:app`] || config.capabilities[`${vendorPrefix.appium}:app`]
248
- config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] =
249
- config[`${vendorPrefix.appium}:tunnelIdentifier`] ||
250
- config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] // Adding the code to connect to sauce labs via sauce tunnel
239
+ config.capabilities[`${vendorPrefix.appium}:deviceName`] = config[`${vendorPrefix.appium}:device`] || config.capabilities[`${vendorPrefix.appium}:deviceName`]
240
+ config.capabilities[`${vendorPrefix.appium}:browserName`] = config[`${vendorPrefix.appium}:browser`] || config.capabilities[`${vendorPrefix.appium}:browserName`]
241
+ config.capabilities[`${vendorPrefix.appium}:app`] = config[`${vendorPrefix.appium}:app`] || config.capabilities[`${vendorPrefix.appium}:app`]
242
+ config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] = config[`${vendorPrefix.appium}:tunnelIdentifier`] || config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] // Adding the code to connect to sauce labs via sauce tunnel
251
243
  } else {
252
244
  config.capabilities.deviceName = config.device || config.capabilities.deviceName
253
245
  config.capabilities.browserName = config.browser || config.capabilities.browserName
@@ -1304,14 +1296,14 @@ class Appium extends Webdriver {
1304
1296
  }
1305
1297
  return browser
1306
1298
  .$$(parseLocator.call(this, searchableLocator))
1307
- .then((els) => els.length && els[0].isDisplayed())
1308
- .then((res) => {
1299
+ .then(els => els.length && els[0].isDisplayed())
1300
+ .then(res => {
1309
1301
  if (res) {
1310
1302
  return true
1311
1303
  }
1312
1304
  return this[direction](scrollLocator, offset, speed)
1313
1305
  .getSource()
1314
- .then((source) => {
1306
+ .then(source => {
1315
1307
  if (source === currentSource) {
1316
1308
  err = true
1317
1309
  } else {
@@ -1324,12 +1316,9 @@ class Appium extends Webdriver {
1324
1316
  timeout * 1000,
1325
1317
  errorMsg,
1326
1318
  )
1327
- .catch((e) => {
1319
+ .catch(e => {
1328
1320
  if (e.message.indexOf('timeout') && e.type !== 'NoSuchElement') {
1329
- throw new AssertionFailedError(
1330
- { customMessage: `Scroll to the end and element ${searchableLocator} was not found` },
1331
- '',
1332
- )
1321
+ throw new AssertionFailedError({ customMessage: `Scroll to the end and element ${searchableLocator} was not found` }, '')
1333
1322
  } else {
1334
1323
  throw e
1335
1324
  }
@@ -1386,8 +1375,8 @@ class Appium extends Webdriver {
1386
1375
  */
1387
1376
  async pullFile(path, dest) {
1388
1377
  onlyForApps.call(this)
1389
- return this.browser.pullFile(path).then((res) =>
1390
- fs.writeFile(dest, Buffer.from(res, 'base64'), (err) => {
1378
+ return this.browser.pullFile(path).then(res =>
1379
+ fs.writeFile(dest, Buffer.from(res, 'base64'), err => {
1391
1380
  if (err) {
1392
1381
  return false
1393
1382
  }
@@ -1759,12 +1748,8 @@ function parseLocator(locator) {
1759
1748
  }
1760
1749
 
1761
1750
  locator = new Locator(locator, 'xpath')
1762
- if (locator.type === 'css' && !this.isWeb)
1763
- throw new Error(
1764
- 'Unable to use css locators in apps. Locator strategies for this request: xpath, id, class name or accessibility id',
1765
- )
1766
- if (locator.type === 'name' && !this.isWeb)
1767
- throw new Error("Can't locate element by name in Native context. Use either ID, class name or accessibility id")
1751
+ if (locator.type === 'css' && !this.isWeb) throw new Error('Unable to use css locators in apps. Locator strategies for this request: xpath, id, class name or accessibility id')
1752
+ if (locator.type === 'name' && !this.isWeb) throw new Error("Can't locate element by name in Native context. Use either ID, class name or accessibility id")
1768
1753
  if (locator.type === 'id' && !this.isWeb && this.platform === 'android') return `//*[@resource-id='${locator.value}']`
1769
1754
  return locator.simplify()
1770
1755
  }
@@ -105,7 +105,7 @@ class FileSystem extends Helper {
105
105
  */
106
106
  seeFileNameMatching(text) {
107
107
  assert.ok(
108
- this.grabFileNames().some((file) => file.includes(text)),
108
+ this.grabFileNames().some(file => file.includes(text)),
109
109
  `File name which contains ${text} not found in ${this.dir}`,
110
110
  )
111
111
  }
@@ -175,7 +175,7 @@ class FileSystem extends Helper {
175
175
  * ```
176
176
  */
177
177
  grabFileNames() {
178
- return fs.readdirSync(this.dir).filter((item) => !fs.lstatSync(path.join(this.dir, item)).isDirectory())
178
+ return fs.readdirSync(this.dir).filter(item => !fs.lstatSync(path.join(this.dir, item)).isDirectory())
179
179
  }
180
180
  }
181
181
 
@@ -216,7 +216,7 @@ function isFileExists(file, timeout) {
216
216
  }
217
217
  })
218
218
 
219
- fs.access(file, fs.constants.R_OK, (err) => {
219
+ fs.access(file, fs.constants.R_OK, err => {
220
220
  if (!err) {
221
221
  clearTimeout(timer)
222
222
  watcher.close()
@@ -170,7 +170,7 @@ class GraphQLDataFactory extends Helper {
170
170
  this.factories = this.config.factories
171
171
 
172
172
  this.created = {}
173
- Object.keys(this.factories).forEach((f) => (this.created[f] = []))
173
+ Object.keys(this.factories).forEach(f => (this.created[f] = []))
174
174
  }
175
175
 
176
176
  static _checkRequirements() {
@@ -278,7 +278,7 @@ class GraphQLDataFactory extends Helper {
278
278
  */
279
279
  _requestCreate(operation, variables) {
280
280
  const { query } = this.factories[operation]
281
- return this.graphqlHelper.sendMutation(query, variables).then((response) => {
281
+ return this.graphqlHelper.sendMutation(query, variables).then(response => {
282
282
  const data = response.data.data[operation]
283
283
  this.created[operation].push(data)
284
284
  this.debugSection('Created', `record: ${data}`)
@@ -297,7 +297,7 @@ class GraphQLDataFactory extends Helper {
297
297
  const deleteOperation = this.factories[operation].revert(data)
298
298
  const { query, variables } = deleteOperation
299
299
 
300
- return this.graphqlHelper.sendMutation(query, variables).then((response) => {
300
+ return this.graphqlHelper.sendMutation(query, variables).then(response => {
301
301
  const idx = this.created[operation].indexOf(data)
302
302
  this.debugSection('Deleted', `record: ${response.data.data}`)
303
303
  this.created[operation].splice(idx, 1)
@@ -1,12 +1,5 @@
1
1
  const Helper = require('@codeceptjs/helper')
2
-
3
- let expect
4
-
5
- import('chai').then((chai) => {
6
- expect = chai.expect
7
- chai.use(require('chai-deep-match'))
8
- })
9
-
2
+ const assert = require('assert')
10
3
  const joi = require('joi')
11
4
 
12
5
  /**
@@ -77,12 +70,10 @@ class JSONResponse extends Helper {
77
70
  _beforeSuite() {
78
71
  this.response = null
79
72
  if (!this.helpers[this.options.requestHelper]) {
80
- throw new Error(
81
- `Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`,
82
- )
73
+ throw new Error(`Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`)
83
74
  }
84
75
  // connect to REST helper
85
- this.helpers[this.options.requestHelper].config.onResponse = (response) => {
76
+ this.helpers[this.options.requestHelper].config.onResponse = response => {
86
77
  this.response = response
87
78
  }
88
79
  }
@@ -110,7 +101,7 @@ class JSONResponse extends Helper {
110
101
  */
111
102
  seeResponseCodeIs(code) {
112
103
  this._checkResponseReady()
113
- expect(this.response.status).to.eql(code, 'Response code is not the same as expected')
104
+ assert.strictEqual(this.response.status, code, 'Response code is not the same as expected')
114
105
  }
115
106
 
116
107
  /**
@@ -124,7 +115,7 @@ class JSONResponse extends Helper {
124
115
  */
125
116
  dontSeeResponseCodeIs(code) {
126
117
  this._checkResponseReady()
127
- expect(this.response.status).not.to.eql(code)
118
+ assert.notStrictEqual(this.response.status, code)
128
119
  }
129
120
 
130
121
  /**
@@ -132,8 +123,7 @@ class JSONResponse extends Helper {
132
123
  */
133
124
  seeResponseCodeIsClientError() {
134
125
  this._checkResponseReady()
135
- expect(this.response.status).to.be.gte(400)
136
- expect(this.response.status).to.be.lt(500)
126
+ assert(this.response.status >= 400 && this.response.status < 500)
137
127
  }
138
128
 
139
129
  /**
@@ -141,8 +131,7 @@ class JSONResponse extends Helper {
141
131
  */
142
132
  seeResponseCodeIsRedirection() {
143
133
  this._checkResponseReady()
144
- expect(this.response.status).to.be.gte(300)
145
- expect(this.response.status).to.be.lt(400)
134
+ assert(this.response.status >= 300 && this.response.status < 400)
146
135
  }
147
136
 
148
137
  /**
@@ -150,8 +139,7 @@ class JSONResponse extends Helper {
150
139
  */
151
140
  seeResponseCodeIsServerError() {
152
141
  this._checkResponseReady()
153
- expect(this.response.status).to.be.gte(500)
154
- expect(this.response.status).to.be.lt(600)
142
+ assert(this.response.status >= 500 && this.response.status < 600)
155
143
  }
156
144
 
157
145
  /**
@@ -164,8 +152,7 @@ class JSONResponse extends Helper {
164
152
  */
165
153
  seeResponseCodeIsSuccessful() {
166
154
  this._checkResponseReady()
167
- expect(this.response.status).to.be.gte(200)
168
- expect(this.response.status).to.be.lt(300)
155
+ assert(this.response.status >= 200 && this.response.status < 300)
169
156
  }
170
157
 
171
158
  /**
@@ -188,17 +175,19 @@ class JSONResponse extends Helper {
188
175
  seeResponseContainsJson(json = {}) {
189
176
  this._checkResponseReady()
190
177
  if (Array.isArray(this.response.data)) {
191
- let fails = 0
178
+ let found = false
192
179
  for (const el of this.response.data) {
193
180
  try {
194
- expect(el).to.deep.match(json)
181
+ this._assertContains(el, json)
182
+ found = true
183
+ break
195
184
  } catch (err) {
196
- fails++
185
+ continue
197
186
  }
198
187
  }
199
- expect(fails < this.response.data.length, `No elements in array matched ${JSON.stringify(json)}`).to.be.true
188
+ assert(found, `No elements in array matched ${JSON.stringify(json)}`)
200
189
  } else {
201
- expect(this.response.data).to.deep.match(json)
190
+ this._assertContains(this.response.data, json)
202
191
  }
203
192
  }
204
193
 
@@ -222,9 +211,22 @@ class JSONResponse extends Helper {
222
211
  dontSeeResponseContainsJson(json = {}) {
223
212
  this._checkResponseReady()
224
213
  if (Array.isArray(this.response.data)) {
225
- this.response.data.forEach((data) => expect(data).not.to.deep.match(json))
214
+ for (const data of this.response.data) {
215
+ try {
216
+ this._assertContains(data, json)
217
+ assert.fail(`Found matching element: ${JSON.stringify(data)}`)
218
+ } catch (err) {
219
+ // expected to fail
220
+ continue
221
+ }
222
+ }
226
223
  } else {
227
- expect(this.response.data).not.to.deep.match(json)
224
+ try {
225
+ this._assertContains(this.response.data, json)
226
+ assert.fail('Response contains the JSON')
227
+ } catch (err) {
228
+ // expected to fail
229
+ }
228
230
  }
229
231
  }
230
232
 
@@ -250,20 +252,27 @@ class JSONResponse extends Helper {
250
252
  seeResponseContainsKeys(keys = []) {
251
253
  this._checkResponseReady()
252
254
  if (Array.isArray(this.response.data)) {
253
- this.response.data.forEach((data) => expect(data).to.include.keys(keys))
255
+ for (const data of this.response.data) {
256
+ for (const key of keys) {
257
+ assert(key in data, `Key "${key}" is not found in ${JSON.stringify(data)}`)
258
+ }
259
+ }
254
260
  } else {
255
- expect(this.response.data).to.include.keys(keys)
261
+ for (const key of keys) {
262
+ assert(key in this.response.data, `Key "${key}" is not found in ${JSON.stringify(this.response.data)}`)
263
+ }
256
264
  }
257
265
  }
258
266
 
259
267
  /**
260
- * Executes a callback function passing in `response` object and chai assertions with `expect`
268
+ * Executes a callback function passing in `response` object and assert
261
269
  * Use it to perform custom checks of response data
262
270
  *
263
271
  * ```js
264
- * I.seeResponseValidByCallback(({ data, status, expect }) => {
265
- * expect(status).to.eql(200);
266
- * expect(data).keys.to.include(['user', 'company']);
272
+ * I.seeResponseValidByCallback(({ data, status }) => {
273
+ * assert.strictEqual(status, 200);
274
+ * assert('user' in data);
275
+ * assert('company' in data);
267
276
  * });
268
277
  * ```
269
278
  *
@@ -271,7 +280,7 @@ class JSONResponse extends Helper {
271
280
  */
272
281
  seeResponseValidByCallback(fn) {
273
282
  this._checkResponseReady()
274
- fn({ ...this.response, expect })
283
+ fn({ ...this.response, assert })
275
284
  const body = fn.toString()
276
285
  fn.toString = () => `${body.split('\n')[1]}...`
277
286
  }
@@ -288,7 +297,7 @@ class JSONResponse extends Helper {
288
297
  */
289
298
  seeResponseEquals(resp) {
290
299
  this._checkResponseReady()
291
- expect(this.response.data).to.deep.equal(resp)
300
+ assert.deepStrictEqual(this.response.data, resp)
292
301
  }
293
302
 
294
303
  /**
@@ -335,6 +344,17 @@ class JSONResponse extends Helper {
335
344
  _checkResponseReady() {
336
345
  if (!this.response) throw new Error('Response is not available')
337
346
  }
347
+
348
+ _assertContains(actual, expected) {
349
+ for (const key in expected) {
350
+ assert(key in actual, `Key "${key}" not found in ${JSON.stringify(actual)}`)
351
+ if (typeof expected[key] === 'object' && expected[key] !== null) {
352
+ this._assertContains(actual[key], expected[key])
353
+ } else {
354
+ assert.deepStrictEqual(actual[key], expected[key], `Values for key "${key}" don't match`)
355
+ }
356
+ }
357
+ }
338
358
  }
339
359
 
340
360
  module.exports = JSONResponse
@@ -111,13 +111,7 @@ class Nightmare extends Helper {
111
111
  const by = Object.keys(locator)[0]
112
112
  const value = locator[by]
113
113
 
114
- this.evaluate_now(
115
- (by, locator, contextEl) => window.codeceptjs.findAndStoreElements(by, locator, contextEl),
116
- done,
117
- by,
118
- value,
119
- contextEl,
120
- )
114
+ this.evaluate_now((by, locator, contextEl) => window.codeceptjs.findAndStoreElements(by, locator, contextEl), done, by, value, contextEl)
121
115
  })
122
116
 
123
117
  this.Nightmare.action('findElement', function (locator, contextEl, done) {
@@ -244,7 +238,7 @@ class Nightmare extends Helper {
244
238
  nodeId: queryResult.nodeId,
245
239
  files: pathsToUpload,
246
240
  },
247
- (err) => {
241
+ err => {
248
242
  if (Object.keys(err).length > 0) {
249
243
  parent.emit('log', 'problem setting input', err)
250
244
  return done(err)
@@ -351,7 +345,7 @@ class Nightmare extends Helper {
351
345
  const outputFile = path.join(global.output_dir, fileName)
352
346
  this.debug(`HAR is saving to ${outputFile}`)
353
347
 
354
- await this.browser.getHAR().then((har) => {
348
+ await this.browser.getHAR().then(har => {
355
349
  require('fs').writeFileSync(outputFile, JSON.stringify({ log: har }))
356
350
  })
357
351
  }
@@ -361,7 +355,7 @@ class Nightmare extends Helper {
361
355
  }
362
356
 
363
357
  async _stopBrowser() {
364
- return this.browser.end().catch((error) => {
358
+ return this.browser.end().catch(error => {
365
359
  this.debugSection('Error on End', error)
366
360
  })
367
361
  }
@@ -445,7 +439,7 @@ class Nightmare extends Helper {
445
439
  // navigating to the same url will cause an error in nightmare, so don't do it
446
440
  return
447
441
  }
448
- return this.browser.goto(url, headers).then((res) => {
442
+ return this.browser.goto(url, headers).then(res => {
449
443
  this.debugSection('URL', res.url)
450
444
  this.debugSection('Code', res.code)
451
445
  this.debugSection('Headers', JSON.stringify(res.headers))
@@ -535,7 +529,7 @@ class Nightmare extends Helper {
535
529
  locator = new Locator(locator, 'css')
536
530
  const num = await this.browser.evaluate(
537
531
  (by, locator) => {
538
- return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
532
+ return window.codeceptjs.findElements(by, locator).filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length
539
533
  },
540
534
  locator.type,
541
535
  locator.value,
@@ -551,7 +545,7 @@ class Nightmare extends Helper {
551
545
  locator = new Locator(locator, 'css')
552
546
  const num = await this.browser.evaluate(
553
547
  (by, locator) => {
554
- return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
548
+ return window.codeceptjs.findElements(by, locator).filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length
555
549
  },
556
550
  locator.type,
557
551
  locator.value,
@@ -598,9 +592,7 @@ class Nightmare extends Helper {
598
592
  */
599
593
  async seeNumberOfElements(locator, num) {
600
594
  const elements = await this._locate(locator)
601
- return equals(
602
- `expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`,
603
- ).assert(elements.length, num)
595
+ return equals(`expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`).assert(elements.length, num)
604
596
  }
605
597
 
606
598
  /**
@@ -608,10 +600,7 @@ class Nightmare extends Helper {
608
600
  */
609
601
  async seeNumberOfVisibleElements(locator, num) {
610
602
  const res = await this.grabNumberOfVisibleElements(locator)
611
- return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(
612
- res,
613
- num,
614
- )
603
+ return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(res, num)
615
604
  }
616
605
 
617
606
  /**
@@ -622,7 +611,7 @@ class Nightmare extends Helper {
622
611
 
623
612
  const num = await this.browser.evaluate(
624
613
  (by, locator) => {
625
- return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
614
+ return window.codeceptjs.findElements(by, locator).filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length
626
615
  },
627
616
  locator.type,
628
617
  locator.value,
@@ -637,7 +626,7 @@ class Nightmare extends Helper {
637
626
  async click(locator, context = null) {
638
627
  const el = await findClickable.call(this, locator, context)
639
628
  assertElementExists(el, locator, 'Clickable')
640
- return this.browser.evaluate((el) => window.codeceptjs.clickEl(el), el).wait(this.options.waitForAction)
629
+ return this.browser.evaluate(el => window.codeceptjs.clickEl(el), el).wait(this.options.waitForAction)
641
630
  }
642
631
 
643
632
  /**
@@ -646,7 +635,7 @@ class Nightmare extends Helper {
646
635
  async doubleClick(locator, context = null) {
647
636
  const el = await findClickable.call(this, locator, context)
648
637
  assertElementExists(el, locator, 'Clickable')
649
- return this.browser.evaluate((el) => window.codeceptjs.doubleClickEl(el), el).wait(this.options.waitForAction)
638
+ return this.browser.evaluate(el => window.codeceptjs.doubleClickEl(el), el).wait(this.options.waitForAction)
650
639
  }
651
640
 
652
641
  /**
@@ -655,7 +644,7 @@ class Nightmare extends Helper {
655
644
  async rightClick(locator, context = null) {
656
645
  const el = await findClickable.call(this, locator, context)
657
646
  assertElementExists(el, locator, 'Clickable')
658
- return this.browser.evaluate((el) => window.codeceptjs.rightClickEl(el), el).wait(this.options.waitForAction)
647
+ return this.browser.evaluate(el => window.codeceptjs.rightClickEl(el), el).wait(this.options.waitForAction)
659
648
  }
660
649
 
661
650
  /**
@@ -665,9 +654,7 @@ class Nightmare extends Helper {
665
654
  locator = new Locator(locator, 'css')
666
655
  const el = await this.browser.findElement(locator.toStrict())
667
656
  assertElementExists(el, locator)
668
- return this.browser
669
- .evaluate((el, x, y) => window.codeceptjs.hoverEl(el, x, y), el, offsetX, offsetY)
670
- .wait(this.options.waitForAction) // wait for hover event to happen
657
+ return this.browser.evaluate((el, x, y) => window.codeceptjs.hoverEl(el, x, y), el, offsetX, offsetY).wait(this.options.waitForAction) // wait for hover event to happen
671
658
  }
672
659
 
673
660
  /**
@@ -676,7 +663,7 @@ class Nightmare extends Helper {
676
663
  * Wrapper for synchronous [evaluate](https://github.com/segmentio/nightmare#evaluatefn-arg1-arg2)
677
664
  */
678
665
  async executeScript(...args) {
679
- return this.browser.evaluate.apply(this.browser, args).catch((err) => err) // Nightmare's first argument is error :(
666
+ return this.browser.evaluate.apply(this.browser, args).catch(err => err) // Nightmare's first argument is error :(
680
667
  }
681
668
 
682
669
  /**
@@ -686,7 +673,7 @@ class Nightmare extends Helper {
686
673
  * Unlike NightmareJS implementation calling `done` will return its first argument.
687
674
  */
688
675
  async executeAsyncScript(...args) {
689
- return this.browser.evaluate.apply(this.browser, args).catch((err) => err) // Nightmare's first argument is error :(
676
+ return this.browser.evaluate.apply(this.browser, args).catch(err => err) // Nightmare's first argument is error :(
690
677
  }
691
678
 
692
679
  /**
@@ -705,7 +692,7 @@ class Nightmare extends Helper {
705
692
  async checkOption(field, context = null) {
706
693
  const els = await findCheckable.call(this, field, context)
707
694
  assertElementExists(els[0], field, 'Checkbox or radio')
708
- return this.browser.evaluate((els) => window.codeceptjs.checkEl(els[0]), els).wait(this.options.waitForAction)
695
+ return this.browser.evaluate(els => window.codeceptjs.checkEl(els[0]), els).wait(this.options.waitForAction)
709
696
  }
710
697
 
711
698
  /**
@@ -714,7 +701,7 @@ class Nightmare extends Helper {
714
701
  async uncheckOption(field, context = null) {
715
702
  const els = await findCheckable.call(this, field, context)
716
703
  assertElementExists(els[0], field, 'Checkbox or radio')
717
- return this.browser.evaluate((els) => window.codeceptjs.unCheckEl(els[0]), els).wait(this.options.waitForAction)
704
+ return this.browser.evaluate(els => window.codeceptjs.unCheckEl(els[0]), els).wait(this.options.waitForAction)
718
705
  }
719
706
 
720
707
  /**
@@ -826,7 +813,7 @@ class Nightmare extends Helper {
826
813
  locator = new Locator(locator, 'css')
827
814
  const els = await this.browser.findElements(locator.toStrict())
828
815
  const texts = []
829
- const getText = (el) => window.codeceptjs.fetchElement(el).innerText
816
+ const getText = el => window.codeceptjs.fetchElement(el).innerText
830
817
  for (const el of els) {
831
818
  texts.push(await this.browser.evaluate(getText, el))
832
819
  }
@@ -855,7 +842,7 @@ class Nightmare extends Helper {
855
842
  locator = new Locator(locator, 'css')
856
843
  const els = await this.browser.findElements(locator.toStrict())
857
844
  const values = []
858
- const getValues = (el) => window.codeceptjs.fetchElement(el).value
845
+ const getValues = el => window.codeceptjs.fetchElement(el).value
859
846
  for (const el of els) {
860
847
  values.push(await this.browser.evaluate(getValues, el))
861
848
  }
@@ -887,9 +874,7 @@ class Nightmare extends Helper {
887
874
 
888
875
  for (let index = 0; index < els.length; index++) {
889
876
  const el = els[index]
890
- array.push(
891
- await this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr),
892
- )
877
+ array.push(await this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr))
893
878
  }
894
879
 
895
880
  return array
@@ -921,7 +906,7 @@ class Nightmare extends Helper {
921
906
 
922
907
  for (let index = 0; index < els.length; index++) {
923
908
  const el = els[index]
924
- array.push(await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).innerHTML, el))
909
+ array.push(await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).innerHTML, el))
925
910
  }
926
911
  this.debugSection('GrabHTML', array)
927
912
 
@@ -953,7 +938,7 @@ class Nightmare extends Helper {
953
938
 
954
939
  const getCssPropForElement = async (el, prop) => {
955
940
  return (
956
- await this.browser.evaluate((el) => {
941
+ await this.browser.evaluate(el => {
957
942
  return window.getComputedStyle(window.codeceptjs.fetchElement(el))
958
943
  }, el)
959
944
  )[toCamelCase(prop)]
@@ -1083,7 +1068,7 @@ class Nightmare extends Helper {
1083
1068
  * {{> wait }}
1084
1069
  */
1085
1070
  async wait(sec) {
1086
- return new Promise((done) => {
1071
+ return new Promise(done => {
1087
1072
  setTimeout(done, sec * 1000)
1088
1073
  })
1089
1074
  }
@@ -1106,7 +1091,7 @@ class Nightmare extends Helper {
1106
1091
  locator.value,
1107
1092
  text,
1108
1093
  )
1109
- .catch((err) => {
1094
+ .catch(err => {
1110
1095
  if (err.message.indexOf('Cannot read property') > -1) {
1111
1096
  throw new Error(`element (${JSON.stringify(context)}) is not in DOM. Unable to wait text.`)
1112
1097
  } else if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
@@ -1132,7 +1117,7 @@ class Nightmare extends Helper {
1132
1117
  locator.type,
1133
1118
  locator.value,
1134
1119
  )
1135
- .catch((err) => {
1120
+ .catch(err => {
1136
1121
  if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1137
1122
  throw new Error(`element (${JSON.stringify(locator)}) still not visible on page after ${sec} sec`)
1138
1123
  } else throw err
@@ -1163,7 +1148,7 @@ class Nightmare extends Helper {
1163
1148
  locator.type,
1164
1149
  locator.value,
1165
1150
  )
1166
- .catch((err) => {
1151
+ .catch(err => {
1167
1152
  if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1168
1153
  throw new Error(`element (${JSON.stringify(locator)}) still visible after ${sec} sec`)
1169
1154
  } else throw err
@@ -1179,7 +1164,7 @@ class Nightmare extends Helper {
1179
1164
 
1180
1165
  return this.browser
1181
1166
  .wait((by, locator) => window.codeceptjs.findElement(by, locator) !== null, locator.type, locator.value)
1182
- .catch((err) => {
1167
+ .catch(err => {
1183
1168
  if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1184
1169
  throw new Error(`element (${JSON.stringify(locator)}) still not present on page after ${sec} sec`)
1185
1170
  } else throw err
@@ -1203,7 +1188,7 @@ class Nightmare extends Helper {
1203
1188
 
1204
1189
  return this.browser
1205
1190
  .wait((by, locator) => window.codeceptjs.findElement(by, locator) === null, locator.type, locator.value)
1206
- .catch((err) => {
1191
+ .catch(err => {
1207
1192
  if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1208
1193
  throw new Error(`element (${JSON.stringify(locator)}) still on page after ${sec} sec`)
1209
1194
  } else throw err
@@ -1348,10 +1333,7 @@ class Nightmare extends Helper {
1348
1333
  return this.executeScript(function () {
1349
1334
  const body = document.body
1350
1335
  const html = document.documentElement
1351
- window.scrollTo(
1352
- 0,
1353
- Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
1354
- )
1336
+ window.scrollTo(0, Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight))
1355
1337
  })
1356
1338
  }
1357
1339
 
@@ -1390,7 +1372,7 @@ async function proceedSee(assertType, text, context) {
1390
1372
 
1391
1373
  const texts = await this.browser.evaluate(
1392
1374
  (by, locator) => {
1393
- return window.codeceptjs.findElements(by, locator).map((el) => el.innerText)
1375
+ return window.codeceptjs.findElements(by, locator).map(el => el.innerText)
1394
1376
  },
1395
1377
  locator.type,
1396
1378
  locator.value,
@@ -1402,8 +1384,8 @@ async function proceedSee(assertType, text, context) {
1402
1384
  async function proceedSeeInField(assertType, field, value) {
1403
1385
  const el = await findField.call(this, field)
1404
1386
  assertElementExists(el, field, 'Field')
1405
- const tag = await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).tagName, el)
1406
- const fieldVal = await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).value, el)
1387
+ const tag = await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).tagName, el)
1388
+ const fieldVal = await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).value, el)
1407
1389
  if (tag === 'select') {
1408
1390
  // locate option by values and check them
1409
1391
  const text = await this.browser.evaluate(
@@ -1421,8 +1403,8 @@ async function proceedSeeInField(assertType, field, value) {
1421
1403
  async function proceedIsChecked(assertType, option) {
1422
1404
  const els = await findCheckable.call(this, option)
1423
1405
  assertElementExists(els, option, 'Checkable')
1424
- const selected = await this.browser.evaluate((els) => {
1425
- return els.map((el) => window.codeceptjs.fetchElement(el).checked).reduce((prev, cur) => prev || cur)
1406
+ const selected = await this.browser.evaluate(els => {
1407
+ return els.map(el => window.codeceptjs.fetchElement(el).checked).reduce((prev, cur) => prev || cur)
1426
1408
  }, els)
1427
1409
  return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
1428
1410
  }