codeceptjs 3.6.4 → 3.6.5-beta.1

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