codeceptjs 3.6.6 → 4.0.0-beta.1

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