codeceptjs 4.0.0-beta.4 → 4.0.0-beta.5

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 (150) hide show
  1. package/README.md +134 -119
  2. package/bin/codecept.js +12 -2
  3. package/bin/test-server.js +53 -0
  4. package/docs/webapi/clearCookie.mustache +1 -1
  5. package/lib/actor.js +66 -102
  6. package/lib/ai.js +130 -121
  7. package/lib/assert/empty.js +3 -5
  8. package/lib/assert/equal.js +4 -7
  9. package/lib/assert/include.js +4 -6
  10. package/lib/assert/throws.js +2 -4
  11. package/lib/assert/truth.js +2 -2
  12. package/lib/codecept.js +139 -87
  13. package/lib/command/check.js +201 -0
  14. package/lib/command/configMigrate.js +2 -4
  15. package/lib/command/definitions.js +8 -26
  16. package/lib/command/generate.js +10 -14
  17. package/lib/command/gherkin/snippets.js +75 -73
  18. package/lib/command/gherkin/steps.js +1 -1
  19. package/lib/command/info.js +42 -8
  20. package/lib/command/init.js +13 -12
  21. package/lib/command/interactive.js +10 -2
  22. package/lib/command/list.js +1 -1
  23. package/lib/command/run-multiple/chunk.js +48 -45
  24. package/lib/command/run-multiple.js +12 -35
  25. package/lib/command/run-workers.js +21 -58
  26. package/lib/command/utils.js +5 -6
  27. package/lib/command/workers/runTests.js +262 -220
  28. package/lib/container.js +386 -238
  29. package/lib/data/context.js +10 -13
  30. package/lib/data/dataScenarioConfig.js +8 -8
  31. package/lib/data/dataTableArgument.js +6 -6
  32. package/lib/data/table.js +5 -11
  33. package/lib/effects.js +223 -0
  34. package/lib/element/WebElement.js +327 -0
  35. package/lib/els.js +158 -0
  36. package/lib/event.js +21 -17
  37. package/lib/heal.js +88 -80
  38. package/lib/helper/AI.js +2 -1
  39. package/lib/helper/ApiDataFactory.js +3 -6
  40. package/lib/helper/Appium.js +47 -51
  41. package/lib/helper/FileSystem.js +3 -3
  42. package/lib/helper/GraphQLDataFactory.js +3 -3
  43. package/lib/helper/JSONResponse.js +75 -37
  44. package/lib/helper/Mochawesome.js +31 -9
  45. package/lib/helper/Nightmare.js +35 -53
  46. package/lib/helper/Playwright.js +262 -267
  47. package/lib/helper/Protractor.js +54 -77
  48. package/lib/helper/Puppeteer.js +246 -260
  49. package/lib/helper/REST.js +5 -17
  50. package/lib/helper/TestCafe.js +21 -44
  51. package/lib/helper/WebDriver.js +151 -170
  52. package/lib/helper/extras/Popup.js +22 -22
  53. package/lib/helper/testcafe/testcafe-utils.js +26 -27
  54. package/lib/listener/emptyRun.js +55 -0
  55. package/lib/listener/exit.js +7 -10
  56. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  57. package/lib/listener/globalTimeout.js +165 -0
  58. package/lib/listener/helpers.js +15 -15
  59. package/lib/listener/mocha.js +1 -1
  60. package/lib/listener/result.js +12 -0
  61. package/lib/listener/retryEnhancer.js +85 -0
  62. package/lib/listener/steps.js +32 -18
  63. package/lib/listener/store.js +20 -0
  64. package/lib/mocha/asyncWrapper.js +231 -0
  65. package/lib/{interfaces → mocha}/bdd.js +3 -3
  66. package/lib/mocha/cli.js +308 -0
  67. package/lib/mocha/factory.js +104 -0
  68. package/lib/{interfaces → mocha}/featureConfig.js +32 -12
  69. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  70. package/lib/mocha/hooks.js +112 -0
  71. package/lib/mocha/index.js +12 -0
  72. package/lib/mocha/inject.js +29 -0
  73. package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
  74. package/lib/mocha/suite.js +82 -0
  75. package/lib/mocha/test.js +181 -0
  76. package/lib/mocha/types.d.ts +42 -0
  77. package/lib/mocha/ui.js +232 -0
  78. package/lib/output.js +82 -62
  79. package/lib/pause.js +160 -138
  80. package/lib/plugin/analyze.js +396 -0
  81. package/lib/plugin/auth.js +435 -0
  82. package/lib/plugin/autoDelay.js +8 -8
  83. package/lib/plugin/autoLogin.js +3 -338
  84. package/lib/plugin/commentStep.js +6 -1
  85. package/lib/plugin/coverage.js +10 -19
  86. package/lib/plugin/customLocator.js +3 -3
  87. package/lib/plugin/customReporter.js +52 -0
  88. package/lib/plugin/eachElement.js +1 -1
  89. package/lib/plugin/fakerTransform.js +1 -1
  90. package/lib/plugin/heal.js +36 -9
  91. package/lib/plugin/htmlReporter.js +1947 -0
  92. package/lib/plugin/pageInfo.js +140 -0
  93. package/lib/plugin/retryFailedStep.js +17 -18
  94. package/lib/plugin/retryTo.js +2 -113
  95. package/lib/plugin/screenshotOnFail.js +17 -58
  96. package/lib/plugin/selenoid.js +15 -35
  97. package/lib/plugin/standardActingHelpers.js +4 -1
  98. package/lib/plugin/stepByStepReport.js +56 -17
  99. package/lib/plugin/stepTimeout.js +5 -12
  100. package/lib/plugin/subtitles.js +4 -4
  101. package/lib/plugin/tryTo.js +3 -102
  102. package/lib/plugin/wdio.js +8 -10
  103. package/lib/recorder.js +155 -124
  104. package/lib/rerun.js +43 -42
  105. package/lib/result.js +161 -0
  106. package/lib/secret.js +1 -1
  107. package/lib/step/base.js +239 -0
  108. package/lib/step/comment.js +10 -0
  109. package/lib/step/config.js +50 -0
  110. package/lib/step/func.js +46 -0
  111. package/lib/step/helper.js +50 -0
  112. package/lib/step/meta.js +99 -0
  113. package/lib/step/record.js +74 -0
  114. package/lib/step/retry.js +11 -0
  115. package/lib/step/section.js +55 -0
  116. package/lib/step.js +21 -332
  117. package/lib/steps.js +50 -0
  118. package/lib/store.js +37 -5
  119. package/lib/template/heal.js +2 -11
  120. package/lib/test-server.js +323 -0
  121. package/lib/timeout.js +66 -0
  122. package/lib/utils.js +351 -218
  123. package/lib/within.js +75 -55
  124. package/lib/workerStorage.js +2 -1
  125. package/lib/workers.js +386 -276
  126. package/package.json +76 -70
  127. package/translations/de-DE.js +4 -3
  128. package/translations/fr-FR.js +4 -3
  129. package/translations/index.js +1 -0
  130. package/translations/it-IT.js +4 -3
  131. package/translations/ja-JP.js +4 -3
  132. package/translations/nl-NL.js +76 -0
  133. package/translations/pl-PL.js +4 -3
  134. package/translations/pt-BR.js +4 -3
  135. package/translations/ru-RU.js +4 -3
  136. package/translations/utils.js +9 -0
  137. package/translations/zh-CN.js +4 -3
  138. package/translations/zh-TW.js +4 -3
  139. package/typings/index.d.ts +188 -186
  140. package/typings/promiseBasedTypes.d.ts +18 -705
  141. package/typings/types.d.ts +301 -804
  142. package/lib/cli.js +0 -256
  143. package/lib/helper/ExpectHelper.js +0 -391
  144. package/lib/helper/SoftExpectHelper.js +0 -381
  145. package/lib/listener/artifacts.js +0 -19
  146. package/lib/listener/timeout.js +0 -109
  147. package/lib/mochaFactory.js +0 -113
  148. package/lib/plugin/debugErrors.js +0 -67
  149. package/lib/scenario.js +0 -224
  150. package/lib/ui.js +0 -236
@@ -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,35 @@ 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
+ if (Array.isArray(expected[key])) {
353
+ // Handle array comparison: each expected element should have a match in actual array
354
+ assert(Array.isArray(actual[key]), `Expected array for key "${key}", but got ${typeof actual[key]}`)
355
+ for (const expectedItem of expected[key]) {
356
+ let found = false
357
+ for (const actualItem of actual[key]) {
358
+ try {
359
+ this._assertContains(actualItem, expectedItem)
360
+ found = true
361
+ break
362
+ } catch (err) {
363
+ continue
364
+ }
365
+ }
366
+ assert(found, `No matching element found in array for ${JSON.stringify(expectedItem)}`)
367
+ }
368
+ } else {
369
+ this._assertContains(actual[key], expected[key])
370
+ }
371
+ } else {
372
+ assert.deepStrictEqual(actual[key], expected[key], `Values for key "${key}" don't match`)
373
+ }
374
+ }
375
+ }
338
376
  }
339
377
 
340
378
  module.exports = JSONResponse
@@ -1,9 +1,9 @@
1
- let addMochawesomeContext
2
1
  let currentTest
3
2
  let currentSuite
4
3
 
5
4
  const Helper = require('@codeceptjs/helper')
6
5
  const { clearString } = require('../utils')
6
+ const { testToFileName } = require('../mocha/test')
7
7
 
8
8
  class Mochawesome extends Helper {
9
9
  constructor(config) {
@@ -15,7 +15,8 @@ class Mochawesome extends Helper {
15
15
  disableScreenshots: false,
16
16
  }
17
17
 
18
- addMochawesomeContext = require('mochawesome/addContext')
18
+ this._addContext = require('mochawesome/addContext')
19
+
19
20
  this._createConfig(config)
20
21
  }
21
22
 
@@ -36,35 +37,56 @@ class Mochawesome extends Helper {
36
37
  }
37
38
 
38
39
  _test(test) {
39
- currentTest = { test }
40
+ // If this is a retried test, we want to add context to the retried test
41
+ // but also potentially preserve context from the original test
42
+ const originalTest = test.retriedTest && test.retriedTest()
43
+ if (originalTest) {
44
+ // This is a retried test - use the retried test for context
45
+ currentTest = { test }
46
+
47
+ // Optionally copy context from original test if it exists
48
+ // Note: mochawesome context is stored in test.ctx, but we need to be careful
49
+ // not to break the mocha context structure
50
+ } else {
51
+ // Normal test (not a retry)
52
+ currentTest = { test }
53
+ }
40
54
  }
41
55
 
42
56
  _failed(test) {
43
57
  if (this.options.disableScreenshots) return
44
58
  let fileName
45
59
  // Get proper name if we are fail on hook
46
- if (test.ctx.test.type === 'hook') {
60
+ if (test.ctx?.test?.type === 'hook') {
47
61
  currentTest = { test: test.ctx.test }
48
62
  // ignore retries if we are in hook
49
63
  test._retries = -1
50
64
  fileName = clearString(`${test.title}_${currentTest.test.title}`)
51
65
  } else {
52
66
  currentTest = { test }
53
- fileName = clearString(test.title)
67
+ fileName = testToFileName(test)
54
68
  }
55
69
  if (this.options.uniqueScreenshotNames) {
56
- const uuid = test.uuid || test.ctx.test.uuid
57
- fileName = `${fileName.substring(0, 10)}_${uuid}`
70
+ fileName = testToFileName(test, { unique: true })
58
71
  }
59
72
  if (test._retries < 1 || test._retries === test.retryNum) {
60
73
  fileName = `${fileName}.failed.png`
61
- return addMochawesomeContext(currentTest, fileName)
74
+ return this._addContext(currentTest, fileName)
62
75
  }
63
76
  }
64
77
 
65
78
  addMochawesomeContext(context) {
66
79
  if (currentTest === '') currentTest = { test: currentSuite.ctx.test }
67
- return addMochawesomeContext(currentTest, context)
80
+
81
+ // For retried tests, make sure we're adding context to the current (retried) test
82
+ // not the original test
83
+ let targetTest = currentTest
84
+ if (currentTest.test && currentTest.test.retriedTest && currentTest.test.retriedTest()) {
85
+ // This test has been retried, make sure we're using the current test for context
86
+ targetTest = { test: currentTest.test }
87
+ }
88
+
89
+ return this._addContext(targetTest, context)
68
90
  }
69
91
  }
70
92
 
@@ -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
  }