codeceptjs 3.6.4 → 3.6.5-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 (88) hide show
  1. package/bin/codecept.js +84 -63
  2. package/lib/assert/empty.js +19 -19
  3. package/lib/assert/equal.js +32 -30
  4. package/lib/assert/error.js +14 -14
  5. package/lib/assert/include.js +42 -42
  6. package/lib/assert/throws.js +13 -11
  7. package/lib/assert/truth.js +17 -18
  8. package/lib/command/configMigrate.js +57 -52
  9. package/lib/command/definitions.js +88 -88
  10. package/lib/command/dryRun.js +65 -63
  11. package/lib/command/generate.js +191 -181
  12. package/lib/command/info.js +39 -37
  13. package/lib/command/init.js +289 -286
  14. package/lib/command/interactive.js +32 -32
  15. package/lib/command/list.js +26 -26
  16. package/lib/command/run-multiple.js +113 -93
  17. package/lib/command/run-rerun.js +22 -22
  18. package/lib/command/run-workers.js +63 -63
  19. package/lib/command/run.js +24 -26
  20. package/lib/command/utils.js +64 -63
  21. package/lib/data/context.js +60 -60
  22. package/lib/data/dataScenarioConfig.js +47 -47
  23. package/lib/data/dataTableArgument.js +29 -29
  24. package/lib/data/table.js +26 -20
  25. package/lib/helper/AI.js +67 -65
  26. package/lib/helper/ApiDataFactory.js +72 -69
  27. package/lib/helper/Appium.js +409 -379
  28. package/lib/helper/ExpectHelper.js +214 -248
  29. package/lib/helper/FileSystem.js +77 -78
  30. package/lib/helper/GraphQL.js +44 -43
  31. package/lib/helper/GraphQLDataFactory.js +49 -50
  32. package/lib/helper/JSONResponse.js +64 -62
  33. package/lib/helper/Mochawesome.js +28 -28
  34. package/lib/helper/MockServer.js +12 -12
  35. package/lib/helper/Nightmare.js +664 -572
  36. package/lib/helper/Playwright.js +1320 -1211
  37. package/lib/helper/Protractor.js +663 -629
  38. package/lib/helper/Puppeteer.js +1232 -1124
  39. package/lib/helper/REST.js +87 -72
  40. package/lib/helper/TestCafe.js +490 -491
  41. package/lib/helper/WebDriver.js +1294 -1156
  42. package/lib/interfaces/bdd.js +38 -51
  43. package/lib/interfaces/featureConfig.js +19 -19
  44. package/lib/interfaces/gherkin.js +122 -111
  45. package/lib/interfaces/scenarioConfig.js +29 -29
  46. package/lib/listener/artifacts.js +9 -9
  47. package/lib/listener/config.js +24 -23
  48. package/lib/listener/exit.js +12 -12
  49. package/lib/listener/helpers.js +42 -42
  50. package/lib/listener/mocha.js +11 -11
  51. package/lib/listener/retry.js +32 -30
  52. package/lib/listener/steps.js +50 -51
  53. package/lib/listener/timeout.js +53 -53
  54. package/lib/plugin/allure.js +14 -14
  55. package/lib/plugin/autoDelay.js +29 -36
  56. package/lib/plugin/autoLogin.js +70 -66
  57. package/lib/plugin/commentStep.js +18 -18
  58. package/lib/plugin/coverage.js +92 -77
  59. package/lib/plugin/customLocator.js +20 -19
  60. package/lib/plugin/debugErrors.js +24 -24
  61. package/lib/plugin/eachElement.js +37 -37
  62. package/lib/plugin/fakerTransform.js +6 -6
  63. package/lib/plugin/heal.js +66 -63
  64. package/lib/plugin/pauseOnFail.js +10 -10
  65. package/lib/plugin/retryFailedStep.js +31 -38
  66. package/lib/plugin/retryTo.js +28 -28
  67. package/lib/plugin/screenshotOnFail.js +107 -86
  68. package/lib/plugin/selenoid.js +131 -117
  69. package/lib/plugin/standardActingHelpers.js +2 -8
  70. package/lib/plugin/stepByStepReport.js +102 -92
  71. package/lib/plugin/stepTimeout.js +23 -22
  72. package/lib/plugin/subtitles.js +34 -34
  73. package/lib/plugin/tryTo.js +39 -29
  74. package/lib/plugin/wdio.js +77 -72
  75. package/lib/template/heal.js +11 -14
  76. package/package.json +4 -2
  77. package/translations/de-DE.js +1 -1
  78. package/translations/fr-FR.js +1 -1
  79. package/translations/index.js +9 -9
  80. package/translations/it-IT.js +1 -1
  81. package/translations/ja-JP.js +1 -1
  82. package/translations/pl-PL.js +1 -1
  83. package/translations/pt-BR.js +1 -1
  84. package/translations/ru-RU.js +1 -1
  85. package/translations/zh-CN.js +1 -1
  86. package/translations/zh-TW.js +1 -1
  87. package/typings/promiseBasedTypes.d.ts +238 -0
  88. package/typings/types.d.ts +32 -0
@@ -1,29 +1,24 @@
1
- const path = require('path');
2
-
3
- const urlResolve = require('url').resolve;
4
-
5
- const Helper = require('@codeceptjs/helper');
6
- const { includes: stringIncludes } = require('../assert/include');
7
- const { urlEquals } = require('../assert/equal');
8
- const { equals } = require('../assert/equal');
9
- const { empty } = require('../assert/empty');
10
- const { truth } = require('../assert/truth');
11
- const Locator = require('../locator');
12
- const ElementNotFound = require('./errors/ElementNotFound');
13
- const {
14
- xpathLocator,
15
- fileExists,
16
- screenshotOutputFolder,
17
- toCamelCase,
18
- } = require('../utils');
1
+ const path = require('path')
2
+
3
+ const urlResolve = require('url').resolve
4
+
5
+ const Helper = require('@codeceptjs/helper')
6
+ const { includes: stringIncludes } = require('../assert/include')
7
+ const { urlEquals } = require('../assert/equal')
8
+ const { equals } = require('../assert/equal')
9
+ const { empty } = require('../assert/empty')
10
+ const { truth } = require('../assert/truth')
11
+ const Locator = require('../locator')
12
+ const ElementNotFound = require('./errors/ElementNotFound')
13
+ const { xpathLocator, fileExists, screenshotOutputFolder, toCamelCase } = require('../utils')
19
14
 
20
15
  const specialKeys = {
21
16
  Backspace: '\u0008',
22
17
  Enter: '\u000d',
23
18
  Delete: '\u007f',
24
- };
19
+ }
25
20
 
26
- let withinStatus = false;
21
+ let withinStatus = false
27
22
 
28
23
  /**
29
24
  * Nightmare helper wraps [Nightmare](https://github.com/segmentio/nightmare) library to provide
@@ -54,12 +49,12 @@ let withinStatus = false;
54
49
  */
55
50
  class Nightmare extends Helper {
56
51
  constructor(config) {
57
- super(config);
52
+ super(config)
58
53
 
59
- this.isRunning = false;
54
+ this.isRunning = false
60
55
 
61
56
  // override defaults with config
62
- this._setConfig(config);
57
+ this._setConfig(config)
63
58
  }
64
59
 
65
60
  _validateConfig(config) {
@@ -75,235 +70,268 @@ class Nightmare extends Helper {
75
70
  keepCookies: false,
76
71
  js_errors: null,
77
72
  enableHAR: false,
78
- };
73
+ }
79
74
 
80
- return Object.assign(defaults, config);
75
+ return Object.assign(defaults, config)
81
76
  }
82
77
 
83
78
  static _config() {
84
79
  return [
85
80
  { name: 'url', message: 'Base url of site to be tested', default: 'http://localhost' },
86
81
  {
87
- name: 'show', message: 'Show browser window', default: true, type: 'confirm',
82
+ name: 'show',
83
+ message: 'Show browser window',
84
+ default: true,
85
+ type: 'confirm',
88
86
  },
89
- ];
87
+ ]
90
88
  }
91
89
 
92
90
  static _checkRequirements() {
93
91
  try {
94
- require('nightmare');
92
+ require('nightmare')
95
93
  } catch (e) {
96
- return ['nightmare'];
94
+ return ['nightmare']
97
95
  }
98
96
  }
99
97
 
100
98
  async _init() {
101
- this.Nightmare = require('nightmare');
99
+ this.Nightmare = require('nightmare')
102
100
 
103
101
  if (this.options.enableHAR) {
104
- require('nightmare-har-plugin').install(this.Nightmare);
102
+ require('nightmare-har-plugin').install(this.Nightmare)
105
103
  }
106
104
 
107
105
  this.Nightmare.action('findElements', function (locator, contextEl, done) {
108
106
  if (!done) {
109
- done = contextEl;
110
- contextEl = null;
107
+ done = contextEl
108
+ contextEl = null
111
109
  }
112
110
 
113
- const by = Object.keys(locator)[0];
114
- const value = locator[by];
111
+ const by = Object.keys(locator)[0]
112
+ const value = locator[by]
115
113
 
116
- this.evaluate_now((by, locator, contextEl) => window.codeceptjs.findAndStoreElements(by, locator, contextEl), done, by, value, contextEl);
117
- });
114
+ this.evaluate_now(
115
+ (by, locator, contextEl) => window.codeceptjs.findAndStoreElements(by, locator, contextEl),
116
+ done,
117
+ by,
118
+ value,
119
+ contextEl,
120
+ )
121
+ })
118
122
 
119
123
  this.Nightmare.action('findElement', function (locator, contextEl, done) {
120
124
  if (!done) {
121
- done = contextEl;
122
- contextEl = null;
125
+ done = contextEl
126
+ contextEl = null
123
127
  }
124
128
 
125
- const by = Object.keys(locator)[0];
126
- const value = locator[by];
129
+ const by = Object.keys(locator)[0]
130
+ const value = locator[by]
127
131
 
128
- this.evaluate_now((by, locator, contextEl) => {
129
- const res = window.codeceptjs.findAndStoreElement(by, locator, contextEl);
130
- if (res === null) {
131
- throw new Error(`Element ${(new Locator(locator))} couldn't be located by ${by}`);
132
- }
133
- return res;
134
- }, done, by, value, contextEl);
135
- });
132
+ this.evaluate_now(
133
+ (by, locator, contextEl) => {
134
+ const res = window.codeceptjs.findAndStoreElement(by, locator, contextEl)
135
+ if (res === null) {
136
+ throw new Error(`Element ${new Locator(locator)} couldn't be located by ${by}`)
137
+ }
138
+ return res
139
+ },
140
+ done,
141
+ by,
142
+ value,
143
+ contextEl,
144
+ )
145
+ })
136
146
 
137
147
  this.Nightmare.action('asyncScript', function () {
138
- let args = Array.prototype.slice.call(arguments);
139
- const done = args.pop();
140
- args = args.splice(1, 0, done);
141
- this.evaluate_now.apply(this, args);
142
- });
148
+ let args = Array.prototype.slice.call(arguments)
149
+ const done = args.pop()
150
+ args = args.splice(1, 0, done)
151
+ this.evaluate_now.apply(this, args)
152
+ })
143
153
 
144
154
  this.Nightmare.action('enterText', function (el, text, clean, done) {
145
- const child = this.child;
146
- const typeFn = () => child.call('type', text, done);
147
-
148
- this.evaluate_now((el, clean) => {
149
- const element = window.codeceptjs.fetchElement(el);
150
- if (clean) element.value = '';
151
- element.focus();
152
- }, () => {
153
- if (clean) return typeFn();
154
- child.call('pressKey', 'End', typeFn); // type End before
155
- }, el, clean);
156
- });
157
-
158
- this.Nightmare.action('pressKey', (ns, options, parent, win, renderer, done) => {
159
- parent.respondTo('pressKey', (ch, done) => {
160
- win.webContents.sendInputEvent({
161
- type: 'keyDown',
162
- keyCode: ch,
163
- });
164
-
165
- win.webContents.sendInputEvent({
166
- type: 'char',
167
- keyCode: ch,
168
- });
169
-
170
- win.webContents.sendInputEvent({
171
- type: 'keyUp',
172
- keyCode: ch,
173
- });
174
- done();
175
- });
176
- done();
177
- }, function (key, done) {
178
- this.child.call('pressKey', key, done);
179
- });
180
-
181
- this.Nightmare.action('triggerMouseEvent', (ns, options, parent, win, renderer, done) => {
182
- parent.respondTo('triggerMouseEvent', (evt, done) => {
183
- win.webContents.sendInputEvent(evt);
184
- done();
185
- });
186
- done();
187
- }, function (event, done) {
188
- this.child.call('triggerMouseEvent', event, done);
189
- });
155
+ const child = this.child
156
+ const typeFn = () => child.call('type', text, done)
157
+
158
+ this.evaluate_now(
159
+ (el, clean) => {
160
+ const element = window.codeceptjs.fetchElement(el)
161
+ if (clean) element.value = ''
162
+ element.focus()
163
+ },
164
+ () => {
165
+ if (clean) return typeFn()
166
+ child.call('pressKey', 'End', typeFn) // type End before
167
+ },
168
+ el,
169
+ clean,
170
+ )
171
+ })
172
+
173
+ this.Nightmare.action(
174
+ 'pressKey',
175
+ (ns, options, parent, win, renderer, done) => {
176
+ parent.respondTo('pressKey', (ch, done) => {
177
+ win.webContents.sendInputEvent({
178
+ type: 'keyDown',
179
+ keyCode: ch,
180
+ })
181
+
182
+ win.webContents.sendInputEvent({
183
+ type: 'char',
184
+ keyCode: ch,
185
+ })
186
+
187
+ win.webContents.sendInputEvent({
188
+ type: 'keyUp',
189
+ keyCode: ch,
190
+ })
191
+ done()
192
+ })
193
+ done()
194
+ },
195
+ function (key, done) {
196
+ this.child.call('pressKey', key, done)
197
+ },
198
+ )
199
+
200
+ this.Nightmare.action(
201
+ 'triggerMouseEvent',
202
+ (ns, options, parent, win, renderer, done) => {
203
+ parent.respondTo('triggerMouseEvent', (evt, done) => {
204
+ win.webContents.sendInputEvent(evt)
205
+ done()
206
+ })
207
+ done()
208
+ },
209
+ function (event, done) {
210
+ this.child.call('triggerMouseEvent', event, done)
211
+ },
212
+ )
190
213
 
191
214
  this.Nightmare.action(
192
215
  'upload',
193
216
  (ns, options, parent, win, renderer, done) => {
194
217
  parent.respondTo('upload', (selector, pathsToUpload, done) => {
195
- parent.emit('log', 'paths', pathsToUpload);
218
+ parent.emit('log', 'paths', pathsToUpload)
196
219
  try {
197
- // attach the debugger
198
- // NOTE: this will fail if devtools is open
199
- win.webContents.debugger.attach('1.1');
220
+ // attach the debugger
221
+ // NOTE: this will fail if devtools is open
222
+ win.webContents.debugger.attach('1.1')
200
223
  } catch (e) {
201
- parent.emit('log', 'problem attaching', e);
202
- return done(e);
224
+ parent.emit('log', 'problem attaching', e)
225
+ return done(e)
203
226
  }
204
227
 
205
228
  win.webContents.debugger.sendCommand('DOM.getDocument', {}, (err, domDocument) => {
206
- win.webContents.debugger.sendCommand('DOM.querySelector', {
207
- nodeId: domDocument.root.nodeId,
208
- selector,
209
- }, (err, queryResult) => {
210
- // HACK: chromium errors appear to be unpopulated objects?
211
- if (Object.keys(err)
212
- .length > 0) {
213
- parent.emit('log', 'problem selecting', err);
214
- return done(err);
215
- }
216
- win.webContents.debugger.sendCommand('DOM.setFileInputFiles', {
217
- nodeId: queryResult.nodeId,
218
- files: pathsToUpload,
219
- }, (err) => {
220
- if (Object.keys(err)
221
- .length > 0) {
222
- parent.emit('log', 'problem setting input', err);
223
- return done(err);
229
+ win.webContents.debugger.sendCommand(
230
+ 'DOM.querySelector',
231
+ {
232
+ nodeId: domDocument.root.nodeId,
233
+ selector,
234
+ },
235
+ (err, queryResult) => {
236
+ // HACK: chromium errors appear to be unpopulated objects?
237
+ if (Object.keys(err).length > 0) {
238
+ parent.emit('log', 'problem selecting', err)
239
+ return done(err)
224
240
  }
225
- win.webContents.debugger.detach();
226
- done(null, pathsToUpload);
227
- });
228
- });
229
- });
230
- });
231
- done();
241
+ win.webContents.debugger.sendCommand(
242
+ 'DOM.setFileInputFiles',
243
+ {
244
+ nodeId: queryResult.nodeId,
245
+ files: pathsToUpload,
246
+ },
247
+ (err) => {
248
+ if (Object.keys(err).length > 0) {
249
+ parent.emit('log', 'problem setting input', err)
250
+ return done(err)
251
+ }
252
+ win.webContents.debugger.detach()
253
+ done(null, pathsToUpload)
254
+ },
255
+ )
256
+ },
257
+ )
258
+ })
259
+ })
260
+ done()
232
261
  },
233
262
  function (selector, pathsToUpload, done) {
234
263
  if (!Array.isArray(pathsToUpload)) {
235
- pathsToUpload = [pathsToUpload];
264
+ pathsToUpload = [pathsToUpload]
236
265
  }
237
266
  this.child.call('upload', selector, pathsToUpload, (err, stuff) => {
238
- done(err, stuff);
239
- });
267
+ done(err, stuff)
268
+ })
240
269
  },
241
- );
270
+ )
242
271
 
243
- return Promise.resolve();
272
+ return Promise.resolve()
244
273
  }
245
274
 
246
275
  async _beforeSuite() {
247
276
  if (!this.options.restart && !this.isRunning) {
248
- this.debugSection('Session', 'Starting singleton browser session');
249
- return this._startBrowser();
277
+ this.debugSection('Session', 'Starting singleton browser session')
278
+ return this._startBrowser()
250
279
  }
251
280
  }
252
281
 
253
282
  async _before() {
254
- if (this.options.restart) return this._startBrowser();
255
- if (!this.isRunning) return this._startBrowser();
256
- return this.browser;
283
+ if (this.options.restart) return this._startBrowser()
284
+ if (!this.isRunning) return this._startBrowser()
285
+ return this.browser
257
286
  }
258
287
 
259
288
  async _after() {
260
- if (!this.isRunning) return;
289
+ if (!this.isRunning) return
261
290
  if (this.options.restart) {
262
- this.isRunning = false;
263
- return this._stopBrowser();
291
+ this.isRunning = false
292
+ return this._stopBrowser()
264
293
  }
265
294
  if (this.options.enableHAR) {
266
- await this.browser.resetHAR();
295
+ await this.browser.resetHAR()
267
296
  }
268
- if (this.options.keepBrowserState) return;
297
+ if (this.options.keepBrowserState) return
269
298
  if (this.options.keepCookies) {
270
- await this.browser.cookies.clearAll();
299
+ await this.browser.cookies.clearAll()
271
300
  }
272
- this.debugSection('Session', 'cleaning up');
273
- return this.executeScript(() => localStorage.clear());
301
+ this.debugSection('Session', 'cleaning up')
302
+ return this.executeScript(() => localStorage.clear())
274
303
  }
275
304
 
276
- _afterSuite() {
277
- }
305
+ _afterSuite() {}
278
306
 
279
307
  _finishTest() {
280
308
  if (!this.options.restart && this.isRunning) {
281
- this._stopBrowser();
309
+ this._stopBrowser()
282
310
  }
283
311
  }
284
312
 
285
313
  async _startBrowser() {
286
- this.context = this.options.rootElement;
314
+ this.context = this.options.rootElement
287
315
  if (this.options.enableHAR) {
288
- this.browser = this.Nightmare(Object.assign(require('nightmare-har-plugin').getDevtoolsOptions(), this.options));
289
- await this.browser;
290
- await this.browser.waitForDevtools();
316
+ this.browser = this.Nightmare(Object.assign(require('nightmare-har-plugin').getDevtoolsOptions(), this.options))
317
+ await this.browser
318
+ await this.browser.waitForDevtools()
291
319
  } else {
292
- this.browser = this.Nightmare(this.options);
293
- await this.browser;
320
+ this.browser = this.Nightmare(this.options)
321
+ await this.browser
294
322
  }
295
- await this.browser.goto('about:blank'); // Load a blank page so .saveScreenshot (/evaluate) will work
296
- this.isRunning = true;
297
- this.browser.on('dom-ready', () => this._injectClientScripts());
298
- this.browser.on('did-start-loading', () => this._injectClientScripts());
299
- this.browser.on('will-navigate', () => this._injectClientScripts());
323
+ await this.browser.goto('about:blank') // Load a blank page so .saveScreenshot (/evaluate) will work
324
+ this.isRunning = true
325
+ this.browser.on('dom-ready', () => this._injectClientScripts())
326
+ this.browser.on('did-start-loading', () => this._injectClientScripts())
327
+ this.browser.on('will-navigate', () => this._injectClientScripts())
300
328
  this.browser.on('console', (type, message) => {
301
- this.debug(`${type}: ${message}`);
302
- });
329
+ this.debug(`${type}: ${message}`)
330
+ })
303
331
 
304
332
  if (this.options.windowSize) {
305
- const size = this.options.windowSize.split('x');
306
- return this.browser.viewport(parseInt(size[0], 10), parseInt(size[1], 10));
333
+ const size = this.options.windowSize.split('x')
334
+ return this.browser.viewport(parseInt(size[0], 10), parseInt(size[1], 10))
307
335
  }
308
336
  }
309
337
 
@@ -316,45 +344,49 @@ class Nightmare extends Helper {
316
344
  * ```
317
345
  */
318
346
  async grabHAR() {
319
- return this.browser.getHAR();
347
+ return this.browser.getHAR()
320
348
  }
321
349
 
322
350
  async saveHAR(fileName) {
323
- const outputFile = path.join(global.output_dir, fileName);
324
- this.debug(`HAR is saving to ${outputFile}`);
351
+ const outputFile = path.join(global.output_dir, fileName)
352
+ this.debug(`HAR is saving to ${outputFile}`)
325
353
 
326
354
  await this.browser.getHAR().then((har) => {
327
- require('fs').writeFileSync(outputFile, JSON.stringify({ log: har }));
328
- });
355
+ require('fs').writeFileSync(outputFile, JSON.stringify({ log: har }))
356
+ })
329
357
  }
330
358
 
331
359
  async resetHAR() {
332
- await this.browser.resetHAR();
360
+ await this.browser.resetHAR()
333
361
  }
334
362
 
335
363
  async _stopBrowser() {
336
364
  return this.browser.end().catch((error) => {
337
- this.debugSection('Error on End', error);
338
- });
365
+ this.debugSection('Error on End', error)
366
+ })
339
367
  }
340
368
 
341
369
  async _withinBegin(locator) {
342
- this.context = locator;
343
- locator = new Locator(locator, 'css');
344
- withinStatus = true;
345
- return this.browser.evaluate((by, locator) => {
346
- const el = window.codeceptjs.findElement(by, locator);
347
- if (!el) throw new Error(`Element by ${by}: ${locator} not found`);
348
- window.codeceptjs.within = el;
349
- }, locator.type, locator.value);
370
+ this.context = locator
371
+ locator = new Locator(locator, 'css')
372
+ withinStatus = true
373
+ return this.browser.evaluate(
374
+ (by, locator) => {
375
+ const el = window.codeceptjs.findElement(by, locator)
376
+ if (!el) throw new Error(`Element by ${by}: ${locator} not found`)
377
+ window.codeceptjs.within = el
378
+ },
379
+ locator.type,
380
+ locator.value,
381
+ )
350
382
  }
351
383
 
352
384
  _withinEnd() {
353
- this.context = this.options.rootElement;
354
- withinStatus = false;
385
+ this.context = this.options.rootElement
386
+ withinStatus = false
355
387
  return this.browser.evaluate(() => {
356
- window.codeceptjs.within = null;
357
- });
388
+ window.codeceptjs.within = null
389
+ })
358
390
  }
359
391
 
360
392
  /**
@@ -377,10 +409,14 @@ class Nightmare extends Helper {
377
409
  * ```
378
410
  */
379
411
  _locate(locator) {
380
- locator = new Locator(locator, 'css');
381
- return this.browser.evaluate((by, locator) => {
382
- return window.codeceptjs.findAndStoreElements(by, locator);
383
- }, locator.type, locator.value);
412
+ locator = new Locator(locator, 'css')
413
+ return this.browser.evaluate(
414
+ (by, locator) => {
415
+ return window.codeceptjs.findAndStoreElements(by, locator)
416
+ },
417
+ locator.type,
418
+ locator.value,
419
+ )
384
420
  }
385
421
 
386
422
  /**
@@ -392,7 +428,7 @@ class Nightmare extends Helper {
392
428
  * ```
393
429
  */
394
430
  haveHeader(header, value) {
395
- return this.browser.header(header, value);
431
+ return this.browser.header(header, value)
396
432
  }
397
433
 
398
434
  /**
@@ -401,223 +437,237 @@ class Nightmare extends Helper {
401
437
  *
402
438
  */
403
439
  async amOnPage(url, headers = null) {
404
- if (!(/^\w+\:\/\//.test(url))) {
405
- url = urlResolve(this.options.url, url);
440
+ if (!/^\w+\:\/\//.test(url)) {
441
+ url = urlResolve(this.options.url, url)
406
442
  }
407
- const currentUrl = await this.browser.url();
443
+ const currentUrl = await this.browser.url()
408
444
  if (url === currentUrl) {
409
445
  // navigating to the same url will cause an error in nightmare, so don't do it
410
- return;
446
+ return
411
447
  }
412
448
  return this.browser.goto(url, headers).then((res) => {
413
- this.debugSection('URL', res.url);
414
- this.debugSection('Code', res.code);
415
- this.debugSection('Headers', JSON.stringify(res.headers));
416
- });
449
+ this.debugSection('URL', res.url)
450
+ this.debugSection('Code', res.code)
451
+ this.debugSection('Headers', JSON.stringify(res.headers))
452
+ })
417
453
  }
418
454
 
419
455
  /**
420
456
  * {{> seeInTitle }}
421
457
  */
422
458
  async seeInTitle(text) {
423
- const title = await this.browser.title();
424
- stringIncludes('web page title').assert(text, title);
459
+ const title = await this.browser.title()
460
+ stringIncludes('web page title').assert(text, title)
425
461
  }
426
462
 
427
463
  /**
428
464
  * {{> dontSeeInTitle }}
429
465
  */
430
466
  async dontSeeInTitle(text) {
431
- const title = await this.browser.title();
432
- stringIncludes('web page title').negate(text, title);
467
+ const title = await this.browser.title()
468
+ stringIncludes('web page title').negate(text, title)
433
469
  }
434
470
 
435
471
  /**
436
472
  * {{> grabTitle }}
437
473
  */
438
474
  async grabTitle() {
439
- return this.browser.title();
475
+ return this.browser.title()
440
476
  }
441
477
 
442
478
  /**
443
479
  * {{> grabCurrentUrl }}
444
480
  */
445
481
  async grabCurrentUrl() {
446
- return this.browser.url();
482
+ return this.browser.url()
447
483
  }
448
484
 
449
485
  /**
450
486
  * {{> seeInCurrentUrl }}
451
487
  */
452
488
  async seeInCurrentUrl(url) {
453
- const currentUrl = await this.browser.url();
454
- stringIncludes('url').assert(url, currentUrl);
489
+ const currentUrl = await this.browser.url()
490
+ stringIncludes('url').assert(url, currentUrl)
455
491
  }
456
492
 
457
493
  /**
458
494
  * {{> dontSeeInCurrentUrl }}
459
495
  */
460
496
  async dontSeeInCurrentUrl(url) {
461
- const currentUrl = await this.browser.url();
462
- stringIncludes('url').negate(url, currentUrl);
497
+ const currentUrl = await this.browser.url()
498
+ stringIncludes('url').negate(url, currentUrl)
463
499
  }
464
500
 
465
501
  /**
466
502
  * {{> seeCurrentUrlEquals }}
467
503
  */
468
504
  async seeCurrentUrlEquals(url) {
469
- const currentUrl = await this.browser.url();
470
- urlEquals(this.options.url).assert(url, currentUrl);
505
+ const currentUrl = await this.browser.url()
506
+ urlEquals(this.options.url).assert(url, currentUrl)
471
507
  }
472
508
 
473
509
  /**
474
510
  * {{> dontSeeCurrentUrlEquals }}
475
511
  */
476
512
  async dontSeeCurrentUrlEquals(url) {
477
- const currentUrl = await this.browser.url();
478
- urlEquals(this.options.url).negate(url, currentUrl);
513
+ const currentUrl = await this.browser.url()
514
+ urlEquals(this.options.url).negate(url, currentUrl)
479
515
  }
480
516
 
481
517
  /**
482
518
  * {{> see }}
483
519
  */
484
520
  async see(text, context = null) {
485
- return proceedSee.call(this, 'assert', text, context);
521
+ return proceedSee.call(this, 'assert', text, context)
486
522
  }
487
523
 
488
524
  /**
489
525
  * {{> dontSee }}
490
526
  */
491
527
  dontSee(text, context = null) {
492
- return proceedSee.call(this, 'negate', text, context);
528
+ return proceedSee.call(this, 'negate', text, context)
493
529
  }
494
530
 
495
531
  /**
496
532
  * {{> seeElement }}
497
533
  */
498
534
  async seeElement(locator) {
499
- locator = new Locator(locator, 'css');
500
- const num = await this.browser.evaluate((by, locator) => {
501
- return window.codeceptjs.findElements(by, locator).filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length;
502
- }, locator.type, locator.value);
503
- equals('number of elements on a page').negate(0, num);
535
+ locator = new Locator(locator, 'css')
536
+ const num = await this.browser.evaluate(
537
+ (by, locator) => {
538
+ return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
539
+ },
540
+ locator.type,
541
+ locator.value,
542
+ )
543
+ equals('number of elements on a page').negate(0, num)
504
544
  }
505
545
 
506
546
  /**
507
547
  * {{> dontSeeElement }}
508
548
  */
509
549
  async dontSeeElement(locator) {
510
- locator = new Locator(locator, 'css');
511
- locator = new Locator(locator, 'css');
512
- const num = await this.browser.evaluate((by, locator) => {
513
- return window.codeceptjs.findElements(by, locator).filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length;
514
- }, locator.type, locator.value);
515
- equals('number of elements on a page').assert(0, num);
550
+ locator = new Locator(locator, 'css')
551
+ locator = new Locator(locator, 'css')
552
+ const num = await this.browser.evaluate(
553
+ (by, locator) => {
554
+ return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
555
+ },
556
+ locator.type,
557
+ locator.value,
558
+ )
559
+ equals('number of elements on a page').assert(0, num)
516
560
  }
517
561
 
518
562
  /**
519
563
  * {{> seeElementInDOM }}
520
564
  */
521
565
  async seeElementInDOM(locator) {
522
- locator = new Locator(locator, 'css');
523
- const els = await this.browser.findElements(locator.toStrict());
524
- empty('elements').negate(els.fill('ELEMENT'));
566
+ locator = new Locator(locator, 'css')
567
+ const els = await this.browser.findElements(locator.toStrict())
568
+ empty('elements').negate(els.fill('ELEMENT'))
525
569
  }
526
570
 
527
571
  /**
528
572
  * {{> dontSeeElementInDOM }}
529
573
  */
530
574
  async dontSeeElementInDOM(locator) {
531
- locator = new Locator(locator, 'css');
532
- const els = await this.browser.findElements(locator.toStrict());
533
- empty('elements').assert(els.fill('ELEMENT'));
575
+ locator = new Locator(locator, 'css')
576
+ const els = await this.browser.findElements(locator.toStrict())
577
+ empty('elements').assert(els.fill('ELEMENT'))
534
578
  }
535
579
 
536
580
  /**
537
581
  * {{> seeInSource }}
538
582
  */
539
583
  async seeInSource(text) {
540
- const source = await this.browser.evaluate(() => document.documentElement.outerHTML);
541
- stringIncludes('HTML source of a page').assert(text, source);
584
+ const source = await this.browser.evaluate(() => document.documentElement.outerHTML)
585
+ stringIncludes('HTML source of a page').assert(text, source)
542
586
  }
543
587
 
544
588
  /**
545
589
  * {{> dontSeeInSource }}
546
590
  */
547
591
  async dontSeeInSource(text) {
548
- const source = await this.browser.evaluate(() => document.documentElement.outerHTML);
549
- stringIncludes('HTML source of a page').negate(text, source);
592
+ const source = await this.browser.evaluate(() => document.documentElement.outerHTML)
593
+ stringIncludes('HTML source of a page').negate(text, source)
550
594
  }
551
595
 
552
596
  /**
553
597
  * {{> seeNumberOfElements }}
554
598
  */
555
599
  async seeNumberOfElements(locator, num) {
556
- const elements = await this._locate(locator);
557
- return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
600
+ 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)
558
604
  }
559
605
 
560
606
  /**
561
607
  * {{> seeNumberOfVisibleElements }}
562
608
  */
563
609
  async seeNumberOfVisibleElements(locator, num) {
564
- const res = await this.grabNumberOfVisibleElements(locator);
565
- return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
610
+ 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
+ )
566
615
  }
567
616
 
568
617
  /**
569
618
  * {{> grabNumberOfVisibleElements }}
570
619
  */
571
620
  async grabNumberOfVisibleElements(locator) {
572
- locator = new Locator(locator, 'css');
621
+ locator = new Locator(locator, 'css')
573
622
 
574
- const num = await this.browser.evaluate((by, locator) => {
575
- return window.codeceptjs.findElements(by, locator)
576
- .filter(e => e.offsetWidth > 0 && e.offsetHeight > 0).length;
577
- }, locator.type, locator.value);
623
+ const num = await this.browser.evaluate(
624
+ (by, locator) => {
625
+ return window.codeceptjs.findElements(by, locator).filter((e) => e.offsetWidth > 0 && e.offsetHeight > 0).length
626
+ },
627
+ locator.type,
628
+ locator.value,
629
+ )
578
630
 
579
- return num;
631
+ return num
580
632
  }
581
633
 
582
634
  /**
583
635
  * {{> click }}
584
636
  */
585
637
  async click(locator, context = null) {
586
- const el = await findClickable.call(this, locator, context);
587
- assertElementExists(el, locator, 'Clickable');
588
- return this.browser.evaluate(el => window.codeceptjs.clickEl(el), el)
589
- .wait(this.options.waitForAction);
638
+ const el = await findClickable.call(this, locator, context)
639
+ assertElementExists(el, locator, 'Clickable')
640
+ return this.browser.evaluate((el) => window.codeceptjs.clickEl(el), el).wait(this.options.waitForAction)
590
641
  }
591
642
 
592
643
  /**
593
644
  * {{> doubleClick }}
594
645
  */
595
646
  async doubleClick(locator, context = null) {
596
- const el = await findClickable.call(this, locator, context);
597
- assertElementExists(el, locator, 'Clickable');
598
- return this.browser.evaluate(el => window.codeceptjs.doubleClickEl(el), el)
599
- .wait(this.options.waitForAction);
647
+ const el = await findClickable.call(this, locator, context)
648
+ assertElementExists(el, locator, 'Clickable')
649
+ return this.browser.evaluate((el) => window.codeceptjs.doubleClickEl(el), el).wait(this.options.waitForAction)
600
650
  }
601
651
 
602
652
  /**
603
653
  * {{> rightClick }}
604
654
  */
605
655
  async rightClick(locator, context = null) {
606
- const el = await findClickable.call(this, locator, context);
607
- assertElementExists(el, locator, 'Clickable');
608
- return this.browser.evaluate(el => window.codeceptjs.rightClickEl(el), el)
609
- .wait(this.options.waitForAction);
656
+ const el = await findClickable.call(this, locator, context)
657
+ assertElementExists(el, locator, 'Clickable')
658
+ return this.browser.evaluate((el) => window.codeceptjs.rightClickEl(el), el).wait(this.options.waitForAction)
610
659
  }
611
660
 
612
661
  /**
613
662
  * {{> moveCursorTo }}
614
663
  */
615
664
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
616
- locator = new Locator(locator, 'css');
617
- const el = await this.browser.findElement(locator.toStrict());
618
- assertElementExists(el, locator);
619
- return this.browser.evaluate((el, x, y) => window.codeceptjs.hoverEl(el, x, y), el, offsetX, offsetY)
620
- .wait(this.options.waitForAction); // wait for hover event to happen
665
+ locator = new Locator(locator, 'css')
666
+ const el = await this.browser.findElement(locator.toStrict())
667
+ 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
621
671
  }
622
672
 
623
673
  /**
@@ -626,8 +676,7 @@ class Nightmare extends Helper {
626
676
  * Wrapper for synchronous [evaluate](https://github.com/segmentio/nightmare#evaluatefn-arg1-arg2)
627
677
  */
628
678
  async executeScript(...args) {
629
- return this.browser.evaluate.apply(this.browser, args)
630
- .catch(err => err); // Nightmare's first argument is error :(
679
+ return this.browser.evaluate.apply(this.browser, args).catch((err) => err) // Nightmare's first argument is error :(
631
680
  }
632
681
 
633
682
  /**
@@ -637,8 +686,7 @@ class Nightmare extends Helper {
637
686
  * Unlike NightmareJS implementation calling `done` will return its first argument.
638
687
  */
639
688
  async executeAsyncScript(...args) {
640
- return this.browser.evaluate.apply(this.browser, args)
641
- .catch(err => err); // Nightmare's first argument is error :(
689
+ return this.browser.evaluate.apply(this.browser, args).catch((err) => err) // Nightmare's first argument is error :(
642
690
  }
643
691
 
644
692
  /**
@@ -646,72 +694,68 @@ class Nightmare extends Helper {
646
694
  */
647
695
  async resizeWindow(width, height) {
648
696
  if (width === 'maximize') {
649
- throw new Error('Nightmare doesn\'t support resizeWindow to maximum!');
697
+ throw new Error("Nightmare doesn't support resizeWindow to maximum!")
650
698
  }
651
- return this.browser.viewport(width, height).wait(this.options.waitForAction);
699
+ return this.browser.viewport(width, height).wait(this.options.waitForAction)
652
700
  }
653
701
 
654
702
  /**
655
703
  * {{> checkOption }}
656
704
  */
657
705
  async checkOption(field, context = null) {
658
- const els = await findCheckable.call(this, field, context);
659
- assertElementExists(els[0], field, 'Checkbox or radio');
660
- return this.browser.evaluate(els => window.codeceptjs.checkEl(els[0]), els)
661
- .wait(this.options.waitForAction);
706
+ const els = await findCheckable.call(this, field, context)
707
+ assertElementExists(els[0], field, 'Checkbox or radio')
708
+ return this.browser.evaluate((els) => window.codeceptjs.checkEl(els[0]), els).wait(this.options.waitForAction)
662
709
  }
663
710
 
664
711
  /**
665
712
  * {{> uncheckOption }}
666
713
  */
667
714
  async uncheckOption(field, context = null) {
668
- const els = await findCheckable.call(this, field, context);
669
- assertElementExists(els[0], field, 'Checkbox or radio');
670
- return this.browser.evaluate(els => window.codeceptjs.unCheckEl(els[0]), els)
671
- .wait(this.options.waitForAction);
715
+ const els = await findCheckable.call(this, field, context)
716
+ assertElementExists(els[0], field, 'Checkbox or radio')
717
+ return this.browser.evaluate((els) => window.codeceptjs.unCheckEl(els[0]), els).wait(this.options.waitForAction)
672
718
  }
673
719
 
674
720
  /**
675
721
  * {{> fillField }}
676
722
  */
677
723
  async fillField(field, value) {
678
- const el = await findField.call(this, field);
679
- assertElementExists(el, field, 'Field');
680
- return this.browser.enterText(el, value.toString(), true)
681
- .wait(this.options.waitForAction);
724
+ const el = await findField.call(this, field)
725
+ assertElementExists(el, field, 'Field')
726
+ return this.browser.enterText(el, value.toString(), true).wait(this.options.waitForAction)
682
727
  }
683
728
 
684
729
  /**
685
730
  * {{> clearField }}
686
731
  */
687
732
  async clearField(field) {
688
- return this.fillField(field, '');
733
+ return this.fillField(field, '')
689
734
  }
690
735
 
691
736
  /**
692
737
  * {{> appendField }}
693
738
  */
694
739
  async appendField(field, value) {
695
- const el = await findField.call(this, field);
696
- assertElementExists(el, field, 'Field');
697
- return this.browser.enterText(el, value.toString(), false)
698
- .wait(this.options.waitForAction);
740
+ const el = await findField.call(this, field)
741
+ assertElementExists(el, field, 'Field')
742
+ return this.browser.enterText(el, value.toString(), false).wait(this.options.waitForAction)
699
743
  }
700
744
 
701
745
  /**
702
746
  * {{> seeInField }}
703
747
  */
704
748
  async seeInField(field, value) {
705
- const _value = (typeof value === 'boolean') ? value : value.toString();
706
- return proceedSeeInField.call(this, 'assert', field, _value);
749
+ const _value = typeof value === 'boolean' ? value : value.toString()
750
+ return proceedSeeInField.call(this, 'assert', field, _value)
707
751
  }
708
752
 
709
753
  /**
710
754
  * {{> dontSeeInField }}
711
755
  */
712
756
  async dontSeeInField(field, value) {
713
- const _value = (typeof value === 'boolean') ? value : value.toString();
714
- return proceedSeeInField.call(this, 'negate', field, _value);
757
+ const _value = typeof value === 'boolean' ? value : value.toString()
758
+ return proceedSeeInField.call(this, 'negate', field, _value)
715
759
  }
716
760
 
717
761
  /**
@@ -720,12 +764,12 @@ class Nightmare extends Helper {
720
764
  */
721
765
  async pressKey(key) {
722
766
  if (Array.isArray(key)) {
723
- key = key.join('+'); // should work with accelerators...
767
+ key = key.join('+') // should work with accelerators...
724
768
  }
725
769
  if (Object.keys(specialKeys).indexOf(key) >= 0) {
726
- key = specialKeys[key];
770
+ key = specialKeys[key]
727
771
  }
728
- return this.browser.pressKey(key).wait(this.options.waitForAction);
772
+ return this.browser.pressKey(key).wait(this.options.waitForAction)
729
773
  }
730
774
 
731
775
  /**
@@ -739,21 +783,21 @@ class Nightmare extends Helper {
739
783
  }
740
784
  */
741
785
  async triggerMouseEvent(event) {
742
- return this.browser.triggerMouseEvent(event).wait(this.options.waitForAction);
786
+ return this.browser.triggerMouseEvent(event).wait(this.options.waitForAction)
743
787
  }
744
788
 
745
789
  /**
746
790
  * {{> seeCheckboxIsChecked }}
747
791
  */
748
792
  async seeCheckboxIsChecked(field) {
749
- return proceedIsChecked.call(this, 'assert', field);
793
+ return proceedIsChecked.call(this, 'assert', field)
750
794
  }
751
795
 
752
796
  /**
753
797
  * {{> dontSeeCheckboxIsChecked }}
754
798
  */
755
799
  async dontSeeCheckboxIsChecked(field) {
756
- return proceedIsChecked.call(this, 'negate', field);
800
+ return proceedIsChecked.call(this, 'negate', field)
757
801
  }
758
802
 
759
803
  /**
@@ -762,167 +806,171 @@ class Nightmare extends Helper {
762
806
  * Doesn't work if the Chromium DevTools panel is open (as Chromium allows only one attachment to the debugger at a time. [See more](https://github.com/rosshinkley/nightmare-upload#important-note-about-setting-file-upload-inputs))
763
807
  */
764
808
  async attachFile(locator, pathToFile) {
765
- const file = path.join(global.codecept_dir, pathToFile);
809
+ const file = path.join(global.codecept_dir, pathToFile)
766
810
 
767
- locator = new Locator(locator, 'css');
811
+ locator = new Locator(locator, 'css')
768
812
  if (!locator.isCSS()) {
769
- throw new Error('Only CSS locator allowed for attachFile in Nightmare helper');
813
+ throw new Error('Only CSS locator allowed for attachFile in Nightmare helper')
770
814
  }
771
815
 
772
816
  if (!fileExists(file)) {
773
- throw new Error(`File at ${file} can not be found on local system`);
817
+ throw new Error(`File at ${file} can not be found on local system`)
774
818
  }
775
- return this.browser.upload(locator.value, file);
819
+ return this.browser.upload(locator.value, file)
776
820
  }
777
821
 
778
822
  /**
779
823
  * {{> grabTextFromAll }}
780
824
  */
781
825
  async grabTextFromAll(locator) {
782
- locator = new Locator(locator, 'css');
783
- const els = await this.browser.findElements(locator.toStrict());
784
- const texts = [];
785
- const getText = el => window.codeceptjs.fetchElement(el).innerText;
826
+ locator = new Locator(locator, 'css')
827
+ const els = await this.browser.findElements(locator.toStrict())
828
+ const texts = []
829
+ const getText = (el) => window.codeceptjs.fetchElement(el).innerText
786
830
  for (const el of els) {
787
- texts.push(await this.browser.evaluate(getText, el));
831
+ texts.push(await this.browser.evaluate(getText, el))
788
832
  }
789
- return texts;
833
+ return texts
790
834
  }
791
835
 
792
836
  /**
793
837
  * {{> grabTextFrom }}
794
838
  */
795
839
  async grabTextFrom(locator) {
796
- locator = new Locator(locator, 'css');
797
- const els = await this.browser.findElement(locator.toStrict());
798
- assertElementExists(els, locator);
799
- const texts = await this.grabTextFromAll(locator);
840
+ locator = new Locator(locator, 'css')
841
+ const els = await this.browser.findElement(locator.toStrict())
842
+ assertElementExists(els, locator)
843
+ const texts = await this.grabTextFromAll(locator)
800
844
  if (texts.length > 1) {
801
- this.debugSection('GrabText', `Using first element out of ${texts.length}`);
845
+ this.debugSection('GrabText', `Using first element out of ${texts.length}`)
802
846
  }
803
847
 
804
- return texts[0];
848
+ return texts[0]
805
849
  }
806
850
 
807
851
  /**
808
852
  * {{> grabValueFromAll }}
809
853
  */
810
854
  async grabValueFromAll(locator) {
811
- locator = new Locator(locator, 'css');
812
- const els = await this.browser.findElements(locator.toStrict());
813
- const values = [];
814
- const getValues = el => window.codeceptjs.fetchElement(el).value;
855
+ locator = new Locator(locator, 'css')
856
+ const els = await this.browser.findElements(locator.toStrict())
857
+ const values = []
858
+ const getValues = (el) => window.codeceptjs.fetchElement(el).value
815
859
  for (const el of els) {
816
- values.push(await this.browser.evaluate(getValues, el));
860
+ values.push(await this.browser.evaluate(getValues, el))
817
861
  }
818
862
 
819
- return values;
863
+ return values
820
864
  }
821
865
 
822
866
  /**
823
867
  * {{> grabValueFrom }}
824
868
  */
825
869
  async grabValueFrom(locator) {
826
- const el = await findField.call(this, locator);
827
- assertElementExists(el, locator, 'Field');
828
- const values = await this.grabValueFromAll(locator);
870
+ const el = await findField.call(this, locator)
871
+ assertElementExists(el, locator, 'Field')
872
+ const values = await this.grabValueFromAll(locator)
829
873
  if (values.length > 1) {
830
- this.debugSection('GrabValue', `Using first element out of ${values.length}`);
874
+ this.debugSection('GrabValue', `Using first element out of ${values.length}`)
831
875
  }
832
876
 
833
- return values[0];
877
+ return values[0]
834
878
  }
835
879
 
836
880
  /**
837
881
  * {{> grabAttributeFromAll }}
838
882
  */
839
883
  async grabAttributeFromAll(locator, attr) {
840
- locator = new Locator(locator, 'css');
841
- const els = await this.browser.findElements(locator.toStrict());
842
- const array = [];
884
+ locator = new Locator(locator, 'css')
885
+ const els = await this.browser.findElements(locator.toStrict())
886
+ const array = []
843
887
 
844
888
  for (let index = 0; index < els.length; index++) {
845
- const el = els[index];
846
- array.push(await this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr));
889
+ const el = els[index]
890
+ array.push(
891
+ await this.browser.evaluate((el, attr) => window.codeceptjs.fetchElement(el).getAttribute(attr), el, attr),
892
+ )
847
893
  }
848
894
 
849
- return array;
895
+ return array
850
896
  }
851
897
 
852
898
  /**
853
899
  * {{> grabAttributeFrom }}
854
900
  */
855
901
  async grabAttributeFrom(locator, attr) {
856
- locator = new Locator(locator, 'css');
857
- const els = await this.browser.findElement(locator.toStrict());
858
- assertElementExists(els, locator);
902
+ locator = new Locator(locator, 'css')
903
+ const els = await this.browser.findElement(locator.toStrict())
904
+ assertElementExists(els, locator)
859
905
 
860
- const attrs = await this.grabAttributeFromAll(locator, attr);
906
+ const attrs = await this.grabAttributeFromAll(locator, attr)
861
907
  if (attrs.length > 1) {
862
- this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
908
+ this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
863
909
  }
864
910
 
865
- return attrs[0];
911
+ return attrs[0]
866
912
  }
867
913
 
868
914
  /**
869
915
  * {{> grabHTMLFromAll }}
870
916
  */
871
917
  async grabHTMLFromAll(locator) {
872
- locator = new Locator(locator, 'css');
873
- const els = await this.browser.findElements(locator.toStrict());
874
- const array = [];
918
+ locator = new Locator(locator, 'css')
919
+ const els = await this.browser.findElements(locator.toStrict())
920
+ const array = []
875
921
 
876
922
  for (let index = 0; index < els.length; index++) {
877
- const el = els[index];
878
- array.push(await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).innerHTML, el));
923
+ const el = els[index]
924
+ array.push(await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).innerHTML, el))
879
925
  }
880
- this.debugSection('GrabHTML', array);
926
+ this.debugSection('GrabHTML', array)
881
927
 
882
- return array;
928
+ return array
883
929
  }
884
930
 
885
931
  /**
886
932
  * {{> grabHTMLFrom }}
887
933
  */
888
934
  async grabHTMLFrom(locator) {
889
- locator = new Locator(locator, 'css');
890
- const els = await this.browser.findElement(locator.toStrict());
891
- assertElementExists(els, locator);
892
- const html = await this.grabHTMLFromAll(locator);
935
+ locator = new Locator(locator, 'css')
936
+ const els = await this.browser.findElement(locator.toStrict())
937
+ assertElementExists(els, locator)
938
+ const html = await this.grabHTMLFromAll(locator)
893
939
  if (html.length > 1) {
894
- this.debugSection('GrabHTML', `Using first element out of ${html.length}`);
940
+ this.debugSection('GrabHTML', `Using first element out of ${html.length}`)
895
941
  }
896
942
 
897
- return html[0];
943
+ return html[0]
898
944
  }
899
945
 
900
946
  /**
901
947
  * {{> grabCssPropertyFrom }}
902
948
  */
903
949
  async grabCssPropertyFrom(locator, cssProperty) {
904
- locator = new Locator(locator, 'css');
905
- const els = await this.browser.findElements(locator.toStrict());
906
- const array = [];
950
+ locator = new Locator(locator, 'css')
951
+ const els = await this.browser.findElements(locator.toStrict())
952
+ const array = []
907
953
 
908
954
  const getCssPropForElement = async (el, prop) => {
909
- return (await this.browser.evaluate((el) => {
910
- return window.getComputedStyle(window.codeceptjs.fetchElement(el));
911
- }, el))[toCamelCase(prop)];
912
- };
955
+ return (
956
+ await this.browser.evaluate((el) => {
957
+ return window.getComputedStyle(window.codeceptjs.fetchElement(el))
958
+ }, el)
959
+ )[toCamelCase(prop)]
960
+ }
913
961
 
914
962
  for (const el of els) {
915
- assertElementExists(el, locator);
916
- const cssValue = await getCssPropForElement(el, cssProperty);
917
- array.push(cssValue);
963
+ assertElementExists(el, locator)
964
+ const cssValue = await getCssPropForElement(el, cssProperty)
965
+ array.push(cssValue)
918
966
  }
919
- this.debugSection('HTML', array);
967
+ this.debugSection('HTML', array)
920
968
 
921
- return array.length > 1 ? array : array[0];
969
+ return array.length > 1 ? array : array[0]
922
970
  }
923
971
 
924
972
  _injectClientScripts() {
925
- return this.browser.inject('js', path.join(__dirname, 'clientscripts', 'nightmare.js'));
973
+ return this.browser.inject('js', path.join(__dirname, 'clientscripts', 'nightmare.js'))
926
974
  }
927
975
 
928
976
  /**
@@ -930,41 +978,41 @@ class Nightmare extends Helper {
930
978
  */
931
979
  async selectOption(select, option) {
932
980
  const fetchAndCheckOption = function (el, locator) {
933
- el = window.codeceptjs.fetchElement(el);
934
- const found = document.evaluate(locator, el, null, 5, null);
935
- let current = null;
936
- const items = [];
937
- while (current = found.iterateNext()) {
938
- items.push(current);
981
+ el = window.codeceptjs.fetchElement(el)
982
+ const found = document.evaluate(locator, el, null, 5, null)
983
+ let current = null
984
+ const items = []
985
+ while ((current = found.iterateNext())) {
986
+ items.push(current)
939
987
  }
940
988
  for (let i = 0; i < items.length; i++) {
941
- current = items[i];
989
+ current = items[i]
942
990
  if (current instanceof HTMLOptionElement) {
943
- current.selected = true;
944
- if (!el.multiple) el.value = current.value;
991
+ current.selected = true
992
+ if (!el.multiple) el.value = current.value
945
993
  }
946
- const event = document.createEvent('HTMLEvents');
947
- event.initEvent('change', true, true);
948
- el.dispatchEvent(event);
994
+ const event = document.createEvent('HTMLEvents')
995
+ event.initEvent('change', true, true)
996
+ el.dispatchEvent(event)
949
997
  }
950
- return !!current;
951
- };
998
+ return !!current
999
+ }
952
1000
 
953
- const el = await findField.call(this, select);
954
- assertElementExists(el, select, 'Selectable field');
1001
+ const el = await findField.call(this, select)
1002
+ assertElementExists(el, select, 'Selectable field')
955
1003
  if (!Array.isArray(option)) {
956
- option = [option];
1004
+ option = [option]
957
1005
  }
958
1006
 
959
1007
  for (const key in option) {
960
- const opt = xpathLocator.literal(option[key]);
961
- const checked = await this.browser.evaluate(fetchAndCheckOption, el, Locator.select.byVisibleText(opt));
1008
+ const opt = xpathLocator.literal(option[key])
1009
+ const checked = await this.browser.evaluate(fetchAndCheckOption, el, Locator.select.byVisibleText(opt))
962
1010
 
963
1011
  if (!checked) {
964
- await this.browser.evaluate(fetchAndCheckOption, el, Locator.select.byValue(opt));
1012
+ await this.browser.evaluate(fetchAndCheckOption, el, Locator.select.byValue(opt))
965
1013
  }
966
1014
  }
967
- return this.browser.wait(this.options.waitForAction);
1015
+ return this.browser.wait(this.options.waitForAction)
968
1016
  }
969
1017
 
970
1018
  /**
@@ -974,7 +1022,7 @@ class Nightmare extends Helper {
974
1022
  * [See more](https://github.com/segmentio/nightmare/blob/master/Readme.md#cookiessetcookie)
975
1023
  */
976
1024
  async setCookie(cookie) {
977
- return this.browser.cookies.set(cookie);
1025
+ return this.browser.cookies.set(cookie)
978
1026
  }
979
1027
 
980
1028
  /**
@@ -982,16 +1030,16 @@ class Nightmare extends Helper {
982
1030
  *
983
1031
  */
984
1032
  async seeCookie(name) {
985
- const res = await this.browser.cookies.get(name);
986
- truth(`cookie ${name}`, 'to be set').assert(res);
1033
+ const res = await this.browser.cookies.get(name)
1034
+ truth(`cookie ${name}`, 'to be set').assert(res)
987
1035
  }
988
1036
 
989
1037
  /**
990
1038
  * {{> dontSeeCookie }}
991
1039
  */
992
1040
  async dontSeeCookie(name) {
993
- const res = await this.browser.cookies.get(name);
994
- truth(`cookie ${name}`, 'to be set').negate(res);
1041
+ const res = await this.browser.cookies.get(name)
1042
+ truth(`cookie ${name}`, 'to be set').negate(res)
995
1043
  }
996
1044
 
997
1045
  /**
@@ -1002,7 +1050,7 @@ class Nightmare extends Helper {
1002
1050
  * Multiple cookies can be received by passing query object `I.grabCookie({ secure: true});`. If you'd like get all cookies for all urls, use: `.grabCookie({ url: null }).`
1003
1051
  */
1004
1052
  async grabCookie(name) {
1005
- return this.browser.cookies.get(name);
1053
+ return this.browser.cookies.get(name)
1006
1054
  }
1007
1055
 
1008
1056
  /**
@@ -1010,34 +1058,34 @@ class Nightmare extends Helper {
1010
1058
  */
1011
1059
  async clearCookie(cookie) {
1012
1060
  if (!cookie) {
1013
- return this.browser.cookies.clearAll();
1061
+ return this.browser.cookies.clearAll()
1014
1062
  }
1015
- return this.browser.cookies.clear(cookie);
1063
+ return this.browser.cookies.clear(cookie)
1016
1064
  }
1017
1065
 
1018
1066
  /**
1019
1067
  * {{> waitForFunction }}
1020
1068
  */
1021
1069
  async waitForFunction(fn, argsOrSec = null, sec = null) {
1022
- let args = [];
1070
+ let args = []
1023
1071
  if (argsOrSec) {
1024
1072
  if (Array.isArray(argsOrSec)) {
1025
- args = argsOrSec;
1073
+ args = argsOrSec
1026
1074
  } else if (typeof argsOrSec === 'number') {
1027
- sec = argsOrSec;
1075
+ sec = argsOrSec
1028
1076
  }
1029
1077
  }
1030
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1031
- return this.browser.wait(fn, ...args);
1078
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1079
+ return this.browser.wait(fn, ...args)
1032
1080
  }
1033
1081
 
1034
1082
  /**
1035
1083
  * {{> wait }}
1036
1084
  */
1037
1085
  async wait(sec) {
1038
- return new Promise(((done) => {
1039
- setTimeout(done, sec * 1000);
1040
- }));
1086
+ return new Promise((done) => {
1087
+ setTimeout(done, sec * 1000)
1088
+ })
1041
1089
  }
1042
1090
 
1043
1091
  /**
@@ -1045,113 +1093,136 @@ class Nightmare extends Helper {
1045
1093
  */
1046
1094
  async waitForText(text, sec, context = null) {
1047
1095
  if (!context) {
1048
- context = this.context;
1096
+ context = this.context
1049
1097
  }
1050
- const locator = new Locator(context, 'css');
1051
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1052
- return this.browser.wait((by, locator, text) => {
1053
- return window.codeceptjs.findElement(by, locator).innerText.indexOf(text) > -1;
1054
- }, locator.type, locator.value, text).catch((err) => {
1055
- if (err.message.indexOf('Cannot read property') > -1) {
1056
- throw new Error(`element (${JSON.stringify(context)}) is not in DOM. Unable to wait text.`);
1057
- } else if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1058
- throw new Error(`there is no element(${JSON.stringify(context)}) with text "${text}" after ${sec} sec`);
1059
- } else throw err;
1060
- });
1098
+ const locator = new Locator(context, 'css')
1099
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1100
+ return this.browser
1101
+ .wait(
1102
+ (by, locator, text) => {
1103
+ return window.codeceptjs.findElement(by, locator).innerText.indexOf(text) > -1
1104
+ },
1105
+ locator.type,
1106
+ locator.value,
1107
+ text,
1108
+ )
1109
+ .catch((err) => {
1110
+ if (err.message.indexOf('Cannot read property') > -1) {
1111
+ throw new Error(`element (${JSON.stringify(context)}) is not in DOM. Unable to wait text.`)
1112
+ } else if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1113
+ throw new Error(`there is no element(${JSON.stringify(context)}) with text "${text}" after ${sec} sec`)
1114
+ } else throw err
1115
+ })
1061
1116
  }
1062
1117
 
1063
1118
  /**
1064
1119
  * {{> waitForVisible }}
1065
1120
  */
1066
1121
  waitForVisible(locator, sec) {
1067
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1068
- locator = new Locator(locator, 'css');
1069
-
1070
- return this.browser.wait((by, locator) => {
1071
- const el = window.codeceptjs.findElement(by, locator);
1072
- if (!el) return false;
1073
- return el.offsetWidth > 0 && el.offsetHeight > 0;
1074
- }, locator.type, locator.value).catch((err) => {
1075
- if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1076
- throw new Error(`element (${JSON.stringify(locator)}) still not visible on page after ${sec} sec`);
1077
- } else throw err;
1078
- });
1122
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1123
+ locator = new Locator(locator, 'css')
1124
+
1125
+ return this.browser
1126
+ .wait(
1127
+ (by, locator) => {
1128
+ const el = window.codeceptjs.findElement(by, locator)
1129
+ if (!el) return false
1130
+ return el.offsetWidth > 0 && el.offsetHeight > 0
1131
+ },
1132
+ locator.type,
1133
+ locator.value,
1134
+ )
1135
+ .catch((err) => {
1136
+ if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1137
+ throw new Error(`element (${JSON.stringify(locator)}) still not visible on page after ${sec} sec`)
1138
+ } else throw err
1139
+ })
1079
1140
  }
1080
1141
 
1081
1142
  /**
1082
1143
  * {{> waitToHide }}
1083
1144
  */
1084
1145
  async waitToHide(locator, sec = null) {
1085
- return this.waitForInvisible(locator, sec);
1146
+ return this.waitForInvisible(locator, sec)
1086
1147
  }
1087
1148
 
1088
1149
  /**
1089
1150
  * {{> waitForInvisible }}
1090
1151
  */
1091
1152
  waitForInvisible(locator, sec) {
1092
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1093
- locator = new Locator(locator, 'css');
1094
-
1095
- return this.browser.wait((by, locator) => {
1096
- const el = window.codeceptjs.findElement(by, locator);
1097
- if (!el) return true;
1098
- return !(el.offsetWidth > 0 && el.offsetHeight > 0);
1099
- }, locator.type, locator.value).catch((err) => {
1100
- if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1101
- throw new Error(`element (${JSON.stringify(locator)}) still visible after ${sec} sec`);
1102
- } else throw err;
1103
- });
1153
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1154
+ locator = new Locator(locator, 'css')
1155
+
1156
+ return this.browser
1157
+ .wait(
1158
+ (by, locator) => {
1159
+ const el = window.codeceptjs.findElement(by, locator)
1160
+ if (!el) return true
1161
+ return !(el.offsetWidth > 0 && el.offsetHeight > 0)
1162
+ },
1163
+ locator.type,
1164
+ locator.value,
1165
+ )
1166
+ .catch((err) => {
1167
+ if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1168
+ throw new Error(`element (${JSON.stringify(locator)}) still visible after ${sec} sec`)
1169
+ } else throw err
1170
+ })
1104
1171
  }
1105
1172
 
1106
1173
  /**
1107
1174
  * {{> waitForElement }}
1108
1175
  */
1109
1176
  async waitForElement(locator, sec) {
1110
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1111
- locator = new Locator(locator, 'css');
1177
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1178
+ locator = new Locator(locator, 'css')
1112
1179
 
1113
- return this.browser.wait((by, locator) => window.codeceptjs.findElement(by, locator) !== null, locator.type, locator.value).catch((err) => {
1114
- if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1115
- throw new Error(`element (${JSON.stringify(locator)}) still not present on page after ${sec} sec`);
1116
- } else throw err;
1117
- });
1180
+ return this.browser
1181
+ .wait((by, locator) => window.codeceptjs.findElement(by, locator) !== null, locator.type, locator.value)
1182
+ .catch((err) => {
1183
+ if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1184
+ throw new Error(`element (${JSON.stringify(locator)}) still not present on page after ${sec} sec`)
1185
+ } else throw err
1186
+ })
1118
1187
  }
1119
1188
 
1120
1189
  async waitUntilExists(locator, sec) {
1121
1190
  console.log(`waitUntilExists deprecated:
1122
1191
  * use 'waitForElement' to wait for element to be attached
1123
- * use 'waitForDetached to wait for element to be removed'`);
1124
- return this.waitForDetached(locator, sec);
1192
+ * use 'waitForDetached to wait for element to be removed'`)
1193
+ return this.waitForDetached(locator, sec)
1125
1194
  }
1126
1195
 
1127
1196
  /**
1128
1197
  * {{> waitForDetached }}
1129
1198
  */
1130
1199
  async waitForDetached(locator, sec) {
1131
- this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1132
- sec = this.browser.options.waitForTimeout / 1000;
1133
- locator = new Locator(locator, 'css');
1200
+ this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1201
+ sec = this.browser.options.waitForTimeout / 1000
1202
+ locator = new Locator(locator, 'css')
1134
1203
 
1135
- return this.browser.wait((by, locator) => window.codeceptjs.findElement(by, locator) === null, locator.type, locator.value).catch((err) => {
1136
- if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1137
- throw new Error(`element (${JSON.stringify(locator)}) still on page after ${sec} sec`);
1138
- } else throw err;
1139
- });
1204
+ return this.browser
1205
+ .wait((by, locator) => window.codeceptjs.findElement(by, locator) === null, locator.type, locator.value)
1206
+ .catch((err) => {
1207
+ if (err.message && err.message.indexOf('.wait() timed out after') > -1) {
1208
+ throw new Error(`element (${JSON.stringify(locator)}) still on page after ${sec} sec`)
1209
+ } else throw err
1210
+ })
1140
1211
  }
1141
1212
 
1142
1213
  /**
1143
1214
  * {{> refreshPage }}
1144
1215
  */
1145
1216
  async refreshPage() {
1146
- return this.browser.refresh();
1217
+ return this.browser.refresh()
1147
1218
  }
1148
1219
 
1149
1220
  /**
1150
1221
  * Reload the page
1151
1222
  */
1152
1223
  refresh() {
1153
- console.log('Deprecated in favor of refreshPage');
1154
- return this.browser.refresh();
1224
+ console.log('Deprecated in favor of refreshPage')
1225
+ return this.browser.refresh()
1155
1226
  }
1156
1227
 
1157
1228
  /**
@@ -1159,70 +1230,74 @@ class Nightmare extends Helper {
1159
1230
  *
1160
1231
  */
1161
1232
  async saveElementScreenshot(locator, fileName) {
1162
- const outputFile = screenshotOutputFolder(fileName);
1233
+ const outputFile = screenshotOutputFolder(fileName)
1163
1234
 
1164
- const rect = await this.grabElementBoundingRect(locator);
1235
+ const rect = await this.grabElementBoundingRect(locator)
1165
1236
 
1166
1237
  const button_clip = {
1167
1238
  x: Math.floor(rect.x),
1168
1239
  y: Math.floor(rect.y),
1169
1240
  width: Math.floor(rect.width),
1170
1241
  height: Math.floor(rect.height),
1171
- };
1242
+ }
1172
1243
 
1173
- this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
1244
+ this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
1174
1245
  // take the screenshot
1175
- await this.browser.screenshot(outputFile, button_clip);
1246
+ await this.browser.screenshot(outputFile, button_clip)
1176
1247
  }
1177
1248
 
1178
1249
  /**
1179
1250
  * {{> grabElementBoundingRect }}
1180
1251
  */
1181
1252
  async grabElementBoundingRect(locator, prop) {
1182
- locator = new Locator(locator, 'css');
1253
+ locator = new Locator(locator, 'css')
1183
1254
 
1184
- const rect = await this.browser.evaluate(async (by, locator) => {
1185
- // store the button in a variable
1255
+ const rect = await this.browser.evaluate(
1256
+ async (by, locator) => {
1257
+ // store the button in a variable
1186
1258
 
1187
- const build_cluster_btn = await window.codeceptjs.findElement(by, locator);
1259
+ const build_cluster_btn = await window.codeceptjs.findElement(by, locator)
1188
1260
 
1189
- // use the getClientRects() function on the button to determine
1190
- // the size and location
1191
- const rect = build_cluster_btn.getBoundingClientRect();
1261
+ // use the getClientRects() function on the button to determine
1262
+ // the size and location
1263
+ const rect = build_cluster_btn.getBoundingClientRect()
1192
1264
 
1193
- // convert the rectangle to a clip object and return it
1194
- return {
1195
- x: rect.left,
1196
- y: rect.top,
1197
- width: rect.width,
1198
- height: rect.height,
1199
- };
1200
- }, locator.type, locator.value);
1265
+ // convert the rectangle to a clip object and return it
1266
+ return {
1267
+ x: rect.left,
1268
+ y: rect.top,
1269
+ width: rect.width,
1270
+ height: rect.height,
1271
+ }
1272
+ },
1273
+ locator.type,
1274
+ locator.value,
1275
+ )
1201
1276
 
1202
- if (prop) return rect[prop];
1203
- return rect;
1277
+ if (prop) return rect[prop]
1278
+ return rect
1204
1279
  }
1205
1280
 
1206
1281
  /**
1207
1282
  * {{> saveScreenshot }}
1208
1283
  */
1209
1284
  async saveScreenshot(fileName, fullPage = this.options.fullPageScreenshots) {
1210
- const outputFile = screenshotOutputFolder(fileName);
1285
+ const outputFile = screenshotOutputFolder(fileName)
1211
1286
 
1212
- this.debug(`Screenshot is saving to ${outputFile}`);
1287
+ this.debug(`Screenshot is saving to ${outputFile}`)
1213
1288
 
1214
1289
  if (!fullPage) {
1215
- return this.browser.screenshot(outputFile);
1290
+ return this.browser.screenshot(outputFile)
1216
1291
  }
1217
1292
  const { height, width } = await this.browser.evaluate(() => {
1218
- return { height: document.body.scrollHeight, width: document.body.scrollWidth };
1219
- });
1220
- await this.browser.viewport(width, height);
1221
- return this.browser.screenshot(outputFile);
1293
+ return { height: document.body.scrollHeight, width: document.body.scrollWidth }
1294
+ })
1295
+ await this.browser.viewport(width, height)
1296
+ return this.browser.screenshot(outputFile)
1222
1297
  }
1223
1298
 
1224
1299
  async _failed() {
1225
- if (withinStatus !== false) await this._withinEnd();
1300
+ if (withinStatus !== false) await this._withinEnd()
1226
1301
  }
1227
1302
 
1228
1303
  /**
@@ -1230,28 +1305,40 @@ class Nightmare extends Helper {
1230
1305
  */
1231
1306
  async scrollTo(locator, offsetX = 0, offsetY = 0) {
1232
1307
  if (typeof locator === 'number' && typeof offsetX === 'number') {
1233
- offsetY = offsetX;
1234
- offsetX = locator;
1235
- locator = null;
1308
+ offsetY = offsetX
1309
+ offsetX = locator
1310
+ locator = null
1236
1311
  }
1237
1312
  if (locator) {
1238
- locator = new Locator(locator, 'css');
1239
- return this.browser.evaluate((by, locator, offsetX, offsetY) => {
1240
- const el = window.codeceptjs.findElement(by, locator);
1241
- if (!el) throw new Error(`Element not found ${by}: ${locator}`);
1242
- const rect = el.getBoundingClientRect();
1243
- window.scrollTo(rect.left + offsetX, rect.top + offsetY);
1244
- }, locator.type, locator.value, offsetX, offsetY);
1313
+ locator = new Locator(locator, 'css')
1314
+ return this.browser.evaluate(
1315
+ (by, locator, offsetX, offsetY) => {
1316
+ const el = window.codeceptjs.findElement(by, locator)
1317
+ if (!el) throw new Error(`Element not found ${by}: ${locator}`)
1318
+ const rect = el.getBoundingClientRect()
1319
+ window.scrollTo(rect.left + offsetX, rect.top + offsetY)
1320
+ },
1321
+ locator.type,
1322
+ locator.value,
1323
+ offsetX,
1324
+ offsetY,
1325
+ )
1245
1326
  }
1246
1327
  // eslint-disable-next-line prefer-arrow-callback
1247
- return this.executeScript(function (x, y) { return window.scrollTo(x, y); }, offsetX, offsetY);
1328
+ return this.executeScript(
1329
+ function (x, y) {
1330
+ return window.scrollTo(x, y)
1331
+ },
1332
+ offsetX,
1333
+ offsetY,
1334
+ )
1248
1335
  }
1249
1336
 
1250
1337
  /**
1251
1338
  * {{> scrollPageToTop }}
1252
1339
  */
1253
1340
  async scrollPageToTop() {
1254
- return this.executeScript(() => window.scrollTo(0, 0));
1341
+ return this.executeScript(() => window.scrollTo(0, 0))
1255
1342
  }
1256
1343
 
1257
1344
  /**
@@ -1260,16 +1347,13 @@ class Nightmare extends Helper {
1260
1347
  async scrollPageToBottom() {
1261
1348
  /* eslint-disable prefer-arrow-callback, comma-dangle */
1262
1349
  return this.executeScript(function () {
1263
- const body = document.body;
1264
- const html = document.documentElement;
1265
- window.scrollTo(0, Math.max(
1266
- body.scrollHeight,
1267
- body.offsetHeight,
1268
- html.clientHeight,
1269
- html.scrollHeight,
1270
- html.offsetHeight
1271
- ));
1272
- });
1350
+ const body = document.body
1351
+ const html = document.documentElement
1352
+ window.scrollTo(
1353
+ 0,
1354
+ Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
1355
+ )
1356
+ })
1273
1357
  /* eslint-enable */
1274
1358
  }
1275
1359
 
@@ -1281,135 +1365,143 @@ class Nightmare extends Helper {
1281
1365
  function getScrollPosition() {
1282
1366
  return {
1283
1367
  x: window.pageXOffset,
1284
- y: window.pageYOffset
1285
- };
1368
+ y: window.pageYOffset,
1369
+ }
1286
1370
  }
1287
1371
  /* eslint-enable comma-dangle */
1288
- return this.executeScript(getScrollPosition);
1372
+ return this.executeScript(getScrollPosition)
1289
1373
  }
1290
1374
  }
1291
1375
 
1292
- module.exports = Nightmare;
1376
+ module.exports = Nightmare
1293
1377
 
1294
1378
  async function proceedSee(assertType, text, context) {
1295
- let description;
1296
- let locator;
1379
+ let description
1380
+ let locator
1297
1381
  if (!context) {
1298
1382
  if (this.context === this.options.rootElement) {
1299
- locator = new Locator(this.context, 'css');
1300
- description = 'web application';
1383
+ locator = new Locator(this.context, 'css')
1384
+ description = 'web application'
1301
1385
  } else {
1302
- description = `current context ${this.context}`;
1303
- locator = new Locator({ xpath: './/*' });
1386
+ description = `current context ${this.context}`
1387
+ locator = new Locator({ xpath: './/*' })
1304
1388
  }
1305
1389
  } else {
1306
- locator = new Locator(context, 'css');
1307
- description = `element ${locator.toString()}`;
1308
- }
1309
-
1310
- const texts = await this.browser.evaluate((by, locator) => {
1311
- return window.codeceptjs.findElements(by, locator).map(el => el.innerText);
1312
- }, locator.type, locator.value);
1313
- const allText = texts.join(' | ');
1314
- return stringIncludes(description)[assertType](text, allText);
1390
+ locator = new Locator(context, 'css')
1391
+ description = `element ${locator.toString()}`
1392
+ }
1393
+
1394
+ const texts = await this.browser.evaluate(
1395
+ (by, locator) => {
1396
+ return window.codeceptjs.findElements(by, locator).map((el) => el.innerText)
1397
+ },
1398
+ locator.type,
1399
+ locator.value,
1400
+ )
1401
+ const allText = texts.join(' | ')
1402
+ return stringIncludes(description)[assertType](text, allText)
1315
1403
  }
1316
1404
 
1317
1405
  async function proceedSeeInField(assertType, field, value) {
1318
- const el = await findField.call(this, field);
1319
- assertElementExists(el, field, 'Field');
1320
- const tag = await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).tagName, el);
1321
- const fieldVal = await this.browser.evaluate(el => window.codeceptjs.fetchElement(el).value, el);
1406
+ const el = await findField.call(this, field)
1407
+ assertElementExists(el, field, 'Field')
1408
+ const tag = await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).tagName, el)
1409
+ const fieldVal = await this.browser.evaluate((el) => window.codeceptjs.fetchElement(el).value, el)
1322
1410
  if (tag === 'select') {
1323
1411
  // locate option by values and check them
1324
- const text = await this.browser.evaluate((el, val) => {
1325
- return el.querySelector(`option[value="${val}"]`).innerText;
1326
- }, el, xpathLocator.literal(fieldVal));
1327
- return equals(`select option by ${field}`)[assertType](value, text);
1412
+ const text = await this.browser.evaluate(
1413
+ (el, val) => {
1414
+ return el.querySelector(`option[value="${val}"]`).innerText
1415
+ },
1416
+ el,
1417
+ xpathLocator.literal(fieldVal),
1418
+ )
1419
+ return equals(`select option by ${field}`)[assertType](value, text)
1328
1420
  }
1329
- return stringIncludes(`field by ${field}`)[assertType](value, fieldVal);
1421
+ return stringIncludes(`field by ${field}`)[assertType](value, fieldVal)
1330
1422
  }
1331
1423
 
1332
1424
  async function proceedIsChecked(assertType, option) {
1333
- const els = await findCheckable.call(this, option);
1334
- assertElementExists(els, option, 'Checkable');
1425
+ const els = await findCheckable.call(this, option)
1426
+ assertElementExists(els, option, 'Checkable')
1335
1427
  const selected = await this.browser.evaluate((els) => {
1336
- return els.map(el => window.codeceptjs.fetchElement(el).checked).reduce((prev, cur) => prev || cur);
1337
- }, els);
1338
- return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
1428
+ return els.map((el) => window.codeceptjs.fetchElement(el).checked).reduce((prev, cur) => prev || cur)
1429
+ }, els)
1430
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
1339
1431
  }
1340
1432
 
1341
1433
  async function findCheckable(locator, context) {
1342
- let contextEl = null;
1434
+ let contextEl = null
1343
1435
  if (context) {
1344
- contextEl = await this.browser.findElement((new Locator(context, 'css')).toStrict());
1436
+ contextEl = await this.browser.findElement(new Locator(context, 'css').toStrict())
1345
1437
  }
1346
1438
 
1347
- const matchedLocator = new Locator(locator);
1439
+ const matchedLocator = new Locator(locator)
1348
1440
  if (!matchedLocator.isFuzzy()) {
1349
- return this.browser.findElements(matchedLocator.toStrict(), contextEl);
1441
+ return this.browser.findElements(matchedLocator.toStrict(), contextEl)
1350
1442
  }
1351
1443
 
1352
- const literal = xpathLocator.literal(locator);
1353
- let els = await this.browser.findElements({ xpath: Locator.checkable.byText(literal) }, contextEl);
1444
+ const literal = xpathLocator.literal(locator)
1445
+ let els = await this.browser.findElements({ xpath: Locator.checkable.byText(literal) }, contextEl)
1354
1446
  if (els.length) {
1355
- return els;
1447
+ return els
1356
1448
  }
1357
- els = await this.browser.findElements({ xpath: Locator.checkable.byName(literal) }, contextEl);
1449
+ els = await this.browser.findElements({ xpath: Locator.checkable.byName(literal) }, contextEl)
1358
1450
  if (els.length) {
1359
- return els;
1451
+ return els
1360
1452
  }
1361
- return this.browser.findElements({ css: locator }, contextEl);
1453
+ return this.browser.findElements({ css: locator }, contextEl)
1362
1454
  }
1363
1455
 
1364
1456
  async function findClickable(locator, context) {
1365
- let contextEl = null;
1457
+ let contextEl = null
1366
1458
  if (context) {
1367
- contextEl = await this.browser.findElement((new Locator(context, 'css')).toStrict());
1459
+ contextEl = await this.browser.findElement(new Locator(context, 'css').toStrict())
1368
1460
  }
1369
1461
 
1370
- const matchedLocator = new Locator(locator);
1462
+ const matchedLocator = new Locator(locator)
1371
1463
  if (!matchedLocator.isFuzzy()) {
1372
- return this.browser.findElement(matchedLocator.toStrict(), contextEl);
1464
+ return this.browser.findElement(matchedLocator.toStrict(), contextEl)
1373
1465
  }
1374
1466
 
1375
- const literal = xpathLocator.literal(locator);
1467
+ const literal = xpathLocator.literal(locator)
1376
1468
 
1377
- let els = await this.browser.findElements({ xpath: Locator.clickable.narrow(literal) }, contextEl);
1469
+ let els = await this.browser.findElements({ xpath: Locator.clickable.narrow(literal) }, contextEl)
1378
1470
  if (els.length) {
1379
- return els[0];
1471
+ return els[0]
1380
1472
  }
1381
1473
 
1382
- els = await this.browser.findElements({ xpath: Locator.clickable.wide(literal) }, contextEl);
1474
+ els = await this.browser.findElements({ xpath: Locator.clickable.wide(literal) }, contextEl)
1383
1475
  if (els.length) {
1384
- return els[0];
1476
+ return els[0]
1385
1477
  }
1386
1478
 
1387
- return this.browser.findElement({ css: locator }, contextEl);
1479
+ return this.browser.findElement({ css: locator }, contextEl)
1388
1480
  }
1389
1481
 
1390
1482
  async function findField(locator) {
1391
- const matchedLocator = new Locator(locator);
1483
+ const matchedLocator = new Locator(locator)
1392
1484
  if (!matchedLocator.isFuzzy()) {
1393
- return this.browser.findElements(matchedLocator.toStrict());
1485
+ return this.browser.findElements(matchedLocator.toStrict())
1394
1486
  }
1395
- const literal = xpathLocator.literal(locator);
1487
+ const literal = xpathLocator.literal(locator)
1396
1488
 
1397
- let els = await this.browser.findElements({ xpath: Locator.field.labelEquals(literal) });
1489
+ let els = await this.browser.findElements({ xpath: Locator.field.labelEquals(literal) })
1398
1490
  if (els.length) {
1399
- return els[0];
1491
+ return els[0]
1400
1492
  }
1401
1493
 
1402
- els = await this.browser.findElements({ xpath: Locator.field.labelContains(literal) });
1494
+ els = await this.browser.findElements({ xpath: Locator.field.labelContains(literal) })
1403
1495
  if (els.length) {
1404
- return els[0];
1496
+ return els[0]
1405
1497
  }
1406
- els = await this.browser.findElements({ xpath: Locator.field.byName(literal) });
1498
+ els = await this.browser.findElements({ xpath: Locator.field.byName(literal) })
1407
1499
  if (els.length) {
1408
- return els[0];
1500
+ return els[0]
1409
1501
  }
1410
- return this.browser.findElement({ css: locator });
1502
+ return this.browser.findElement({ css: locator })
1411
1503
  }
1412
1504
 
1413
1505
  function assertElementExists(el, locator, prefix, suffix) {
1414
- if (el === null) throw new ElementNotFound(locator, prefix, suffix);
1506
+ if (el === null) throw new ElementNotFound(locator, prefix, suffix)
1415
1507
  }