codeceptjs 4.0.0-beta.2 → 4.0.0-beta.4

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 (152) hide show
  1. package/README.md +2 -2
  2. package/bin/codecept.js +84 -81
  3. package/lib/actor.js +13 -13
  4. package/lib/ai.js +10 -13
  5. package/lib/assert/empty.js +20 -21
  6. package/lib/assert/equal.js +37 -39
  7. package/lib/assert/error.js +14 -14
  8. package/lib/assert/include.js +46 -47
  9. package/lib/assert/throws.js +13 -11
  10. package/lib/assert/truth.js +19 -22
  11. package/lib/assert.js +4 -2
  12. package/lib/cli.js +56 -49
  13. package/lib/codecept.js +145 -155
  14. package/lib/colorUtils.js +3 -3
  15. package/lib/command/configMigrate.js +58 -52
  16. package/lib/command/definitions.js +88 -89
  17. package/lib/command/dryRun.js +79 -81
  18. package/lib/command/generate.js +197 -188
  19. package/lib/command/gherkin/init.js +27 -16
  20. package/lib/command/gherkin/snippets.js +21 -21
  21. package/lib/command/gherkin/steps.js +8 -8
  22. package/lib/command/info.js +40 -38
  23. package/lib/command/init.js +290 -288
  24. package/lib/command/interactive.js +32 -32
  25. package/lib/command/list.js +26 -26
  26. package/lib/command/run-multiple/chunk.js +5 -5
  27. package/lib/command/run-multiple/collection.js +3 -3
  28. package/lib/command/run-multiple/run.js +6 -2
  29. package/lib/command/run-multiple.js +113 -93
  30. package/lib/command/run-rerun.js +20 -25
  31. package/lib/command/run-workers.js +64 -66
  32. package/lib/command/run.js +26 -29
  33. package/lib/command/utils.js +80 -65
  34. package/lib/command/workers/runTests.js +11 -12
  35. package/lib/config.js +10 -9
  36. package/lib/container.js +40 -48
  37. package/lib/data/context.js +60 -59
  38. package/lib/data/dataScenarioConfig.js +47 -47
  39. package/lib/data/dataTableArgument.js +29 -29
  40. package/lib/data/table.js +26 -20
  41. package/lib/event.js +163 -167
  42. package/lib/heal.js +14 -18
  43. package/lib/helper/AI.js +130 -41
  44. package/lib/helper/ApiDataFactory.js +74 -70
  45. package/lib/helper/Appium.js +416 -388
  46. package/lib/helper/ExpectHelper.js +40 -48
  47. package/lib/helper/FileSystem.js +80 -79
  48. package/lib/helper/GraphQL.js +44 -43
  49. package/lib/helper/GraphQLDataFactory.js +51 -51
  50. package/lib/helper/JSONResponse.js +65 -62
  51. package/lib/helper/Mochawesome.js +28 -28
  52. package/lib/helper/Nightmare.js +664 -571
  53. package/lib/helper/Playwright.js +1367 -1222
  54. package/lib/helper/Protractor.js +663 -635
  55. package/lib/helper/Puppeteer.js +1232 -1132
  56. package/lib/helper/REST.js +183 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -486
  59. package/lib/helper/WebDriver.js +1246 -1297
  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 +4 -4
  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 +4 -3
  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 +7 -8
  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 +7 -11
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +19 -15
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +45 -38
  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 +112 -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 -3
  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 -33
  136. package/package.json +67 -68
  137. package/translations/de-DE.js +2 -1
  138. package/translations/fr-FR.js +2 -2
  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 +423 -65
  148. package/typings/promiseBasedTypes.d.ts +41 -172
  149. package/typings/types.d.ts +43 -178
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
  152. package/lib/helper/MockServer.js +0 -223
@@ -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,68 +827,71 @@ 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
  /**
849
861
  * {{> grabPageScrollPosition }}
850
862
  */
851
863
  async grabPageScrollPosition() {
852
- /* eslint-disable comma-dangle */
853
864
  function getScrollPosition() {
854
865
  return {
855
866
  x: window.pageXOffset,
856
- y: window.pageYOffset
857
- };
867
+ y: window.pageYOffset,
868
+ }
858
869
  }
859
- /* eslint-enable comma-dangle */
860
- return this.executeScript(getScrollPosition);
870
+
871
+ return this.executeScript(getScrollPosition)
861
872
  }
862
873
 
863
874
  /**
864
875
  * {{> seeTitleEquals }}
865
876
  */
866
877
  async seeTitleEquals(text) {
867
- const title = await this.page.title();
868
- return equals('web page title').assert(title, text);
878
+ const title = await this.page.title()
879
+ return equals('web page title').assert(title, text)
869
880
  }
870
881
 
871
882
  /**
872
883
  * {{> dontSeeInTitle }}
873
884
  */
874
885
  async dontSeeInTitle(text) {
875
- const title = await this.page.title();
876
- stringIncludes('web page title').negate(text, title);
886
+ const title = await this.page.title()
887
+ stringIncludes('web page title').negate(text, title)
877
888
  }
878
889
 
879
890
  /**
880
891
  * {{> grabTitle }}
881
892
  */
882
893
  async grabTitle() {
883
- return this.page.title();
894
+ return this.page.title()
884
895
  }
885
896
 
886
897
  /**
@@ -894,8 +905,8 @@ class Puppeteer extends Helper {
894
905
  * {{ react }}
895
906
  */
896
907
  async _locate(locator) {
897
- const context = await this.context;
898
- return findElements.call(this, context, locator);
908
+ const context = await this.context
909
+ return findElements.call(this, context, locator)
899
910
  }
900
911
 
901
912
  /**
@@ -907,10 +918,10 @@ class Puppeteer extends Helper {
907
918
  * ```
908
919
  */
909
920
  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];
921
+ const context = providedContext || (await this._getContext())
922
+ const els = await findCheckable.call(this, locator, context)
923
+ assertElementExists(els[0], locator, 'Checkbox or radio')
924
+ return els[0]
914
925
  }
915
926
 
916
927
  /**
@@ -921,8 +932,8 @@ class Puppeteer extends Helper {
921
932
  * ```
922
933
  */
923
934
  async _locateClickable(locator) {
924
- const context = await this.context;
925
- return findClickable.call(this, context, locator);
935
+ const context = await this.context
936
+ return findClickable.call(this, context, locator)
926
937
  }
927
938
 
928
939
  /**
@@ -933,7 +944,7 @@ class Puppeteer extends Helper {
933
944
  * ```
934
945
  */
935
946
  async _locateFields(locator) {
936
- return findFields.call(this, locator);
947
+ return findFields.call(this, locator)
937
948
  }
938
949
 
939
950
  /**
@@ -941,7 +952,7 @@ class Puppeteer extends Helper {
941
952
  *
942
953
  */
943
954
  async grabWebElements(locator) {
944
- return this._locate(locator);
955
+ return this._locate(locator)
945
956
  }
946
957
 
947
958
  /**
@@ -955,17 +966,17 @@ class Puppeteer extends Helper {
955
966
  * @param {number} [num=1]
956
967
  */
957
968
  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];
969
+ const pages = await this.browser.pages()
970
+ const index = pages.indexOf(this.page)
971
+ this.withinLocator = null
972
+ const page = pages[index + num]
962
973
 
963
974
  if (!page) {
964
- throw new Error(`There is no ability to switch to next tab with offset ${num}`);
975
+ throw new Error(`There is no ability to switch to next tab with offset ${num}`)
965
976
  }
966
977
 
967
- await this._setPage(page);
968
- return this._waitForAction();
978
+ await this._setPage(page)
979
+ return this._waitForAction()
969
980
  }
970
981
 
971
982
  /**
@@ -978,17 +989,17 @@ class Puppeteer extends Helper {
978
989
  * @param {number} [num=1]
979
990
  */
980
991
  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];
992
+ const pages = await this.browser.pages()
993
+ const index = pages.indexOf(this.page)
994
+ this.withinLocator = null
995
+ const page = pages[index - num]
985
996
 
986
997
  if (!page) {
987
- throw new Error(`There is no ability to switch to previous tab with offset ${num}`);
998
+ throw new Error(`There is no ability to switch to previous tab with offset ${num}`)
988
999
  }
989
1000
 
990
- await this._setPage(page);
991
- return this._waitForAction();
1001
+ await this._setPage(page)
1002
+ return this._waitForAction()
992
1003
  }
993
1004
 
994
1005
  /**
@@ -999,10 +1010,10 @@ class Puppeteer extends Helper {
999
1010
  * ```
1000
1011
  */
1001
1012
  async closeCurrentTab() {
1002
- const oldPage = this.page;
1003
- await this.switchToPreviousTab();
1004
- await oldPage.close();
1005
- return this._waitForAction();
1013
+ const oldPage = this.page
1014
+ await this.switchToPreviousTab()
1015
+ await oldPage.close()
1016
+ return this._waitForAction()
1006
1017
  }
1007
1018
 
1008
1019
  /**
@@ -1013,15 +1024,15 @@ class Puppeteer extends Helper {
1013
1024
  * ```
1014
1025
  */
1015
1026
  async closeOtherTabs() {
1016
- const pages = await this.browser.pages();
1017
- const otherPages = pages.filter(page => page !== this.page);
1027
+ const pages = await this.browser.pages()
1028
+ const otherPages = pages.filter((page) => page !== this.page)
1018
1029
 
1019
- let p = Promise.resolve();
1030
+ let p = Promise.resolve()
1020
1031
  otherPages.forEach((page) => {
1021
- p = p.then(() => page.close());
1022
- });
1023
- await p;
1024
- return this._waitForAction();
1032
+ p = p.then(() => page.close())
1033
+ })
1034
+ await p
1035
+ return this._waitForAction()
1025
1036
  }
1026
1037
 
1027
1038
  /**
@@ -1032,16 +1043,16 @@ class Puppeteer extends Helper {
1032
1043
  * ```
1033
1044
  */
1034
1045
  async openNewTab() {
1035
- await this._setPage(await this.browser.newPage());
1036
- return this._waitForAction();
1046
+ await this._setPage(await this.browser.newPage())
1047
+ return this._waitForAction()
1037
1048
  }
1038
1049
 
1039
1050
  /**
1040
1051
  * {{> grabNumberOfOpenTabs }}
1041
1052
  */
1042
1053
  async grabNumberOfOpenTabs() {
1043
- const pages = await this.browser.pages();
1044
- return pages.length;
1054
+ const pages = await this.browser.pages()
1055
+ return pages.length
1045
1056
  }
1046
1057
 
1047
1058
  /**
@@ -1049,14 +1060,22 @@ class Puppeteer extends Helper {
1049
1060
  * {{ react }}
1050
1061
  */
1051
1062
  async seeElement(locator) {
1052
- let els = await this._locate(locator);
1053
- els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1063
+ let els = await this._locate(locator)
1064
+ els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1054
1065
  // 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));
1066
+ els = await Promise.all(
1067
+ els.map(
1068
+ async (el) =>
1069
+ (await el.evaluate(
1070
+ (node) =>
1071
+ window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1072
+ )) && el,
1073
+ ),
1074
+ )
1056
1075
  try {
1057
- return empty('visible elements').negate(els.filter(v => v).fill('ELEMENT'));
1076
+ return empty('visible elements').negate(els.filter((v) => v).fill('ELEMENT'))
1058
1077
  } catch (e) {
1059
- dontSeeElementError(locator);
1078
+ dontSeeElementError(locator)
1060
1079
  }
1061
1080
  }
1062
1081
 
@@ -1065,14 +1084,22 @@ class Puppeteer extends Helper {
1065
1084
  * {{ react }}
1066
1085
  */
1067
1086
  async dontSeeElement(locator) {
1068
- let els = await this._locate(locator);
1069
- els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1087
+ let els = await this._locate(locator)
1088
+ els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1070
1089
  // 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));
1090
+ els = await Promise.all(
1091
+ els.map(
1092
+ async (el) =>
1093
+ (await el.evaluate(
1094
+ (node) =>
1095
+ window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1096
+ )) && el,
1097
+ ),
1098
+ )
1072
1099
  try {
1073
- return empty('visible elements').assert(els.filter(v => v).fill('ELEMENT'));
1100
+ return empty('visible elements').assert(els.filter((v) => v).fill('ELEMENT'))
1074
1101
  } catch (e) {
1075
- seeElementError(locator);
1102
+ seeElementError(locator)
1076
1103
  }
1077
1104
  }
1078
1105
 
@@ -1080,11 +1107,11 @@ class Puppeteer extends Helper {
1080
1107
  * {{> seeElementInDOM }}
1081
1108
  */
1082
1109
  async seeElementInDOM(locator) {
1083
- const els = await this._locate(locator);
1110
+ const els = await this._locate(locator)
1084
1111
  try {
1085
- return empty('elements on page').negate(els.filter(v => v).fill('ELEMENT'));
1112
+ return empty('elements on page').negate(els.filter((v) => v).fill('ELEMENT'))
1086
1113
  } catch (e) {
1087
- dontSeeElementInDOMError(locator);
1114
+ dontSeeElementInDOMError(locator)
1088
1115
  }
1089
1116
  }
1090
1117
 
@@ -1092,11 +1119,11 @@ class Puppeteer extends Helper {
1092
1119
  * {{> dontSeeElementInDOM }}
1093
1120
  */
1094
1121
  async dontSeeElementInDOM(locator) {
1095
- const els = await this._locate(locator);
1122
+ const els = await this._locate(locator)
1096
1123
  try {
1097
- return empty('elements on a page').assert(els.filter(v => v).fill('ELEMENT'));
1124
+ return empty('elements on a page').assert(els.filter((v) => v).fill('ELEMENT'))
1098
1125
  } catch (e) {
1099
- seeElementInDOMError(locator);
1126
+ seeElementInDOMError(locator)
1100
1127
  }
1101
1128
  }
1102
1129
 
@@ -1106,7 +1133,7 @@ class Puppeteer extends Helper {
1106
1133
  * {{ react }}
1107
1134
  */
1108
1135
  async click(locator, context = null) {
1109
- return proceedClick.call(this, locator, context);
1136
+ return proceedClick.call(this, locator, context)
1110
1137
  }
1111
1138
 
1112
1139
  /**
@@ -1115,28 +1142,33 @@ class Puppeteer extends Helper {
1115
1142
  * {{ react }}
1116
1143
  */
1117
1144
  async forceClick(locator, context = null) {
1118
- let matcher = await this.context;
1145
+ let matcher = await this.context
1119
1146
  if (context) {
1120
- const els = await this._locate(context);
1121
- assertElementExists(els, context);
1122
- matcher = els[0];
1147
+ const els = await this._locate(context)
1148
+ assertElementExists(els, context)
1149
+ matcher = els[0]
1123
1150
  }
1124
1151
 
1125
- const els = await findClickable.call(this, matcher, locator);
1152
+ const els = await findClickable.call(this, matcher, locator)
1126
1153
  if (context) {
1127
- assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
1154
+ assertElementExists(
1155
+ els,
1156
+ locator,
1157
+ 'Clickable element',
1158
+ `was not found inside element ${new Locator(context).toString()}`,
1159
+ )
1128
1160
  } else {
1129
- assertElementExists(els, locator, 'Clickable element');
1161
+ assertElementExists(els, locator, 'Clickable element')
1130
1162
  }
1131
- const elem = els[0];
1163
+ const elem = els[0]
1132
1164
  return this.executeScript((el) => {
1133
1165
  if (document.activeElement instanceof HTMLElement) {
1134
- document.activeElement.blur();
1166
+ document.activeElement.blur()
1135
1167
  }
1136
- const event = document.createEvent('MouseEvent');
1137
- event.initEvent('click', true, true);
1138
- return el.dispatchEvent(event);
1139
- }, elem);
1168
+ const event = document.createEvent('MouseEvent')
1169
+ event.initEvent('click', true, true)
1170
+ return el.dispatchEvent(event)
1171
+ }, elem)
1140
1172
  }
1141
1173
 
1142
1174
  /**
@@ -1145,7 +1177,7 @@ class Puppeteer extends Helper {
1145
1177
  * {{ react }}
1146
1178
  */
1147
1179
  async clickLink(locator, context = null) {
1148
- return proceedClick.call(this, locator, context, { waitForNavigation: true });
1180
+ return proceedClick.call(this, locator, context, { waitForNavigation: true })
1149
1181
  }
1150
1182
 
1151
1183
  /**
@@ -1166,16 +1198,16 @@ class Puppeteer extends Helper {
1166
1198
  * @param {string} [downloadPath='downloads'] change this parameter to set another directory for saving
1167
1199
  */
1168
1200
  async handleDownloads(downloadPath = 'downloads') {
1169
- downloadPath = path.join(global.output_dir, downloadPath);
1201
+ downloadPath = path.join(global.output_dir, downloadPath)
1170
1202
  if (!fs.existsSync(downloadPath)) {
1171
- fs.mkdirSync(downloadPath, '0777');
1203
+ fs.mkdirSync(downloadPath, '0777')
1172
1204
  }
1173
- fsExtra.emptyDirSync(downloadPath);
1205
+ fsExtra.emptyDirSync(downloadPath)
1174
1206
 
1175
1207
  try {
1176
- return this.page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath });
1208
+ return this.page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath })
1177
1209
  } catch (e) {
1178
- return this.page._client().send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath });
1210
+ return this.page._client().send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath })
1179
1211
  }
1180
1212
  }
1181
1213
 
@@ -1185,27 +1217,27 @@ class Puppeteer extends Helper {
1185
1217
  * Please use `handleDownloads()` instead.
1186
1218
  */
1187
1219
  async downloadFile(locator, customName) {
1188
- let fileName;
1189
- await this.page.setRequestInterception(true);
1220
+ let fileName
1221
+ await this.page.setRequestInterception(true)
1190
1222
 
1191
1223
  const xRequest = await new Promise((resolve) => {
1192
1224
  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);
1225
+ console.log('rq', request, customName)
1226
+ const grabbedFileName = request.url().split('/')[request.url().split('/').length - 1]
1227
+ const fileExtension = request.url().split('/')[request.url().split('/').length - 1].split('.')[1]
1228
+ console.log('nm', customName, fileExtension)
1197
1229
  if (customName && path.extname(customName) !== fileExtension) {
1198
- console.log('bypassing a request');
1199
- request.continue();
1200
- return;
1230
+ console.log('bypassing a request')
1231
+ request.continue()
1232
+ return
1201
1233
  }
1202
- customName ? fileName = `${customName}.${fileExtension}` : fileName = grabbedFileName;
1203
- request.abort();
1204
- resolve(request);
1205
- });
1206
- });
1234
+ customName ? (fileName = `${customName}.${fileExtension}`) : (fileName = grabbedFileName)
1235
+ request.abort()
1236
+ resolve(request)
1237
+ })
1238
+ })
1207
1239
 
1208
- await this.click(locator);
1240
+ await this.click(locator)
1209
1241
 
1210
1242
  const options = {
1211
1243
  encoding: null,
@@ -1213,10 +1245,10 @@ class Puppeteer extends Helper {
1213
1245
  uri: xRequest._url,
1214
1246
  body: xRequest._postData,
1215
1247
  headers: xRequest._headers,
1216
- };
1248
+ }
1217
1249
 
1218
- const cookies = await this.page.cookies();
1219
- options.headers.Cookie = cookies.map(ck => `${ck.name}=${ck.value}`).join(';');
1250
+ const cookies = await this.page.cookies()
1251
+ options.headers.Cookie = cookies.map((ck) => `${ck.name}=${ck.value}`).join(';')
1220
1252
 
1221
1253
  const response = await axios({
1222
1254
  method: options.method,
@@ -1224,24 +1256,26 @@ class Puppeteer extends Helper {
1224
1256
  headers: options.headers,
1225
1257
  responseType: 'arraybuffer',
1226
1258
  onDownloadProgress(e) {
1227
- console.log('+', e);
1259
+ console.log('+', e)
1228
1260
  },
1229
- });
1261
+ })
1230
1262
 
1231
- const outputFile = path.join(`${global.output_dir}/${fileName}`);
1263
+ const outputFile = path.join(`${global.output_dir}/${fileName}`)
1232
1264
 
1233
1265
  try {
1234
1266
  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
- });
1267
+ const wstream = fs.createWriteStream(outputFile)
1268
+ console.log(response)
1269
+ wstream.write(response.data)
1270
+ wstream.end()
1271
+ this.debug(`File is downloaded in ${outputFile}`)
1272
+ wstream.on('finish', () => {
1273
+ resolve(fileName)
1274
+ })
1275
+ wstream.on('error', reject)
1276
+ })
1243
1277
  } catch (error) {
1244
- throw new Error(`There is something wrong with downloaded file. ${error}`);
1278
+ throw new Error(`There is something wrong with downloaded file. ${error}`)
1245
1279
  }
1246
1280
  }
1247
1281
 
@@ -1251,7 +1285,7 @@ class Puppeteer extends Helper {
1251
1285
  * {{ react }}
1252
1286
  */
1253
1287
  async doubleClick(locator, context = null) {
1254
- return proceedClick.call(this, locator, context, { clickCount: 2 });
1288
+ return proceedClick.call(this, locator, context, { clickCount: 2 })
1255
1289
  }
1256
1290
 
1257
1291
  /**
@@ -1260,20 +1294,19 @@ class Puppeteer extends Helper {
1260
1294
  * {{ react }}
1261
1295
  */
1262
1296
  async rightClick(locator, context = null) {
1263
- return proceedClick.call(this, locator, context, { button: 'right' });
1297
+ return proceedClick.call(this, locator, context, { button: 'right' })
1264
1298
  }
1265
1299
 
1266
1300
  /**
1267
1301
  * {{> checkOption }}
1268
1302
  */
1269
1303
  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());
1304
+ const elm = await this._locateCheckable(field, context)
1305
+ const curentlyChecked = await elm.getProperty('checked').then((checkedProperty) => checkedProperty.jsonValue())
1273
1306
  // Only check if NOT currently checked
1274
1307
  if (!curentlyChecked) {
1275
- await elm.click();
1276
- return this._waitForAction();
1308
+ await elm.click()
1309
+ return this._waitForAction()
1277
1310
  }
1278
1311
  }
1279
1312
 
@@ -1281,13 +1314,12 @@ class Puppeteer extends Helper {
1281
1314
  * {{> uncheckOption }}
1282
1315
  */
1283
1316
  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());
1317
+ const elm = await this._locateCheckable(field, context)
1318
+ const curentlyChecked = await elm.getProperty('checked').then((checkedProperty) => checkedProperty.jsonValue())
1287
1319
  // Only uncheck if currently checked
1288
1320
  if (curentlyChecked) {
1289
- await elm.click();
1290
- return this._waitForAction();
1321
+ await elm.click()
1322
+ return this._waitForAction()
1291
1323
  }
1292
1324
  }
1293
1325
 
@@ -1295,32 +1327,32 @@ class Puppeteer extends Helper {
1295
1327
  * {{> seeCheckboxIsChecked }}
1296
1328
  */
1297
1329
  async seeCheckboxIsChecked(field) {
1298
- return proceedIsChecked.call(this, 'assert', field);
1330
+ return proceedIsChecked.call(this, 'assert', field)
1299
1331
  }
1300
1332
 
1301
1333
  /**
1302
1334
  * {{> dontSeeCheckboxIsChecked }}
1303
1335
  */
1304
1336
  async dontSeeCheckboxIsChecked(field) {
1305
- return proceedIsChecked.call(this, 'negate', field);
1337
+ return proceedIsChecked.call(this, 'negate', field)
1306
1338
  }
1307
1339
 
1308
1340
  /**
1309
1341
  * {{> pressKeyDown }}
1310
1342
  */
1311
1343
  async pressKeyDown(key) {
1312
- key = getNormalizedKey.call(this, key);
1313
- await this.page.keyboard.down(key);
1314
- return this._waitForAction();
1344
+ key = getNormalizedKey.call(this, key)
1345
+ await this.page.keyboard.down(key)
1346
+ return this._waitForAction()
1315
1347
  }
1316
1348
 
1317
1349
  /**
1318
1350
  * {{> pressKeyUp }}
1319
1351
  */
1320
1352
  async pressKeyUp(key) {
1321
- key = getNormalizedKey.call(this, key);
1322
- await this.page.keyboard.up(key);
1323
- return this._waitForAction();
1353
+ key = getNormalizedKey.call(this, key)
1354
+ await this.page.keyboard.up(key)
1355
+ return this._waitForAction()
1324
1356
  }
1325
1357
 
1326
1358
  /**
@@ -1329,28 +1361,28 @@ class Puppeteer extends Helper {
1329
1361
  * {{> pressKeyWithKeyNormalization }}
1330
1362
  */
1331
1363
  async pressKey(key) {
1332
- const modifiers = [];
1364
+ const modifiers = []
1333
1365
  if (Array.isArray(key)) {
1334
1366
  for (let k of key) {
1335
- k = getNormalizedKey.call(this, k);
1367
+ k = getNormalizedKey.call(this, k)
1336
1368
  if (isModifierKey(k)) {
1337
- modifiers.push(k);
1369
+ modifiers.push(k)
1338
1370
  } else {
1339
- key = k;
1340
- break;
1371
+ key = k
1372
+ break
1341
1373
  }
1342
1374
  }
1343
1375
  } else {
1344
- key = getNormalizedKey.call(this, key);
1376
+ key = getNormalizedKey.call(this, key)
1345
1377
  }
1346
1378
  for (const modifier of modifiers) {
1347
- await this.page.keyboard.down(modifier);
1379
+ await this.page.keyboard.down(modifier)
1348
1380
  }
1349
- await this.page.keyboard.press(key);
1381
+ await this.page.keyboard.press(key)
1350
1382
  for (const modifier of modifiers) {
1351
- await this.page.keyboard.up(modifier);
1383
+ await this.page.keyboard.up(modifier)
1352
1384
  }
1353
- return this._waitForAction();
1385
+ return this._waitForAction()
1354
1386
  }
1355
1387
 
1356
1388
  /**
@@ -1358,13 +1390,13 @@ class Puppeteer extends Helper {
1358
1390
  */
1359
1391
  async type(keys, delay = null) {
1360
1392
  if (!Array.isArray(keys)) {
1361
- keys = keys.toString();
1362
- keys = keys.split('');
1393
+ keys = keys.toString()
1394
+ keys = keys.split('')
1363
1395
  }
1364
1396
 
1365
1397
  for (const key of keys) {
1366
- await this.page.keyboard.press(key);
1367
- if (delay) await this.wait(delay / 1000);
1398
+ await this.page.keyboard.press(key)
1399
+ if (delay) await this.wait(delay / 1000)
1368
1400
  }
1369
1401
  }
1370
1402
 
@@ -1373,28 +1405,28 @@ class Puppeteer extends Helper {
1373
1405
  * {{ react }}
1374
1406
  */
1375
1407
  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());
1408
+ const els = await findVisibleFields.call(this, field)
1409
+ assertElementExists(els, field, 'Field')
1410
+ const el = els[0]
1411
+ const tag = await el.getProperty('tagName').then((el) => el.jsonValue())
1412
+ const editable = await el.getProperty('contenteditable').then((el) => el.jsonValue())
1381
1413
  if (tag === 'INPUT' || tag === 'TEXTAREA') {
1382
- await this._evaluateHandeInContext(el => el.value = '', el);
1414
+ await this._evaluateHandeInContext((el) => (el.value = ''), el)
1383
1415
  } else if (editable) {
1384
- await this._evaluateHandeInContext(el => el.innerHTML = '', el);
1416
+ await this._evaluateHandeInContext((el) => (el.innerHTML = ''), el)
1385
1417
  }
1386
1418
 
1387
- highlightActiveElement.call(this, el, await this._getContext());
1388
- await el.type(value.toString(), { delay: this.options.pressKeyDelay });
1419
+ highlightActiveElement.call(this, el, await this._getContext())
1420
+ await el.type(value.toString(), { delay: this.options.pressKeyDelay })
1389
1421
 
1390
- return this._waitForAction();
1422
+ return this._waitForAction()
1391
1423
  }
1392
1424
 
1393
1425
  /**
1394
1426
  * {{> clearField }}
1395
1427
  */
1396
1428
  async clearField(field) {
1397
- return this.fillField(field, '');
1429
+ return this.fillField(field, '')
1398
1430
  }
1399
1431
 
1400
1432
  /**
@@ -1403,28 +1435,28 @@ class Puppeteer extends Helper {
1403
1435
  * {{ react }}
1404
1436
  */
1405
1437
  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();
1438
+ const els = await findVisibleFields.call(this, field)
1439
+ assertElementExists(els, field, 'Field')
1440
+ highlightActiveElement.call(this, els[0], await this._getContext())
1441
+ await els[0].press('End')
1442
+ await els[0].type(value.toString(), { delay: this.options.pressKeyDelay })
1443
+ return this._waitForAction()
1412
1444
  }
1413
1445
 
1414
1446
  /**
1415
1447
  * {{> seeInField }}
1416
1448
  */
1417
1449
  async seeInField(field, value) {
1418
- const _value = (typeof value === 'boolean') ? value : value.toString();
1419
- return proceedSeeInField.call(this, 'assert', field, _value);
1450
+ const _value = typeof value === 'boolean' ? value : value.toString()
1451
+ return proceedSeeInField.call(this, 'assert', field, _value)
1420
1452
  }
1421
1453
 
1422
1454
  /**
1423
1455
  * {{> dontSeeInField }}
1424
1456
  */
1425
1457
  async dontSeeInField(field, value) {
1426
- const _value = (typeof value === 'boolean') ? value : value.toString();
1427
- return proceedSeeInField.call(this, 'negate', field, _value);
1458
+ const _value = typeof value === 'boolean' ? value : value.toString()
1459
+ return proceedSeeInField.call(this, 'negate', field, _value)
1428
1460
  }
1429
1461
 
1430
1462
  /**
@@ -1433,48 +1465,48 @@ class Puppeteer extends Helper {
1433
1465
  * {{> attachFile }}
1434
1466
  */
1435
1467
  async attachFile(locator, pathToFile) {
1436
- const file = path.join(global.codecept_dir, pathToFile);
1468
+ const file = path.join(global.codecept_dir, pathToFile)
1437
1469
 
1438
1470
  if (!fileExists(file)) {
1439
- throw new Error(`File at ${file} can not be found on local system`);
1471
+ throw new Error(`File at ${file} can not be found on local system`)
1440
1472
  }
1441
- const els = await findFields.call(this, locator);
1442
- assertElementExists(els, locator, 'Field');
1443
- await els[0].uploadFile(file);
1444
- return this._waitForAction();
1473
+ const els = await findFields.call(this, locator)
1474
+ assertElementExists(els, locator, 'Field')
1475
+ await els[0].uploadFile(file)
1476
+ return this._waitForAction()
1445
1477
  }
1446
1478
 
1447
1479
  /**
1448
1480
  * {{> selectOption }}
1449
1481
  */
1450
1482
  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>');
1483
+ const els = await findVisibleFields.call(this, select)
1484
+ assertElementExists(els, select, 'Selectable field')
1485
+ const el = els[0]
1486
+ if ((await el.getProperty('tagName').then((t) => t.jsonValue())) !== 'SELECT') {
1487
+ throw new Error('Element is not <select>')
1456
1488
  }
1457
- highlightActiveElement.call(this, els[0], await this._getContext());
1458
- if (!Array.isArray(option)) option = [option];
1489
+ highlightActiveElement.call(this, els[0], await this._getContext())
1490
+ if (!Array.isArray(option)) option = [option]
1459
1491
 
1460
1492
  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) });
1493
+ const opt = xpathLocator.literal(option[key])
1494
+ let optEl = await findElements.call(this, el, { xpath: Locator.select.byVisibleText(opt) })
1463
1495
  if (optEl.length) {
1464
- this._evaluateHandeInContext(el => el.selected = true, optEl[0]);
1465
- continue;
1496
+ this._evaluateHandeInContext((el) => (el.selected = true), optEl[0])
1497
+ continue
1466
1498
  }
1467
- optEl = await findElements.call(this, el, { xpath: Locator.select.byValue(opt) });
1499
+ optEl = await findElements.call(this, el, { xpath: Locator.select.byValue(opt) })
1468
1500
  if (optEl.length) {
1469
- this._evaluateHandeInContext(el => el.selected = true, optEl[0]);
1501
+ this._evaluateHandeInContext((el) => (el.selected = true), optEl[0])
1470
1502
  }
1471
1503
  }
1472
1504
  await this._evaluateHandeInContext((element) => {
1473
- element.dispatchEvent(new Event('input', { bubbles: true }));
1474
- element.dispatchEvent(new Event('change', { bubbles: true }));
1475
- }, el);
1505
+ element.dispatchEvent(new Event('input', { bubbles: true }))
1506
+ element.dispatchEvent(new Event('change', { bubbles: true }))
1507
+ }, el)
1476
1508
 
1477
- return this._waitForAction();
1509
+ return this._waitForAction()
1478
1510
  }
1479
1511
 
1480
1512
  /**
@@ -1482,40 +1514,48 @@ class Puppeteer extends Helper {
1482
1514
  * {{ react }}
1483
1515
  */
1484
1516
  async grabNumberOfVisibleElements(locator) {
1485
- let els = await this._locate(locator);
1486
- els = (await Promise.all(els.map(el => el.boundingBox() && el))).filter(v => v);
1517
+ let els = await this._locate(locator)
1518
+ els = (await Promise.all(els.map((el) => el.boundingBox() && el))).filter((v) => v)
1487
1519
  // 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));
1520
+ els = await Promise.all(
1521
+ els.map(
1522
+ async (el) =>
1523
+ (await el.evaluate(
1524
+ (node) =>
1525
+ window.getComputedStyle(node).visibility !== 'hidden' && window.getComputedStyle(node).display !== 'none',
1526
+ )) && el,
1527
+ ),
1528
+ )
1489
1529
 
1490
- return els.filter(v => v).length;
1530
+ return els.filter((v) => v).length
1491
1531
  }
1492
1532
 
1493
1533
  /**
1494
1534
  * {{> seeInCurrentUrl }}
1495
1535
  */
1496
1536
  async seeInCurrentUrl(url) {
1497
- stringIncludes('url').assert(url, await this._getPageUrl());
1537
+ stringIncludes('url').assert(url, await this._getPageUrl())
1498
1538
  }
1499
1539
 
1500
1540
  /**
1501
1541
  * {{> dontSeeInCurrentUrl }}
1502
1542
  */
1503
1543
  async dontSeeInCurrentUrl(url) {
1504
- stringIncludes('url').negate(url, await this._getPageUrl());
1544
+ stringIncludes('url').negate(url, await this._getPageUrl())
1505
1545
  }
1506
1546
 
1507
1547
  /**
1508
1548
  * {{> seeCurrentUrlEquals }}
1509
1549
  */
1510
1550
  async seeCurrentUrlEquals(url) {
1511
- urlEquals(this.options.url).assert(url, await this._getPageUrl());
1551
+ urlEquals(this.options.url).assert(url, await this._getPageUrl())
1512
1552
  }
1513
1553
 
1514
1554
  /**
1515
1555
  * {{> dontSeeCurrentUrlEquals }}
1516
1556
  */
1517
1557
  async dontSeeCurrentUrlEquals(url) {
1518
- urlEquals(this.options.url).negate(url, await this._getPageUrl());
1558
+ urlEquals(this.options.url).negate(url, await this._getPageUrl())
1519
1559
  }
1520
1560
 
1521
1561
  /**
@@ -1524,14 +1564,14 @@ class Puppeteer extends Helper {
1524
1564
  * {{ react }}
1525
1565
  */
1526
1566
  async see(text, context = null) {
1527
- return proceedSee.call(this, 'assert', text, context);
1567
+ return proceedSee.call(this, 'assert', text, context)
1528
1568
  }
1529
1569
 
1530
1570
  /**
1531
1571
  * {{> seeTextEquals }}
1532
1572
  */
1533
1573
  async seeTextEquals(text, context = null) {
1534
- return proceedSee.call(this, 'assert', text, context, true);
1574
+ return proceedSee.call(this, 'assert', text, context, true)
1535
1575
  }
1536
1576
 
1537
1577
  /**
@@ -1540,14 +1580,14 @@ class Puppeteer extends Helper {
1540
1580
  * {{ react }}
1541
1581
  */
1542
1582
  async dontSee(text, context = null) {
1543
- return proceedSee.call(this, 'negate', text, context);
1583
+ return proceedSee.call(this, 'negate', text, context)
1544
1584
  }
1545
1585
 
1546
1586
  /**
1547
1587
  * {{> grabSource }}
1548
1588
  */
1549
1589
  async grabSource() {
1550
- return this.page.content();
1590
+ return this.page.content()
1551
1591
  }
1552
1592
 
1553
1593
  /**
@@ -1560,32 +1600,32 @@ class Puppeteer extends Helper {
1560
1600
  * @return {Promise<any[]>}
1561
1601
  */
1562
1602
  async grabBrowserLogs() {
1563
- const logs = consoleLogStore.entries;
1564
- consoleLogStore.clear();
1565
- return logs;
1603
+ const logs = consoleLogStore.entries
1604
+ consoleLogStore.clear()
1605
+ return logs
1566
1606
  }
1567
1607
 
1568
1608
  /**
1569
1609
  * {{> grabCurrentUrl }}
1570
1610
  */
1571
1611
  async grabCurrentUrl() {
1572
- return this._getPageUrl();
1612
+ return this._getPageUrl()
1573
1613
  }
1574
1614
 
1575
1615
  /**
1576
1616
  * {{> seeInSource }}
1577
1617
  */
1578
1618
  async seeInSource(text) {
1579
- const source = await this.page.content();
1580
- stringIncludes('HTML source of a page').assert(text, source);
1619
+ const source = await this.page.content()
1620
+ stringIncludes('HTML source of a page').assert(text, source)
1581
1621
  }
1582
1622
 
1583
1623
  /**
1584
1624
  * {{> dontSeeInSource }}
1585
1625
  */
1586
1626
  async dontSeeInSource(text) {
1587
- const source = await this.page.content();
1588
- stringIncludes('HTML source of a page').negate(text, source);
1627
+ const source = await this.page.content()
1628
+ stringIncludes('HTML source of a page').negate(text, source)
1589
1629
  }
1590
1630
 
1591
1631
  /**
@@ -1594,8 +1634,10 @@ class Puppeteer extends Helper {
1594
1634
  * {{ react }}
1595
1635
  */
1596
1636
  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);
1637
+ const elements = await this._locate(locator)
1638
+ return equals(
1639
+ `expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`,
1640
+ ).assert(elements.length, num)
1599
1641
  }
1600
1642
 
1601
1643
  /**
@@ -1604,8 +1646,11 @@ class Puppeteer extends Helper {
1604
1646
  * {{ react }}
1605
1647
  */
1606
1648
  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);
1649
+ const res = await this.grabNumberOfVisibleElements(locator)
1650
+ return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(
1651
+ res,
1652
+ num,
1653
+ )
1609
1654
  }
1610
1655
 
1611
1656
  /**
@@ -1613,9 +1658,9 @@ class Puppeteer extends Helper {
1613
1658
  */
1614
1659
  async setCookie(cookie) {
1615
1660
  if (Array.isArray(cookie)) {
1616
- return this.page.setCookie(...cookie);
1661
+ return this.page.setCookie(...cookie)
1617
1662
  }
1618
- return this.page.setCookie(cookie);
1663
+ return this.page.setCookie(cookie)
1619
1664
  }
1620
1665
 
1621
1666
  /**
@@ -1623,16 +1668,16 @@ class Puppeteer extends Helper {
1623
1668
  *
1624
1669
  */
1625
1670
  async seeCookie(name) {
1626
- const cookies = await this.page.cookies();
1627
- empty(`cookie ${name} to be set`).negate(cookies.filter(c => c.name === name));
1671
+ const cookies = await this.page.cookies()
1672
+ empty(`cookie ${name} to be set`).negate(cookies.filter((c) => c.name === name))
1628
1673
  }
1629
1674
 
1630
1675
  /**
1631
1676
  * {{> dontSeeCookie }}
1632
1677
  */
1633
1678
  async dontSeeCookie(name) {
1634
- const cookies = await this.page.cookies();
1635
- empty(`cookie ${name} to be set`).assert(cookies.filter(c => c.name === name));
1679
+ const cookies = await this.page.cookies()
1680
+ empty(`cookie ${name} not to be set`).assert(cookies.filter((c) => c.name === name))
1636
1681
  }
1637
1682
 
1638
1683
  /**
@@ -1641,10 +1686,10 @@ class Puppeteer extends Helper {
1641
1686
  * Returns cookie in JSON format. If name not passed returns all cookies for this domain.
1642
1687
  */
1643
1688
  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];
1689
+ const cookies = await this.page.cookies()
1690
+ if (!name) return cookies
1691
+ const cookie = cookies.filter((c) => c.name === name)
1692
+ if (cookie[0]) return cookie[0]
1648
1693
  }
1649
1694
 
1650
1695
  /**
@@ -1652,44 +1697,47 @@ class Puppeteer extends Helper {
1652
1697
  */
1653
1698
  async waitForCookie(name, sec) {
1654
1699
  // by default, we will retry 3 times
1655
- let retries = 3;
1656
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1700
+ let retries = 3
1701
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1657
1702
 
1658
1703
  if (sec) {
1659
- retries = sec;
1704
+ retries = sec
1660
1705
  } else {
1661
- retries = Math.ceil(waitTimeout / 1000) - 1;
1706
+ retries = Math.ceil(waitTimeout / 1000) - 1
1662
1707
  }
1663
1708
 
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
- };
1709
+ return promiseRetry(
1710
+ async (retry, number) => {
1711
+ const _grabCookie = async (name) => {
1712
+ const cookies = await this.page.cookies()
1713
+ const cookie = cookies.filter((c) => c.name === name)
1714
+ if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
1715
+ }
1670
1716
 
1671
- this.debugSection('Wait for cookie: ', name);
1672
- if (number > 1) this.debugSection('Retrying... Attempt #', number);
1717
+ this.debugSection('Wait for cookie: ', name)
1718
+ if (number > 1) this.debugSection('Retrying... Attempt #', number)
1673
1719
 
1674
- try {
1675
- await _grabCookie(name);
1676
- } catch (e) {
1677
- retry(e);
1678
- }
1679
- }, { retries, maxTimeout: 1000 });
1720
+ try {
1721
+ await _grabCookie(name)
1722
+ } catch (e) {
1723
+ retry(e)
1724
+ }
1725
+ },
1726
+ { retries, maxTimeout: 1000 },
1727
+ )
1680
1728
  }
1681
1729
 
1682
1730
  /**
1683
1731
  * {{> clearCookie }}
1684
1732
  */
1685
1733
  async clearCookie(name) {
1686
- const cookies = await this.page.cookies();
1734
+ const cookies = await this.page.cookies()
1687
1735
  if (!name) {
1688
- return this.page.deleteCookie.apply(this.page, cookies);
1736
+ return this.page.deleteCookie.apply(this.page, cookies)
1689
1737
  }
1690
- const cookie = cookies.filter(c => c.name === name);
1691
- if (!cookie[0]) return;
1692
- return this.page.deleteCookie(cookie[0]);
1738
+ const cookie = cookies.filter((c) => c.name === name)
1739
+ if (!cookie[0]) return
1740
+ return this.page.deleteCookie(cookie[0])
1693
1741
  }
1694
1742
 
1695
1743
  /**
@@ -1698,11 +1746,11 @@ class Puppeteer extends Helper {
1698
1746
  * {{> executeScript }}
1699
1747
  */
1700
1748
  async executeScript(...args) {
1701
- let context = await this._getContext();
1749
+ let context = await this._getContext()
1702
1750
  if (this.context && this.context.constructor.name === 'CdpFrame') {
1703
- context = this.context; // switching to iframe context
1751
+ context = this.context // switching to iframe context
1704
1752
  }
1705
- return context.evaluate.apply(context, args);
1753
+ return context.evaluate.apply(context, args)
1706
1754
  }
1707
1755
 
1708
1756
  /**
@@ -1711,16 +1759,16 @@ class Puppeteer extends Helper {
1711
1759
  */
1712
1760
  async executeAsyncScript(...args) {
1713
1761
  const asyncFn = function () {
1714
- const args = Array.from(arguments);
1715
- const fn = eval(`(${args.shift()})`); // eslint-disable-line no-eval
1762
+ const args = Array.from(arguments)
1763
+ const fn = eval(`(${args.shift()})`) // eslint-disable-line no-eval
1716
1764
  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);
1765
+ args.push(done)
1766
+ fn.apply(null, args)
1767
+ })
1768
+ }
1769
+ args[0] = args[0].toString()
1770
+ args.unshift(asyncFn)
1771
+ return this.page.evaluate.apply(this.page, args)
1724
1772
  }
1725
1773
 
1726
1774
  /**
@@ -1728,12 +1776,12 @@ class Puppeteer extends Helper {
1728
1776
  * {{ react }}
1729
1777
  */
1730
1778
  async grabTextFromAll(locator) {
1731
- const els = await this._locate(locator);
1732
- const texts = [];
1779
+ const els = await this._locate(locator)
1780
+ const texts = []
1733
1781
  for (const el of els) {
1734
- texts.push(await (await el.getProperty('innerText')).jsonValue());
1782
+ texts.push(await (await el.getProperty('innerText')).jsonValue())
1735
1783
  }
1736
- return texts;
1784
+ return texts
1737
1785
  }
1738
1786
 
1739
1787
  /**
@@ -1741,60 +1789,60 @@ class Puppeteer extends Helper {
1741
1789
  * {{ react }}
1742
1790
  */
1743
1791
  async grabTextFrom(locator) {
1744
- const texts = await this.grabTextFromAll(locator);
1745
- assertElementExists(texts, locator);
1792
+ const texts = await this.grabTextFromAll(locator)
1793
+ assertElementExists(texts, locator)
1746
1794
  if (texts.length > 1) {
1747
- this.debugSection('GrabText', `Using first element out of ${texts.length}`);
1795
+ this.debugSection('GrabText', `Using first element out of ${texts.length}`)
1748
1796
  }
1749
1797
 
1750
- return texts[0];
1798
+ return texts[0]
1751
1799
  }
1752
1800
 
1753
1801
  /**
1754
1802
  * {{> grabValueFromAll }}
1755
1803
  */
1756
1804
  async grabValueFromAll(locator) {
1757
- const els = await findFields.call(this, locator);
1758
- const values = [];
1805
+ const els = await findFields.call(this, locator)
1806
+ const values = []
1759
1807
  for (const el of els) {
1760
- values.push(await (await el.getProperty('value')).jsonValue());
1808
+ values.push(await (await el.getProperty('value')).jsonValue())
1761
1809
  }
1762
- return values;
1810
+ return values
1763
1811
  }
1764
1812
 
1765
1813
  /**
1766
1814
  * {{> grabValueFrom }}
1767
1815
  */
1768
1816
  async grabValueFrom(locator) {
1769
- const values = await this.grabValueFromAll(locator);
1770
- assertElementExists(values, locator);
1817
+ const values = await this.grabValueFromAll(locator)
1818
+ assertElementExists(values, locator)
1771
1819
  if (values.length > 1) {
1772
- this.debugSection('GrabValue', `Using first element out of ${values.length}`);
1820
+ this.debugSection('GrabValue', `Using first element out of ${values.length}`)
1773
1821
  }
1774
1822
 
1775
- return values[0];
1823
+ return values[0]
1776
1824
  }
1777
1825
 
1778
1826
  /**
1779
1827
  * {{> grabHTMLFromAll }}
1780
1828
  */
1781
1829
  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;
1830
+ const els = await this._locate(locator)
1831
+ const values = await Promise.all(els.map((el) => el.evaluate((element) => element.innerHTML, el)))
1832
+ return values
1785
1833
  }
1786
1834
 
1787
1835
  /**
1788
1836
  * {{> grabHTMLFrom }}
1789
1837
  */
1790
1838
  async grabHTMLFrom(locator) {
1791
- const html = await this.grabHTMLFromAll(locator);
1792
- assertElementExists(html, locator);
1839
+ const html = await this.grabHTMLFromAll(locator)
1840
+ assertElementExists(html, locator)
1793
1841
  if (html.length > 1) {
1794
- this.debugSection('GrabHTML', `Using first element out of ${html.length}`);
1842
+ this.debugSection('GrabHTML', `Using first element out of ${html.length}`)
1795
1843
  }
1796
1844
 
1797
- return html[0];
1845
+ return html[0]
1798
1846
  }
1799
1847
 
1800
1848
  /**
@@ -1802,11 +1850,13 @@ class Puppeteer extends Helper {
1802
1850
  * {{ react }}
1803
1851
  */
1804
1852
  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)]);
1853
+ const els = await this._locate(locator)
1854
+ const res = await Promise.all(
1855
+ els.map((el) => el.evaluate((el) => JSON.parse(JSON.stringify(getComputedStyle(el))), el)),
1856
+ )
1857
+ const cssValues = res.map((props) => props[toCamelCase(cssProperty)])
1808
1858
 
1809
- return cssValues;
1859
+ return cssValues
1810
1860
  }
1811
1861
 
1812
1862
  /**
@@ -1814,14 +1864,14 @@ class Puppeteer extends Helper {
1814
1864
  * {{ react }}
1815
1865
  */
1816
1866
  async grabCssPropertyFrom(locator, cssProperty) {
1817
- const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty);
1818
- assertElementExists(cssValues, locator);
1867
+ const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
1868
+ assertElementExists(cssValues, locator)
1819
1869
 
1820
1870
  if (cssValues.length > 1) {
1821
- this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`);
1871
+ this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`)
1822
1872
  }
1823
1873
 
1824
- return cssValues[0];
1874
+ return cssValues[0]
1825
1875
  }
1826
1876
 
1827
1877
  /**
@@ -1829,35 +1879,37 @@ class Puppeteer extends Helper {
1829
1879
  * {{ react }}
1830
1880
  */
1831
1881
  async seeCssPropertiesOnElements(locator, cssProperties) {
1832
- const res = await this._locate(locator);
1833
- assertElementExists(res, locator);
1882
+ const res = await this._locate(locator)
1883
+ assertElementExists(res, locator)
1834
1884
 
1835
- const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
1836
- const elemAmount = res.length;
1837
- let props = [];
1885
+ const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties)
1886
+ const elemAmount = res.length
1887
+ let props = []
1838
1888
 
1839
1889
  for (const element of res) {
1840
1890
  for (const prop of Object.keys(cssProperties)) {
1841
- const cssProp = await this.grabCssPropertyFrom(locator, prop);
1891
+ const cssProp = await this.grabCssPropertyFrom(locator, prop)
1842
1892
  if (isColorProperty(prop)) {
1843
- props.push(convertColorToRGBA(cssProp));
1893
+ props.push(convertColorToRGBA(cssProp))
1844
1894
  } else {
1845
- props.push(cssProp);
1895
+ props.push(cssProp)
1846
1896
  }
1847
1897
  }
1848
1898
  }
1849
1899
 
1850
- const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
1851
- if (!Array.isArray(props)) props = [props];
1852
- let chunked = chunkArray(props, values.length);
1900
+ const values = Object.keys(cssPropertiesCamelCase).map((key) => cssPropertiesCamelCase[key])
1901
+ if (!Array.isArray(props)) props = [props]
1902
+ let chunked = chunkArray(props, values.length)
1853
1903
  chunked = chunked.filter((val) => {
1854
1904
  for (let i = 0; i < val.length; ++i) {
1855
1905
  // eslint-disable-next-line eqeqeq
1856
- if (val[i] != values[i]) return false;
1906
+ if (val[i] != values[i]) return false
1857
1907
  }
1858
- return true;
1859
- });
1860
- return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
1908
+ return true
1909
+ })
1910
+ return equals(
1911
+ `all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
1912
+ ).assert(chunked.length, elemAmount)
1861
1913
  }
1862
1914
 
1863
1915
  /**
@@ -1865,34 +1917,40 @@ class Puppeteer extends Helper {
1865
1917
  * {{ react }}
1866
1918
  */
1867
1919
  async seeAttributesOnElements(locator, attributes) {
1868
- const elements = await this._locate(locator);
1869
- assertElementExists(elements, locator);
1920
+ const elements = await this._locate(locator)
1921
+ assertElementExists(elements, locator)
1870
1922
 
1871
- const expectedAttributes = Object.entries(attributes);
1923
+ const expectedAttributes = Object.entries(attributes)
1872
1924
 
1873
1925
  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
- });
1926
+ const elementAttributes = {}
1927
+ await Promise.all(
1928
+ expectedAttributes.map(async ([attribute, expectedValue]) => {
1929
+ const actualValue = await element.evaluate((el, attr) => el[attr] || el.getAttribute(attr), attribute)
1930
+ elementAttributes[attribute] = actualValue
1931
+ }),
1932
+ )
1933
+ return elementAttributes
1934
+ })
1881
1935
 
1882
- const actualAttributes = await Promise.all(valuesPromises);
1936
+ const actualAttributes = await Promise.all(valuesPromises)
1883
1937
 
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
- }));
1938
+ const matchingElements = actualAttributes.filter((attrs) =>
1939
+ expectedAttributes.every(([attribute, expectedValue]) => {
1940
+ const actualValue = attrs[attribute]
1941
+ if (!actualValue) return false
1942
+ if (actualValue.toString().match(new RegExp(expectedValue.toString()))) return true
1943
+ return expectedValue === actualValue
1944
+ }),
1945
+ )
1890
1946
 
1891
- const elementsCount = elements.length;
1892
- const matchingCount = matchingElements.length;
1947
+ const elementsCount = elements.length
1948
+ const matchingCount = matchingElements.length
1893
1949
 
1894
- return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`)
1895
- .assert(matchingCount, elementsCount);
1950
+ return equals(`all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`).assert(
1951
+ matchingCount,
1952
+ elementsCount,
1953
+ )
1896
1954
  }
1897
1955
 
1898
1956
  /**
@@ -1900,21 +1958,21 @@ class Puppeteer extends Helper {
1900
1958
  * {{ react }}
1901
1959
  */
1902
1960
  async dragSlider(locator, offsetX = 0) {
1903
- const src = await this._locate(locator);
1904
- assertElementExists(src, locator, 'Slider Element');
1961
+ const src = await this._locate(locator)
1962
+ assertElementExists(src, locator, 'Slider Element')
1905
1963
 
1906
1964
  // Note: Using public api .getClickablePoint because the .BoundingBox does not take into account iframe offsets
1907
- const sliderSource = await getClickablePoint(src[0]);
1965
+ const sliderSource = await getClickablePoint(src[0])
1908
1966
 
1909
1967
  // Drag start point
1910
- await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 });
1911
- await this.page.mouse.down();
1968
+ await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 })
1969
+ await this.page.mouse.down()
1912
1970
 
1913
1971
  // Drag destination
1914
- await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 });
1915
- await this.page.mouse.up();
1972
+ await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 })
1973
+ await this.page.mouse.up()
1916
1974
 
1917
- await this._waitForAction();
1975
+ await this._waitForAction()
1918
1976
  }
1919
1977
 
1920
1978
  /**
@@ -1922,13 +1980,13 @@ class Puppeteer extends Helper {
1922
1980
  * {{ react }}
1923
1981
  */
1924
1982
  async grabAttributeFromAll(locator, attr) {
1925
- const els = await this._locate(locator);
1926
- const array = [];
1983
+ const els = await this._locate(locator)
1984
+ const array = []
1927
1985
  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());
1986
+ const a = await this._evaluateHandeInContext((el, attr) => el[attr] || el.getAttribute(attr), els[index], attr)
1987
+ array.push(await a.jsonValue())
1930
1988
  }
1931
- return array;
1989
+ return array
1932
1990
  }
1933
1991
 
1934
1992
  /**
@@ -1936,84 +1994,84 @@ class Puppeteer extends Helper {
1936
1994
  * {{ react }}
1937
1995
  */
1938
1996
  async grabAttributeFrom(locator, attr) {
1939
- const attrs = await this.grabAttributeFromAll(locator, attr);
1940
- assertElementExists(attrs, locator);
1997
+ const attrs = await this.grabAttributeFromAll(locator, attr)
1998
+ assertElementExists(attrs, locator)
1941
1999
  if (attrs.length > 1) {
1942
- this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
2000
+ this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
1943
2001
  }
1944
2002
 
1945
- return attrs[0];
2003
+ return attrs[0]
1946
2004
  }
1947
2005
 
1948
2006
  /**
1949
2007
  * {{> saveElementScreenshot }}
1950
2008
  */
1951
2009
  async saveElementScreenshot(locator, fileName) {
1952
- const outputFile = screenshotOutputFolder(fileName);
2010
+ const outputFile = screenshotOutputFolder(fileName)
1953
2011
 
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' });
2012
+ const res = await this._locate(locator)
2013
+ assertElementExists(res, locator)
2014
+ if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`)
2015
+ const elem = res[0]
2016
+ this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
2017
+ return elem.screenshot({ path: outputFile, type: 'png' })
1960
2018
  }
1961
2019
 
1962
2020
  /**
1963
2021
  * {{> saveScreenshot }}
1964
2022
  */
1965
2023
  async saveScreenshot(fileName, fullPage) {
1966
- const fullPageOption = fullPage || this.options.fullPageScreenshots;
1967
- let outputFile = screenshotOutputFolder(fileName);
2024
+ const fullPageOption = fullPage || this.options.fullPageScreenshots
2025
+ let outputFile = screenshotOutputFolder(fileName)
1968
2026
 
1969
- this.debug(`Screenshot is saving to ${outputFile}`);
2027
+ this.debug(`Screenshot is saving to ${outputFile}`)
1970
2028
 
1971
2029
  await this.page.screenshot({
1972
2030
  path: outputFile,
1973
2031
  fullPage: fullPageOption,
1974
2032
  type: 'png',
1975
- });
2033
+ })
1976
2034
 
1977
2035
  if (this.activeSessionName) {
1978
2036
  for (const sessionName in this.sessionPages) {
1979
- const activeSessionPage = this.sessionPages[sessionName];
1980
- outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`);
2037
+ const activeSessionPage = this.sessionPages[sessionName]
2038
+ outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`)
1981
2039
 
1982
- this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`);
2040
+ this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`)
1983
2041
 
1984
2042
  if (activeSessionPage) {
1985
2043
  await activeSessionPage.screenshot({
1986
2044
  path: outputFile,
1987
2045
  fullPage: fullPageOption,
1988
2046
  type: 'png',
1989
- });
2047
+ })
1990
2048
  }
1991
2049
  }
1992
2050
  }
1993
2051
  }
1994
2052
 
1995
2053
  async _failed(test) {
1996
- await this._withinEnd();
2054
+ await this._withinEnd()
1997
2055
 
1998
2056
  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;
2057
+ await this.page.tracing.stop()
2058
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.failed.json')
2059
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName)
2060
+ test.artifacts.trace = _traceName
2003
2061
  }
2004
2062
  }
2005
2063
 
2006
2064
  async _passed(test) {
2007
- await this._withinEnd();
2065
+ await this._withinEnd()
2008
2066
 
2009
2067
  if (this.options.trace) {
2010
- await this.page.tracing.stop();
2068
+ await this.page.tracing.stop()
2011
2069
  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;
2070
+ const _traceName = this.currentRunningTest.artifacts.trace.replace('.json', '.passed.json')
2071
+ fs.renameSync(this.currentRunningTest.artifacts.trace, _traceName)
2072
+ test.artifacts.trace = _traceName
2015
2073
  } else {
2016
- fs.unlinkSync(this.currentRunningTest.artifacts.trace);
2074
+ fs.unlinkSync(this.currentRunningTest.artifacts.trace)
2017
2075
  }
2018
2076
  }
2019
2077
  }
@@ -2022,70 +2080,74 @@ class Puppeteer extends Helper {
2022
2080
  * {{> wait }}
2023
2081
  */
2024
2082
  async wait(sec) {
2025
- return new Promise(((done) => {
2026
- setTimeout(done, sec * 1000);
2027
- }));
2083
+ return new Promise((done) => {
2084
+ setTimeout(done, sec * 1000)
2085
+ })
2028
2086
  }
2029
2087
 
2030
2088
  /**
2031
2089
  * {{> waitForEnabled }}
2032
2090
  */
2033
2091
  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();
2092
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2093
+ locator = new Locator(locator, 'css')
2094
+ await this.context
2095
+ let waiter
2096
+ const context = await this._getContext()
2039
2097
  if (locator.isCSS()) {
2040
2098
  const enabledFn = function (locator) {
2041
- const els = document.querySelectorAll(locator);
2099
+ const els = document.querySelectorAll(locator)
2042
2100
  if (!els || els.length === 0) {
2043
- return false;
2101
+ return false
2044
2102
  }
2045
- return Array.prototype.filter.call(els, el => !el.disabled).length > 0;
2046
- };
2047
- waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value);
2103
+ return Array.prototype.filter.call(els, (el) => !el.disabled).length > 0
2104
+ }
2105
+ waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value)
2048
2106
  } else {
2049
2107
  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());
2108
+ eval($XPath) // eslint-disable-line no-eval
2109
+ return $XPath(null, locator).filter((el) => !el.disabled).length > 0
2110
+ }
2111
+ waiter = context.waitForFunction(enabledFn, { timeout: waitTimeout }, locator.value, $XPath.toString())
2054
2112
  }
2055
2113
  return waiter.catch((err) => {
2056
- throw new Error(`element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`);
2057
- });
2114
+ throw new Error(
2115
+ `element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`,
2116
+ )
2117
+ })
2058
2118
  }
2059
2119
 
2060
2120
  /**
2061
2121
  * {{> waitForValue }}
2062
2122
  */
2063
2123
  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();
2124
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2125
+ const locator = new Locator(field, 'css')
2126
+ await this.context
2127
+ let waiter
2128
+ const context = await this._getContext()
2069
2129
  if (locator.isCSS()) {
2070
2130
  const valueFn = function (locator, value) {
2071
- const els = document.querySelectorAll(locator);
2131
+ const els = document.querySelectorAll(locator)
2072
2132
  if (!els || els.length === 0) {
2073
- return false;
2133
+ return false
2074
2134
  }
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);
2135
+ return Array.prototype.filter.call(els, (el) => (el.value.toString() || '').indexOf(value) !== -1).length > 0
2136
+ }
2137
+ waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, value)
2078
2138
  } else {
2079
2139
  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);
2140
+ eval($XPath) // eslint-disable-line no-eval
2141
+ return $XPath(null, locator).filter((el) => (el.value || '').indexOf(value) !== -1).length > 0
2142
+ }
2143
+ waiter = context.waitForFunction(valueFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), value)
2084
2144
  }
2085
2145
  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
- });
2146
+ const loc = locator.toString()
2147
+ throw new Error(
2148
+ `element (${loc}) is not in DOM or there is no element(${loc}) with value "${value}" after ${waitTimeout / 1000} sec\n${err.message}`,
2149
+ )
2150
+ })
2089
2151
  }
2090
2152
 
2091
2153
  /**
@@ -2093,45 +2155,49 @@ class Puppeteer extends Helper {
2093
2155
  * {{ react }}
2094
2156
  */
2095
2157
  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();
2158
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2159
+ locator = new Locator(locator, 'css')
2160
+ let waiter
2161
+ const context = await this._getContext()
2100
2162
  if (locator.isCSS()) {
2101
2163
  const visibleFn = function (locator, num) {
2102
- const els = document.querySelectorAll(locator);
2164
+ const els = document.querySelectorAll(locator)
2103
2165
  if (!els || els.length === 0) {
2104
- return false;
2166
+ return false
2105
2167
  }
2106
- return Array.prototype.filter.call(els, el => el.offsetParent !== null).length === num;
2107
- };
2108
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, num);
2168
+ return Array.prototype.filter.call(els, (el) => el.offsetParent !== null).length === num
2169
+ }
2170
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, num)
2109
2171
  } else {
2110
2172
  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);
2173
+ eval($XPath) // eslint-disable-line no-eval
2174
+ return $XPath(null, locator).filter((el) => el.offsetParent !== null).length === num
2175
+ }
2176
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString(), num)
2115
2177
  }
2116
2178
  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
- });
2179
+ throw new Error(
2180
+ `The number of elements (${locator.toString()}) is not ${num} after ${waitTimeout / 1000} sec\n${err.message}`,
2181
+ )
2182
+ })
2119
2183
  }
2120
2184
 
2121
2185
  /**
2122
2186
  * {{> waitForClickable }}
2123
2187
  */
2124
2188
  async waitForClickable(locator, waitTimeout) {
2125
- const els = await this._locate(locator);
2126
- assertElementExists(els, locator);
2189
+ const els = await this._locate(locator)
2190
+ assertElementExists(els, locator)
2127
2191
 
2128
2192
  return this.waitForFunction(isElementClickable, [els[0]], waitTimeout).catch(async (e) => {
2129
2193
  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`);
2194
+ throw new Error(
2195
+ `element ${new Locator(locator).toString()} still not clickable after ${waitTimeout || this.options.waitForTimeout / 1000} sec`,
2196
+ )
2131
2197
  } else {
2132
- throw e;
2198
+ throw e
2133
2199
  }
2134
- });
2200
+ })
2135
2201
  }
2136
2202
 
2137
2203
  /**
@@ -2139,19 +2205,21 @@ class Puppeteer extends Helper {
2139
2205
  * {{ react }}
2140
2206
  */
2141
2207
  async waitForElement(locator, sec) {
2142
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2143
- locator = new Locator(locator, 'css');
2208
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2209
+ locator = new Locator(locator, 'css')
2144
2210
 
2145
- let waiter;
2146
- const context = await this._getContext();
2211
+ let waiter
2212
+ const context = await this._getContext()
2147
2213
  if (locator.isCSS()) {
2148
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout });
2214
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout })
2149
2215
  } else {
2150
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout });
2216
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout })
2151
2217
  }
2152
2218
  return waiter.catch((err) => {
2153
- throw new Error(`element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${err.message}`);
2154
- });
2219
+ throw new Error(
2220
+ `element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${err.message}`,
2221
+ )
2222
+ })
2155
2223
  }
2156
2224
 
2157
2225
  /**
@@ -2160,160 +2228,191 @@ class Puppeteer extends Helper {
2160
2228
  * {{ react }}
2161
2229
  */
2162
2230
  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();
2231
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2232
+ locator = new Locator(locator, 'css')
2233
+ await this.context
2234
+ let waiter
2235
+ const context = await this._getContext()
2168
2236
  if (locator.isCSS()) {
2169
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, visible: true });
2237
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, visible: true })
2170
2238
  } else {
2171
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, visible: true });
2239
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, visible: true })
2172
2240
  }
2173
2241
  return waiter.catch((err) => {
2174
- throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${err.message}`);
2175
- });
2242
+ throw new Error(
2243
+ `element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${err.message}`,
2244
+ )
2245
+ })
2176
2246
  }
2177
2247
 
2178
2248
  /**
2179
2249
  * {{> waitForInvisible }}
2180
2250
  */
2181
2251
  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();
2252
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2253
+ locator = new Locator(locator, 'css')
2254
+ await this.context
2255
+ let waiter
2256
+ const context = await this._getContext()
2187
2257
  if (locator.isCSS()) {
2188
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true });
2258
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true })
2189
2259
  } else {
2190
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true });
2260
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true })
2191
2261
  }
2192
2262
  return waiter.catch((err) => {
2193
- throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${err.message}`);
2194
- });
2263
+ throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${err.message}`)
2264
+ })
2195
2265
  }
2196
2266
 
2197
2267
  /**
2198
2268
  * {{> waitToHide }}
2199
2269
  */
2200
2270
  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();
2271
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2272
+ locator = new Locator(locator, 'css')
2273
+ let waiter
2274
+ const context = await this._getContext()
2205
2275
  if (locator.isCSS()) {
2206
- waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true });
2276
+ waiter = context.waitForSelector(locator.simplify(), { timeout: waitTimeout, hidden: true })
2207
2277
  } else {
2208
- waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true });
2278
+ waiter = _waitForElement.call(this, locator, { timeout: waitTimeout, hidden: true })
2209
2279
  }
2210
2280
  return waiter.catch((err) => {
2211
- throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`);
2212
- });
2281
+ throw new Error(
2282
+ `element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`,
2283
+ )
2284
+ })
2213
2285
  }
2214
2286
 
2215
2287
  /**
2216
2288
  * {{> waitForNumberOfTabs }}
2217
2289
  */
2218
2290
  async waitForNumberOfTabs(expectedTabs, sec) {
2219
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2220
- let currentTabs;
2221
- let count = 0;
2291
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2292
+ let currentTabs
2293
+ let count = 0
2222
2294
 
2223
2295
  do {
2224
- currentTabs = await this.grabNumberOfOpenTabs();
2225
- await this.wait(1);
2226
- count += 1000;
2227
- if (currentTabs >= expectedTabs) return;
2228
- } while (count <= waitTimeout);
2296
+ currentTabs = await this.grabNumberOfOpenTabs()
2297
+ await this.wait(1)
2298
+ count += 1000
2299
+ if (currentTabs >= expectedTabs) return
2300
+ } while (count <= waitTimeout)
2229
2301
 
2230
- throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`);
2302
+ throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`)
2231
2303
  }
2232
2304
 
2233
2305
  async _getContext() {
2234
2306
  if (this.context && this.context.constructor.name === 'CdpFrame') {
2235
- return this.context;
2307
+ return this.context
2236
2308
  }
2237
- return this.page;
2309
+ return this.page
2238
2310
  }
2239
2311
 
2240
2312
  /**
2241
2313
  * {{> waitInUrl }}
2242
2314
  */
2243
2315
  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
- });
2316
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2317
+
2318
+ return this.page
2319
+ .waitForFunction(
2320
+ (urlPart) => {
2321
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2322
+ return currUrl.indexOf(urlPart) > -1
2323
+ },
2324
+ { timeout: waitTimeout },
2325
+ urlPart,
2326
+ )
2327
+ .catch(async (e) => {
2328
+ const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2329
+ if (/Waiting failed:/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2330
+ throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
2331
+ } else {
2332
+ throw e
2333
+ }
2334
+ })
2257
2335
  }
2258
2336
 
2259
2337
  /**
2260
2338
  * {{> waitUrlEquals }}
2261
2339
  */
2262
2340
  async waitUrlEquals(urlPart, sec = null) {
2263
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2341
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2264
2342
 
2265
- const baseUrl = this.options.url;
2343
+ const baseUrl = this.options.url
2266
2344
  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
- });
2345
+ urlPart = baseUrl + urlPart
2346
+ }
2347
+
2348
+ return this.page
2349
+ .waitForFunction(
2350
+ (urlPart) => {
2351
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2352
+ return currUrl.indexOf(urlPart) > -1
2353
+ },
2354
+ { timeout: waitTimeout },
2355
+ urlPart,
2356
+ )
2357
+ .catch(async (e) => {
2358
+ const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2359
+ if (/Waiting failed/i.test(e.message) || /failed: timeout/i.test(e.message)) {
2360
+ throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
2361
+ } else {
2362
+ throw e
2363
+ }
2364
+ })
2281
2365
  }
2282
2366
 
2283
2367
  /**
2284
2368
  * {{> waitForText }}
2285
2369
  */
2286
2370
  async waitForText(text, sec = null, context = null) {
2287
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2288
- let waiter;
2371
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2372
+ let waiter
2289
2373
 
2290
- const contextObject = await this._getContext();
2374
+ const contextObject = await this._getContext()
2291
2375
 
2292
2376
  if (context) {
2293
- const locator = new Locator(context, 'css');
2377
+ const locator = new Locator(context, 'css')
2294
2378
  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);
2379
+ waiter = contextObject.waitForFunction(
2380
+ (locator, text) => {
2381
+ const el = document.querySelector(locator)
2382
+ if (!el) return false
2383
+ return el.innerText.indexOf(text) > -1
2384
+ },
2385
+ { timeout: waitTimeout },
2386
+ locator.value,
2387
+ text,
2388
+ )
2300
2389
  }
2301
2390
 
2302
2391
  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());
2392
+ waiter = contextObject.waitForFunction(
2393
+ (locator, text, $XPath) => {
2394
+ eval($XPath) // eslint-disable-line no-eval
2395
+ const el = $XPath(null, locator)
2396
+ if (!el.length) return false
2397
+ return el[0].innerText.indexOf(text) > -1
2398
+ },
2399
+ { timeout: waitTimeout },
2400
+ locator.value,
2401
+ text,
2402
+ $XPath.toString(),
2403
+ )
2309
2404
  }
2310
2405
  } else {
2311
- waiter = contextObject.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, { timeout: waitTimeout }, text);
2406
+ waiter = contextObject.waitForFunction(
2407
+ (text) => document.body && document.body.innerText.indexOf(text) > -1,
2408
+ { timeout: waitTimeout },
2409
+ text,
2410
+ )
2312
2411
  }
2313
2412
 
2314
2413
  return waiter.catch((err) => {
2315
- throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${err.message}`);
2316
- });
2414
+ throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${err.message}`)
2415
+ })
2317
2416
  }
2318
2417
 
2319
2418
  /**
@@ -2328,8 +2427,8 @@ class Puppeteer extends Helper {
2328
2427
  * @param {?number} [sec=null] seconds to wait
2329
2428
  */
2330
2429
  async waitForRequest(urlOrPredicate, sec = null) {
2331
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2332
- return this.page.waitForRequest(urlOrPredicate, { timeout });
2430
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2431
+ return this.page.waitForRequest(urlOrPredicate, { timeout })
2333
2432
  }
2334
2433
 
2335
2434
  /**
@@ -2344,8 +2443,8 @@ class Puppeteer extends Helper {
2344
2443
  * @param {?number} [sec=null] number of seconds to wait
2345
2444
  */
2346
2445
  async waitForResponse(urlOrPredicate, sec = null) {
2347
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2348
- return this.page.waitForResponse(urlOrPredicate, { timeout });
2446
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2447
+ return this.page.waitForResponse(urlOrPredicate, { timeout })
2349
2448
  }
2350
2449
 
2351
2450
  /**
@@ -2354,37 +2453,37 @@ class Puppeteer extends Helper {
2354
2453
  async switchTo(locator) {
2355
2454
  if (Number.isInteger(locator)) {
2356
2455
  // Select by frame index of current context
2357
- let frames = [];
2456
+ let frames = []
2358
2457
  if (this.context && typeof this.context.childFrames === 'function') {
2359
- frames = await this.context.childFrames();
2458
+ frames = await this.context.childFrames()
2360
2459
  } else {
2361
- frames = await this.page.mainFrame().childFrames();
2460
+ frames = await this.page.mainFrame().childFrames()
2362
2461
  }
2363
2462
 
2364
2463
  if (locator >= 0 && locator < frames.length) {
2365
- this.context = frames[locator];
2464
+ this.context = frames[locator]
2366
2465
  } else {
2367
- throw new Error('Frame index out of bounds');
2466
+ throw new Error('Frame index out of bounds')
2368
2467
  }
2369
- return;
2468
+ return
2370
2469
  }
2371
2470
 
2372
2471
  if (!locator) {
2373
- this.context = await this.page.mainFrame();
2374
- return;
2472
+ this.context = await this.page.mainFrame()
2473
+ return
2375
2474
  }
2376
2475
 
2377
2476
  // Select iframe by selector
2378
- const els = await this._locate(locator);
2379
- assertElementExists(els, locator);
2477
+ const els = await this._locate(locator)
2478
+ assertElementExists(els, locator)
2380
2479
 
2381
- const iframeElement = els[0];
2382
- const contentFrame = await iframeElement.contentFrame();
2480
+ const iframeElement = els[0]
2481
+ const contentFrame = await iframeElement.contentFrame()
2383
2482
 
2384
2483
  if (contentFrame) {
2385
- this.context = contentFrame;
2484
+ this.context = contentFrame
2386
2485
  } else {
2387
- throw new Error('Element "#invalidIframeSelector" was not found by text|CSS|XPath');
2486
+ throw new Error('Element "#invalidIframeSelector" was not found by text|CSS|XPath')
2388
2487
  }
2389
2488
  }
2390
2489
 
@@ -2392,17 +2491,17 @@ class Puppeteer extends Helper {
2392
2491
  * {{> waitForFunction }}
2393
2492
  */
2394
2493
  async waitForFunction(fn, argsOrSec = null, sec = null) {
2395
- let args = [];
2494
+ let args = []
2396
2495
  if (argsOrSec) {
2397
2496
  if (Array.isArray(argsOrSec)) {
2398
- args = argsOrSec;
2497
+ args = argsOrSec
2399
2498
  } else if (typeof argsOrSec === 'number') {
2400
- sec = argsOrSec;
2499
+ sec = argsOrSec
2401
2500
  }
2402
2501
  }
2403
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2404
- const context = await this._getContext();
2405
- return context.waitForFunction(fn, { timeout: waitTimeout }, ...args);
2502
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2503
+ const context = await this._getContext()
2504
+ return context.waitForFunction(fn, { timeout: waitTimeout }, ...args)
2406
2505
  }
2407
2506
 
2408
2507
  /**
@@ -2417,87 +2516,87 @@ class Puppeteer extends Helper {
2417
2516
  timeout: this.options.getPageTimeout,
2418
2517
  waitUntil: this.options.waitForNavigation,
2419
2518
  ...opts,
2420
- };
2421
- return this.page.waitForNavigation(opts);
2519
+ }
2520
+ return this.page.waitForNavigation(opts)
2422
2521
  }
2423
2522
 
2424
2523
  async waitUntilExists(locator, sec) {
2425
2524
  console.log(`waitUntilExists deprecated:
2426
2525
  * 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);
2526
+ * use 'waitForDetached to wait for element to be removed'`)
2527
+ return this.waitForDetached(locator, sec)
2429
2528
  }
2430
2529
 
2431
2530
  /**
2432
2531
  * {{> waitForDetached }}
2433
2532
  */
2434
2533
  async waitForDetached(locator, sec) {
2435
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2436
- locator = new Locator(locator, 'css');
2534
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2535
+ locator = new Locator(locator, 'css')
2437
2536
 
2438
- let waiter;
2439
- const context = await this._getContext();
2537
+ let waiter
2538
+ const context = await this._getContext()
2440
2539
  if (locator.isCSS()) {
2441
2540
  const visibleFn = function (locator) {
2442
- return document.querySelector(locator) === null;
2443
- };
2444
- waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value);
2541
+ return document.querySelector(locator) === null
2542
+ }
2543
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value)
2445
2544
  } else {
2446
2545
  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());
2546
+ eval($XPath) // eslint-disable-line no-eval
2547
+ return $XPath(null, locator).length === 0
2548
+ }
2549
+ waiter = context.waitForFunction(visibleFn, { timeout: waitTimeout }, locator.value, $XPath.toString())
2451
2550
  }
2452
2551
  return waiter.catch((err) => {
2453
- throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
2454
- });
2552
+ throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`)
2553
+ })
2455
2554
  }
2456
2555
 
2457
2556
  async _waitForAction() {
2458
- return this.wait(this.options.waitForAction / 1000);
2557
+ return this.wait(this.options.waitForAction / 1000)
2459
2558
  }
2460
2559
 
2461
2560
  /**
2462
2561
  * {{> grabDataFromPerformanceTiming }}
2463
2562
  */
2464
2563
  async grabDataFromPerformanceTiming() {
2465
- return perfTiming;
2564
+ return perfTiming
2466
2565
  }
2467
2566
 
2468
2567
  /**
2469
2568
  * {{> grabElementBoundingRect }}
2470
2569
  */
2471
2570
  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;
2571
+ const els = await this._locate(locator)
2572
+ assertElementExists(els, locator)
2573
+ const rect = await els[0].boundingBox()
2574
+ if (prop) return rect[prop]
2575
+ return rect
2477
2576
  }
2478
2577
 
2479
2578
  /**
2480
- * Mocks network request using [`Request Interception`](https://pptr.dev/next/guides/request-interception)
2579
+ * Mocks network request using [`Request Interception`](https://pptr.dev/guides/network-interception)
2481
2580
  *
2482
2581
  * ```js
2483
2582
  * I.mockRoute(/(\.png$)|(\.jpg$)/, route => route.abort());
2484
2583
  * ```
2485
- * This method allows intercepting and mocking requests & responses. [Learn more about it](https://pptr.dev/next/guides/request-interception)
2584
+ * This method allows intercepting and mocking requests & responses. [Learn more about it](https://pptr.dev/guides/network-interception)
2486
2585
  *
2487
2586
  * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2488
2587
  * @param {function} [handler] a function to process request
2489
2588
  */
2490
2589
  async mockRoute(url, handler) {
2491
- await this.page.setRequestInterception(true);
2590
+ await this.page.setRequestInterception(true)
2492
2591
 
2493
- this.page.on('request', interceptedRequest => {
2592
+ this.page.on('request', (interceptedRequest) => {
2494
2593
  if (interceptedRequest.url().match(url)) {
2495
2594
  // @ts-ignore
2496
- handler(interceptedRequest);
2595
+ handler(interceptedRequest)
2497
2596
  } else {
2498
- interceptedRequest.continue();
2597
+ interceptedRequest.continue()
2499
2598
  }
2500
- });
2599
+ })
2501
2600
  }
2502
2601
 
2503
2602
  /**
@@ -2510,18 +2609,18 @@ class Puppeteer extends Helper {
2510
2609
  * @param {string|RegExp} [url] URL, regex or pattern for to match URL
2511
2610
  */
2512
2611
  async stopMockingRoute(url) {
2513
- await this.page.setRequestInterception(true);
2612
+ await this.page.setRequestInterception(true)
2514
2613
 
2515
- this.page.off('request');
2614
+ this.page.off('request')
2516
2615
 
2517
2616
  // Resume normal request handling for the given URL
2518
- this.page.on('request', interceptedRequest => {
2617
+ this.page.on('request', (interceptedRequest) => {
2519
2618
  if (interceptedRequest.url().includes(url)) {
2520
- interceptedRequest.continue();
2619
+ interceptedRequest.continue()
2521
2620
  } else {
2522
- interceptedRequest.continue();
2621
+ interceptedRequest.continue()
2523
2622
  }
2524
- });
2623
+ })
2525
2624
  }
2526
2625
 
2527
2626
  /**
@@ -2529,7 +2628,7 @@ class Puppeteer extends Helper {
2529
2628
  * {{> flushNetworkTraffics }}
2530
2629
  */
2531
2630
  flushNetworkTraffics() {
2532
- flushNetworkTraffics.call(this);
2631
+ flushNetworkTraffics.call(this)
2533
2632
  }
2534
2633
 
2535
2634
  /**
@@ -2537,7 +2636,7 @@ class Puppeteer extends Helper {
2537
2636
  * {{> stopRecordingTraffic }}
2538
2637
  */
2539
2638
  stopRecordingTraffic() {
2540
- stopRecordingTraffic.call(this);
2639
+ stopRecordingTraffic.call(this)
2541
2640
  }
2542
2641
 
2543
2642
  /**
@@ -2545,11 +2644,11 @@ class Puppeteer extends Helper {
2545
2644
  *
2546
2645
  */
2547
2646
  async startRecordingTraffic() {
2548
- this.flushNetworkTraffics();
2549
- this.recording = true;
2550
- this.recordedAtLeastOnce = true;
2647
+ this.flushNetworkTraffics()
2648
+ this.recording = true
2649
+ this.recordedAtLeastOnce = true
2551
2650
 
2552
- await this.page.setRequestInterception(true);
2651
+ await this.page.setRequestInterception(true)
2553
2652
 
2554
2653
  this.page.on('request', (request) => {
2555
2654
  const information = {
@@ -2558,16 +2657,16 @@ class Puppeteer extends Helper {
2558
2657
  requestHeaders: request.headers(),
2559
2658
  requestPostData: request.postData(),
2560
2659
  response: request.response(),
2561
- };
2660
+ }
2562
2661
 
2563
- this.debugSection('REQUEST: ', JSON.stringify(information));
2662
+ this.debugSection('REQUEST: ', JSON.stringify(information))
2564
2663
 
2565
2664
  if (typeof information.requestPostData === 'object') {
2566
- information.requestPostData = JSON.parse(information.requestPostData);
2665
+ information.requestPostData = JSON.parse(information.requestPostData)
2567
2666
  }
2568
- request.continue();
2569
- this.requests.push(information);
2570
- });
2667
+ request.continue()
2668
+ this.requests.push(information)
2669
+ })
2571
2670
  }
2572
2671
 
2573
2672
  /**
@@ -2575,17 +2674,15 @@ class Puppeteer extends Helper {
2575
2674
  * {{> grabRecordedNetworkTraffics }}
2576
2675
  */
2577
2676
  async grabRecordedNetworkTraffics() {
2578
- return grabRecordedNetworkTraffics.call(this);
2677
+ return grabRecordedNetworkTraffics.call(this)
2579
2678
  }
2580
2679
 
2581
2680
  /**
2582
2681
  *
2583
2682
  * {{> seeTraffic }}
2584
2683
  */
2585
- async seeTraffic({
2586
- name, url, parameters, requestPostData, timeout = 10,
2587
- }) {
2588
- await seeTraffic.call(this, ...arguments);
2684
+ async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) {
2685
+ await seeTraffic.call(this, ...arguments)
2589
2686
  }
2590
2687
 
2591
2688
  /**
@@ -2594,56 +2691,47 @@ class Puppeteer extends Helper {
2594
2691
  *
2595
2692
  */
2596
2693
  dontSeeTraffic({ name, url }) {
2597
- dontSeeTraffic.call(this, ...arguments);
2694
+ dontSeeTraffic.call(this, ...arguments)
2598
2695
  }
2599
2696
 
2600
2697
  async getNewCDPSession() {
2601
- const client = await this.page.target().createCDPSession();
2602
- return client;
2698
+ const client = await this.page.target().createCDPSession()
2699
+ return client
2603
2700
  }
2604
2701
 
2605
2702
  /**
2606
2703
  * {{> startRecordingWebSocketMessages }}
2607
2704
  */
2608
2705
  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
- );
2706
+ this.flushWebSocketMessages()
2707
+ this.recordingWebSocketMessages = true
2708
+ this.recordedWebSocketMessagesAtLeastOnce = true
2623
2709
 
2624
- this.cdpSession.on(
2625
- 'Network.webSocketFrameSent',
2626
- (payload) => {
2627
- this._logWebsocketMessages(this._getWebSocketLog('SENT', payload));
2628
- },
2629
- );
2710
+ this.cdpSession = await this.getNewCDPSession()
2711
+ await this.cdpSession.send('Network.enable')
2712
+ await this.cdpSession.send('Page.enable')
2630
2713
 
2631
- this.cdpSession.on(
2632
- 'Network.webSocketFrameError',
2633
- (payload) => {
2634
- this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload));
2635
- },
2636
- );
2714
+ this.cdpSession.on('Network.webSocketFrameReceived', (payload) => {
2715
+ this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload))
2716
+ })
2717
+
2718
+ this.cdpSession.on('Network.webSocketFrameSent', (payload) => {
2719
+ this._logWebsocketMessages(this._getWebSocketLog('SENT', payload))
2720
+ })
2721
+
2722
+ this.cdpSession.on('Network.webSocketFrameError', (payload) => {
2723
+ this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload))
2724
+ })
2637
2725
  }
2638
2726
 
2639
2727
  /**
2640
2728
  * {{> stopRecordingWebSocketMessages }}
2641
2729
  */
2642
2730
  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;
2731
+ await this.cdpSession.send('Network.disable')
2732
+ await this.cdpSession.send('Page.disable')
2733
+ this.page.removeAllListeners('Network')
2734
+ this.recordingWebSocketMessages = false
2647
2735
  }
2648
2736
 
2649
2737
  /**
@@ -2655,394 +2743,404 @@ class Puppeteer extends Helper {
2655
2743
  grabWebSocketMessages() {
2656
2744
  if (!this.recordingWebSocketMessages) {
2657
2745
  if (!this.recordedWebSocketMessagesAtLeastOnce) {
2658
- throw new Error('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
2746
+ throw new Error(
2747
+ 'Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.',
2748
+ )
2659
2749
  }
2660
2750
  }
2661
- return this.webSocketMessages;
2751
+ return this.webSocketMessages
2662
2752
  }
2663
2753
 
2664
2754
  /**
2665
2755
  * Resets all recorded WS messages.
2666
2756
  */
2667
2757
  flushWebSocketMessages() {
2668
- this.webSocketMessages = [];
2758
+ this.webSocketMessages = []
2669
2759
  }
2670
2760
 
2671
2761
  _getWebSocketMessage(payload) {
2672
2762
  if (payload.errorMessage) {
2673
- return payload.errorMessage;
2763
+ return payload.errorMessage
2674
2764
  }
2675
2765
 
2676
- return payload.response.payloadData;
2766
+ return payload.response.payloadData
2677
2767
  }
2678
2768
 
2679
2769
  _getWebSocketLog(prefix, payload) {
2680
- return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`;
2770
+ return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`
2681
2771
  }
2682
2772
 
2683
2773
  _logWebsocketMessages(message) {
2684
- this.webSocketMessages += message;
2774
+ this.webSocketMessages.push(message)
2685
2775
  }
2686
2776
  }
2687
2777
 
2688
- export default Puppeteer;
2778
+ module.exports = Puppeteer
2689
2779
 
2690
2780
  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());
2781
+ if (locator.react) return findReactElements.call(this, locator)
2782
+ locator = new Locator(locator, 'css')
2783
+ if (!locator.isXPath()) return matcher.$$(locator.simplify())
2694
2784
  // puppeteer version < 19.4.0 is no longer supported. This one is backward support.
2695
2785
  if (puppeteer.default?.defaultBrowserRevision) {
2696
- return matcher.$$(`xpath/${locator.value}`);
2786
+ return matcher.$$(`xpath/${locator.value}`)
2697
2787
  }
2698
- return matcher.$x(locator.value);
2788
+ return matcher.$x(locator.value)
2699
2789
  }
2700
2790
 
2701
2791
  async function proceedClick(locator, context = null, options = {}) {
2702
- let matcher = await this.context;
2792
+ let matcher = await this.context
2703
2793
  if (context) {
2704
- const els = await this._locate(context);
2705
- assertElementExists(els, context);
2706
- matcher = els[0];
2794
+ const els = await this._locate(context)
2795
+ assertElementExists(els, context)
2796
+ matcher = els[0]
2707
2797
  }
2708
- const els = await findClickable.call(this, matcher, locator);
2798
+ const els = await findClickable.call(this, matcher, locator)
2709
2799
  if (context) {
2710
- assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
2800
+ assertElementExists(
2801
+ els,
2802
+ locator,
2803
+ 'Clickable element',
2804
+ `was not found inside element ${new Locator(context).toString()}`,
2805
+ )
2711
2806
  } else {
2712
- assertElementExists(els, locator, 'Clickable element');
2807
+ assertElementExists(els, locator, 'Clickable element')
2713
2808
  }
2714
2809
 
2715
- highlightActiveElement.call(this, els[0], await this._getContext());
2810
+ highlightActiveElement.call(this, els[0], await this._getContext())
2716
2811
 
2717
- await els[0].click(options);
2718
- const promises = [];
2812
+ await els[0].click(options)
2813
+ const promises = []
2719
2814
  if (options.waitForNavigation) {
2720
- promises.push(this.waitForNavigation());
2815
+ promises.push(this.waitForNavigation())
2721
2816
  }
2722
- promises.push(this._waitForAction());
2817
+ promises.push(this._waitForAction())
2723
2818
 
2724
- return Promise.all(promises);
2819
+ return Promise.all(promises)
2725
2820
  }
2726
2821
 
2727
2822
  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);
2823
+ if (locator.react) return findReactElements.call(this, locator)
2824
+ locator = new Locator(locator)
2825
+ if (!locator.isFuzzy()) return findElements.call(this, matcher, locator)
2731
2826
 
2732
- let els;
2733
- const literal = xpathLocator.literal(locator.value);
2827
+ let els
2828
+ const literal = xpathLocator.literal(locator.value)
2734
2829
 
2735
- els = await findElements.call(this, matcher, Locator.clickable.narrow(literal));
2736
- if (els.length) return els;
2830
+ els = await findElements.call(this, matcher, Locator.clickable.narrow(literal))
2831
+ if (els.length) return els
2737
2832
 
2738
- els = await findElements.call(this, matcher, Locator.clickable.wide(literal));
2739
- if (els.length) return els;
2833
+ els = await findElements.call(this, matcher, Locator.clickable.wide(literal))
2834
+ if (els.length) return els
2740
2835
 
2741
2836
  try {
2742
- els = await findElements.call(this, matcher, Locator.clickable.self(literal));
2743
- if (els.length) return els;
2837
+ els = await findElements.call(this, matcher, Locator.clickable.self(literal))
2838
+ if (els.length) return els
2744
2839
  } catch (err) {
2745
2840
  // Do nothing
2746
2841
  }
2747
2842
 
2748
- return findElements.call(this, matcher, locator.value); // by css or xpath
2843
+ return findElements.call(this, matcher, locator.value) // by css or xpath
2749
2844
  }
2750
2845
 
2751
2846
  async function proceedSee(assertType, text, context, strict = false) {
2752
- let description;
2753
- let allText;
2847
+ let description
2848
+ let allText
2754
2849
  if (!context) {
2755
- let el = await this.context;
2850
+ let el = await this.context
2756
2851
 
2757
2852
  if (el && !el.getProperty) {
2758
2853
  // Fallback to body
2759
- el = await this.context.$('body');
2854
+ el = await this.context.$('body')
2760
2855
  }
2761
2856
 
2762
- allText = [await el.getProperty('innerText').then(p => p.jsonValue())];
2763
- description = 'web application';
2857
+ allText = [await el.getProperty('innerText').then((p) => p.jsonValue())]
2858
+ description = 'web application'
2764
2859
  } 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())));
2860
+ const locator = new Locator(context, 'css')
2861
+ description = `element ${locator.toString()}`
2862
+ const els = await this._locate(locator)
2863
+ assertElementExists(els, locator.toString())
2864
+ allText = await Promise.all(els.map((el) => el.getProperty('innerText').then((p) => p.jsonValue())))
2770
2865
  }
2771
2866
 
2772
2867
  if (strict) {
2773
- return allText.map(elText => equals(description)[assertType](text, elText));
2868
+ return allText.map((elText) => equals(description)[assertType](text, elText))
2774
2869
  }
2775
- return stringIncludes(description)[assertType](normalizeSpacesInString(text), normalizeSpacesInString(allText.join(' | ')));
2870
+ return stringIncludes(description)[assertType](
2871
+ normalizeSpacesInString(text),
2872
+ normalizeSpacesInString(allText.join(' | ')),
2873
+ )
2776
2874
  }
2777
2875
 
2778
2876
  async function findCheckable(locator, context) {
2779
- let contextEl = await this.context;
2877
+ let contextEl = await this.context
2780
2878
  if (typeof context === 'string') {
2781
- contextEl = await findElements.call(this, contextEl, (new Locator(context, 'css')).simplify());
2782
- contextEl = contextEl[0];
2879
+ contextEl = await findElements.call(this, contextEl, new Locator(context, 'css').simplify())
2880
+ contextEl = contextEl[0]
2783
2881
  }
2784
2882
 
2785
- const matchedLocator = new Locator(locator);
2883
+ const matchedLocator = new Locator(locator)
2786
2884
  if (!matchedLocator.isFuzzy()) {
2787
- return findElements.call(this, contextEl, matchedLocator.simplify());
2885
+ return findElements.call(this, contextEl, matchedLocator.simplify())
2788
2886
  }
2789
2887
 
2790
- const literal = xpathLocator.literal(locator);
2791
- let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal));
2888
+ const literal = xpathLocator.literal(locator)
2889
+ let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal))
2792
2890
  if (els.length) {
2793
- return els;
2891
+ return els
2794
2892
  }
2795
- els = await findElements.call(this, contextEl, Locator.checkable.byName(literal));
2893
+ els = await findElements.call(this, contextEl, Locator.checkable.byName(literal))
2796
2894
  if (els.length) {
2797
- return els;
2895
+ return els
2798
2896
  }
2799
- return findElements.call(this, contextEl, locator);
2897
+ return findElements.call(this, contextEl, locator)
2800
2898
  }
2801
2899
 
2802
2900
  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);
2901
+ let els = await findCheckable.call(this, option)
2902
+ assertElementExists(els, option, 'Checkable')
2903
+ els = await Promise.all(els.map((el) => el.getProperty('checked')))
2904
+ els = await Promise.all(els.map((el) => el.jsonValue()))
2905
+ const selected = els.reduce((prev, cur) => prev || cur)
2906
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
2809
2907
  }
2810
2908
 
2811
2909
  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]);
2910
+ const els = await findFields.call(this, locator)
2911
+ const visible = await Promise.all(els.map((el) => el.boundingBox()))
2912
+ return els.filter((el, index) => visible[index])
2815
2913
  }
2816
2914
 
2817
2915
  async function findFields(locator) {
2818
- const matchedLocator = new Locator(locator);
2916
+ const matchedLocator = new Locator(locator)
2819
2917
  if (!matchedLocator.isFuzzy()) {
2820
- return this._locate(matchedLocator);
2918
+ return this._locate(matchedLocator)
2821
2919
  }
2822
- const literal = xpathLocator.literal(locator);
2920
+ const literal = xpathLocator.literal(locator)
2823
2921
 
2824
- let els = await this._locate({ xpath: Locator.field.labelEquals(literal) });
2922
+ let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
2825
2923
  if (els.length) {
2826
- return els;
2924
+ return els
2827
2925
  }
2828
2926
 
2829
- els = await this._locate({ xpath: Locator.field.labelContains(literal) });
2927
+ els = await this._locate({ xpath: Locator.field.labelContains(literal) })
2830
2928
  if (els.length) {
2831
- return els;
2929
+ return els
2832
2930
  }
2833
- els = await this._locate({ xpath: Locator.field.byName(literal) });
2931
+ els = await this._locate({ xpath: Locator.field.byName(literal) })
2834
2932
  if (els.length) {
2835
- return els;
2933
+ return els
2836
2934
  }
2837
- return this._locate({ css: locator });
2935
+ return this._locate({ css: locator })
2838
2936
  }
2839
2937
 
2840
2938
  async function proceedDragAndDrop(sourceLocator, destinationLocator) {
2841
- const src = await this._locate(sourceLocator);
2842
- assertElementExists(src, sourceLocator, 'Source Element');
2939
+ const src = await this._locate(sourceLocator)
2940
+ assertElementExists(src, sourceLocator, 'Source Element')
2843
2941
 
2844
- const dst = await this._locate(destinationLocator);
2845
- assertElementExists(dst, destinationLocator, 'Destination Element');
2942
+ const dst = await this._locate(destinationLocator)
2943
+ assertElementExists(dst, destinationLocator, 'Destination Element')
2846
2944
 
2847
2945
  // 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]);
2946
+ const dragSource = await getClickablePoint(src[0])
2947
+ const dragDestination = await getClickablePoint(dst[0])
2850
2948
 
2851
2949
  // Drag start point
2852
- await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 });
2853
- await this.page.mouse.down();
2950
+ await this.page.mouse.move(dragSource.x, dragSource.y, { steps: 5 })
2951
+ await this.page.mouse.down()
2854
2952
 
2855
2953
  // Drag destination
2856
- await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 });
2857
- await this.page.mouse.up();
2954
+ await this.page.mouse.move(dragDestination.x, dragDestination.y, { steps: 5 })
2955
+ await this.page.mouse.up()
2858
2956
 
2859
- await this._waitForAction();
2957
+ await this._waitForAction()
2860
2958
  }
2861
2959
 
2862
2960
  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());
2961
+ const els = await findVisibleFields.call(this, field)
2962
+ assertElementExists(els, field, 'Field')
2963
+ const el = els[0]
2964
+ const tag = await el.getProperty('tagName').then((el) => el.jsonValue())
2965
+ const fieldType = await el.getProperty('type').then((el) => el.jsonValue())
2868
2966
 
2869
2967
  const proceedMultiple = async (elements) => {
2870
- const fields = Array.isArray(elements) ? elements : [elements];
2968
+ const fields = Array.isArray(elements) ? elements : [elements]
2871
2969
 
2872
- const elementValues = [];
2970
+ const elementValues = []
2873
2971
  for (const element of fields) {
2874
- elementValues.push(await element.getProperty('value').then(el => el.jsonValue()));
2972
+ elementValues.push(await element.getProperty('value').then((el) => el.jsonValue()))
2875
2973
  }
2876
2974
 
2877
2975
  if (typeof value === 'boolean') {
2878
- equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length);
2976
+ equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length)
2879
2977
  } else {
2880
2978
  if (assertType === 'assert') {
2881
- equals(`select option by ${field}`)[assertType](true, elementValues.length > 0);
2979
+ equals(`select option by ${field}`)[assertType](true, elementValues.length > 0)
2882
2980
  }
2883
- elementValues.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val));
2981
+ elementValues.forEach((val) => stringIncludes(`fields by ${field}`)[assertType](value, val))
2884
2982
  }
2885
- };
2983
+ }
2886
2984
 
2887
2985
  if (tag === 'SELECT') {
2888
- const selectedOptions = await el.$$('option:checked');
2986
+ const selectedOptions = await el.$$('option:checked')
2889
2987
  // locate option by values and check them
2890
2988
  if (value === '') {
2891
- return proceedMultiple(selectedOptions);
2989
+ return proceedMultiple(selectedOptions)
2892
2990
  }
2893
2991
 
2894
- const options = await filterFieldsByValue(selectedOptions, value, true);
2895
- return proceedMultiple(options);
2992
+ const options = await filterFieldsByValue(selectedOptions, value, true)
2993
+ return proceedMultiple(options)
2896
2994
  }
2897
2995
 
2898
2996
  if (tag === 'INPUT') {
2899
2997
  if (fieldType === 'checkbox' || fieldType === 'radio') {
2900
2998
  if (typeof value === 'boolean') {
2901
2999
  // Filter by values
2902
- const options = await filterFieldsBySelectionState(els, true);
2903
- return proceedMultiple(options);
3000
+ const options = await filterFieldsBySelectionState(els, true)
3001
+ return proceedMultiple(options)
2904
3002
  }
2905
3003
 
2906
- const options = await filterFieldsByValue(els, value, true);
2907
- return proceedMultiple(options);
3004
+ const options = await filterFieldsByValue(els, value, true)
3005
+ return proceedMultiple(options)
2908
3006
  }
2909
- return proceedMultiple(els[0]);
3007
+ return proceedMultiple(els[0])
2910
3008
  }
2911
- const fieldVal = await el.getProperty('value').then(el => el.jsonValue());
2912
- return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal);
3009
+ const fieldVal = await el.getProperty('value').then((el) => el.jsonValue())
3010
+ return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal)
2913
3011
  }
2914
3012
 
2915
3013
  async function filterFieldsByValue(elements, value, onlySelected) {
2916
- const matches = [];
3014
+ const matches = []
2917
3015
  for (const element of elements) {
2918
- const val = await element.getProperty('value').then(el => el.jsonValue());
2919
- let isSelected = true;
3016
+ const val = await element.getProperty('value').then((el) => el.jsonValue())
3017
+ let isSelected = true
2920
3018
  if (onlySelected) {
2921
- isSelected = await elementSelected(element);
3019
+ isSelected = await elementSelected(element)
2922
3020
  }
2923
3021
  if ((value == null || val.indexOf(value) > -1) && isSelected) {
2924
- matches.push(element);
3022
+ matches.push(element)
2925
3023
  }
2926
3024
  }
2927
- return matches;
3025
+ return matches
2928
3026
  }
2929
3027
 
2930
3028
  async function filterFieldsBySelectionState(elements, state) {
2931
- const matches = [];
3029
+ const matches = []
2932
3030
  for (const element of elements) {
2933
- const isSelected = await elementSelected(element);
3031
+ const isSelected = await elementSelected(element)
2934
3032
  if (isSelected === state) {
2935
- matches.push(element);
3033
+ matches.push(element)
2936
3034
  }
2937
3035
  }
2938
- return matches;
3036
+ return matches
2939
3037
  }
2940
3038
 
2941
3039
  async function elementSelected(element) {
2942
- const type = await element.getProperty('type').then(el => el.jsonValue());
3040
+ const type = await element.getProperty('type').then((el) => el.jsonValue())
2943
3041
 
2944
3042
  if (type === 'checkbox' || type === 'radio') {
2945
- return element.getProperty('checked').then(el => el.jsonValue());
3043
+ return element.getProperty('checked').then((el) => el.jsonValue())
2946
3044
  }
2947
- return element.getProperty('selected').then(el => el.jsonValue());
3045
+ return element.getProperty('selected').then((el) => el.jsonValue())
2948
3046
  }
2949
3047
 
2950
3048
  function isFrameLocator(locator) {
2951
- locator = new Locator(locator);
3049
+ locator = new Locator(locator)
2952
3050
  if (locator.isFrame()) {
2953
- const _locator = new Locator(locator);
2954
- return _locator.value;
3051
+ const _locator = new Locator(locator)
3052
+ return _locator.value
2955
3053
  }
2956
- return false;
3054
+ return false
2957
3055
  }
2958
3056
 
2959
3057
  function assertElementExists(res, locator, prefix, suffix) {
2960
3058
  if (!res || res.length === 0) {
2961
- throw new ElementNotFound(locator, prefix, suffix);
3059
+ throw new ElementNotFound(locator, prefix, suffix)
2962
3060
  }
2963
3061
  }
2964
3062
 
2965
3063
  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);
3064
+ const found = document.evaluate(selector, element || document.body, null, 5, null)
3065
+ const res = []
3066
+ let current = null
3067
+ while ((current = found.iterateNext())) {
3068
+ res.push(current)
2971
3069
  }
2972
- return res;
3070
+ return res
2973
3071
  }
2974
3072
 
2975
3073
  async function targetCreatedHandler(page) {
2976
- if (!page) return;
2977
- this.withinLocator = null;
3074
+ if (!page) return
3075
+ this.withinLocator = null
2978
3076
  page.on('load', () => {
2979
- page.$('body')
3077
+ page
3078
+ .$('body')
2980
3079
  .catch(() => null)
2981
- .then(context => this.context = context);
2982
- });
3080
+ .then((context) => (this.context = context))
3081
+ })
2983
3082
  page.on('console', (msg) => {
2984
- this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '));
2985
- consoleLogStore.add(msg);
2986
- });
3083
+ this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg._text || '') + msg.args().join(' '))
3084
+ consoleLogStore.add(msg)
3085
+ })
2987
3086
 
2988
3087
  if (this.options.userAgent) {
2989
- await page.setUserAgent(this.options.userAgent);
3088
+ await page.setUserAgent(this.options.userAgent)
2990
3089
  }
2991
3090
  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 });
3091
+ const dimensions = this.options.windowSize.split('x')
3092
+ const width = parseInt(dimensions[0], 10)
3093
+ const height = parseInt(dimensions[1], 10)
3094
+ await page.setViewport({ width, height })
2996
3095
  }
2997
3096
  }
2998
3097
 
2999
3098
  // BC compatibility for Puppeteer < 10
3000
3099
  async function getClickablePoint(el) {
3001
- if (el.clickablePoint) return el.clickablePoint();
3002
- if (el._clickablePoint) return el._clickablePoint();
3003
- return null;
3100
+ if (el.clickablePoint) return el.clickablePoint()
3101
+ if (el._clickablePoint) return el._clickablePoint()
3102
+ return null
3004
3103
  }
3005
3104
 
3006
3105
  // List of key values to key definitions
3007
3106
  // https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3008
3107
  const keyDefinitionMap = {
3009
- /* 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',
3108
+ 0: 'Digit0',
3109
+ 1: 'Digit1',
3110
+ 2: 'Digit2',
3111
+ 3: 'Digit3',
3112
+ 4: 'Digit4',
3113
+ 5: 'Digit5',
3114
+ 6: 'Digit6',
3115
+ 7: 'Digit7',
3116
+ 8: 'Digit8',
3117
+ 9: 'Digit9',
3118
+ a: 'KeyA',
3119
+ b: 'KeyB',
3120
+ c: 'KeyC',
3121
+ d: 'KeyD',
3122
+ e: 'KeyE',
3123
+ f: 'KeyF',
3124
+ g: 'KeyG',
3125
+ h: 'KeyH',
3126
+ i: 'KeyI',
3127
+ j: 'KeyJ',
3128
+ k: 'KeyK',
3129
+ l: 'KeyL',
3130
+ m: 'KeyM',
3131
+ n: 'KeyN',
3132
+ o: 'KeyO',
3133
+ p: 'KeyP',
3134
+ q: 'KeyQ',
3135
+ r: 'KeyR',
3136
+ s: 'KeyS',
3137
+ t: 'KeyT',
3138
+ u: 'KeyU',
3139
+ v: 'KeyV',
3140
+ w: 'KeyW',
3141
+ x: 'KeyX',
3142
+ y: 'KeyY',
3143
+ z: 'KeyZ',
3046
3144
  ';': 'Semicolon',
3047
3145
  '=': 'Equal',
3048
3146
  ',': 'Comma',
@@ -3053,91 +3151,93 @@ const keyDefinitionMap = {
3053
3151
  '[': 'BracketLeft',
3054
3152
  '\\': 'Backslash',
3055
3153
  ']': 'BracketRight',
3056
- '\'': 'Quote',
3057
- /* eslint-enable quote-props */
3058
- };
3154
+ "'": 'Quote',
3155
+ }
3059
3156
 
3060
3157
  function getNormalizedKey(key) {
3061
- const normalizedKey = getNormalizedKeyAttributeValue(key);
3158
+ const normalizedKey = getNormalizedKeyAttributeValue(key)
3062
3159
  if (key !== normalizedKey) {
3063
- this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`);
3160
+ this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`)
3064
3161
  }
3065
3162
  // Use key definition to ensure correct key is displayed when Shift modifier is active
3066
3163
  if (Object.prototype.hasOwnProperty.call(keyDefinitionMap, normalizedKey)) {
3067
- return keyDefinitionMap[normalizedKey];
3164
+ return keyDefinitionMap[normalizedKey]
3068
3165
  }
3069
- return normalizedKey;
3166
+ return normalizedKey
3070
3167
  }
3071
3168
 
3072
3169
  function highlightActiveElement(element, context) {
3073
3170
  if (this.options.highlightElement && global.debugMode) {
3074
- highlightElement(element, context);
3171
+ highlightElement(element, context)
3075
3172
  }
3076
3173
  }
3077
3174
 
3078
3175
  function _waitForElement(locator, options) {
3079
3176
  try {
3080
- return this.context.waitForXPath(locator.value, options);
3177
+ return this.context.waitForXPath(locator.value, options)
3081
3178
  } catch (e) {
3082
- return this.context.waitForSelector(`::-p-xpath(${locator.value})`, options);
3179
+ return this.context.waitForSelector(`::-p-xpath(${locator.value})`, options)
3083
3180
  }
3084
3181
  }
3085
3182
 
3086
3183
  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;
3184
+ const resqScript = await fs.promises.readFile(require.resolve('resq'), 'utf-8')
3185
+ await this.page.evaluate(resqScript.toString())
3186
+
3187
+ await this.page.evaluate(() => window.resq.waitToLoadReact())
3188
+ const arrayHandle = await this.page.evaluateHandle(
3189
+ (obj) => {
3190
+ const { selector, props, state } = obj
3191
+ let elements = window.resq.resq$$(selector)
3192
+ if (Object.keys(props).length) {
3193
+ elements = elements.byProps(props)
3194
+ }
3195
+ if (Object.keys(state).length) {
3196
+ elements = elements.byState(state)
3116
3197
  }
3117
3198
 
3118
- if (isFragment) {
3119
- nodes = nodes.concat(node);
3120
- } else {
3121
- nodes.push(node);
3199
+ if (!elements.length) {
3200
+ return []
3122
3201
  }
3123
- });
3124
3202
 
3125
- return [...nodes];
3126
- }, {
3127
- selector: locator.react,
3128
- props: locator.props || {},
3129
- state: locator.state || {},
3130
- });
3203
+ // resq returns an array of HTMLElements if the React component is a fragment
3204
+ // this avoids having nested arrays of nodes which the driver does not understand
3205
+ // [[div, div], [div, div]] => [div, div, div, div]
3206
+ let nodes = []
3131
3207
 
3132
- const properties = await arrayHandle.getProperties();
3133
- const result = [];
3208
+ elements.forEach((element) => {
3209
+ let { node, isFragment } = element
3210
+
3211
+ if (!node) {
3212
+ isFragment = true
3213
+ node = element.children
3214
+ }
3215
+
3216
+ if (isFragment) {
3217
+ nodes = nodes.concat(node)
3218
+ } else {
3219
+ nodes.push(node)
3220
+ }
3221
+ })
3222
+
3223
+ return [...nodes]
3224
+ },
3225
+ {
3226
+ selector: locator.react,
3227
+ props: locator.props || {},
3228
+ state: locator.state || {},
3229
+ },
3230
+ )
3231
+
3232
+ const properties = await arrayHandle.getProperties()
3233
+ const result = []
3134
3234
  for (const property of properties.values()) {
3135
- const elementHandle = property.asElement();
3235
+ const elementHandle = property.asElement()
3136
3236
  if (elementHandle) {
3137
- result.push(elementHandle);
3237
+ result.push(elementHandle)
3138
3238
  }
3139
3239
  }
3140
3240
 
3141
- await arrayHandle.dispose();
3142
- return result;
3241
+ await arrayHandle.dispose()
3242
+ return result
3143
3243
  }