codeceptjs 3.6.7 → 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 (149) 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
@@ -1,21 +1,20 @@
1
- const axios = require('axios')
2
- const fs = require('fs')
3
- const fsExtra = require('fs-extra')
4
- const path = require('path')
5
-
6
- const Helper = require('@codeceptjs/helper')
7
- const { v4: uuidv4 } = require('uuid')
8
- const promiseRetry = require('promise-retry')
9
- const Locator = require('../locator')
10
- const recorder = require('../recorder')
11
- const store = require('../store')
12
- const stringIncludes = require('../assert/include').includes
13
- const { urlEquals } = require('../assert/equal')
14
- const { equals } = require('../assert/equal')
15
- const { empty } = require('../assert/empty')
16
- const { truth } = require('../assert/truth')
17
- const isElementClickable = require('./scripts/isElementClickable')
18
- const {
1
+ import axios from 'axios';
2
+ import fs from 'fs';
3
+ import fsExtra from 'fs-extra';
4
+ import path from 'path';
5
+ import Helper from '@codeceptjs/helper';
6
+ import { v4 as uuidv4 } from 'uuid';
7
+ import promiseRetry from 'promise-retry';
8
+ import Locator from '../locator.js';
9
+ import recorder from '../recorder.js';
10
+ import { store } from '../store.js';
11
+ import { includes as stringIncludes } from '../assert/include.js';
12
+ import { urlEquals, equals } from '../assert/equal.js';
13
+ import { empty } from '../assert/empty.js';
14
+ import { truth } from '../assert/truth';
15
+ import isElementClickable from './scripts/isElementClickable';
16
+
17
+ import {
19
18
  xpathLocator,
20
19
  ucfirst,
21
20
  fileExists,
@@ -28,32 +27,33 @@ const {
28
27
  isModifierKey,
29
28
  requireWithFallback,
30
29
  normalizeSpacesInString,
31
- } = require('../utils')
32
- const { isColorProperty, convertColorToRGBA } = require('../colorUtils')
33
- const ElementNotFound = require('./errors/ElementNotFound')
34
- const RemoteBrowserConnectionRefused = require('./errors/RemoteBrowserConnectionRefused')
35
- const Popup = require('./extras/Popup')
36
- const Console = require('./extras/Console')
37
- const { highlightElement } = require('./scripts/highlightElement')
38
- const { blurElement } = require('./scripts/blurElement')
39
- const {
30
+ } from '../utils.js';
31
+
32
+ import { isColorProperty, convertColorToRGBA } from '../colorUtils';
33
+ import ElementNotFound from './errors/ElementNotFound.js';
34
+ import RemoteBrowserConnectionRefused from './errors/RemoteBrowserConnectionRefused';
35
+ import Popup from './extras/Popup';
36
+ import Console from './extras/Console';
37
+ import findReact from './extras/React';
38
+ import { highlightElement } from './scripts/highlightElement';
39
+ import { blurElement } from './scripts/blurElement';
40
+ import { focusElement } from './scripts/focusElement';
41
+
42
+ import {
40
43
  dontSeeElementError,
41
44
  seeElementError,
42
45
  dontSeeElementInDOMError,
43
46
  seeElementInDOMError,
44
- } = require('./errors/ElementAssertion')
45
- const {
46
- dontSeeTraffic,
47
- seeTraffic,
48
- grabRecordedNetworkTraffics,
49
- stopRecordingTraffic,
50
- flushNetworkTraffics,
51
- } = require('./network/actions')
52
-
53
- let puppeteer
54
- let perfTiming
55
- const popupStore = new Popup()
56
- const consoleLogStore = new Console()
47
+ } from './errors/ElementAssertion';
48
+
49
+ import {
50
+ dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics,
51
+ } from './network/actions';
52
+
53
+ let puppeteer;
54
+ let perfTiming;
55
+ const popupStore = new Popup();
56
+ const consoleLogStore = new Console();
57
57
 
58
58
  /**
59
59
  * ## Configuration
@@ -85,7 +85,7 @@ const consoleLogStore = new Console()
85
85
  * @prop {object} [chrome] - pass additional [Puppeteer run options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions).
86
86
  * @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
87
87
  */
88
- const config = {}
88
+ const config = {};
89
89
 
90
90
  /**
91
91
  * Uses [Google Chrome's Puppeteer](https://github.com/GoogleChrome/puppeteer) library to run tests inside headless Chrome.
@@ -222,29 +222,29 @@ const config = {}
222
222
  */
223
223
  class Puppeteer extends Helper {
224
224
  constructor(config) {
225
- super(config)
225
+ super(config);
226
226
 
227
- puppeteer = requireWithFallback('puppeteer', 'puppeteer-core')
227
+ puppeteer = requireWithFallback('puppeteer', 'puppeteer-core');
228
228
  // set defaults
229
- this.isRemoteBrowser = false
230
- this.isRunning = false
231
- this.isAuthenticated = false
232
- this.sessionPages = {}
233
- this.activeSessionName = ''
229
+ this.isRemoteBrowser = false;
230
+ this.isRunning = false;
231
+ this.isAuthenticated = false;
232
+ this.sessionPages = {};
233
+ this.activeSessionName = '';
234
234
 
235
235
  // for network stuff
236
- this.requests = []
237
- this.recording = false
238
- this.recordedAtLeastOnce = false
236
+ this.requests = [];
237
+ this.recording = false;
238
+ this.recordedAtLeastOnce = false;
239
239
 
240
240
  // for websocket messages
241
- this.webSocketMessages = []
242
- this.recordingWebSocketMessages = false
243
- this.recordedWebSocketMessagesAtLeastOnce = false
244
- this.cdpSession = null
241
+ this.webSocketMessages = [];
242
+ this.recordingWebSocketMessages = false;
243
+ this.recordedWebSocketMessagesAtLeastOnce = false;
244
+ this.cdpSession = null;
245
245
 
246
246
  // override defaults with config
247
- this._setConfig(config)
247
+ this._setConfig(config);
248
248
  }
249
249
 
250
250
  _validateConfig(config) {
@@ -265,161 +265,156 @@ class Puppeteer extends Helper {
265
265
  show: false,
266
266
  defaultPopupAction: 'accept',
267
267
  highlightElement: false,
268
- }
268
+ };
269
269
 
270
- return Object.assign(defaults, config)
270
+ return Object.assign(defaults, config);
271
271
  }
272
272
 
273
273
  _getOptions(config) {
274
- return config.browser === 'firefox'
275
- ? Object.assign(this.options.firefox, { product: 'firefox' })
276
- : this.options.chrome
274
+ return config.browser === 'firefox' ? Object.assign(this.options.firefox, { product: 'firefox' }) : this.options.chrome;
277
275
  }
278
276
 
279
277
  _setConfig(config) {
280
- this.options = this._validateConfig(config)
278
+ this.options = this._validateConfig(config);
281
279
  this.puppeteerOptions = {
282
280
  headless: !this.options.show,
283
281
  ...this._getOptions(config),
284
- }
285
- if (this.puppeteerOptions.headless) this.puppeteerOptions.headless = 'new'
286
- this.isRemoteBrowser = !!this.puppeteerOptions.browserWSEndpoint
287
- popupStore.defaultAction = this.options.defaultPopupAction
282
+ };
283
+ if (this.puppeteerOptions.headless) this.puppeteerOptions.headless = 'new';
284
+ this.isRemoteBrowser = !!this.puppeteerOptions.browserWSEndpoint;
285
+ popupStore.defaultAction = this.options.defaultPopupAction;
288
286
  }
289
287
 
290
288
  static _config() {
291
289
  return [
292
290
  { name: 'url', message: 'Base url of site to be tested', default: 'http://localhost' },
293
291
  {
294
- name: 'show',
295
- message: 'Show browser window',
296
- default: true,
297
- type: 'confirm',
292
+ name: 'show', message: 'Show browser window', default: true, type: 'confirm',
298
293
  },
299
294
  {
300
- name: 'windowSize',
301
- message: 'Browser viewport size',
302
- default: '1200x900',
295
+ name: 'windowSize', message: 'Browser viewport size', default: '1200x900',
303
296
  },
304
- ]
297
+ ];
305
298
  }
306
299
 
307
300
  static _checkRequirements() {
308
301
  try {
309
- requireWithFallback('puppeteer', 'puppeteer-core')
302
+ requireWithFallback('puppeteer', 'puppeteer-core');
310
303
  } catch (e) {
311
- return ['puppeteer']
304
+ return ['puppeteer'];
312
305
  }
313
306
  }
314
307
 
315
- _init() {}
308
+ _init() {
309
+ }
316
310
 
317
311
  _beforeSuite() {
318
312
  if (!this.options.restart && !this.options.manualStart && !this.isRunning) {
319
- this.debugSection('Session', 'Starting singleton browser session')
320
- return this._startBrowser()
313
+ this.debugSection('Session', 'Starting singleton browser session');
314
+ return this._startBrowser();
321
315
  }
322
316
  }
323
317
 
324
318
  async _before(test) {
325
- this.sessionPages = {}
326
- this.currentRunningTest = test
319
+ this.sessionPages = {};
320
+ this.currentRunningTest = test;
327
321
  recorder.retry({
328
322
  retries: process.env.FAILED_STEP_RETRIES || 3,
329
- when: (err) => {
330
- if (!err || typeof err.message !== 'string') {
331
- return false
323
+ when: err => {
324
+ if (!err || typeof (err.message) !== 'string') {
325
+ return false;
332
326
  }
333
327
  // ignore context errors
334
- return err.message.includes('context')
328
+ return err.message.includes('context');
335
329
  },
336
- })
337
- if (this.options.restart && !this.options.manualStart) return this._startBrowser()
338
- if (!this.isRunning && !this.options.manualStart) return this._startBrowser()
339
- return this.browser
330
+ });
331
+ if (this.options.restart && !this.options.manualStart) return this._startBrowser();
332
+ if (!this.isRunning && !this.options.manualStart) return this._startBrowser();
333
+ return this.browser;
340
334
  }
341
335
 
342
336
  async _after() {
343
- if (!this.isRunning) return
337
+ if (!this.isRunning) return;
344
338
 
345
339
  // close other sessions
346
- const contexts = this.browser.browserContexts()
347
- const defaultCtx = contexts.shift()
340
+ const contexts = this.browser.browserContexts();
341
+ const defaultCtx = contexts.shift();
348
342
 
349
- await Promise.all(contexts.map((c) => c.close()))
343
+ await Promise.all(contexts.map(c => c.close()));
350
344
 
351
345
  if (this.options.restart) {
352
- this.isRunning = false
353
- return this._stopBrowser()
346
+ this.isRunning = false;
347
+ return this._stopBrowser();
354
348
  }
355
349
 
356
350
  // ensure this.page is from default context
357
351
  if (this.page) {
358
- const existingPages = defaultCtx.targets().filter((t) => t.type() === 'page')
359
- await this._setPage(await existingPages[0].page())
352
+ const existingPages = defaultCtx.targets().filter(t => t.type() === 'page');
353
+ await this._setPage(await existingPages[0].page());
360
354
  }
361
355
 
362
- if (this.options.keepBrowserState) return
356
+ if (this.options.keepBrowserState) return;
363
357
 
364
358
  if (!this.options.keepCookies) {
365
- this.debugSection('Session', 'cleaning cookies and localStorage')
366
- await this.clearCookie()
359
+ this.debugSection('Session', 'cleaning cookies and localStorage');
360
+ await this.clearCookie();
367
361
  }
368
- const currentUrl = await this.grabCurrentUrl()
362
+ const currentUrl = await this.grabCurrentUrl();
369
363
 
370
364
  if (currentUrl.startsWith('http')) {
371
365
  await this.executeScript('localStorage.clear();').catch((err) => {
372
- if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
373
- })
366
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
367
+ });
374
368
  await this.executeScript('sessionStorage.clear();').catch((err) => {
375
- if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
376
- })
369
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
370
+ });
377
371
  }
378
- await this.closeOtherTabs()
379
- return this.browser
372
+ await this.closeOtherTabs();
373
+ return this.browser;
380
374
  }
381
375
 
382
- _afterSuite() {}
376
+ _afterSuite() {
377
+ }
383
378
 
384
379
  _finishTest() {
385
- if (!this.options.restart && this.isRunning) return this._stopBrowser()
380
+ if (!this.options.restart && this.isRunning) return this._stopBrowser();
386
381
  }
387
382
 
388
383
  _session() {
389
384
  return {
390
385
  start: async (name = '') => {
391
- this.debugSection('Incognito Tab', 'opened')
392
- this.activeSessionName = name
386
+ this.debugSection('Incognito Tab', 'opened');
387
+ this.activeSessionName = name;
393
388
 
394
- const bc = await this.browser.createBrowserContext()
395
- await bc.newPage()
389
+ const bc = await this.browser.createBrowserContext();
390
+ await bc.newPage();
396
391
 
397
392
  // Create a new page inside context.
398
- return bc
393
+ return bc;
399
394
  },
400
395
  stop: async () => {
401
396
  // is closed by _after
402
397
  },
403
398
  loadVars: async (context) => {
404
- const existingPages = context.targets().filter((t) => t.type() === 'page')
405
- this.sessionPages[this.activeSessionName] = await existingPages[0].page()
406
- return this._setPage(this.sessionPages[this.activeSessionName])
399
+ const existingPages = context.targets().filter(t => t.type() === 'page');
400
+ this.sessionPages[this.activeSessionName] = await existingPages[0].page();
401
+ return this._setPage(this.sessionPages[this.activeSessionName]);
407
402
  },
408
403
  restoreVars: async (session) => {
409
- this.withinLocator = null
404
+ this.withinLocator = null;
410
405
 
411
406
  if (!session) {
412
- this.activeSessionName = ''
407
+ this.activeSessionName = '';
413
408
  } else {
414
- this.activeSessionName = session
409
+ this.activeSessionName = session;
415
410
  }
416
- const defaultCtx = this.browser.defaultBrowserContext()
417
- const existingPages = defaultCtx.targets().filter((t) => t.type() === 'page')
418
- await this._setPage(await existingPages[0].page())
411
+ const defaultCtx = this.browser.defaultBrowserContext();
412
+ const existingPages = defaultCtx.targets().filter(t => t.type() === 'page');
413
+ await this._setPage(await existingPages[0].page());
419
414
 
420
- return this._waitForAction()
415
+ return this._waitForAction();
421
416
  },
422
- }
417
+ };
423
418
  }
424
419
 
425
420
  /**
@@ -440,7 +435,7 @@ class Puppeteer extends Helper {
440
435
  * @param {function} fn async function that is executed with Puppeteer as argument
441
436
  */
442
437
  usePuppeteerTo(description, fn) {
443
- return this._useTo(...arguments)
438
+ return this._useTo(...arguments);
444
439
  }
445
440
 
446
441
  /**
@@ -454,7 +449,7 @@ class Puppeteer extends Helper {
454
449
  * ```
455
450
  */
456
451
  amAcceptingPopups() {
457
- popupStore.actionType = 'accept'
452
+ popupStore.actionType = 'accept';
458
453
  }
459
454
 
460
455
  /**
@@ -463,7 +458,7 @@ class Puppeteer extends Helper {
463
458
  * libraries](http://jster.net/category/windows-modals-popups).
464
459
  */
465
460
  acceptPopup() {
466
- popupStore.assertPopupActionType('accept')
461
+ popupStore.assertPopupActionType('accept');
467
462
  }
468
463
 
469
464
  /**
@@ -477,23 +472,23 @@ class Puppeteer extends Helper {
477
472
  * ```
478
473
  */
479
474
  amCancellingPopups() {
480
- popupStore.actionType = 'cancel'
475
+ popupStore.actionType = 'cancel';
481
476
  }
482
477
 
483
478
  /**
484
479
  * Dismisses the active JavaScript popup, as created by window.alert|window.confirm|window.prompt.
485
480
  */
486
481
  cancelPopup() {
487
- popupStore.assertPopupActionType('cancel')
482
+ popupStore.assertPopupActionType('cancel');
488
483
  }
489
484
 
490
485
  /**
491
486
  * {{> seeInPopup }}
492
487
  */
493
488
  async seeInPopup(text) {
494
- popupStore.assertPopupVisible()
495
- const popupText = await popupStore.popup.message()
496
- stringIncludes('text in popup').assert(text, popupText)
489
+ popupStore.assertPopupVisible();
490
+ const popupText = await popupStore.popup.message();
491
+ stringIncludes('text in popup').assert(text, popupText);
497
492
  }
498
493
 
499
494
  /**
@@ -501,25 +496,25 @@ class Puppeteer extends Helper {
501
496
  * @param {object} page page to set
502
497
  */
503
498
  async _setPage(page) {
504
- page = await page
505
- this._addPopupListener(page)
506
- this._addErrorListener(page)
507
- this.page = page
508
- if (!page) return
509
- page.setDefaultNavigationTimeout(this.options.getPageTimeout)
510
- this.context = await this.page.$('body')
499
+ page = await page;
500
+ this._addPopupListener(page);
501
+ this._addErrorListener(page);
502
+ this.page = page;
503
+ if (!page) return;
504
+ page.setDefaultNavigationTimeout(this.options.getPageTimeout);
505
+ this.context = await this.page.$('body');
511
506
  if (this.options.browser === 'chrome') {
512
- await page.bringToFront()
507
+ await page.bringToFront();
513
508
  }
514
509
  }
515
510
 
516
511
  async _addErrorListener(page) {
517
512
  if (!page) {
518
- return
513
+ return;
519
514
  }
520
515
  page.on('error', async (error) => {
521
- console.error('Puppeteer page error', error)
522
- })
516
+ console.error('Puppeteer page error', error);
517
+ });
523
518
  }
524
519
 
525
520
  /**
@@ -531,32 +526,32 @@ class Puppeteer extends Helper {
531
526
  */
532
527
  _addPopupListener(page) {
533
528
  if (!page) {
534
- return
529
+ return;
535
530
  }
536
531
  page.on('dialog', async (dialog) => {
537
- popupStore.popup = dialog
538
- const action = popupStore.actionType || this.options.defaultPopupAction
539
- await this._waitForAction()
532
+ popupStore.popup = dialog;
533
+ const action = popupStore.actionType || this.options.defaultPopupAction;
534
+ await this._waitForAction();
540
535
 
541
536
  switch (action) {
542
537
  case 'accept':
543
- return dialog.accept()
538
+ return dialog.accept();
544
539
 
545
540
  case 'cancel':
546
- return dialog.dismiss()
541
+ return dialog.dismiss();
547
542
 
548
543
  default: {
549
- throw new Error('Unknown popup action type. Only "accept" or "cancel" are accepted')
544
+ throw new Error('Unknown popup action type. Only "accept" or "cancel" are accepted');
550
545
  }
551
546
  }
552
- })
547
+ });
553
548
  }
554
549
 
555
550
  /**
556
551
  * Gets page URL including hash.
557
552
  */
558
553
  async _getPageUrl() {
559
- return this.executeScript(() => window.location.href)
554
+ return this.executeScript(() => window.location.href);
560
555
  }
561
556
 
562
557
  /**
@@ -569,134 +564,128 @@ class Puppeteer extends Helper {
569
564
  */
570
565
  async grabPopupText() {
571
566
  if (popupStore.popup) {
572
- return popupStore.popup.message()
567
+ return popupStore.popup.message();
573
568
  }
574
- return null
569
+ return null;
575
570
  }
576
571
 
577
572
  async _startBrowser() {
578
573
  if (this.isRemoteBrowser) {
579
574
  try {
580
- this.browser = await puppeteer.connect(this.puppeteerOptions)
575
+ this.browser = await puppeteer.connect(this.puppeteerOptions);
581
576
  } catch (err) {
582
577
  if (err.toString().indexOf('ECONNREFUSED')) {
583
- throw new RemoteBrowserConnectionRefused(err)
578
+ throw new RemoteBrowserConnectionRefused(err);
584
579
  }
585
- throw err
580
+ throw err;
586
581
  }
587
582
  } else {
588
- this.browser = await puppeteer.launch(this.puppeteerOptions)
583
+ this.browser = await puppeteer.launch(this.puppeteerOptions);
589
584
  }
590
585
 
591
- this.browser.on('targetcreated', (target) =>
592
- target
593
- .page()
594
- .then((page) => targetCreatedHandler.call(this, page))
595
- .catch((e) => {
596
- console.error('Puppeteer page error', e)
597
- }),
598
- )
586
+ this.browser.on('targetcreated', target => target.page().then(page => targetCreatedHandler.call(this, page)).catch((e) => {
587
+ console.error('Puppeteer page error', e);
588
+ }));
599
589
  this.browser.on('targetchanged', (target) => {
600
- this.debugSection('Url', target.url())
601
- })
590
+ this.debugSection('Url', target.url());
591
+ });
602
592
 
603
- const existingPages = await this.browser.pages()
604
- const mainPage = existingPages[0] || (await this.browser.newPage())
593
+ const existingPages = await this.browser.pages();
594
+ const mainPage = existingPages[0] || (await this.browser.newPage());
605
595
 
606
596
  if (existingPages.length) {
607
597
  // Run the handler as it will not be triggered if the page already exists
608
- targetCreatedHandler.call(this, mainPage)
598
+ targetCreatedHandler.call(this, mainPage);
609
599
  }
610
- await this._setPage(mainPage)
611
- await this.closeOtherTabs()
600
+ await this._setPage(mainPage);
601
+ await this.closeOtherTabs();
612
602
 
613
- this.isRunning = true
603
+ this.isRunning = true;
614
604
  }
615
605
 
616
606
  async _stopBrowser() {
617
- this.withinLocator = null
618
- this._setPage(null)
619
- this.context = null
620
- popupStore.clear()
621
- this.isAuthenticated = false
622
- await this.browser.close()
607
+ this.withinLocator = null;
608
+ this._setPage(null);
609
+ this.context = null;
610
+ popupStore.clear();
611
+ this.isAuthenticated = false;
612
+ await this.browser.close();
623
613
  if (this.isRemoteBrowser) {
624
- await this.browser.disconnect()
614
+ await this.browser.disconnect();
625
615
  }
626
616
  }
627
617
 
628
618
  async _evaluateHandeInContext(...args) {
629
- const context = await this._getContext()
630
- return context.evaluateHandle(...args)
619
+ const context = await this._getContext();
620
+ return context.evaluateHandle(...args);
631
621
  }
632
622
 
633
623
  async _withinBegin(locator) {
634
624
  if (this.withinLocator) {
635
- throw new Error("Can't start within block inside another within block")
625
+ throw new Error('Can\'t start within block inside another within block');
636
626
  }
637
627
 
638
- const frame = isFrameLocator(locator)
628
+ const frame = isFrameLocator(locator);
639
629
 
640
630
  if (frame) {
641
631
  if (Array.isArray(frame)) {
642
- return this.switchTo(null).then(() =>
643
- frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve()),
644
- )
632
+ return this.switchTo(null)
633
+ .then(() => frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve()));
645
634
  }
646
- await this.switchTo(frame)
647
- this.withinLocator = new Locator(frame)
648
- return
635
+ await this.switchTo(frame);
636
+ this.withinLocator = new Locator(frame);
637
+ return;
649
638
  }
650
639
 
651
- const els = await this._locate(locator)
652
- assertElementExists(els, locator)
653
- this.context = els[0]
640
+ const els = await this._locate(locator);
641
+ assertElementExists(els, locator);
642
+ this.context = els[0];
654
643
 
655
- this.withinLocator = new Locator(locator)
644
+ this.withinLocator = new Locator(locator);
656
645
  }
657
646
 
658
647
  async _withinEnd() {
659
- this.withinLocator = null
660
- this.context = await this.page.mainFrame().$('body')
648
+ this.withinLocator = null;
649
+ this.context = await this.page.mainFrame().$('body');
661
650
  }
662
651
 
663
652
  _extractDataFromPerformanceTiming(timing, ...dataNames) {
664
- const navigationStart = timing.navigationStart
653
+ const navigationStart = timing.navigationStart;
665
654
 
666
- const extractedData = {}
655
+ const extractedData = {};
667
656
  dataNames.forEach((name) => {
668
- extractedData[name] = timing[name] - navigationStart
669
- })
657
+ extractedData[name] = timing[name] - navigationStart;
658
+ });
670
659
 
671
- return extractedData
660
+ return extractedData;
672
661
  }
673
662
 
674
663
  /**
675
664
  * {{> amOnPage }}
676
665
  */
677
666
  async amOnPage(url) {
678
- if (!/^\w+\:\/\//.test(url)) {
679
- url = this.options.url + url
667
+ if (!(/^\w+\:\/\//.test(url))) {
668
+ url = this.options.url + url;
680
669
  }
681
670
 
682
- if (this.options.basicAuth && this.isAuthenticated !== true) {
671
+ if (this.options.basicAuth && (this.isAuthenticated !== true)) {
683
672
  if (url.includes(this.options.url)) {
684
- await this.page.authenticate(this.options.basicAuth)
685
- this.isAuthenticated = true
673
+ await this.page.authenticate(this.options.basicAuth);
674
+ this.isAuthenticated = true;
686
675
  }
687
676
  }
688
677
 
689
678
  if (this.options.trace) {
690
- const fileName = `${`${global.output_dir}${path.sep}trace${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.json`
691
- const dir = path.dirname(fileName)
692
- if (!fileExists(dir)) fs.mkdirSync(dir)
693
- await this.page.tracing.start({ screenshots: true, path: fileName })
694
- this.currentRunningTest.artifacts.trace = fileName
679
+ const fileName = `${`${global.output_dir}${path.sep}trace${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.json`;
680
+ const dir = path.dirname(fileName);
681
+ if (!fileExists(dir)) fs.mkdirSync(dir);
682
+ await this.page.tracing.start({ screenshots: true, path: fileName });
683
+ this.currentRunningTest.artifacts.trace = fileName;
695
684
  }
696
685
 
697
- await this.page.goto(url, { waitUntil: this.options.waitForNavigation })
686
+ await this.page.goto(url, { waitUntil: this.options.waitForNavigation });
698
687
 
699
- const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)))
688
+ const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)));
700
689
 
701
690
  perfTiming = this._extractDataFromPerformanceTiming(
702
691
  performanceTiming,
@@ -704,9 +693,9 @@ class Puppeteer extends Helper {
704
693
  'domInteractive',
705
694
  'domContentLoadedEventEnd',
706
695
  'loadEventEnd',
707
- )
696
+ );
708
697
 
709
- return this._waitForAction()
698
+ return this._waitForAction();
710
699
  }
711
700
 
712
701
  /**
@@ -720,11 +709,11 @@ class Puppeteer extends Helper {
720
709
  */
721
710
  async resizeWindow(width, height) {
722
711
  if (width === 'maximize') {
723
- throw new Error("Puppeteer can't control windows, so it can't maximize it")
712
+ throw new Error('Puppeteer can\'t control windows, so it can\'t maximize it');
724
713
  }
725
714
 
726
- await this.page.setViewport({ width, height })
727
- return this._waitForAction()
715
+ await this.page.setViewport({ width, height });
716
+ return this._waitForAction();
728
717
  }
729
718
 
730
719
  /**
@@ -740,9 +729,9 @@ class Puppeteer extends Helper {
740
729
  */
741
730
  async setPuppeteerRequestHeaders(customHeaders) {
742
731
  if (!customHeaders) {
743
- throw new Error('Cannot send empty headers.')
732
+ throw new Error('Cannot send empty headers.');
744
733
  }
745
- return this.page.setExtraHTTPHeaders(customHeaders)
734
+ return this.page.setExtraHTTPHeaders(customHeaders);
746
735
  }
747
736
 
748
737
  /**
@@ -750,13 +739,13 @@ class Puppeteer extends Helper {
750
739
  * {{ react }}
751
740
  */
752
741
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
753
- const els = await this._locate(locator)
754
- assertElementExists(els, locator)
742
+ const els = await this._locate(locator);
743
+ assertElementExists(els, locator);
755
744
 
756
745
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
757
- const { x, y } = await getClickablePoint(els[0])
758
- await this.page.mouse.move(x + offsetX, y + offsetY)
759
- return this._waitForAction()
746
+ const { x, y } = await getClickablePoint(els[0]);
747
+ await this.page.mouse.move(x + offsetX, y + offsetY);
748
+ return this._waitForAction();
760
749
  }
761
750
 
762
751
  /**
@@ -764,13 +753,13 @@ class Puppeteer extends Helper {
764
753
  *
765
754
  */
766
755
  async focus(locator) {
767
- const els = await this._locate(locator)
768
- assertElementExists(els, locator, 'Element to focus')
769
- const el = els[0]
756
+ const els = await this._locate(locator);
757
+ assertElementExists(els, locator, 'Element to focus');
758
+ const el = els[0];
770
759
 
771
- await el.click()
772
- await el.focus()
773
- return this._waitForAction()
760
+ await el.click();
761
+ await el.focus();
762
+ return this._waitForAction();
774
763
  }
775
764
 
776
765
  /**
@@ -778,25 +767,25 @@ class Puppeteer extends Helper {
778
767
  *
779
768
  */
780
769
  async blur(locator) {
781
- const els = await this._locate(locator)
782
- assertElementExists(els, locator, 'Element to blur')
770
+ const els = await this._locate(locator);
771
+ assertElementExists(els, locator, 'Element to blur');
783
772
 
784
- await blurElement(els[0], this.page)
785
- return this._waitForAction()
773
+ await blurElement(els[0], this.page);
774
+ return this._waitForAction();
786
775
  }
787
776
 
788
777
  /**
789
778
  * {{> dragAndDrop }}
790
779
  */
791
780
  async dragAndDrop(srcElement, destElement) {
792
- return proceedDragAndDrop.call(this, srcElement, destElement)
781
+ return proceedDragAndDrop.call(this, srcElement, destElement);
793
782
  }
794
783
 
795
784
  /**
796
785
  * {{> refreshPage }}
797
786
  */
798
787
  async refreshPage() {
799
- return this.page.reload({ timeout: this.options.getPageTimeout, waitUntil: this.options.waitForNavigation })
788
+ return this.page.reload({ timeout: this.options.getPageTimeout, waitUntil: this.options.waitForNavigation });
800
789
  }
801
790
 
802
791
  /**
@@ -804,8 +793,8 @@ class Puppeteer extends Helper {
804
793
  */
805
794
  scrollPageToTop() {
806
795
  return this.executeScript(() => {
807
- window.scrollTo(0, 0)
808
- })
796
+ window.scrollTo(0, 0);
797
+ });
809
798
  }
810
799
 
811
800
  /**
@@ -813,13 +802,16 @@ class Puppeteer extends Helper {
813
802
  */
814
803
  scrollPageToBottom() {
815
804
  return this.executeScript(() => {
816
- const body = document.body
817
- const html = document.documentElement
818
- window.scrollTo(
819
- 0,
820
- Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
821
- )
822
- })
805
+ const body = document.body;
806
+ const html = document.documentElement;
807
+ window.scrollTo(0, Math.max(
808
+ body.scrollHeight,
809
+ body.offsetHeight,
810
+ html.clientHeight,
811
+ html.scrollHeight,
812
+ html.offsetHeight,
813
+ ));
814
+ });
823
815
  }
824
816
 
825
817
  /**
@@ -827,34 +819,30 @@ class Puppeteer extends Helper {
827
819
  */
828
820
  async scrollTo(locator, offsetX = 0, offsetY = 0) {
829
821
  if (typeof locator === 'number' && typeof offsetX === 'number') {
830
- offsetY = offsetX
831
- offsetX = locator
832
- locator = null
822
+ offsetY = offsetX;
823
+ offsetX = locator;
824
+ locator = null;
833
825
  }
834
826
 
835
827
  if (locator) {
836
- const els = await this._locate(locator)
837
- assertElementExists(els, locator, 'Element')
838
- const el = els[0]
839
- await el.evaluate((el) => el.scrollIntoView())
840
- const elementCoordinates = await getClickablePoint(els[0])
841
- await this.executeScript(
842
- (x, y) => window.scrollBy(x, y),
843
- elementCoordinates.x + offsetX,
844
- elementCoordinates.y + offsetY,
845
- )
828
+ const els = await this._locate(locator);
829
+ assertElementExists(els, locator, 'Element');
830
+ const el = els[0];
831
+ await el.evaluate((el) => el.scrollIntoView());
832
+ const elementCoordinates = await getClickablePoint(els[0]);
833
+ await this.executeScript((x, y) => window.scrollBy(x, y), elementCoordinates.x + offsetX, elementCoordinates.y + offsetY);
846
834
  } else {
847
- await this.executeScript((x, y) => window.scrollTo(x, y), offsetX, offsetY)
835
+ await this.executeScript((x, y) => window.scrollTo(x, y), offsetX, offsetY);
848
836
  }
849
- return this._waitForAction()
837
+ return this._waitForAction();
850
838
  }
851
839
 
852
840
  /**
853
841
  * {{> seeInTitle }}
854
842
  */
855
843
  async seeInTitle(text) {
856
- const title = await this.page.title()
857
- stringIncludes('web page title').assert(text, title)
844
+ const title = await this.page.title();
845
+ stringIncludes('web page title').assert(text, title);
858
846
  }
859
847
 
860
848
  /**
@@ -865,34 +853,34 @@ class Puppeteer extends Helper {
865
853
  function getScrollPosition() {
866
854
  return {
867
855
  x: window.pageXOffset,
868
- y: window.pageYOffset,
869
- }
856
+ y: window.pageYOffset
857
+ };
870
858
  }
871
859
  /* eslint-enable comma-dangle */
872
- return this.executeScript(getScrollPosition)
860
+ return this.executeScript(getScrollPosition);
873
861
  }
874
862
 
875
863
  /**
876
864
  * {{> seeTitleEquals }}
877
865
  */
878
866
  async seeTitleEquals(text) {
879
- const title = await this.page.title()
880
- return equals('web page title').assert(title, text)
867
+ const title = await this.page.title();
868
+ return equals('web page title').assert(title, text);
881
869
  }
882
870
 
883
871
  /**
884
872
  * {{> dontSeeInTitle }}
885
873
  */
886
874
  async dontSeeInTitle(text) {
887
- const title = await this.page.title()
888
- stringIncludes('web page title').negate(text, title)
875
+ const title = await this.page.title();
876
+ stringIncludes('web page title').negate(text, title);
889
877
  }
890
878
 
891
879
  /**
892
880
  * {{> grabTitle }}
893
881
  */
894
882
  async grabTitle() {
895
- return this.page.title()
883
+ return this.page.title();
896
884
  }
897
885
 
898
886
  /**
@@ -906,8 +894,8 @@ class Puppeteer extends Helper {
906
894
  * {{ react }}
907
895
  */
908
896
  async _locate(locator) {
909
- const context = await this.context
910
- return findElements.call(this, context, locator)
897
+ const context = await this.context;
898
+ return findElements.call(this, context, locator);
911
899
  }
912
900
 
913
901
  /**
@@ -919,10 +907,10 @@ class Puppeteer extends Helper {
919
907
  * ```
920
908
  */
921
909
  async _locateCheckable(locator, providedContext = null) {
922
- const context = providedContext || (await this._getContext())
923
- const els = await findCheckable.call(this, locator, context)
924
- assertElementExists(els[0], locator, 'Checkbox or radio')
925
- return els[0]
910
+ const context = providedContext || (await this._getContext());
911
+ const els = await findCheckable.call(this, locator, context);
912
+ assertElementExists(els[0], locator, 'Checkbox or radio');
913
+ return els[0];
926
914
  }
927
915
 
928
916
  /**
@@ -933,8 +921,8 @@ class Puppeteer extends Helper {
933
921
  * ```
934
922
  */
935
923
  async _locateClickable(locator) {
936
- const context = await this.context
937
- return findClickable.call(this, context, locator)
924
+ const context = await this.context;
925
+ return findClickable.call(this, context, locator);
938
926
  }
939
927
 
940
928
  /**
@@ -945,7 +933,7 @@ class Puppeteer extends Helper {
945
933
  * ```
946
934
  */
947
935
  async _locateFields(locator) {
948
- return findFields.call(this, locator)
936
+ return findFields.call(this, locator);
949
937
  }
950
938
 
951
939
  /**
@@ -953,7 +941,7 @@ class Puppeteer extends Helper {
953
941
  *
954
942
  */
955
943
  async grabWebElements(locator) {
956
- return this._locate(locator)
944
+ return this._locate(locator);
957
945
  }
958
946
 
959
947
  /**
@@ -967,17 +955,17 @@ class Puppeteer extends Helper {
967
955
  * @param {number} [num=1]
968
956
  */
969
957
  async switchToNextTab(num = 1) {
970
- const pages = await this.browser.pages()
971
- const index = pages.indexOf(this.page)
972
- this.withinLocator = null
973
- const page = pages[index + num]
958
+ const pages = await this.browser.pages();
959
+ const index = pages.indexOf(this.page);
960
+ this.withinLocator = null;
961
+ const page = pages[index + num];
974
962
 
975
963
  if (!page) {
976
- throw new Error(`There is no ability to switch to next tab with offset ${num}`)
964
+ throw new Error(`There is no ability to switch to next tab with offset ${num}`);
977
965
  }
978
966
 
979
- await this._setPage(page)
980
- return this._waitForAction()
967
+ await this._setPage(page);
968
+ return this._waitForAction();
981
969
  }
982
970
 
983
971
  /**
@@ -990,17 +978,17 @@ class Puppeteer extends Helper {
990
978
  * @param {number} [num=1]
991
979
  */
992
980
  async switchToPreviousTab(num = 1) {
993
- const pages = await this.browser.pages()
994
- const index = pages.indexOf(this.page)
995
- this.withinLocator = null
996
- const page = pages[index - num]
981
+ const pages = await this.browser.pages();
982
+ const index = pages.indexOf(this.page);
983
+ this.withinLocator = null;
984
+ const page = pages[index - num];
997
985
 
998
986
  if (!page) {
999
- throw new Error(`There is no ability to switch to previous tab with offset ${num}`)
987
+ throw new Error(`There is no ability to switch to previous tab with offset ${num}`);
1000
988
  }
1001
989
 
1002
- await this._setPage(page)
1003
- return this._waitForAction()
990
+ await this._setPage(page);
991
+ return this._waitForAction();
1004
992
  }
1005
993
 
1006
994
  /**
@@ -1011,10 +999,10 @@ class Puppeteer extends Helper {
1011
999
  * ```
1012
1000
  */
1013
1001
  async closeCurrentTab() {
1014
- const oldPage = this.page
1015
- await this.switchToPreviousTab()
1016
- await oldPage.close()
1017
- return this._waitForAction()
1002
+ const oldPage = this.page;
1003
+ await this.switchToPreviousTab();
1004
+ await oldPage.close();
1005
+ return this._waitForAction();
1018
1006
  }
1019
1007
 
1020
1008
  /**
@@ -1025,15 +1013,15 @@ class Puppeteer extends Helper {
1025
1013
  * ```
1026
1014
  */
1027
1015
  async closeOtherTabs() {
1028
- const pages = await this.browser.pages()
1029
- const otherPages = pages.filter((page) => page !== this.page)
1016
+ const pages = await this.browser.pages();
1017
+ const otherPages = pages.filter(page => page !== this.page);
1030
1018
 
1031
- let p = Promise.resolve()
1019
+ let p = Promise.resolve();
1032
1020
  otherPages.forEach((page) => {
1033
- p = p.then(() => page.close())
1034
- })
1035
- await p
1036
- return this._waitForAction()
1021
+ p = p.then(() => page.close());
1022
+ });
1023
+ await p;
1024
+ return this._waitForAction();
1037
1025
  }
1038
1026
 
1039
1027
  /**
@@ -1044,16 +1032,16 @@ class Puppeteer extends Helper {
1044
1032
  * ```
1045
1033
  */
1046
1034
  async openNewTab() {
1047
- await this._setPage(await this.browser.newPage())
1048
- return this._waitForAction()
1035
+ await this._setPage(await this.browser.newPage());
1036
+ return this._waitForAction();
1049
1037
  }
1050
1038
 
1051
1039
  /**
1052
1040
  * {{> grabNumberOfOpenTabs }}
1053
1041
  */
1054
1042
  async grabNumberOfOpenTabs() {
1055
- const pages = await this.browser.pages()
1056
- return pages.length
1043
+ const pages = await this.browser.pages();
1044
+ return pages.length;
1057
1045
  }
1058
1046
 
1059
1047
  /**
@@ -1061,22 +1049,14 @@ class Puppeteer extends Helper {
1061
1049
  * {{ react }}
1062
1050
  */
1063
1051
  async seeElement(locator) {
1064
- let els = await this._locate(locator)
1065
- els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1052
+ let els = await this._locate(locator);
1053
+ els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1066
1054
  // Puppeteer visibility was ignored? | Remove when Puppeteer is fixed
1067
- els = await Promise.all(
1068
- els.map(
1069
- async (el) =>
1070
- (await el.evaluate(
1071
- (node) =>
1072
- window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1073
- )) && el,
1074
- ),
1075
- )
1055
+ els = await Promise.all(els.map(async el => (await el.evaluate(node => window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none')) && el));
1076
1056
  try {
1077
- return empty('visible elements').negate(els.filter((v) => v).fill('ELEMENT'))
1057
+ return empty('visible elements').negate(els.filter(v => v).fill('ELEMENT'));
1078
1058
  } catch (e) {
1079
- dontSeeElementError(locator)
1059
+ dontSeeElementError(locator);
1080
1060
  }
1081
1061
  }
1082
1062
 
@@ -1085,22 +1065,14 @@ class Puppeteer extends Helper {
1085
1065
  * {{ react }}
1086
1066
  */
1087
1067
  async dontSeeElement(locator) {
1088
- let els = await this._locate(locator)
1089
- els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1068
+ let els = await this._locate(locator);
1069
+ els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1090
1070
  // Puppeteer visibility was ignored? | Remove when Puppeteer is fixed
1091
- els = await Promise.all(
1092
- els.map(
1093
- async (el) =>
1094
- (await el.evaluate(
1095
- (node) =>
1096
- window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1097
- )) && el,
1098
- ),
1099
- )
1071
+ els = await Promise.all(els.map(async el => (await el.evaluate(node => window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none')) && el));
1100
1072
  try {
1101
- return empty('visible elements').assert(els.filter((v) => v).fill('ELEMENT'))
1073
+ return empty('visible elements').assert(els.filter(v => v).fill('ELEMENT'));
1102
1074
  } catch (e) {
1103
- seeElementError(locator)
1075
+ seeElementError(locator);
1104
1076
  }
1105
1077
  }
1106
1078
 
@@ -1108,11 +1080,11 @@ class Puppeteer extends Helper {
1108
1080
  * {{> seeElementInDOM }}
1109
1081
  */
1110
1082
  async seeElementInDOM(locator) {
1111
- const els = await this._locate(locator)
1083
+ const els = await this._locate(locator);
1112
1084
  try {
1113
- return empty('elements on page').negate(els.filter((v) => v).fill('ELEMENT'))
1085
+ return empty('elements on page').negate(els.filter(v => v).fill('ELEMENT'));
1114
1086
  } catch (e) {
1115
- dontSeeElementInDOMError(locator)
1087
+ dontSeeElementInDOMError(locator);
1116
1088
  }
1117
1089
  }
1118
1090
 
@@ -1120,11 +1092,11 @@ class Puppeteer extends Helper {
1120
1092
  * {{> dontSeeElementInDOM }}
1121
1093
  */
1122
1094
  async dontSeeElementInDOM(locator) {
1123
- const els = await this._locate(locator)
1095
+ const els = await this._locate(locator);
1124
1096
  try {
1125
- return empty('elements on a page').assert(els.filter((v) => v).fill('ELEMENT'))
1097
+ return empty('elements on a page').assert(els.filter(v => v).fill('ELEMENT'));
1126
1098
  } catch (e) {
1127
- seeElementInDOMError(locator)
1099
+ seeElementInDOMError(locator);
1128
1100
  }
1129
1101
  }
1130
1102
 
@@ -1134,7 +1106,7 @@ class Puppeteer extends Helper {
1134
1106
  * {{ react }}
1135
1107
  */
1136
1108
  async click(locator, context = null) {
1137
- return proceedClick.call(this, locator, context)
1109
+ return proceedClick.call(this, locator, context);
1138
1110
  }
1139
1111
 
1140
1112
  /**
@@ -1143,33 +1115,28 @@ class Puppeteer extends Helper {
1143
1115
  * {{ react }}
1144
1116
  */
1145
1117
  async forceClick(locator, context = null) {
1146
- let matcher = await this.context
1118
+ let matcher = await this.context;
1147
1119
  if (context) {
1148
- const els = await this._locate(context)
1149
- assertElementExists(els, context)
1150
- matcher = els[0]
1120
+ const els = await this._locate(context);
1121
+ assertElementExists(els, context);
1122
+ matcher = els[0];
1151
1123
  }
1152
1124
 
1153
- const els = await findClickable.call(this, matcher, locator)
1125
+ const els = await findClickable.call(this, matcher, locator);
1154
1126
  if (context) {
1155
- assertElementExists(
1156
- els,
1157
- locator,
1158
- 'Clickable element',
1159
- `was not found inside element ${new Locator(context).toString()}`,
1160
- )
1127
+ assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
1161
1128
  } else {
1162
- assertElementExists(els, locator, 'Clickable element')
1129
+ assertElementExists(els, locator, 'Clickable element');
1163
1130
  }
1164
- const elem = els[0]
1131
+ const elem = els[0];
1165
1132
  return this.executeScript((el) => {
1166
1133
  if (document.activeElement instanceof HTMLElement) {
1167
- document.activeElement.blur()
1134
+ document.activeElement.blur();
1168
1135
  }
1169
- const event = document.createEvent('MouseEvent')
1170
- event.initEvent('click', true, true)
1171
- return el.dispatchEvent(event)
1172
- }, elem)
1136
+ const event = document.createEvent('MouseEvent');
1137
+ event.initEvent('click', true, true);
1138
+ return el.dispatchEvent(event);
1139
+ }, elem);
1173
1140
  }
1174
1141
 
1175
1142
  /**
@@ -1178,7 +1145,7 @@ class Puppeteer extends Helper {
1178
1145
  * {{ react }}
1179
1146
  */
1180
1147
  async clickLink(locator, context = null) {
1181
- return proceedClick.call(this, locator, context, { waitForNavigation: true })
1148
+ return proceedClick.call(this, locator, context, { waitForNavigation: true });
1182
1149
  }
1183
1150
 
1184
1151
  /**
@@ -1199,16 +1166,16 @@ class Puppeteer extends Helper {
1199
1166
  * @param {string} [downloadPath='downloads'] change this parameter to set another directory for saving
1200
1167
  */
1201
1168
  async handleDownloads(downloadPath = 'downloads') {
1202
- downloadPath = path.join(global.output_dir, downloadPath)
1169
+ downloadPath = path.join(global.output_dir, downloadPath);
1203
1170
  if (!fs.existsSync(downloadPath)) {
1204
- fs.mkdirSync(downloadPath, '0777')
1171
+ fs.mkdirSync(downloadPath, '0777');
1205
1172
  }
1206
- fsExtra.emptyDirSync(downloadPath)
1173
+ fsExtra.emptyDirSync(downloadPath);
1207
1174
 
1208
1175
  try {
1209
- return this.page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath })
1176
+ return this.page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath });
1210
1177
  } catch (e) {
1211
- return this.page._client().send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath })
1178
+ return this.page._client().send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath });
1212
1179
  }
1213
1180
  }
1214
1181
 
@@ -1218,27 +1185,27 @@ class Puppeteer extends Helper {
1218
1185
  * Please use `handleDownloads()` instead.
1219
1186
  */
1220
1187
  async downloadFile(locator, customName) {
1221
- let fileName
1222
- await this.page.setRequestInterception(true)
1188
+ let fileName;
1189
+ await this.page.setRequestInterception(true);
1223
1190
 
1224
1191
  const xRequest = await new Promise((resolve) => {
1225
1192
  this.page.on('request', (request) => {
1226
- console.log('rq', request, customName)
1227
- const grabbedFileName = request.url().split('/')[request.url().split('/').length - 1]
1228
- const fileExtension = request.url().split('/')[request.url().split('/').length - 1].split('.')[1]
1229
- console.log('nm', customName, fileExtension)
1193
+ console.log('rq', request, customName);
1194
+ const grabbedFileName = request.url().split('/')[request.url().split('/').length - 1];
1195
+ const fileExtension = request.url().split('/')[request.url().split('/').length - 1].split('.')[1];
1196
+ console.log('nm', customName, fileExtension);
1230
1197
  if (customName && path.extname(customName) !== fileExtension) {
1231
- console.log('bypassing a request')
1232
- request.continue()
1233
- return
1198
+ console.log('bypassing a request');
1199
+ request.continue();
1200
+ return;
1234
1201
  }
1235
- customName ? (fileName = `${customName}.${fileExtension}`) : (fileName = grabbedFileName)
1236
- request.abort()
1237
- resolve(request)
1238
- })
1239
- })
1202
+ customName ? fileName = `${customName}.${fileExtension}` : fileName = grabbedFileName;
1203
+ request.abort();
1204
+ resolve(request);
1205
+ });
1206
+ });
1240
1207
 
1241
- await this.click(locator)
1208
+ await this.click(locator);
1242
1209
 
1243
1210
  const options = {
1244
1211
  encoding: null,
@@ -1246,10 +1213,10 @@ class Puppeteer extends Helper {
1246
1213
  uri: xRequest._url,
1247
1214
  body: xRequest._postData,
1248
1215
  headers: xRequest._headers,
1249
- }
1216
+ };
1250
1217
 
1251
- const cookies = await this.page.cookies()
1252
- options.headers.Cookie = cookies.map((ck) => `${ck.name}=${ck.value}`).join(';')
1218
+ const cookies = await this.page.cookies();
1219
+ options.headers.Cookie = cookies.map(ck => `${ck.name}=${ck.value}`).join(';');
1253
1220
 
1254
1221
  const response = await axios({
1255
1222
  method: options.method,
@@ -1257,26 +1224,24 @@ class Puppeteer extends Helper {
1257
1224
  headers: options.headers,
1258
1225
  responseType: 'arraybuffer',
1259
1226
  onDownloadProgress(e) {
1260
- console.log('+', e)
1227
+ console.log('+', e);
1261
1228
  },
1262
- })
1229
+ });
1263
1230
 
1264
- const outputFile = path.join(`${global.output_dir}/${fileName}`)
1231
+ const outputFile = path.join(`${global.output_dir}/${fileName}`);
1265
1232
 
1266
1233
  try {
1267
1234
  await new Promise((resolve, reject) => {
1268
- const wstream = fs.createWriteStream(outputFile)
1269
- console.log(response)
1270
- wstream.write(response.data)
1271
- wstream.end()
1272
- this.debug(`File is downloaded in ${outputFile}`)
1273
- wstream.on('finish', () => {
1274
- resolve(fileName)
1275
- })
1276
- wstream.on('error', reject)
1277
- })
1235
+ const wstream = fs.createWriteStream(outputFile);
1236
+ console.log(response);
1237
+ wstream.write(response.data);
1238
+ wstream.end();
1239
+ this.debug(`File is downloaded in ${outputFile}`);
1240
+ wstream.on('finish', () => { resolve(fileName); });
1241
+ wstream.on('error', reject);
1242
+ });
1278
1243
  } catch (error) {
1279
- throw new Error(`There is something wrong with downloaded file. ${error}`)
1244
+ throw new Error(`There is something wrong with downloaded file. ${error}`);
1280
1245
  }
1281
1246
  }
1282
1247
 
@@ -1286,7 +1251,7 @@ class Puppeteer extends Helper {
1286
1251
  * {{ react }}
1287
1252
  */
1288
1253
  async doubleClick(locator, context = null) {
1289
- return proceedClick.call(this, locator, context, { clickCount: 2 })
1254
+ return proceedClick.call(this, locator, context, { clickCount: 2 });
1290
1255
  }
1291
1256
 
1292
1257
  /**
@@ -1295,19 +1260,20 @@ class Puppeteer extends Helper {
1295
1260
  * {{ react }}
1296
1261
  */
1297
1262
  async rightClick(locator, context = null) {
1298
- return proceedClick.call(this, locator, context, { button: 'right' })
1263
+ return proceedClick.call(this, locator, context, { button: 'right' });
1299
1264
  }
1300
1265
 
1301
1266
  /**
1302
1267
  * {{> checkOption }}
1303
1268
  */
1304
1269
  async checkOption(field, context = null) {
1305
- const elm = await this._locateCheckable(field, context)
1306
- const curentlyChecked = await elm.getProperty('checked').then((checkedProperty) => checkedProperty.jsonValue())
1270
+ const elm = await this._locateCheckable(field, context);
1271
+ const curentlyChecked = await elm.getProperty('checked')
1272
+ .then(checkedProperty => checkedProperty.jsonValue());
1307
1273
  // Only check if NOT currently checked
1308
1274
  if (!curentlyChecked) {
1309
- await elm.click()
1310
- return this._waitForAction()
1275
+ await elm.click();
1276
+ return this._waitForAction();
1311
1277
  }
1312
1278
  }
1313
1279
 
@@ -1315,12 +1281,13 @@ class Puppeteer extends Helper {
1315
1281
  * {{> uncheckOption }}
1316
1282
  */
1317
1283
  async uncheckOption(field, context = null) {
1318
- const elm = await this._locateCheckable(field, context)
1319
- const curentlyChecked = await elm.getProperty('checked').then((checkedProperty) => checkedProperty.jsonValue())
1284
+ const elm = await this._locateCheckable(field, context);
1285
+ const curentlyChecked = await elm.getProperty('checked')
1286
+ .then(checkedProperty => checkedProperty.jsonValue());
1320
1287
  // Only uncheck if currently checked
1321
1288
  if (curentlyChecked) {
1322
- await elm.click()
1323
- return this._waitForAction()
1289
+ await elm.click();
1290
+ return this._waitForAction();
1324
1291
  }
1325
1292
  }
1326
1293
 
@@ -1328,32 +1295,32 @@ class Puppeteer extends Helper {
1328
1295
  * {{> seeCheckboxIsChecked }}
1329
1296
  */
1330
1297
  async seeCheckboxIsChecked(field) {
1331
- return proceedIsChecked.call(this, 'assert', field)
1298
+ return proceedIsChecked.call(this, 'assert', field);
1332
1299
  }
1333
1300
 
1334
1301
  /**
1335
1302
  * {{> dontSeeCheckboxIsChecked }}
1336
1303
  */
1337
1304
  async dontSeeCheckboxIsChecked(field) {
1338
- return proceedIsChecked.call(this, 'negate', field)
1305
+ return proceedIsChecked.call(this, 'negate', field);
1339
1306
  }
1340
1307
 
1341
1308
  /**
1342
1309
  * {{> pressKeyDown }}
1343
1310
  */
1344
1311
  async pressKeyDown(key) {
1345
- key = getNormalizedKey.call(this, key)
1346
- await this.page.keyboard.down(key)
1347
- return this._waitForAction()
1312
+ key = getNormalizedKey.call(this, key);
1313
+ await this.page.keyboard.down(key);
1314
+ return this._waitForAction();
1348
1315
  }
1349
1316
 
1350
1317
  /**
1351
1318
  * {{> pressKeyUp }}
1352
1319
  */
1353
1320
  async pressKeyUp(key) {
1354
- key = getNormalizedKey.call(this, key)
1355
- await this.page.keyboard.up(key)
1356
- return this._waitForAction()
1321
+ key = getNormalizedKey.call(this, key);
1322
+ await this.page.keyboard.up(key);
1323
+ return this._waitForAction();
1357
1324
  }
1358
1325
 
1359
1326
  /**
@@ -1362,28 +1329,28 @@ class Puppeteer extends Helper {
1362
1329
  * {{> pressKeyWithKeyNormalization }}
1363
1330
  */
1364
1331
  async pressKey(key) {
1365
- const modifiers = []
1332
+ const modifiers = [];
1366
1333
  if (Array.isArray(key)) {
1367
1334
  for (let k of key) {
1368
- k = getNormalizedKey.call(this, k)
1335
+ k = getNormalizedKey.call(this, k);
1369
1336
  if (isModifierKey(k)) {
1370
- modifiers.push(k)
1337
+ modifiers.push(k);
1371
1338
  } else {
1372
- key = k
1373
- break
1339
+ key = k;
1340
+ break;
1374
1341
  }
1375
1342
  }
1376
1343
  } else {
1377
- key = getNormalizedKey.call(this, key)
1344
+ key = getNormalizedKey.call(this, key);
1378
1345
  }
1379
1346
  for (const modifier of modifiers) {
1380
- await this.page.keyboard.down(modifier)
1347
+ await this.page.keyboard.down(modifier);
1381
1348
  }
1382
- await this.page.keyboard.press(key)
1349
+ await this.page.keyboard.press(key);
1383
1350
  for (const modifier of modifiers) {
1384
- await this.page.keyboard.up(modifier)
1351
+ await this.page.keyboard.up(modifier);
1385
1352
  }
1386
- return this._waitForAction()
1353
+ return this._waitForAction();
1387
1354
  }
1388
1355
 
1389
1356
  /**
@@ -1391,13 +1358,13 @@ class Puppeteer extends Helper {
1391
1358
  */
1392
1359
  async type(keys, delay = null) {
1393
1360
  if (!Array.isArray(keys)) {
1394
- keys = keys.toString()
1395
- keys = keys.split('')
1361
+ keys = keys.toString();
1362
+ keys = keys.split('');
1396
1363
  }
1397
1364
 
1398
1365
  for (const key of keys) {
1399
- await this.page.keyboard.press(key)
1400
- if (delay) await this.wait(delay / 1000)
1366
+ await this.page.keyboard.press(key);
1367
+ if (delay) await this.wait(delay / 1000);
1401
1368
  }
1402
1369
  }
1403
1370
 
@@ -1406,28 +1373,28 @@ class Puppeteer extends Helper {
1406
1373
  * {{ react }}
1407
1374
  */
1408
1375
  async fillField(field, value) {
1409
- const els = await findVisibleFields.call(this, field)
1410
- assertElementExists(els, field, 'Field')
1411
- const el = els[0]
1412
- const tag = await el.getProperty('tagName').then((el) => el.jsonValue())
1413
- const editable = await el.getProperty('contenteditable').then((el) => el.jsonValue())
1376
+ const els = await findVisibleFields.call(this, field);
1377
+ assertElementExists(els, field, 'Field');
1378
+ const el = els[0];
1379
+ const tag = await el.getProperty('tagName').then(el => el.jsonValue());
1380
+ const editable = await el.getProperty('contenteditable').then(el => el.jsonValue());
1414
1381
  if (tag === 'INPUT' || tag === 'TEXTAREA') {
1415
- await this._evaluateHandeInContext((el) => (el.value = ''), el)
1382
+ await this._evaluateHandeInContext(el => el.value = '', el);
1416
1383
  } else if (editable) {
1417
- await this._evaluateHandeInContext((el) => (el.innerHTML = ''), el)
1384
+ await this._evaluateHandeInContext(el => el.innerHTML = '', el);
1418
1385
  }
1419
1386
 
1420
- highlightActiveElement.call(this, el, await this._getContext())
1421
- await el.type(value.toString(), { delay: this.options.pressKeyDelay })
1387
+ highlightActiveElement.call(this, el, await this._getContext());
1388
+ await el.type(value.toString(), { delay: this.options.pressKeyDelay });
1422
1389
 
1423
- return this._waitForAction()
1390
+ return this._waitForAction();
1424
1391
  }
1425
1392
 
1426
1393
  /**
1427
1394
  * {{> clearField }}
1428
1395
  */
1429
1396
  async clearField(field) {
1430
- return this.fillField(field, '')
1397
+ return this.fillField(field, '');
1431
1398
  }
1432
1399
 
1433
1400
  /**
@@ -1436,28 +1403,28 @@ class Puppeteer extends Helper {
1436
1403
  * {{ react }}
1437
1404
  */
1438
1405
  async appendField(field, value) {
1439
- const els = await findVisibleFields.call(this, field)
1440
- assertElementExists(els, field, 'Field')
1441
- highlightActiveElement.call(this, els[0], await this._getContext())
1442
- await els[0].press('End')
1443
- await els[0].type(value.toString(), { delay: this.options.pressKeyDelay })
1444
- return this._waitForAction()
1406
+ const els = await findVisibleFields.call(this, field);
1407
+ assertElementExists(els, field, 'Field');
1408
+ highlightActiveElement.call(this, els[0], await this._getContext());
1409
+ await els[0].press('End');
1410
+ await els[0].type(value.toString(), { delay: this.options.pressKeyDelay });
1411
+ return this._waitForAction();
1445
1412
  }
1446
1413
 
1447
1414
  /**
1448
1415
  * {{> seeInField }}
1449
1416
  */
1450
1417
  async seeInField(field, value) {
1451
- const _value = typeof value === 'boolean' ? value : value.toString()
1452
- return proceedSeeInField.call(this, 'assert', field, _value)
1418
+ const _value = (typeof value === 'boolean') ? value : value.toString();
1419
+ return proceedSeeInField.call(this, 'assert', field, _value);
1453
1420
  }
1454
1421
 
1455
1422
  /**
1456
1423
  * {{> dontSeeInField }}
1457
1424
  */
1458
1425
  async dontSeeInField(field, value) {
1459
- const _value = typeof value === 'boolean' ? value : value.toString()
1460
- return proceedSeeInField.call(this, 'negate', field, _value)
1426
+ const _value = (typeof value === 'boolean') ? value : value.toString();
1427
+ return proceedSeeInField.call(this, 'negate', field, _value);
1461
1428
  }
1462
1429
 
1463
1430
  /**
@@ -1466,48 +1433,48 @@ class Puppeteer extends Helper {
1466
1433
  * {{> attachFile }}
1467
1434
  */
1468
1435
  async attachFile(locator, pathToFile) {
1469
- const file = path.join(global.codecept_dir, pathToFile)
1436
+ const file = path.join(global.codecept_dir, pathToFile);
1470
1437
 
1471
1438
  if (!fileExists(file)) {
1472
- throw new Error(`File at ${file} can not be found on local system`)
1439
+ throw new Error(`File at ${file} can not be found on local system`);
1473
1440
  }
1474
- const els = await findFields.call(this, locator)
1475
- assertElementExists(els, locator, 'Field')
1476
- await els[0].uploadFile(file)
1477
- return this._waitForAction()
1441
+ const els = await findFields.call(this, locator);
1442
+ assertElementExists(els, locator, 'Field');
1443
+ await els[0].uploadFile(file);
1444
+ return this._waitForAction();
1478
1445
  }
1479
1446
 
1480
1447
  /**
1481
1448
  * {{> selectOption }}
1482
1449
  */
1483
1450
  async selectOption(select, option) {
1484
- const els = await findVisibleFields.call(this, select)
1485
- assertElementExists(els, select, 'Selectable field')
1486
- const el = els[0]
1487
- if ((await el.getProperty('tagName').then((t) => t.jsonValue())) !== 'SELECT') {
1488
- throw new Error('Element is not <select>')
1451
+ const els = await findVisibleFields.call(this, select);
1452
+ assertElementExists(els, select, 'Selectable field');
1453
+ const el = els[0];
1454
+ if ((await el.getProperty('tagName').then(t => t.jsonValue())) !== 'SELECT') {
1455
+ throw new Error('Element is not <select>');
1489
1456
  }
1490
- highlightActiveElement.call(this, els[0], await this._getContext())
1491
- if (!Array.isArray(option)) option = [option]
1457
+ highlightActiveElement.call(this, els[0], await this._getContext());
1458
+ if (!Array.isArray(option)) option = [option];
1492
1459
 
1493
1460
  for (const key in option) {
1494
- const opt = xpathLocator.literal(option[key])
1495
- let optEl = await findElements.call(this, el, { xpath: Locator.select.byVisibleText(opt) })
1461
+ const opt = xpathLocator.literal(option[key]);
1462
+ let optEl = await findElements.call(this, el, { xpath: Locator.select.byVisibleText(opt) });
1496
1463
  if (optEl.length) {
1497
- this._evaluateHandeInContext((el) => (el.selected = true), optEl[0])
1498
- continue
1464
+ this._evaluateHandeInContext(el => el.selected = true, optEl[0]);
1465
+ continue;
1499
1466
  }
1500
- optEl = await findElements.call(this, el, { xpath: Locator.select.byValue(opt) })
1467
+ optEl = await findElements.call(this, el, { xpath: Locator.select.byValue(opt) });
1501
1468
  if (optEl.length) {
1502
- this._evaluateHandeInContext((el) => (el.selected = true), optEl[0])
1469
+ this._evaluateHandeInContext(el => el.selected = true, optEl[0]);
1503
1470
  }
1504
1471
  }
1505
1472
  await this._evaluateHandeInContext((element) => {
1506
- element.dispatchEvent(new Event('input', { bubbles: true }))
1507
- element.dispatchEvent(new Event('change', { bubbles: true }))
1508
- }, el)
1473
+ element.dispatchEvent(new Event('input', { bubbles: true }));
1474
+ element.dispatchEvent(new Event('change', { bubbles: true }));
1475
+ }, el);
1509
1476
 
1510
- return this._waitForAction()
1477
+ return this._waitForAction();
1511
1478
  }
1512
1479
 
1513
1480
  /**
@@ -1515,48 +1482,40 @@ class Puppeteer extends Helper {
1515
1482
  * {{ react }}
1516
1483
  */
1517
1484
  async grabNumberOfVisibleElements(locator) {
1518
- let els = await this._locate(locator)
1519
- els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1485
+ let els = await this._locate(locator);
1486
+ els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1520
1487
  // Puppeteer visibility was ignored? | Remove when Puppeteer is fixed
1521
- els = await Promise.all(
1522
- els.map(
1523
- async (el) =>
1524
- (await el.evaluate(
1525
- (node) =>
1526
- window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1527
- )) && el,
1528
- ),
1529
- )
1488
+ els = await Promise.all(els.map(async el => (await el.evaluate(node => window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none')) && el));
1530
1489
 
1531
- return els.filter((v) => v).length
1490
+ return els.filter(v => v).length;
1532
1491
  }
1533
1492
 
1534
1493
  /**
1535
1494
  * {{> seeInCurrentUrl }}
1536
1495
  */
1537
1496
  async seeInCurrentUrl(url) {
1538
- stringIncludes('url').assert(url, await this._getPageUrl())
1497
+ stringIncludes('url').assert(url, await this._getPageUrl());
1539
1498
  }
1540
1499
 
1541
1500
  /**
1542
1501
  * {{> dontSeeInCurrentUrl }}
1543
1502
  */
1544
1503
  async dontSeeInCurrentUrl(url) {
1545
- stringIncludes('url').negate(url, await this._getPageUrl())
1504
+ stringIncludes('url').negate(url, await this._getPageUrl());
1546
1505
  }
1547
1506
 
1548
1507
  /**
1549
1508
  * {{> seeCurrentUrlEquals }}
1550
1509
  */
1551
1510
  async seeCurrentUrlEquals(url) {
1552
- urlEquals(this.options.url).assert(url, await this._getPageUrl())
1511
+ urlEquals(this.options.url).assert(url, await this._getPageUrl());
1553
1512
  }
1554
1513
 
1555
1514
  /**
1556
1515
  * {{> dontSeeCurrentUrlEquals }}
1557
1516
  */
1558
1517
  async dontSeeCurrentUrlEquals(url) {
1559
- urlEquals(this.options.url).negate(url, await this._getPageUrl())
1518
+ urlEquals(this.options.url).negate(url, await this._getPageUrl());
1560
1519
  }
1561
1520
 
1562
1521
  /**
@@ -1565,14 +1524,14 @@ class Puppeteer extends Helper {
1565
1524
  * {{ react }}
1566
1525
  */
1567
1526
  async see(text, context = null) {
1568
- return proceedSee.call(this, 'assert', text, context)
1527
+ return proceedSee.call(this, 'assert', text, context);
1569
1528
  }
1570
1529
 
1571
1530
  /**
1572
1531
  * {{> seeTextEquals }}
1573
1532
  */
1574
1533
  async seeTextEquals(text, context = null) {
1575
- return proceedSee.call(this, 'assert', text, context, true)
1534
+ return proceedSee.call(this, 'assert', text, context, true);
1576
1535
  }
1577
1536
 
1578
1537
  /**
@@ -1581,14 +1540,14 @@ class Puppeteer extends Helper {
1581
1540
  * {{ react }}
1582
1541
  */
1583
1542
  async dontSee(text, context = null) {
1584
- return proceedSee.call(this, 'negate', text, context)
1543
+ return proceedSee.call(this, 'negate', text, context);
1585
1544
  }
1586
1545
 
1587
1546
  /**
1588
1547
  * {{> grabSource }}
1589
1548
  */
1590
1549
  async grabSource() {
1591
- return this.page.content()
1550
+ return this.page.content();
1592
1551
  }
1593
1552
 
1594
1553
  /**
@@ -1601,32 +1560,32 @@ class Puppeteer extends Helper {
1601
1560
  * @return {Promise<any[]>}
1602
1561
  */
1603
1562
  async grabBrowserLogs() {
1604
- const logs = consoleLogStore.entries
1605
- consoleLogStore.clear()
1606
- return logs
1563
+ const logs = consoleLogStore.entries;
1564
+ consoleLogStore.clear();
1565
+ return logs;
1607
1566
  }
1608
1567
 
1609
1568
  /**
1610
1569
  * {{> grabCurrentUrl }}
1611
1570
  */
1612
1571
  async grabCurrentUrl() {
1613
- return this._getPageUrl()
1572
+ return this._getPageUrl();
1614
1573
  }
1615
1574
 
1616
1575
  /**
1617
1576
  * {{> seeInSource }}
1618
1577
  */
1619
1578
  async seeInSource(text) {
1620
- const source = await this.page.content()
1621
- stringIncludes('HTML source of a page').assert(text, source)
1579
+ const source = await this.page.content();
1580
+ stringIncludes('HTML source of a page').assert(text, source);
1622
1581
  }
1623
1582
 
1624
1583
  /**
1625
1584
  * {{> dontSeeInSource }}
1626
1585
  */
1627
1586
  async dontSeeInSource(text) {
1628
- const source = await this.page.content()
1629
- stringIncludes('HTML source of a page').negate(text, source)
1587
+ const source = await this.page.content();
1588
+ stringIncludes('HTML source of a page').negate(text, source);
1630
1589
  }
1631
1590
 
1632
1591
  /**
@@ -1635,10 +1594,8 @@ class Puppeteer extends Helper {
1635
1594
  * {{ react }}
1636
1595
  */
1637
1596
  async seeNumberOfElements(locator, num) {
1638
- const elements = await this._locate(locator)
1639
- return equals(
1640
- `expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`,
1641
- ).assert(elements.length, num)
1597
+ const elements = await this._locate(locator);
1598
+ return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
1642
1599
  }
1643
1600
 
1644
1601
  /**
@@ -1647,11 +1604,8 @@ class Puppeteer extends Helper {
1647
1604
  * {{ react }}
1648
1605
  */
1649
1606
  async seeNumberOfVisibleElements(locator, num) {
1650
- const res = await this.grabNumberOfVisibleElements(locator)
1651
- return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(
1652
- res,
1653
- num,
1654
- )
1607
+ const res = await this.grabNumberOfVisibleElements(locator);
1608
+ return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
1655
1609
  }
1656
1610
 
1657
1611
  /**
@@ -1659,9 +1613,9 @@ class Puppeteer extends Helper {
1659
1613
  */
1660
1614
  async setCookie(cookie) {
1661
1615
  if (Array.isArray(cookie)) {
1662
- return this.page.setCookie(...cookie)
1616
+ return this.page.setCookie(...cookie);
1663
1617
  }
1664
- return this.page.setCookie(cookie)
1618
+ return this.page.setCookie(cookie);
1665
1619
  }
1666
1620
 
1667
1621
  /**
@@ -1669,16 +1623,16 @@ class Puppeteer extends Helper {
1669
1623
  *
1670
1624
  */
1671
1625
  async seeCookie(name) {
1672
- const cookies = await this.page.cookies()
1673
- empty(`cookie ${name} to be set`).negate(cookies.filter((c) => c.name === name))
1626
+ const cookies = await this.page.cookies();
1627
+ empty(`cookie ${name} to be set`).negate(cookies.filter(c => c.name === name));
1674
1628
  }
1675
1629
 
1676
1630
  /**
1677
1631
  * {{> dontSeeCookie }}
1678
1632
  */
1679
1633
  async dontSeeCookie(name) {
1680
- const cookies = await this.page.cookies()
1681
- empty(`cookie ${name} not to be set`).assert(cookies.filter((c) => c.name === name))
1634
+ const cookies = await this.page.cookies();
1635
+ empty(`cookie ${name} to be set`).assert(cookies.filter(c => c.name === name));
1682
1636
  }
1683
1637
 
1684
1638
  /**
@@ -1687,10 +1641,10 @@ class Puppeteer extends Helper {
1687
1641
  * Returns cookie in JSON format. If name not passed returns all cookies for this domain.
1688
1642
  */
1689
1643
  async grabCookie(name) {
1690
- const cookies = await this.page.cookies()
1691
- if (!name) return cookies
1692
- const cookie = cookies.filter((c) => c.name === name)
1693
- if (cookie[0]) return cookie[0]
1644
+ const cookies = await this.page.cookies();
1645
+ if (!name) return cookies;
1646
+ const cookie = cookies.filter(c => c.name === name);
1647
+ if (cookie[0]) return cookie[0];
1694
1648
  }
1695
1649
 
1696
1650
  /**
@@ -1698,47 +1652,44 @@ class Puppeteer extends Helper {
1698
1652
  */
1699
1653
  async waitForCookie(name, sec) {
1700
1654
  // by default, we will retry 3 times
1701
- let retries = 3
1702
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1655
+ let retries = 3;
1656
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1703
1657
 
1704
1658
  if (sec) {
1705
- retries = sec
1659
+ retries = sec;
1706
1660
  } else {
1707
- retries = Math.ceil(waitTimeout / 1000) - 1
1661
+ retries = Math.ceil(waitTimeout / 1000) - 1;
1708
1662
  }
1709
1663
 
1710
- return promiseRetry(
1711
- async (retry, number) => {
1712
- const _grabCookie = async (name) => {
1713
- const cookies = await this.page.cookies()
1714
- const cookie = cookies.filter((c) => c.name === name)
1715
- if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
1716
- }
1664
+ return promiseRetry(async (retry, number) => {
1665
+ const _grabCookie = async (name) => {
1666
+ const cookies = await this.page.cookies();
1667
+ const cookie = cookies.filter(c => c.name === name);
1668
+ if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
1669
+ };
1717
1670
 
1718
- this.debugSection('Wait for cookie: ', name)
1719
- if (number > 1) this.debugSection('Retrying... Attempt #', number)
1671
+ this.debugSection('Wait for cookie: ', name);
1672
+ if (number > 1) this.debugSection('Retrying... Attempt #', number);
1720
1673
 
1721
- try {
1722
- await _grabCookie(name)
1723
- } catch (e) {
1724
- retry(e)
1725
- }
1726
- },
1727
- { retries, maxTimeout: 1000 },
1728
- )
1674
+ try {
1675
+ await _grabCookie(name);
1676
+ } catch (e) {
1677
+ retry(e);
1678
+ }
1679
+ }, { retries, maxTimeout: 1000 });
1729
1680
  }
1730
1681
 
1731
1682
  /**
1732
1683
  * {{> clearCookie }}
1733
1684
  */
1734
1685
  async clearCookie(name) {
1735
- const cookies = await this.page.cookies()
1686
+ const cookies = await this.page.cookies();
1736
1687
  if (!name) {
1737
- return this.page.deleteCookie.apply(this.page, cookies)
1688
+ return this.page.deleteCookie.apply(this.page, cookies);
1738
1689
  }
1739
- const cookie = cookies.filter((c) => c.name === name)
1740
- if (!cookie[0]) return
1741
- return this.page.deleteCookie(cookie[0])
1690
+ const cookie = cookies.filter(c => c.name === name);
1691
+ if (!cookie[0]) return;
1692
+ return this.page.deleteCookie(cookie[0]);
1742
1693
  }
1743
1694
 
1744
1695
  /**
@@ -1747,11 +1698,11 @@ class Puppeteer extends Helper {
1747
1698
  * {{> executeScript }}
1748
1699
  */
1749
1700
  async executeScript(...args) {
1750
- let context = await this._getContext()
1701
+ let context = await this._getContext();
1751
1702
  if (this.context && this.context.constructor.name === 'CdpFrame') {
1752
- context = this.context // switching to iframe context
1703
+ context = this.context; // switching to iframe context
1753
1704
  }
1754
- return context.evaluate.apply(context, args)
1705
+ return context.evaluate.apply(context, args);
1755
1706
  }
1756
1707
 
1757
1708
  /**
@@ -1760,16 +1711,16 @@ class Puppeteer extends Helper {
1760
1711
  */
1761
1712
  async executeAsyncScript(...args) {
1762
1713
  const asyncFn = function () {
1763
- const args = Array.from(arguments)
1764
- const fn = eval(`(${args.shift()})`) // eslint-disable-line no-eval
1714
+ const args = Array.from(arguments);
1715
+ const fn = eval(`(${args.shift()})`); // eslint-disable-line no-eval
1765
1716
  return new Promise((done) => {
1766
- args.push(done)
1767
- fn.apply(null, args)
1768
- })
1769
- }
1770
- args[0] = args[0].toString()
1771
- args.unshift(asyncFn)
1772
- return this.page.evaluate.apply(this.page, args)
1717
+ args.push(done);
1718
+ fn.apply(null, args);
1719
+ });
1720
+ };
1721
+ args[0] = args[0].toString();
1722
+ args.unshift(asyncFn);
1723
+ return this.page.evaluate.apply(this.page, args);
1773
1724
  }
1774
1725
 
1775
1726
  /**
@@ -1777,12 +1728,12 @@ class Puppeteer extends Helper {
1777
1728
  * {{ react }}
1778
1729
  */
1779
1730
  async grabTextFromAll(locator) {
1780
- const els = await this._locate(locator)
1781
- const texts = []
1731
+ const els = await this._locate(locator);
1732
+ const texts = [];
1782
1733
  for (const el of els) {
1783
- texts.push(await (await el.getProperty('innerText')).jsonValue())
1734
+ texts.push(await (await el.getProperty('innerText')).jsonValue());
1784
1735
  }
1785
- return texts
1736
+ return texts;
1786
1737
  }
1787
1738
 
1788
1739
  /**
@@ -1790,60 +1741,60 @@ class Puppeteer extends Helper {
1790
1741
  * {{ react }}
1791
1742
  */
1792
1743
  async grabTextFrom(locator) {
1793
- const texts = await this.grabTextFromAll(locator)
1794
- assertElementExists(texts, locator)
1744
+ const texts = await this.grabTextFromAll(locator);
1745
+ assertElementExists(texts, locator);
1795
1746
  if (texts.length > 1) {
1796
- this.debugSection('GrabText', `Using first element out of ${texts.length}`)
1747
+ this.debugSection('GrabText', `Using first element out of ${texts.length}`);
1797
1748
  }
1798
1749
 
1799
- return texts[0]
1750
+ return texts[0];
1800
1751
  }
1801
1752
 
1802
1753
  /**
1803
1754
  * {{> grabValueFromAll }}
1804
1755
  */
1805
1756
  async grabValueFromAll(locator) {
1806
- const els = await findFields.call(this, locator)
1807
- const values = []
1757
+ const els = await findFields.call(this, locator);
1758
+ const values = [];
1808
1759
  for (const el of els) {
1809
- values.push(await (await el.getProperty('value')).jsonValue())
1760
+ values.push(await (await el.getProperty('value')).jsonValue());
1810
1761
  }
1811
- return values
1762
+ return values;
1812
1763
  }
1813
1764
 
1814
1765
  /**
1815
1766
  * {{> grabValueFrom }}
1816
1767
  */
1817
1768
  async grabValueFrom(locator) {
1818
- const values = await this.grabValueFromAll(locator)
1819
- assertElementExists(values, locator)
1769
+ const values = await this.grabValueFromAll(locator);
1770
+ assertElementExists(values, locator);
1820
1771
  if (values.length > 1) {
1821
- this.debugSection('GrabValue', `Using first element out of ${values.length}`)
1772
+ this.debugSection('GrabValue', `Using first element out of ${values.length}`);
1822
1773
  }
1823
1774
 
1824
- return values[0]
1775
+ return values[0];
1825
1776
  }
1826
1777
 
1827
1778
  /**
1828
1779
  * {{> grabHTMLFromAll }}
1829
1780
  */
1830
1781
  async grabHTMLFromAll(locator) {
1831
- const els = await this._locate(locator)
1832
- const values = await Promise.all(els.map((el) => el.evaluate((element) => element.innerHTML, el)))
1833
- return values
1782
+ const els = await this._locate(locator);
1783
+ const values = await Promise.all(els.map(el => el.evaluate(element => element.innerHTML, el)));
1784
+ return values;
1834
1785
  }
1835
1786
 
1836
1787
  /**
1837
1788
  * {{> grabHTMLFrom }}
1838
1789
  */
1839
1790
  async grabHTMLFrom(locator) {
1840
- const html = await this.grabHTMLFromAll(locator)
1841
- assertElementExists(html, locator)
1791
+ const html = await this.grabHTMLFromAll(locator);
1792
+ assertElementExists(html, locator);
1842
1793
  if (html.length > 1) {
1843
- this.debugSection('GrabHTML', `Using first element out of ${html.length}`)
1794
+ this.debugSection('GrabHTML', `Using first element out of ${html.length}`);
1844
1795
  }
1845
1796
 
1846
- return html[0]
1797
+ return html[0];
1847
1798
  }
1848
1799
 
1849
1800
  /**
@@ -1851,13 +1802,11 @@ class Puppeteer extends Helper {
1851
1802
  * {{ react }}
1852
1803
  */
1853
1804
  async grabCssPropertyFromAll(locator, cssProperty) {
1854
- const els = await this._locate(locator)
1855
- const res = await Promise.all(
1856
- els.map((el) => el.evaluate((el) => JSON.parse(JSON.stringify(getComputedStyle(el))), el)),
1857
- )
1858
- const cssValues = res.map((props) => props[toCamelCase(cssProperty)])
1805
+ const els = await this._locate(locator);
1806
+ const res = await Promise.all(els.map(el => el.evaluate(el => JSON.parse(JSON.stringify(getComputedStyle(el))), el)));
1807
+ const cssValues = res.map(props => props[toCamelCase(cssProperty)]);
1859
1808
 
1860
- return cssValues
1809
+ return cssValues;
1861
1810
  }
1862
1811
 
1863
1812
  /**
@@ -1865,14 +1814,14 @@ class Puppeteer extends Helper {
1865
1814
  * {{ react }}
1866
1815
  */
1867
1816
  async grabCssPropertyFrom(locator, cssProperty) {
1868
- const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
1869
- assertElementExists(cssValues, locator)
1817
+ const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty);
1818
+ assertElementExists(cssValues, locator);
1870
1819
 
1871
1820
  if (cssValues.length > 1) {
1872
- this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`)
1821
+ this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`);
1873
1822
  }
1874
1823
 
1875
- return cssValues[0]
1824
+ return cssValues[0];
1876
1825
  }
1877
1826
 
1878
1827
  /**
@@ -1880,37 +1829,35 @@ class Puppeteer extends Helper {
1880
1829
  * {{ react }}
1881
1830
  */
1882
1831
  async seeCssPropertiesOnElements(locator, cssProperties) {
1883
- const res = await this._locate(locator)
1884
- assertElementExists(res, locator)
1832
+ const res = await this._locate(locator);
1833
+ assertElementExists(res, locator);
1885
1834
 
1886
- const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties)
1887
- const elemAmount = res.length
1888
- let props = []
1835
+ const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
1836
+ const elemAmount = res.length;
1837
+ let props = [];
1889
1838
 
1890
1839
  for (const element of res) {
1891
1840
  for (const prop of Object.keys(cssProperties)) {
1892
- const cssProp = await this.grabCssPropertyFrom(locator, prop)
1841
+ const cssProp = await this.grabCssPropertyFrom(locator, prop);
1893
1842
  if (isColorProperty(prop)) {
1894
- props.push(convertColorToRGBA(cssProp))
1843
+ props.push(convertColorToRGBA(cssProp));
1895
1844
  } else {
1896
- props.push(cssProp)
1845
+ props.push(cssProp);
1897
1846
  }
1898
1847
  }
1899
1848
  }
1900
1849
 
1901
- const values = Object.keys(cssPropertiesCamelCase).map((key) => cssPropertiesCamelCase[key])
1902
- if (!Array.isArray(props)) props = [props]
1903
- let chunked = chunkArray(props, values.length)
1850
+ const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
1851
+ if (!Array.isArray(props)) props = [props];
1852
+ let chunked = chunkArray(props, values.length);
1904
1853
  chunked = chunked.filter((val) => {
1905
1854
  for (let i = 0; i < val.length; ++i) {
1906
1855
  // eslint-disable-next-line eqeqeq
1907
- if (val[i] != values[i]) return false
1856
+ if (val[i] != values[i]) return false;
1908
1857
  }
1909
- return true
1910
- })
1911
- return equals(
1912
- `all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
1913
- ).assert(chunked.length, elemAmount)
1858
+ return true;
1859
+ });
1860
+ return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
1914
1861
  }
1915
1862
 
1916
1863
  /**
@@ -1918,40 +1865,34 @@ class Puppeteer extends Helper {
1918
1865
  * {{ react }}
1919
1866
  */
1920
1867
  async seeAttributesOnElements(locator, attributes) {
1921
- const elements = await this._locate(locator)
1922
- assertElementExists(elements, locator)
1868
+ const elements = await this._locate(locator);
1869
+ assertElementExists(elements, locator);
1923
1870
 
1924
- const expectedAttributes = Object.entries(attributes)
1871
+ const expectedAttributes = Object.entries(attributes);
1925
1872
 
1926
1873
  const valuesPromises = elements.map(async (element) => {
1927
- const elementAttributes = {}
1928
- await Promise.all(
1929
- expectedAttributes.map(async ([attribute, expectedValue]) => {
1930
- const actualValue = await element.evaluate((el, attr) => el[attr] || el.getAttribute(attr), attribute)
1931
- elementAttributes[attribute] = actualValue
1932
- }),
1933
- )
1934
- return elementAttributes
1935
- })
1874
+ const elementAttributes = {};
1875
+ await Promise.all(expectedAttributes.map(async ([attribute, expectedValue]) => {
1876
+ const actualValue = await element.evaluate((el, attr) => el[attr] || el.getAttribute(attr), attribute);
1877
+ elementAttributes[attribute] = actualValue;
1878
+ }));
1879
+ return elementAttributes;
1880
+ });
1936
1881
 
1937
- const actualAttributes = await Promise.all(valuesPromises)
1882
+ const actualAttributes = await Promise.all(valuesPromises);
1938
1883
 
1939
- const matchingElements = actualAttributes.filter((attrs) =>
1940
- expectedAttributes.every(([attribute, expectedValue]) => {
1941
- const actualValue = attrs[attribute]
1942
- if (!actualValue) return false
1943
- if (actualValue.toString().match(new RegExp(expectedValue.toString()))) return true
1944
- return expectedValue === actualValue
1945
- }),
1946
- )
1884
+ const matchingElements = actualAttributes.filter((attrs) => expectedAttributes.every(([attribute, expectedValue]) => {
1885
+ const actualValue = attrs[attribute];
1886
+ if (!actualValue) return false;
1887
+ if (actualValue.toString().match(new RegExp(expectedValue.toString()))) return true;
1888
+ return expectedValue === actualValue;
1889
+ }));
1947
1890
 
1948
- const elementsCount = elements.length
1949
- const matchingCount = matchingElements.length
1891
+ const elementsCount = elements.length;
1892
+ const matchingCount = matchingElements.length;
1950
1893
 
1951
- return equals(`all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`).assert(
1952
- matchingCount,
1953
- elementsCount,
1954
- )
1894
+ return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`)
1895
+ .assert(matchingCount, elementsCount);
1955
1896
  }
1956
1897
 
1957
1898
  /**
@@ -1959,21 +1900,21 @@ class Puppeteer extends Helper {
1959
1900
  * {{ react }}
1960
1901
  */
1961
1902
  async dragSlider(locator, offsetX = 0) {
1962
- const src = await this._locate(locator)
1963
- assertElementExists(src, locator, 'Slider Element')
1903
+ const src = await this._locate(locator);
1904
+ assertElementExists(src, locator, 'Slider Element');
1964
1905
 
1965
1906
  // Note: Using public api .getClickablePoint because the .BoundingBox does not take into account iframe offsets
1966
- const sliderSource = await getClickablePoint(src[0])
1907
+ const sliderSource = await getClickablePoint(src[0]);
1967
1908
 
1968
1909
  // Drag start point
1969
- await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 })
1970
- await this.page.mouse.down()
1910
+ await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 });
1911
+ await this.page.mouse.down();
1971
1912
 
1972
1913
  // Drag destination
1973
- await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 })
1974
- await this.page.mouse.up()
1914
+ await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 });
1915
+ await this.page.mouse.up();
1975
1916
 
1976
- await this._waitForAction()
1917
+ await this._waitForAction();
1977
1918
  }
1978
1919
 
1979
1920
  /**
@@ -1981,13 +1922,13 @@ class Puppeteer extends Helper {
1981
1922
  * {{ react }}
1982
1923
  */
1983
1924
  async grabAttributeFromAll(locator, attr) {
1984
- const els = await this._locate(locator)
1985
- const array = []
1925
+ const els = await this._locate(locator);
1926
+ const array = [];
1986
1927
  for (let index = 0; index < els.length; index++) {
1987
- const a = await this._evaluateHandeInContext((el, attr) => el[attr] || el.getAttribute(attr), els[index], attr)
1988
- array.push(await a.jsonValue())
1928
+ const a = await this._evaluateHandeInContext((el, attr) => el[attr] || el.getAttribute(attr), els[index], attr);
1929
+ array.push(await a.jsonValue());
1989
1930
  }
1990
- return array
1931
+ return array;
1991
1932
  }
1992
1933
 
1993
1934
  /**
@@ -1995,84 +1936,84 @@ class Puppeteer extends Helper {
1995
1936
  * {{ react }}
1996
1937
  */
1997
1938
  async grabAttributeFrom(locator, attr) {
1998
- const attrs = await this.grabAttributeFromAll(locator, attr)
1999
- assertElementExists(attrs, locator)
1939
+ const attrs = await this.grabAttributeFromAll(locator, attr);
1940
+ assertElementExists(attrs, locator);
2000
1941
  if (attrs.length > 1) {
2001
- this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
1942
+ this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
2002
1943
  }
2003
1944
 
2004
- return attrs[0]
1945
+ return attrs[0];
2005
1946
  }
2006
1947
 
2007
1948
  /**
2008
1949
  * {{> saveElementScreenshot }}
2009
1950
  */
2010
1951
  async saveElementScreenshot(locator, fileName) {
2011
- const outputFile = screenshotOutputFolder(fileName)
1952
+ const outputFile = screenshotOutputFolder(fileName);
2012
1953
 
2013
- const res = await this._locate(locator)
2014
- assertElementExists(res, locator)
2015
- if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`)
2016
- const elem = res[0]
2017
- this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
2018
- return elem.screenshot({ path: outputFile, type: 'png' })
1954
+ const res = await this._locate(locator);
1955
+ assertElementExists(res, locator);
1956
+ if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
1957
+ const elem = res[0];
1958
+ this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
1959
+ return elem.screenshot({ path: outputFile, type: 'png' });
2019
1960
  }
2020
1961
 
2021
1962
  /**
2022
1963
  * {{> saveScreenshot }}
2023
1964
  */
2024
1965
  async saveScreenshot(fileName, fullPage) {
2025
- const fullPageOption = fullPage || this.options.fullPageScreenshots
2026
- let outputFile = screenshotOutputFolder(fileName)
1966
+ const fullPageOption = fullPage || this.options.fullPageScreenshots;
1967
+ let outputFile = screenshotOutputFolder(fileName);
2027
1968
 
2028
- this.debug(`Screenshot is saving to ${outputFile}`)
1969
+ this.debug(`Screenshot is saving to ${outputFile}`);
2029
1970
 
2030
1971
  await this.page.screenshot({
2031
1972
  path: outputFile,
2032
1973
  fullPage: fullPageOption,
2033
1974
  type: 'png',
2034
- })
1975
+ });
2035
1976
 
2036
1977
  if (this.activeSessionName) {
2037
1978
  for (const sessionName in this.sessionPages) {
2038
- const activeSessionPage = this.sessionPages[sessionName]
2039
- outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`)
1979
+ const activeSessionPage = this.sessionPages[sessionName];
1980
+ outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`);
2040
1981
 
2041
- this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`)
1982
+ this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`);
2042
1983
 
2043
1984
  if (activeSessionPage) {
2044
1985
  await activeSessionPage.screenshot({
2045
1986
  path: outputFile,
2046
1987
  fullPage: fullPageOption,
2047
1988
  type: 'png',
2048
- })
1989
+ });
2049
1990
  }
2050
1991
  }
2051
1992
  }
2052
1993
  }
2053
1994
 
2054
1995
  async _failed(test) {
2055
- await this._withinEnd()
1996
+ await this._withinEnd();
2056
1997
 
2057
1998
  if (this.options.trace) {
2058
- await this.page.tracing.stop()
2059
- const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.failed.json')
2060
- fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName)
2061
- test.artifacts.trace = _traceName
1999
+ await this.page.tracing.stop();
2000
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.failed.json');
2001
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName);
2002
+ test.artifacts.trace = _traceName;
2062
2003
  }
2063
2004
  }
2064
2005
 
2065
2006
  async _passed(test) {
2066
- await this._withinEnd()
2007
+ await this._withinEnd();
2067
2008
 
2068
2009
  if (this.options.trace) {
2069
- await this.page.tracing.stop()
2010
+ await this.page.tracing.stop();
2070
2011
  if (this.options.keepTraceForPassedTests) {
2071
- const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.passed.json')
2072
- fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName)
2073
- test.artifacts.trace = _traceName
2012
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.passed.json');
2013
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName);
2014
+ test.artifacts.trace = _traceName;
2074
2015
  } else {
2075
- fs.unlinkSync(this.currentRunningTest.artifacts.trace)
2016
+ fs.unlinkSync(this.currentRunningTest.artifacts.trace);
2076
2017
  }
2077
2018
  }
2078
2019
  }
@@ -2081,74 +2022,70 @@ class Puppeteer extends Helper {
2081
2022
  * {{> wait }}
2082
2023
  */
2083
2024
  async wait(sec) {
2084
- return new Promise((done) => {
2085
- setTimeout(done, sec * 1000)
2086
- })
2025
+ return new Promise(((done) => {
2026
+ setTimeout(done, sec * 1000);
2027
+ }));
2087
2028
  }
2088
2029
 
2089
2030
  /**
2090
2031
  * {{> waitForEnabled }}
2091
2032
  */
2092
2033
  async waitForEnabled(locator, sec) {
2093
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2094
- locator = new Locator(locator, 'css')
2095
- await this.context
2096
- let waiter
2097
- const context = await this._getContext()
2034
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2035
+ locator = new Locator(locator, 'css');
2036
+ await this.context;
2037
+ let waiter;
2038
+ const context = await this._getContext();
2098
2039
  if (locator.isCSS()) {
2099
2040
  const enabledFn = function (locator) {
2100
- const els = document.querySelectorAll(locator)
2041
+ const els = document.querySelectorAll(locator);
2101
2042
  if (!els || els.length === 0) {
2102
- return false
2043
+ return false;
2103
2044
  }
2104
- return Array.prototype.filter.call(els, (el) => !el.disabled).length > 0
2105
- }
2106
- waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value)
2045
+ return Array.prototype.filter.call(els, el => !el.disabled).length > 0;
2046
+ };
2047
+ waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value);
2107
2048
  } else {
2108
2049
  const enabledFn = function (locator, $XPath) {
2109
- eval($XPath) // eslint-disable-line no-eval
2110
- return $XPath(null, locator).filter((el) => !el.disabled).length > 0
2111
- }
2112
- waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value, $XPath.toString())
2050
+ eval($XPath); // eslint-disable-line no-eval
2051
+ return $XPath(null, locator).filter(el => !el.disabled).length > 0;
2052
+ };
2053
+ waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value, $XPath.toString());
2113
2054
  }
2114
2055
  return waiter.catch((err) => {
2115
- throw new Error(
2116
- `element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`,
2117
- )
2118
- })
2056
+ throw new Error(`element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`);
2057
+ });
2119
2058
  }
2120
2059
 
2121
2060
  /**
2122
2061
  * {{> waitForValue }}
2123
2062
  */
2124
2063
  async waitForValue(field, value, sec) {
2125
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2126
- const locator = new Locator(field, 'css')
2127
- await this.context
2128
- let waiter
2129
- const context = await this._getContext()
2064
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2065
+ const locator = new Locator(field, 'css');
2066
+ await this.context;
2067
+ let waiter;
2068
+ const context = await this._getContext();
2130
2069
  if (locator.isCSS()) {
2131
2070
  const valueFn = function (locator, value) {
2132
- const els = document.querySelectorAll(locator)
2071
+ const els = document.querySelectorAll(locator);
2133
2072
  if (!els || els.length === 0) {
2134
- return false
2073
+ return false;
2135
2074
  }
2136
- return Array.prototype.filter.call(els, (el) => (el.value.toString() || '').indexOf(value) !== -1).length > 0
2137
- }
2138
- waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, value)
2075
+ return Array.prototype.filter.call(els, el => (el.value.toString() || '').indexOf(value) !== -1).length > 0;
2076
+ };
2077
+ waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, value);
2139
2078
  } else {
2140
2079
  const valueFn = function (locator, $XPath, value) {
2141
- eval($XPath) // eslint-disable-line no-eval
2142
- return $XPath(null, locator).filter((el) => (el.value || '').indexOf(value) !== -1).length > 0
2143
- }
2144
- waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), value)
2080
+ eval($XPath); // eslint-disable-line no-eval
2081
+ return $XPath(null, locator).filter(el => (el.value || '').indexOf(value) !== -1).length > 0;
2082
+ };
2083
+ waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), value);
2145
2084
  }
2146
2085
  return waiter.catch((err) => {
2147
- const loc = locator.toString()
2148
- throw new Error(
2149
- `element (${loc}) is not in DOM or there is no element(${loc}) with value "${value}" after ${waitTimeout / 1000} sec\n${err.message}`,
2150
- )
2151
- })
2086
+ const loc = locator.toString();
2087
+ throw new Error(`element (${loc}) is not in DOM or there is no element(${loc}) with value "${value}" after ${waitTimeout / 1000} sec\n${err.message}`);
2088
+ });
2152
2089
  }
2153
2090
 
2154
2091
  /**
@@ -2156,49 +2093,45 @@ class Puppeteer extends Helper {
2156
2093
  * {{ react }}
2157
2094
  */
2158
2095
  async waitNumberOfVisibleElements(locator, num, sec) {
2159
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2160
- locator = new Locator(locator, 'css')
2161
- let waiter
2162
- const context = await this._getContext()
2096
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2097
+ locator = new Locator(locator, 'css');
2098
+ let waiter;
2099
+ const context = await this._getContext();
2163
2100
  if (locator.isCSS()) {
2164
2101
  const visibleFn = function (locator, num) {
2165
- const els = document.querySelectorAll(locator)
2102
+ const els = document.querySelectorAll(locator);
2166
2103
  if (!els || els.length === 0) {
2167
- return false
2104
+ return false;
2168
2105
  }
2169
- return Array.prototype.filter.call(els, (el) => el.offsetParent !== null).length === num
2170
- }
2171
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, num)
2106
+ return Array.prototype.filter.call(els, el => el.offsetParent !== null).length === num;
2107
+ };
2108
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, num);
2172
2109
  } else {
2173
2110
  const visibleFn = function (locator, $XPath, num) {
2174
- eval($XPath) // eslint-disable-line no-eval
2175
- return $XPath(null, locator).filter((el) => el.offsetParent !== null).length === num
2176
- }
2177
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), num)
2111
+ eval($XPath); // eslint-disable-line no-eval
2112
+ return $XPath(null, locator).filter(el => el.offsetParent !== null).length === num;
2113
+ };
2114
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), num);
2178
2115
  }
2179
2116
  return waiter.catch((err) => {
2180
- throw new Error(
2181
- `The number of elements (${locator.toString()}) is not ${num} after ${waitTimeout / 1000} sec\n${err.message}`,
2182
- )
2183
- })
2117
+ throw new Error(`The number of elements (${locator.toString()}) is not ${num} after ${waitTimeout / 1000} sec\n${err.message}`);
2118
+ });
2184
2119
  }
2185
2120
 
2186
2121
  /**
2187
2122
  * {{> waitForClickable }}
2188
2123
  */
2189
2124
  async waitForClickable(locator, waitTimeout) {
2190
- const els = await this._locate(locator)
2191
- assertElementExists(els, locator)
2125
+ const els = await this._locate(locator);
2126
+ assertElementExists(els, locator);
2192
2127
 
2193
2128
  return this.waitForFunction(isElementClickable, [els[0]], waitTimeout).catch(async (e) => {
2194
2129
  if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2195
- throw new Error(
2196
- `element ${new Locator(locator).toString()} still not clickable after ${waitTimeout || this.options.waitForTimeout / 1000} sec`,
2197
- )
2130
+ throw new Error(`element ${new Locator(locator).toString()} still not clickable after ${waitTimeout || this.options.waitForTimeout / 1000} sec`);
2198
2131
  } else {
2199
- throw e
2132
+ throw e;
2200
2133
  }
2201
- })
2134
+ });
2202
2135
  }
2203
2136
 
2204
2137
  /**
@@ -2206,21 +2139,19 @@ class Puppeteer extends Helper {
2206
2139
  * {{ react }}
2207
2140
  */
2208
2141
  async waitForElement(locator, sec) {
2209
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2210
- locator = new Locator(locator, 'css')
2142
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2143
+ locator = new Locator(locator, 'css');
2211
2144
 
2212
- let waiter
2213
- const context = await this._getContext()
2145
+ let waiter;
2146
+ const context = await this._getContext();
2214
2147
  if (locator.isCSS()) {
2215
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout })
2148
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout });
2216
2149
  } else {
2217
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout })
2150
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout });
2218
2151
  }
2219
2152
  return waiter.catch((err) => {
2220
- throw new Error(
2221
- `element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${err.message}`,
2222
- )
2223
- })
2153
+ throw new Error(`element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${err.message}`);
2154
+ });
2224
2155
  }
2225
2156
 
2226
2157
  /**
@@ -2229,191 +2160,160 @@ class Puppeteer extends Helper {
2229
2160
  * {{ react }}
2230
2161
  */
2231
2162
  async waitForVisible(locator, sec) {
2232
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2233
- locator = new Locator(locator, 'css')
2234
- await this.context
2235
- let waiter
2236
- const context = await this._getContext()
2163
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2164
+ locator = new Locator(locator, 'css');
2165
+ await this.context;
2166
+ let waiter;
2167
+ const context = await this._getContext();
2237
2168
  if (locator.isCSS()) {
2238
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, visible: true })
2169
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, visible: true });
2239
2170
  } else {
2240
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, visible: true })
2171
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, visible: true });
2241
2172
  }
2242
2173
  return waiter.catch((err) => {
2243
- throw new Error(
2244
- `element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${err.message}`,
2245
- )
2246
- })
2174
+ throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${err.message}`);
2175
+ });
2247
2176
  }
2248
2177
 
2249
2178
  /**
2250
2179
  * {{> waitForInvisible }}
2251
2180
  */
2252
2181
  async waitForInvisible(locator, sec) {
2253
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2254
- locator = new Locator(locator, 'css')
2255
- await this.context
2256
- let waiter
2257
- const context = await this._getContext()
2182
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2183
+ locator = new Locator(locator, 'css');
2184
+ await this.context;
2185
+ let waiter;
2186
+ const context = await this._getContext();
2258
2187
  if (locator.isCSS()) {
2259
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true })
2188
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true });
2260
2189
  } else {
2261
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true })
2190
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true });
2262
2191
  }
2263
2192
  return waiter.catch((err) => {
2264
- throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${err.message}`)
2265
- })
2193
+ throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${err.message}`);
2194
+ });
2266
2195
  }
2267
2196
 
2268
2197
  /**
2269
2198
  * {{> waitToHide }}
2270
2199
  */
2271
2200
  async waitToHide(locator, sec) {
2272
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2273
- locator = new Locator(locator, 'css')
2274
- let waiter
2275
- const context = await this._getContext()
2201
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2202
+ locator = new Locator(locator, 'css');
2203
+ let waiter;
2204
+ const context = await this._getContext();
2276
2205
  if (locator.isCSS()) {
2277
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true })
2206
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true });
2278
2207
  } else {
2279
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true })
2208
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true });
2280
2209
  }
2281
2210
  return waiter.catch((err) => {
2282
- throw new Error(
2283
- `element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`,
2284
- )
2285
- })
2211
+ throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`);
2212
+ });
2286
2213
  }
2287
2214
 
2288
2215
  /**
2289
2216
  * {{> waitForNumberOfTabs }}
2290
2217
  */
2291
2218
  async waitForNumberOfTabs(expectedTabs, sec) {
2292
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2293
- let currentTabs
2294
- let count = 0
2219
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2220
+ let currentTabs;
2221
+ let count = 0;
2295
2222
 
2296
2223
  do {
2297
- currentTabs = await this.grabNumberOfOpenTabs()
2298
- await this.wait(1)
2299
- count += 1000
2300
- if (currentTabs >= expectedTabs) return
2301
- } while (count <= waitTimeout)
2224
+ currentTabs = await this.grabNumberOfOpenTabs();
2225
+ await this.wait(1);
2226
+ count += 1000;
2227
+ if (currentTabs >= expectedTabs) return;
2228
+ } while (count <= waitTimeout);
2302
2229
 
2303
- throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`)
2230
+ throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`);
2304
2231
  }
2305
2232
 
2306
2233
  async _getContext() {
2307
2234
  if (this.context && this.context.constructor.name === 'CdpFrame') {
2308
- return this.context
2235
+ return this.context;
2309
2236
  }
2310
- return this.page
2237
+ return this.page;
2311
2238
  }
2312
2239
 
2313
2240
  /**
2314
2241
  * {{> waitInUrl }}
2315
2242
  */
2316
2243
  async waitInUrl(urlPart, sec = null) {
2317
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2318
-
2319
- return this.page
2320
- .waitForFunction(
2321
- (urlPart) => {
2322
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2323
- return currUrl.indexOf(urlPart) > -1
2324
- },
2325
- { timeout: waitTimeout },
2326
- urlPart,
2327
- )
2328
- .catch(async (e) => {
2329
- const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2330
- if (/Waiting failed:/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2331
- throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
2332
- } else {
2333
- throw e
2334
- }
2335
- })
2244
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2245
+
2246
+ return this.page.waitForFunction((urlPart) => {
2247
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
2248
+ return currUrl.indexOf(urlPart) > -1;
2249
+ }, { timeout: waitTimeout }, urlPart).catch(async (e) => {
2250
+ const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
2251
+ if (/Waiting failed:/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2252
+ throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
2253
+ } else {
2254
+ throw e;
2255
+ }
2256
+ });
2336
2257
  }
2337
2258
 
2338
2259
  /**
2339
2260
  * {{> waitUrlEquals }}
2340
2261
  */
2341
2262
  async waitUrlEquals(urlPart, sec = null) {
2342
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2263
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2343
2264
 
2344
- const baseUrl = this.options.url
2265
+ const baseUrl = this.options.url;
2345
2266
  if (urlPart.indexOf('http') < 0) {
2346
- urlPart = baseUrl + urlPart
2347
- }
2348
-
2349
- return this.page
2350
- .waitForFunction(
2351
- (urlPart) => {
2352
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2353
- return currUrl.indexOf(urlPart) > -1
2354
- },
2355
- { timeout: waitTimeout },
2356
- urlPart,
2357
- )
2358
- .catch(async (e) => {
2359
- const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2360
- if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2361
- throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
2362
- } else {
2363
- throw e
2364
- }
2365
- })
2267
+ urlPart = baseUrl + urlPart;
2268
+ }
2269
+
2270
+ return this.page.waitForFunction((urlPart) => {
2271
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
2272
+ return currUrl.indexOf(urlPart) > -1;
2273
+ }, { timeout: waitTimeout }, urlPart).catch(async (e) => {
2274
+ const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
2275
+ if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2276
+ throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
2277
+ } else {
2278
+ throw e;
2279
+ }
2280
+ });
2366
2281
  }
2367
2282
 
2368
2283
  /**
2369
2284
  * {{> waitForText }}
2370
2285
  */
2371
2286
  async waitForText(text, sec = null, context = null) {
2372
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2373
- let waiter
2287
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2288
+ let waiter;
2374
2289
 
2375
- const contextObject = await this._getContext()
2290
+ const contextObject = await this._getContext();
2376
2291
 
2377
2292
  if (context) {
2378
- const locator = new Locator(context, 'css')
2293
+ const locator = new Locator(context, 'css');
2379
2294
  if (locator.isCSS()) {
2380
- waiter = contextObject.waitForFunction(
2381
- (locator, text) => {
2382
- const el = document.querySelector(locator)
2383
- if (!el) return false
2384
- return el.innerText.indexOf(text) > -1
2385
- },
2386
- { timeout: waitTimeout },
2387
- locator.value,
2388
- text,
2389
- )
2295
+ waiter = contextObject.waitForFunction((locator, text) => {
2296
+ const el = document.querySelector(locator);
2297
+ if (!el) return false;
2298
+ return el.innerText.indexOf(text) > -1;
2299
+ }, { timeout: waitTimeout }, locator.value, text);
2390
2300
  }
2391
2301
 
2392
2302
  if (locator.isXPath()) {
2393
- waiter = contextObject.waitForFunction(
2394
- (locator, text, $XPath) => {
2395
- eval($XPath) // eslint-disable-line no-eval
2396
- const el = $XPath(null, locator)
2397
- if (!el.length) return false
2398
- return el[0].innerText.indexOf(text) > -1
2399
- },
2400
- { timeout: waitTimeout },
2401
- locator.value,
2402
- text,
2403
- $XPath.toString(),
2404
- )
2303
+ waiter = contextObject.waitForFunction((locator, text, $XPath) => {
2304
+ eval($XPath); // eslint-disable-line no-eval
2305
+ const el = $XPath(null, locator);
2306
+ if (!el.length) return false;
2307
+ return el[0].innerText.indexOf(text) > -1;
2308
+ }, { timeout: waitTimeout }, locator.value, text, $XPath.toString());
2405
2309
  }
2406
2310
  } else {
2407
- waiter = contextObject.waitForFunction(
2408
- (text) => document.body && document.body.innerText.indexOf(text) > -1,
2409
- { timeout: waitTimeout },
2410
- text,
2411
- )
2311
+ waiter = contextObject.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, { timeout: waitTimeout }, text);
2412
2312
  }
2413
2313
 
2414
2314
  return waiter.catch((err) => {
2415
- throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${err.message}`)
2416
- })
2315
+ throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${err.message}`);
2316
+ });
2417
2317
  }
2418
2318
 
2419
2319
  /**
@@ -2428,8 +2328,8 @@ class Puppeteer extends Helper {
2428
2328
  * @param {?number} [sec=null] seconds to wait
2429
2329
  */
2430
2330
  async waitForRequest(urlOrPredicate, sec = null) {
2431
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2432
- return this.page.waitForRequest(urlOrPredicate, { timeout })
2331
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2332
+ return this.page.waitForRequest(urlOrPredicate, { timeout });
2433
2333
  }
2434
2334
 
2435
2335
  /**
@@ -2444,8 +2344,8 @@ class Puppeteer extends Helper {
2444
2344
  * @param {?number} [sec=null] number of seconds to wait
2445
2345
  */
2446
2346
  async waitForResponse(urlOrPredicate, sec = null) {
2447
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2448
- return this.page.waitForResponse(urlOrPredicate, { timeout })
2347
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2348
+ return this.page.waitForResponse(urlOrPredicate, { timeout });
2449
2349
  }
2450
2350
 
2451
2351
  /**
@@ -2454,37 +2354,37 @@ class Puppeteer extends Helper {
2454
2354
  async switchTo(locator) {
2455
2355
  if (Number.isInteger(locator)) {
2456
2356
  // Select by frame index of current context
2457
- let frames = []
2357
+ let frames = [];
2458
2358
  if (this.context && typeof this.context.childFrames === 'function') {
2459
- frames = await this.context.childFrames()
2359
+ frames = await this.context.childFrames();
2460
2360
  } else {
2461
- frames = await this.page.mainFrame().childFrames()
2361
+ frames = await this.page.mainFrame().childFrames();
2462
2362
  }
2463
2363
 
2464
2364
  if (locator >= 0 && locator < frames.length) {
2465
- this.context = frames[locator]
2365
+ this.context = frames[locator];
2466
2366
  } else {
2467
- throw new Error('Frame index out of bounds')
2367
+ throw new Error('Frame index out of bounds');
2468
2368
  }
2469
- return
2369
+ return;
2470
2370
  }
2471
2371
 
2472
2372
  if (!locator) {
2473
- this.context = await this.page.mainFrame()
2474
- return
2373
+ this.context = await this.page.mainFrame();
2374
+ return;
2475
2375
  }
2476
2376
 
2477
2377
  // Select iframe by selector
2478
- const els = await this._locate(locator)
2479
- assertElementExists(els, locator)
2378
+ const els = await this._locate(locator);
2379
+ assertElementExists(els, locator);
2480
2380
 
2481
- const iframeElement = els[0]
2482
- const contentFrame = await iframeElement.contentFrame()
2381
+ const iframeElement = els[0];
2382
+ const contentFrame = await iframeElement.contentFrame();
2483
2383
 
2484
2384
  if (contentFrame) {
2485
- this.context = contentFrame
2385
+ this.context = contentFrame;
2486
2386
  } else {
2487
- throw new Error('Element "#invalidIframeSelector" was not found by text|CSS|XPath')
2387
+ throw new Error('Element "#invalidIframeSelector" was not found by text|CSS|XPath');
2488
2388
  }
2489
2389
  }
2490
2390
 
@@ -2492,17 +2392,17 @@ class Puppeteer extends Helper {
2492
2392
  * {{> waitForFunction }}
2493
2393
  */
2494
2394
  async waitForFunction(fn, argsOrSec = null, sec = null) {
2495
- let args = []
2395
+ let args = [];
2496
2396
  if (argsOrSec) {
2497
2397
  if (Array.isArray(argsOrSec)) {
2498
- args = argsOrSec
2398
+ args = argsOrSec;
2499
2399
  } else if (typeof argsOrSec === 'number') {
2500
- sec = argsOrSec
2400
+ sec = argsOrSec;
2501
2401
  }
2502
2402
  }
2503
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2504
- const context = await this._getContext()
2505
- return context.waitForFunction(fn, { timeout: waitTimeout }, ...args)
2403
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2404
+ const context = await this._getContext();
2405
+ return context.waitForFunction(fn, { timeout: waitTimeout }, ...args);
2506
2406
  }
2507
2407
 
2508
2408
  /**
@@ -2517,87 +2417,87 @@ class Puppeteer extends Helper {
2517
2417
  timeout: this.options.getPageTimeout,
2518
2418
  waitUntil: this.options.waitForNavigation,
2519
2419
  ...opts,
2520
- }
2521
- return this.page.waitForNavigation(opts)
2420
+ };
2421
+ return this.page.waitForNavigation(opts);
2522
2422
  }
2523
2423
 
2524
2424
  async waitUntilExists(locator, sec) {
2525
2425
  console.log(`waitUntilExists deprecated:
2526
2426
  * use 'waitForElement' to wait for element to be attached
2527
- * use 'waitForDetached to wait for element to be removed'`)
2528
- return this.waitForDetached(locator, sec)
2427
+ * use 'waitForDetached to wait for element to be removed'`);
2428
+ return this.waitForDetached(locator, sec);
2529
2429
  }
2530
2430
 
2531
2431
  /**
2532
2432
  * {{> waitForDetached }}
2533
2433
  */
2534
2434
  async waitForDetached(locator, sec) {
2535
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2536
- locator = new Locator(locator, 'css')
2435
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2436
+ locator = new Locator(locator, 'css');
2537
2437
 
2538
- let waiter
2539
- const context = await this._getContext()
2438
+ let waiter;
2439
+ const context = await this._getContext();
2540
2440
  if (locator.isCSS()) {
2541
2441
  const visibleFn = function (locator) {
2542
- return document.querySelector(locator) === null
2543
- }
2544
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value)
2442
+ return document.querySelector(locator) === null;
2443
+ };
2444
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value);
2545
2445
  } else {
2546
2446
  const visibleFn = function (locator, $XPath) {
2547
- eval($XPath) // eslint-disable-line no-eval
2548
- return $XPath(null, locator).length === 0
2549
- }
2550
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString())
2447
+ eval($XPath); // eslint-disable-line no-eval
2448
+ return $XPath(null, locator).length === 0;
2449
+ };
2450
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString());
2551
2451
  }
2552
2452
  return waiter.catch((err) => {
2553
- throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`)
2554
- })
2453
+ throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
2454
+ });
2555
2455
  }
2556
2456
 
2557
2457
  async _waitForAction() {
2558
- return this.wait(this.options.waitForAction / 1000)
2458
+ return this.wait(this.options.waitForAction / 1000);
2559
2459
  }
2560
2460
 
2561
2461
  /**
2562
2462
  * {{> grabDataFromPerformanceTiming }}
2563
2463
  */
2564
2464
  async grabDataFromPerformanceTiming() {
2565
- return perfTiming
2465
+ return perfTiming;
2566
2466
  }
2567
2467
 
2568
2468
  /**
2569
2469
  * {{> grabElementBoundingRect }}
2570
2470
  */
2571
2471
  async grabElementBoundingRect(locator, prop) {
2572
- const els = await this._locate(locator)
2573
- assertElementExists(els, locator)
2574
- const rect = await els[0].boundingBox()
2575
- if (prop) return rect[prop]
2576
- return rect
2472
+ const els = await this._locate(locator);
2473
+ assertElementExists(els, locator);
2474
+ const rect = await els[0].boundingBox();
2475
+ if (prop) return rect[prop];
2476
+ return rect;
2577
2477
  }
2578
2478
 
2579
2479
  /**
2580
- * Mocks network request using [`Request Interception`](https://pptr.dev/guides/network-interception)
2480
+ * Mocks network request using [`Request Interception`](https://pptr.dev/next/guides/request-interception)
2581
2481
  *
2582
2482
  * ```js
2583
2483
  * I.mockRoute(/(\.png$)|(\.jpg$)/, route => route.abort());
2584
2484
  * ```
2585
- * This method allows intercepting and mocking requests & responses. [Learn more about it](https://pptr.dev/guides/network-interception)
2485
+ * This method allows intercepting and mocking requests & responses. [Learn more about it](https://pptr.dev/next/guides/request-interception)
2586
2486
  *
2587
2487
  * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2588
2488
  * @param {function} [handler] a function to process request
2589
2489
  */
2590
2490
  async mockRoute(url, handler) {
2591
- await this.page.setRequestInterception(true)
2491
+ await this.page.setRequestInterception(true);
2592
2492
 
2593
- this.page.on('request', (interceptedRequest) => {
2493
+ this.page.on('request', interceptedRequest => {
2594
2494
  if (interceptedRequest.url().match(url)) {
2595
2495
  // @ts-ignore
2596
- handler(interceptedRequest)
2496
+ handler(interceptedRequest);
2597
2497
  } else {
2598
- interceptedRequest.continue()
2498
+ interceptedRequest.continue();
2599
2499
  }
2600
- })
2500
+ });
2601
2501
  }
2602
2502
 
2603
2503
  /**
@@ -2610,18 +2510,18 @@ class Puppeteer extends Helper {
2610
2510
  * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2611
2511
  */
2612
2512
  async stopMockingRoute(url) {
2613
- await this.page.setRequestInterception(true)
2513
+ await this.page.setRequestInterception(true);
2614
2514
 
2615
- this.page.off('request')
2515
+ this.page.off('request');
2616
2516
 
2617
2517
  // Resume normal request handling for the given URL
2618
- this.page.on('request', (interceptedRequest) => {
2518
+ this.page.on('request', interceptedRequest => {
2619
2519
  if (interceptedRequest.url().includes(url)) {
2620
- interceptedRequest.continue()
2520
+ interceptedRequest.continue();
2621
2521
  } else {
2622
- interceptedRequest.continue()
2522
+ interceptedRequest.continue();
2623
2523
  }
2624
- })
2524
+ });
2625
2525
  }
2626
2526
 
2627
2527
  /**
@@ -2629,7 +2529,7 @@ class Puppeteer extends Helper {
2629
2529
  * {{> flushNetworkTraffics }}
2630
2530
  */
2631
2531
  flushNetworkTraffics() {
2632
- flushNetworkTraffics.call(this)
2532
+ flushNetworkTraffics.call(this);
2633
2533
  }
2634
2534
 
2635
2535
  /**
@@ -2637,7 +2537,7 @@ class Puppeteer extends Helper {
2637
2537
  * {{> stopRecordingTraffic }}
2638
2538
  */
2639
2539
  stopRecordingTraffic() {
2640
- stopRecordingTraffic.call(this)
2540
+ stopRecordingTraffic.call(this);
2641
2541
  }
2642
2542
 
2643
2543
  /**
@@ -2645,11 +2545,11 @@ class Puppeteer extends Helper {
2645
2545
  *
2646
2546
  */
2647
2547
  async startRecordingTraffic() {
2648
- this.flushNetworkTraffics()
2649
- this.recording = true
2650
- this.recordedAtLeastOnce = true
2548
+ this.flushNetworkTraffics();
2549
+ this.recording = true;
2550
+ this.recordedAtLeastOnce = true;
2651
2551
 
2652
- await this.page.setRequestInterception(true)
2552
+ await this.page.setRequestInterception(true);
2653
2553
 
2654
2554
  this.page.on('request', (request) => {
2655
2555
  const information = {
@@ -2658,16 +2558,16 @@ class Puppeteer extends Helper {
2658
2558
  requestHeaders: request.headers(),
2659
2559
  requestPostData: request.postData(),
2660
2560
  response: request.response(),
2661
- }
2561
+ };
2662
2562
 
2663
- this.debugSection('REQUEST: ', JSON.stringify(information))
2563
+ this.debugSection('REQUEST: ', JSON.stringify(information));
2664
2564
 
2665
2565
  if (typeof information.requestPostData === 'object') {
2666
- information.requestPostData = JSON.parse(information.requestPostData)
2566
+ information.requestPostData = JSON.parse(information.requestPostData);
2667
2567
  }
2668
- request.continue()
2669
- this.requests.push(information)
2670
- })
2568
+ request.continue();
2569
+ this.requests.push(information);
2570
+ });
2671
2571
  }
2672
2572
 
2673
2573
  /**
@@ -2675,15 +2575,17 @@ class Puppeteer extends Helper {
2675
2575
  * {{> grabRecordedNetworkTraffics }}
2676
2576
  */
2677
2577
  async grabRecordedNetworkTraffics() {
2678
- return grabRecordedNetworkTraffics.call(this)
2578
+ return grabRecordedNetworkTraffics.call(this);
2679
2579
  }
2680
2580
 
2681
2581
  /**
2682
2582
  *
2683
2583
  * {{> seeTraffic }}
2684
2584
  */
2685
- async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) {
2686
- await seeTraffic.call(this, ...arguments)
2585
+ async seeTraffic({
2586
+ name, url, parameters, requestPostData, timeout = 10,
2587
+ }) {
2588
+ await seeTraffic.call(this, ...arguments);
2687
2589
  }
2688
2590
 
2689
2591
  /**
@@ -2692,47 +2594,56 @@ class Puppeteer extends Helper {
2692
2594
  *
2693
2595
  */
2694
2596
  dontSeeTraffic({ name, url }) {
2695
- dontSeeTraffic.call(this, ...arguments)
2597
+ dontSeeTraffic.call(this, ...arguments);
2696
2598
  }
2697
2599
 
2698
2600
  async getNewCDPSession() {
2699
- const client = await this.page.target().createCDPSession()
2700
- return client
2601
+ const client = await this.page.target().createCDPSession();
2602
+ return client;
2701
2603
  }
2702
2604
 
2703
2605
  /**
2704
2606
  * {{> startRecordingWebSocketMessages }}
2705
2607
  */
2706
2608
  async startRecordingWebSocketMessages() {
2707
- this.flushWebSocketMessages()
2708
- this.recordingWebSocketMessages = true
2709
- this.recordedWebSocketMessagesAtLeastOnce = true
2710
-
2711
- this.cdpSession = await this.getNewCDPSession()
2712
- await this.cdpSession.send('Network.enable')
2713
- await this.cdpSession.send('Page.enable')
2714
-
2715
- this.cdpSession.on('Network.webSocketFrameReceived', (payload) => {
2716
- this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload))
2717
- })
2609
+ this.flushWebSocketMessages();
2610
+ this.recordingWebSocketMessages = true;
2611
+ this.recordedWebSocketMessagesAtLeastOnce = true;
2612
+
2613
+ this.cdpSession = await this.getNewCDPSession();
2614
+ await this.cdpSession.send('Network.enable');
2615
+ await this.cdpSession.send('Page.enable');
2616
+
2617
+ this.cdpSession.on(
2618
+ 'Network.webSocketFrameReceived',
2619
+ (payload) => {
2620
+ this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload));
2621
+ },
2622
+ );
2718
2623
 
2719
- this.cdpSession.on('Network.webSocketFrameSent', (payload) => {
2720
- this._logWebsocketMessages(this._getWebSocketLog('SENT', payload))
2721
- })
2624
+ this.cdpSession.on(
2625
+ 'Network.webSocketFrameSent',
2626
+ (payload) => {
2627
+ this._logWebsocketMessages(this._getWebSocketLog('SENT', payload));
2628
+ },
2629
+ );
2722
2630
 
2723
- this.cdpSession.on('Network.webSocketFrameError', (payload) => {
2724
- this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload))
2725
- })
2631
+ this.cdpSession.on(
2632
+ 'Network.webSocketFrameError',
2633
+ (payload) => {
2634
+ this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload));
2635
+ },
2636
+ );
2726
2637
  }
2727
2638
 
2728
2639
  /**
2729
2640
  * {{> stopRecordingWebSocketMessages }}
2730
2641
  */
2731
2642
  async stopRecordingWebSocketMessages() {
2732
- await this.cdpSession.send('Network.disable')
2733
- await this.cdpSession.send('Page.disable')
2734
- this.page.removeAllListeners('Network')
2735
- this.recordingWebSocketMessages = false
2643
+ await this.cdpSession.send('Network.disable');
2644
+ await this.cdpSession.send('Page.disable');
2645
+ this.page.removeAllListeners('Network');
2646
+ this.recordingWebSocketMessages = false;
2736
2647
  }
2737
2648
 
2738
2649
  /**
@@ -2744,405 +2655,394 @@ class Puppeteer extends Helper {
2744
2655
  grabWebSocketMessages() {
2745
2656
  if (!this.recordingWebSocketMessages) {
2746
2657
  if (!this.recordedWebSocketMessagesAtLeastOnce) {
2747
- throw new Error(
2748
- 'Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.',
2749
- )
2658
+ throw new Error('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
2750
2659
  }
2751
2660
  }
2752
- return this.webSocketMessages
2661
+ return this.webSocketMessages;
2753
2662
  }
2754
2663
 
2755
2664
  /**
2756
2665
  * Resets all recorded WS messages.
2757
2666
  */
2758
2667
  flushWebSocketMessages() {
2759
- this.webSocketMessages = []
2668
+ this.webSocketMessages = [];
2760
2669
  }
2761
2670
 
2762
2671
  _getWebSocketMessage(payload) {
2763
2672
  if (payload.errorMessage) {
2764
- return payload.errorMessage
2673
+ return payload.errorMessage;
2765
2674
  }
2766
2675
 
2767
- return payload.response.payloadData
2676
+ return payload.response.payloadData;
2768
2677
  }
2769
2678
 
2770
2679
  _getWebSocketLog(prefix, payload) {
2771
- return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`
2680
+ return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`;
2772
2681
  }
2773
2682
 
2774
2683
  _logWebsocketMessages(message) {
2775
- this.webSocketMessages += message
2684
+ this.webSocketMessages += message;
2776
2685
  }
2777
2686
  }
2778
2687
 
2779
- module.exports = Puppeteer
2688
+ export default Puppeteer;
2780
2689
 
2781
2690
  async function findElements(matcher, locator) {
2782
- if (locator.react) return findReactElements.call(this, locator)
2783
- locator = new Locator(locator, 'css')
2784
- if (!locator.isXPath()) return matcher.$$(locator.simplify())
2691
+ if (locator.react) return findReactElements.call(this, locator);
2692
+ locator = new Locator(locator, 'css');
2693
+ if (!locator.isXPath()) return matcher.$$(locator.simplify());
2785
2694
  // puppeteer version < 19.4.0 is no longer supported. This one is backward support.
2786
2695
  if (puppeteer.default?.defaultBrowserRevision) {
2787
- return matcher.$$(`xpath/${locator.value}`)
2696
+ return matcher.$$(`xpath/${locator.value}`);
2788
2697
  }
2789
- return matcher.$x(locator.value)
2698
+ return matcher.$x(locator.value);
2790
2699
  }
2791
2700
 
2792
2701
  async function proceedClick(locator, context = null, options = {}) {
2793
- let matcher = await this.context
2702
+ let matcher = await this.context;
2794
2703
  if (context) {
2795
- const els = await this._locate(context)
2796
- assertElementExists(els, context)
2797
- matcher = els[0]
2704
+ const els = await this._locate(context);
2705
+ assertElementExists(els, context);
2706
+ matcher = els[0];
2798
2707
  }
2799
- const els = await findClickable.call(this, matcher, locator)
2708
+ const els = await findClickable.call(this, matcher, locator);
2800
2709
  if (context) {
2801
- assertElementExists(
2802
- els,
2803
- locator,
2804
- 'Clickable element',
2805
- `was not found inside element ${new Locator(context).toString()}`,
2806
- )
2710
+ assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
2807
2711
  } else {
2808
- assertElementExists(els, locator, 'Clickable element')
2712
+ assertElementExists(els, locator, 'Clickable element');
2809
2713
  }
2810
2714
 
2811
- highlightActiveElement.call(this, els[0], await this._getContext())
2715
+ highlightActiveElement.call(this, els[0], await this._getContext());
2812
2716
 
2813
- await els[0].click(options)
2814
- const promises = []
2717
+ await els[0].click(options);
2718
+ const promises = [];
2815
2719
  if (options.waitForNavigation) {
2816
- promises.push(this.waitForNavigation())
2720
+ promises.push(this.waitForNavigation());
2817
2721
  }
2818
- promises.push(this._waitForAction())
2722
+ promises.push(this._waitForAction());
2819
2723
 
2820
- return Promise.all(promises)
2724
+ return Promise.all(promises);
2821
2725
  }
2822
2726
 
2823
2727
  async function findClickable(matcher, locator) {
2824
- if (locator.react) return findReactElements.call(this, locator)
2825
- locator = new Locator(locator)
2826
- if (!locator.isFuzzy()) return findElements.call(this, matcher, locator)
2728
+ if (locator.react) return findReactElements.call(this, locator);
2729
+ locator = new Locator(locator);
2730
+ if (!locator.isFuzzy()) return findElements.call(this, matcher, locator);
2827
2731
 
2828
- let els
2829
- const literal = xpathLocator.literal(locator.value)
2732
+ let els;
2733
+ const literal = xpathLocator.literal(locator.value);
2830
2734
 
2831
- els = await findElements.call(this, matcher, Locator.clickable.narrow(literal))
2832
- if (els.length) return els
2735
+ els = await findElements.call(this, matcher, Locator.clickable.narrow(literal));
2736
+ if (els.length) return els;
2833
2737
 
2834
- els = await findElements.call(this, matcher, Locator.clickable.wide(literal))
2835
- if (els.length) return els
2738
+ els = await findElements.call(this, matcher, Locator.clickable.wide(literal));
2739
+ if (els.length) return els;
2836
2740
 
2837
2741
  try {
2838
- els = await findElements.call(this, matcher, Locator.clickable.self(literal))
2839
- if (els.length) return els
2742
+ els = await findElements.call(this, matcher, Locator.clickable.self(literal));
2743
+ if (els.length) return els;
2840
2744
  } catch (err) {
2841
2745
  // Do nothing
2842
2746
  }
2843
2747
 
2844
- return findElements.call(this, matcher, locator.value) // by css or xpath
2748
+ return findElements.call(this, matcher, locator.value); // by css or xpath
2845
2749
  }
2846
2750
 
2847
2751
  async function proceedSee(assertType, text, context, strict = false) {
2848
- let description
2849
- let allText
2752
+ let description;
2753
+ let allText;
2850
2754
  if (!context) {
2851
- let el = await this.context
2755
+ let el = await this.context;
2852
2756
 
2853
2757
  if (el && !el.getProperty) {
2854
2758
  // Fallback to body
2855
- el = await this.context.$('body')
2759
+ el = await this.context.$('body');
2856
2760
  }
2857
2761
 
2858
- allText = [await el.getProperty('innerText').then((p) => p.jsonValue())]
2859
- description = 'web application'
2762
+ allText = [await el.getProperty('innerText').then(p => p.jsonValue())];
2763
+ description = 'web application';
2860
2764
  } else {
2861
- const locator = new Locator(context, 'css')
2862
- description = `element ${locator.toString()}`
2863
- const els = await this._locate(locator)
2864
- assertElementExists(els, locator.toString())
2865
- allText = await Promise.all(els.map((el) => el.getProperty('innerText').then((p) => p.jsonValue())))
2765
+ const locator = new Locator(context, 'css');
2766
+ description = `element ${locator.toString()}`;
2767
+ const els = await this._locate(locator);
2768
+ assertElementExists(els, locator.toString());
2769
+ allText = await Promise.all(els.map(el => el.getProperty('innerText').then(p => p.jsonValue())));
2866
2770
  }
2867
2771
 
2868
2772
  if (strict) {
2869
- return allText.map((elText) => equals(description)[assertType](text, elText))
2773
+ return allText.map(elText => equals(description)[assertType](text, elText));
2870
2774
  }
2871
- return stringIncludes(description)[assertType](
2872
- normalizeSpacesInString(text),
2873
- normalizeSpacesInString(allText.join(' | ')),
2874
- )
2775
+ return stringIncludes(description)[assertType](normalizeSpacesInString(text), normalizeSpacesInString(allText.join(' | ')));
2875
2776
  }
2876
2777
 
2877
2778
  async function findCheckable(locator, context) {
2878
- let contextEl = await this.context
2779
+ let contextEl = await this.context;
2879
2780
  if (typeof context === 'string') {
2880
- contextEl = await findElements.call(this, contextEl, new Locator(context, 'css').simplify())
2881
- contextEl = contextEl[0]
2781
+ contextEl = await findElements.call(this, contextEl, (new Locator(context, 'css')).simplify());
2782
+ contextEl = contextEl[0];
2882
2783
  }
2883
2784
 
2884
- const matchedLocator = new Locator(locator)
2785
+ const matchedLocator = new Locator(locator);
2885
2786
  if (!matchedLocator.isFuzzy()) {
2886
- return findElements.call(this, contextEl, matchedLocator.simplify())
2787
+ return findElements.call(this, contextEl, matchedLocator.simplify());
2887
2788
  }
2888
2789
 
2889
- const literal = xpathLocator.literal(locator)
2890
- let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal))
2790
+ const literal = xpathLocator.literal(locator);
2791
+ let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal));
2891
2792
  if (els.length) {
2892
- return els
2793
+ return els;
2893
2794
  }
2894
- els = await findElements.call(this, contextEl, Locator.checkable.byName(literal))
2795
+ els = await findElements.call(this, contextEl, Locator.checkable.byName(literal));
2895
2796
  if (els.length) {
2896
- return els
2797
+ return els;
2897
2798
  }
2898
- return findElements.call(this, contextEl, locator)
2799
+ return findElements.call(this, contextEl, locator);
2899
2800
  }
2900
2801
 
2901
2802
  async function proceedIsChecked(assertType, option) {
2902
- let els = await findCheckable.call(this, option)
2903
- assertElementExists(els, option, 'Checkable')
2904
- els = await Promise.all(els.map((el) => el.getProperty('checked')))
2905
- els = await Promise.all(els.map((el) => el.jsonValue()))
2906
- const selected = els.reduce((prev, cur) => prev || cur)
2907
- return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
2803
+ let els = await findCheckable.call(this, option);
2804
+ assertElementExists(els, option, 'Checkable');
2805
+ els = await Promise.all(els.map(el => el.getProperty('checked')));
2806
+ els = await Promise.all(els.map(el => el.jsonValue()));
2807
+ const selected = els.reduce((prev, cur) => prev || cur);
2808
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
2908
2809
  }
2909
2810
 
2910
2811
  async function findVisibleFields(locator) {
2911
- const els = await findFields.call(this, locator)
2912
- const visible = await Promise.all(els.map((el) => el.boundingBox()))
2913
- return els.filter((el, index) => visible[index])
2812
+ const els = await findFields.call(this, locator);
2813
+ const visible = await Promise.all(els.map(el => el.boundingBox()));
2814
+ return els.filter((el, index) => visible[index]);
2914
2815
  }
2915
2816
 
2916
2817
  async function findFields(locator) {
2917
- const matchedLocator = new Locator(locator)
2818
+ const matchedLocator = new Locator(locator);
2918
2819
  if (!matchedLocator.isFuzzy()) {
2919
- return this._locate(matchedLocator)
2820
+ return this._locate(matchedLocator);
2920
2821
  }
2921
- const literal = xpathLocator.literal(locator)
2822
+ const literal = xpathLocator.literal(locator);
2922
2823
 
2923
- let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
2824
+ let els = await this._locate({ xpath: Locator.field.labelEquals(literal) });
2924
2825
  if (els.length) {
2925
- return els
2826
+ return els;
2926
2827
  }
2927
2828
 
2928
- els = await this._locate({ xpath: Locator.field.labelContains(literal) })
2829
+ els = await this._locate({ xpath: Locator.field.labelContains(literal) });
2929
2830
  if (els.length) {
2930
- return els
2831
+ return els;
2931
2832
  }
2932
- els = await this._locate({ xpath: Locator.field.byName(literal) })
2833
+ els = await this._locate({ xpath: Locator.field.byName(literal) });
2933
2834
  if (els.length) {
2934
- return els
2835
+ return els;
2935
2836
  }
2936
- return this._locate({ css: locator })
2837
+ return this._locate({ css: locator });
2937
2838
  }
2938
2839
 
2939
2840
  async function proceedDragAndDrop(sourceLocator, destinationLocator) {
2940
- const src = await this._locate(sourceLocator)
2941
- assertElementExists(src, sourceLocator, 'Source Element')
2841
+ const src = await this._locate(sourceLocator);
2842
+ assertElementExists(src, sourceLocator, 'Source Element');
2942
2843
 
2943
- const dst = await this._locate(destinationLocator)
2944
- assertElementExists(dst, destinationLocator, 'Destination Element')
2844
+ const dst = await this._locate(destinationLocator);
2845
+ assertElementExists(dst, destinationLocator, 'Destination Element');
2945
2846
 
2946
2847
  // Note: Using public api .getClickablePoint becaues the .BoundingBox does not take into account iframe offsets
2947
- const dragSource = await getClickablePoint(src[0])
2948
- const dragDestination = await getClickablePoint(dst[0])
2848
+ const dragSource = await getClickablePoint(src[0]);
2849
+ const dragDestination = await getClickablePoint(dst[0]);
2949
2850
 
2950
2851
  // Drag start point
2951
- await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 })
2952
- await this.page.mouse.down()
2852
+ await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 });
2853
+ await this.page.mouse.down();
2953
2854
 
2954
2855
  // Drag destination
2955
- await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 })
2956
- await this.page.mouse.up()
2856
+ await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 });
2857
+ await this.page.mouse.up();
2957
2858
 
2958
- await this._waitForAction()
2859
+ await this._waitForAction();
2959
2860
  }
2960
2861
 
2961
2862
  async function proceedSeeInField(assertType, field, value) {
2962
- const els = await findVisibleFields.call(this, field)
2963
- assertElementExists(els, field, 'Field')
2964
- const el = els[0]
2965
- const tag = await el.getProperty('tagName').then((el) => el.jsonValue())
2966
- const fieldType = await el.getProperty('type').then((el) => el.jsonValue())
2863
+ const els = await findVisibleFields.call(this, field);
2864
+ assertElementExists(els, field, 'Field');
2865
+ const el = els[0];
2866
+ const tag = await el.getProperty('tagName').then(el => el.jsonValue());
2867
+ const fieldType = await el.getProperty('type').then(el => el.jsonValue());
2967
2868
 
2968
2869
  const proceedMultiple = async (elements) => {
2969
- const fields = Array.isArray(elements) ? elements : [elements]
2870
+ const fields = Array.isArray(elements) ? elements : [elements];
2970
2871
 
2971
- const elementValues = []
2872
+ const elementValues = [];
2972
2873
  for (const element of fields) {
2973
- elementValues.push(await element.getProperty('value').then((el) => el.jsonValue()))
2874
+ elementValues.push(await element.getProperty('value').then(el => el.jsonValue()));
2974
2875
  }
2975
2876
 
2976
2877
  if (typeof value === 'boolean') {
2977
- equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length)
2878
+ equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length);
2978
2879
  } else {
2979
2880
  if (assertType === 'assert') {
2980
- equals(`select option by ${field}`)[assertType](true, elementValues.length > 0)
2881
+ equals(`select option by ${field}`)[assertType](true, elementValues.length > 0);
2981
2882
  }
2982
- elementValues.forEach((val) => stringIncludes(`fields by ${field}`)[assertType](value, val))
2883
+ elementValues.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val));
2983
2884
  }
2984
- }
2885
+ };
2985
2886
 
2986
2887
  if (tag === 'SELECT') {
2987
- const selectedOptions = await el.$$('option:checked')
2888
+ const selectedOptions = await el.$$('option:checked');
2988
2889
  // locate option by values and check them
2989
2890
  if (value === '') {
2990
- return proceedMultiple(selectedOptions)
2891
+ return proceedMultiple(selectedOptions);
2991
2892
  }
2992
2893
 
2993
- const options = await filterFieldsByValue(selectedOptions, value, true)
2994
- return proceedMultiple(options)
2894
+ const options = await filterFieldsByValue(selectedOptions, value, true);
2895
+ return proceedMultiple(options);
2995
2896
  }
2996
2897
 
2997
2898
  if (tag === 'INPUT') {
2998
2899
  if (fieldType === 'checkbox' || fieldType === 'radio') {
2999
2900
  if (typeof value === 'boolean') {
3000
2901
  // Filter by values
3001
- const options = await filterFieldsBySelectionState(els, true)
3002
- return proceedMultiple(options)
2902
+ const options = await filterFieldsBySelectionState(els, true);
2903
+ return proceedMultiple(options);
3003
2904
  }
3004
2905
 
3005
- const options = await filterFieldsByValue(els, value, true)
3006
- return proceedMultiple(options)
2906
+ const options = await filterFieldsByValue(els, value, true);
2907
+ return proceedMultiple(options);
3007
2908
  }
3008
- return proceedMultiple(els[0])
2909
+ return proceedMultiple(els[0]);
3009
2910
  }
3010
- const fieldVal = await el.getProperty('value').then((el) => el.jsonValue())
3011
- return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal)
2911
+ const fieldVal = await el.getProperty('value').then(el => el.jsonValue());
2912
+ return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal);
3012
2913
  }
3013
2914
 
3014
2915
  async function filterFieldsByValue(elements, value, onlySelected) {
3015
- const matches = []
2916
+ const matches = [];
3016
2917
  for (const element of elements) {
3017
- const val = await element.getProperty('value').then((el) => el.jsonValue())
3018
- let isSelected = true
2918
+ const val = await element.getProperty('value').then(el => el.jsonValue());
2919
+ let isSelected = true;
3019
2920
  if (onlySelected) {
3020
- isSelected = await elementSelected(element)
2921
+ isSelected = await elementSelected(element);
3021
2922
  }
3022
2923
  if ((value == null || val.indexOf(value) > -1) && isSelected) {
3023
- matches.push(element)
2924
+ matches.push(element);
3024
2925
  }
3025
2926
  }
3026
- return matches
2927
+ return matches;
3027
2928
  }
3028
2929
 
3029
2930
  async function filterFieldsBySelectionState(elements, state) {
3030
- const matches = []
2931
+ const matches = [];
3031
2932
  for (const element of elements) {
3032
- const isSelected = await elementSelected(element)
2933
+ const isSelected = await elementSelected(element);
3033
2934
  if (isSelected === state) {
3034
- matches.push(element)
2935
+ matches.push(element);
3035
2936
  }
3036
2937
  }
3037
- return matches
2938
+ return matches;
3038
2939
  }
3039
2940
 
3040
2941
  async function elementSelected(element) {
3041
- const type = await element.getProperty('type').then((el) => el.jsonValue())
2942
+ const type = await element.getProperty('type').then(el => el.jsonValue());
3042
2943
 
3043
2944
  if (type === 'checkbox' || type === 'radio') {
3044
- return element.getProperty('checked').then((el) => el.jsonValue())
2945
+ return element.getProperty('checked').then(el => el.jsonValue());
3045
2946
  }
3046
- return element.getProperty('selected').then((el) => el.jsonValue())
2947
+ return element.getProperty('selected').then(el => el.jsonValue());
3047
2948
  }
3048
2949
 
3049
2950
  function isFrameLocator(locator) {
3050
- locator = new Locator(locator)
2951
+ locator = new Locator(locator);
3051
2952
  if (locator.isFrame()) {
3052
- const _locator = new Locator(locator)
3053
- return _locator.value
2953
+ const _locator = new Locator(locator);
2954
+ return _locator.value;
3054
2955
  }
3055
- return false
2956
+ return false;
3056
2957
  }
3057
2958
 
3058
2959
  function assertElementExists(res, locator, prefix, suffix) {
3059
2960
  if (!res || res.length === 0) {
3060
- throw new ElementNotFound(locator, prefix, suffix)
2961
+ throw new ElementNotFound(locator, prefix, suffix);
3061
2962
  }
3062
2963
  }
3063
2964
 
3064
2965
  function $XPath(element, selector) {
3065
- const found = document.evaluate(selector, element || document.body, null, 5, null)
3066
- const res = []
3067
- let current = null
3068
- while ((current = found.iterateNext())) {
3069
- res.push(current)
2966
+ const found = document.evaluate(selector, element || document.body, null, 5, null);
2967
+ const res = [];
2968
+ let current = null;
2969
+ while (current = found.iterateNext()) {
2970
+ res.push(current);
3070
2971
  }
3071
- return res
2972
+ return res;
3072
2973
  }
3073
2974
 
3074
2975
  async function targetCreatedHandler(page) {
3075
- if (!page) return
3076
- this.withinLocator = null
2976
+ if (!page) return;
2977
+ this.withinLocator = null;
3077
2978
  page.on('load', () => {
3078
- page
3079
- .$('body')
2979
+ page.$('body')
3080
2980
  .catch(() => null)
3081
- .then((context) => (this.context = context))
3082
- })
2981
+ .then(context => this.context = context);
2982
+ });
3083
2983
  page.on('console', (msg) => {
3084
- this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '))
3085
- consoleLogStore.add(msg)
3086
- })
2984
+ this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '));
2985
+ consoleLogStore.add(msg);
2986
+ });
3087
2987
 
3088
2988
  if (this.options.userAgent) {
3089
- await page.setUserAgent(this.options.userAgent)
2989
+ await page.setUserAgent(this.options.userAgent);
3090
2990
  }
3091
2991
  if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0) {
3092
- const dimensions = this.options.windowSize.split('x')
3093
- const width = parseInt(dimensions[0], 10)
3094
- const height = parseInt(dimensions[1], 10)
3095
- await page.setViewport({ width, height })
2992
+ const dimensions = this.options.windowSize.split('x');
2993
+ const width = parseInt(dimensions[0], 10);
2994
+ const height = parseInt(dimensions[1], 10);
2995
+ await page.setViewport({ width, height });
3096
2996
  }
3097
2997
  }
3098
2998
 
3099
2999
  // BC compatibility for Puppeteer < 10
3100
3000
  async function getClickablePoint(el) {
3101
- if (el.clickablePoint) return el.clickablePoint()
3102
- if (el._clickablePoint) return el._clickablePoint()
3103
- return null
3001
+ if (el.clickablePoint) return el.clickablePoint();
3002
+ if (el._clickablePoint) return el._clickablePoint();
3003
+ return null;
3104
3004
  }
3105
3005
 
3106
3006
  // List of key values to key definitions
3107
3007
  // https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3108
3008
  const keyDefinitionMap = {
3109
3009
  /* eslint-disable quote-props */
3110
- 0: 'Digit0',
3111
- 1: 'Digit1',
3112
- 2: 'Digit2',
3113
- 3: 'Digit3',
3114
- 4: 'Digit4',
3115
- 5: 'Digit5',
3116
- 6: 'Digit6',
3117
- 7: 'Digit7',
3118
- 8: 'Digit8',
3119
- 9: 'Digit9',
3120
- a: 'KeyA',
3121
- b: 'KeyB',
3122
- c: 'KeyC',
3123
- d: 'KeyD',
3124
- e: 'KeyE',
3125
- f: 'KeyF',
3126
- g: 'KeyG',
3127
- h: 'KeyH',
3128
- i: 'KeyI',
3129
- j: 'KeyJ',
3130
- k: 'KeyK',
3131
- l: 'KeyL',
3132
- m: 'KeyM',
3133
- n: 'KeyN',
3134
- o: 'KeyO',
3135
- p: 'KeyP',
3136
- q: 'KeyQ',
3137
- r: 'KeyR',
3138
- s: 'KeyS',
3139
- t: 'KeyT',
3140
- u: 'KeyU',
3141
- v: 'KeyV',
3142
- w: 'KeyW',
3143
- x: 'KeyX',
3144
- y: 'KeyY',
3145
- z: 'KeyZ',
3010
+ '0': 'Digit0',
3011
+ '1': 'Digit1',
3012
+ '2': 'Digit2',
3013
+ '3': 'Digit3',
3014
+ '4': 'Digit4',
3015
+ '5': 'Digit5',
3016
+ '6': 'Digit6',
3017
+ '7': 'Digit7',
3018
+ '8': 'Digit8',
3019
+ '9': 'Digit9',
3020
+ 'a': 'KeyA',
3021
+ 'b': 'KeyB',
3022
+ 'c': 'KeyC',
3023
+ 'd': 'KeyD',
3024
+ 'e': 'KeyE',
3025
+ 'f': 'KeyF',
3026
+ 'g': 'KeyG',
3027
+ 'h': 'KeyH',
3028
+ 'i': 'KeyI',
3029
+ 'j': 'KeyJ',
3030
+ 'k': 'KeyK',
3031
+ 'l': 'KeyL',
3032
+ 'm': 'KeyM',
3033
+ 'n': 'KeyN',
3034
+ 'o': 'KeyO',
3035
+ 'p': 'KeyP',
3036
+ 'q': 'KeyQ',
3037
+ 'r': 'KeyR',
3038
+ 's': 'KeyS',
3039
+ 't': 'KeyT',
3040
+ 'u': 'KeyU',
3041
+ 'v': 'KeyV',
3042
+ 'w': 'KeyW',
3043
+ 'x': 'KeyX',
3044
+ 'y': 'KeyY',
3045
+ 'z': 'KeyZ',
3146
3046
  ';': 'Semicolon',
3147
3047
  '=': 'Equal',
3148
3048
  ',': 'Comma',
@@ -3153,94 +3053,91 @@ const keyDefinitionMap = {
3153
3053
  '[': 'BracketLeft',
3154
3054
  '\\': 'Backslash',
3155
3055
  ']': 'BracketRight',
3156
- "'": 'Quote',
3056
+ '\'': 'Quote',
3157
3057
  /* eslint-enable quote-props */
3158
- }
3058
+ };
3159
3059
 
3160
3060
  function getNormalizedKey(key) {
3161
- const normalizedKey = getNormalizedKeyAttributeValue(key)
3061
+ const normalizedKey = getNormalizedKeyAttributeValue(key);
3162
3062
  if (key !== normalizedKey) {
3163
- this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`)
3063
+ this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`);
3164
3064
  }
3165
3065
  // Use key definition to ensure correct key is displayed when Shift modifier is active
3166
3066
  if (Object.prototype.hasOwnProperty.call(keyDefinitionMap, normalizedKey)) {
3167
- return keyDefinitionMap[normalizedKey]
3067
+ return keyDefinitionMap[normalizedKey];
3168
3068
  }
3169
- return normalizedKey
3069
+ return normalizedKey;
3170
3070
  }
3171
3071
 
3172
3072
  function highlightActiveElement(element, context) {
3173
3073
  if (this.options.highlightElement && global.debugMode) {
3174
- highlightElement(element, context)
3074
+ highlightElement(element, context);
3175
3075
  }
3176
3076
  }
3177
3077
 
3178
3078
  function _waitForElement(locator, options) {
3179
3079
  try {
3180
- return this.context.waitForXPath(locator.value, options)
3080
+ return this.context.waitForXPath(locator.value, options);
3181
3081
  } catch (e) {
3182
- return this.context.waitForSelector(`::-p-xpath(${locator.value})`, options)
3082
+ return this.context.waitForSelector(`::-p-xpath(${locator.value})`, options);
3183
3083
  }
3184
3084
  }
3185
3085
 
3186
3086
  async function findReactElements(locator, props = {}, state = {}) {
3187
- const resqScript = await fs.promises.readFile(require.resolve('resq'), 'utf-8')
3188
- await this.page.evaluate(resqScript.toString())
3189
-
3190
- await this.page.evaluate(() => window.resq.waitToLoadReact())
3191
- const arrayHandle = await this.page.evaluateHandle(
3192
- (obj) => {
3193
- const { selector, props, state } = obj
3194
- let elements = window.resq.resq$$(selector)
3195
- if (Object.keys(props).length) {
3196
- elements = elements.byProps(props)
3197
- }
3198
- if (Object.keys(state).length) {
3199
- elements = elements.byState(state)
3200
- }
3087
+ const resqScript = await fs.promises.readFile(require.resolve('resq'), 'utf-8');
3088
+ await this.page.evaluate(resqScript.toString());
3201
3089
 
3202
- if (!elements.length) {
3203
- return []
3204
- }
3090
+ await this.page.evaluate(() => window.resq.waitToLoadReact());
3091
+ const arrayHandle = await this.page.evaluateHandle((obj) => {
3092
+ const { selector, props, state } = obj;
3093
+ let elements = window.resq.resq$$(selector);
3094
+ if (Object.keys(props).length) {
3095
+ elements = elements.byProps(props);
3096
+ }
3097
+ if (Object.keys(state).length) {
3098
+ elements = elements.byState(state);
3099
+ }
3205
3100
 
3206
- // resq returns an array of HTMLElements if the React component is a fragment
3207
- // this avoids having nested arrays of nodes which the driver does not understand
3208
- // [[div, div], [div, div]] => [div, div, div, div]
3209
- let nodes = []
3101
+ if (!elements.length) {
3102
+ return [];
3103
+ }
3210
3104
 
3211
- elements.forEach((element) => {
3212
- let { node, isFragment } = element
3105
+ // resq returns an array of HTMLElements if the React component is a fragment
3106
+ // this avoids having nested arrays of nodes which the driver does not understand
3107
+ // [[div, div], [div, div]] => [div, div, div, div]
3108
+ let nodes = [];
3213
3109
 
3214
- if (!node) {
3215
- isFragment = true
3216
- node = element.children
3217
- }
3110
+ elements.forEach((element) => {
3111
+ let { node, isFragment } = element;
3218
3112
 
3219
- if (isFragment) {
3220
- nodes = nodes.concat(node)
3221
- } else {
3222
- nodes.push(node)
3223
- }
3224
- })
3225
-
3226
- return [...nodes]
3227
- },
3228
- {
3229
- selector: locator.react,
3230
- props: locator.props || {},
3231
- state: locator.state || {},
3232
- },
3233
- )
3234
-
3235
- const properties = await arrayHandle.getProperties()
3236
- const result = []
3113
+ if (!node) {
3114
+ isFragment = true;
3115
+ node = element.children;
3116
+ }
3117
+
3118
+ if (isFragment) {
3119
+ nodes = nodes.concat(node);
3120
+ } else {
3121
+ nodes.push(node);
3122
+ }
3123
+ });
3124
+
3125
+ return [...nodes];
3126
+ }, {
3127
+ selector: locator.react,
3128
+ props: locator.props || {},
3129
+ state: locator.state || {},
3130
+ });
3131
+
3132
+ const properties = await arrayHandle.getProperties();
3133
+ const result = [];
3237
3134
  for (const property of properties.values()) {
3238
- const elementHandle = property.asElement()
3135
+ const elementHandle = property.asElement();
3239
3136
  if (elementHandle) {
3240
- result.push(elementHandle)
3137
+ result.push(elementHandle);
3241
3138
  }
3242
3139
  }
3243
3140
 
3244
- await arrayHandle.dispose()
3245
- return result
3141
+ await arrayHandle.dispose();
3142
+ return result;
3246
3143
  }