codeceptjs 4.0.0-beta.1 → 4.0.0-beta.3

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