codeceptjs 4.0.0-beta.2 → 4.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/bin/codecept.js +84 -81
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +10 -13
  4. package/lib/assert/empty.js +20 -21
  5. package/lib/assert/equal.js +37 -39
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +46 -47
  8. package/lib/assert/throws.js +13 -11
  9. package/lib/assert/truth.js +19 -22
  10. package/lib/assert.js +4 -2
  11. package/lib/cli.js +57 -49
  12. package/lib/codecept.js +142 -155
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +58 -52
  15. package/lib/command/definitions.js +88 -89
  16. package/lib/command/dryRun.js +71 -68
  17. package/lib/command/generate.js +197 -188
  18. package/lib/command/gherkin/init.js +27 -16
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +40 -38
  22. package/lib/command/init.js +290 -288
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +6 -2
  28. package/lib/command/run-multiple.js +113 -93
  29. package/lib/command/run-rerun.js +20 -25
  30. package/lib/command/run-workers.js +64 -66
  31. package/lib/command/run.js +26 -29
  32. package/lib/command/utils.js +80 -65
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +10 -9
  35. package/lib/container.js +40 -48
  36. package/lib/data/context.js +60 -59
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +26 -20
  40. package/lib/event.js +163 -167
  41. package/lib/heal.js +13 -17
  42. package/lib/helper/AI.js +130 -41
  43. package/lib/helper/ApiDataFactory.js +73 -69
  44. package/lib/helper/Appium.js +413 -382
  45. package/lib/helper/ExpectHelper.js +40 -48
  46. package/lib/helper/FileSystem.js +80 -79
  47. package/lib/helper/GraphQL.js +44 -43
  48. package/lib/helper/GraphQLDataFactory.js +50 -50
  49. package/lib/helper/JSONResponse.js +65 -62
  50. package/lib/helper/Mochawesome.js +28 -28
  51. package/lib/helper/MockServer.js +12 -14
  52. package/lib/helper/Nightmare.js +662 -566
  53. package/lib/helper/Playwright.js +1361 -1216
  54. package/lib/helper/Protractor.js +663 -627
  55. package/lib/helper/Puppeteer.js +1231 -1128
  56. package/lib/helper/REST.js +159 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -484
  59. package/lib/helper/WebDriver.js +1297 -1156
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +3 -2
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +6 -7
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +6 -10
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +6 -10
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +40 -33
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +115 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -2
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -32
  136. package/package.json +56 -57
  137. package/translations/de-DE.js +1 -1
  138. package/translations/fr-FR.js +1 -1
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +415 -65
  148. package/typings/promiseBasedTypes.d.ts +32 -0
  149. package/typings/types.d.ts +32 -0
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
@@ -1,17 +1,18 @@
1
- import path from 'path';
2
- import fs from 'fs';
3
- import Helper from '@codeceptjs/helper';
4
- import { v4 as uuidv4 } from 'uuid';
5
- import assert from 'assert';
6
- import promiseRetry from 'promise-retry';
7
- import Locator from '../locator.js';
8
- import recorder from '../recorder.js';
9
- import { includes as stringIncludes } from '../assert/include.js';
10
- import { urlEquals, equals } from '../assert/equal.js';
11
- import { empty } from '../assert/empty.js';
12
- import { truth } from '../assert/truth.js';
13
-
14
- import {
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+
4
+ const Helper = require('@codeceptjs/helper')
5
+ const { v4: uuidv4 } = require('uuid')
6
+ const assert = require('assert')
7
+ const promiseRetry = require('promise-retry')
8
+ const Locator = require('../locator')
9
+ const recorder = require('../recorder')
10
+ const stringIncludes = require('../assert/include').includes
11
+ const { urlEquals } = require('../assert/equal')
12
+ const { equals } = require('../assert/equal')
13
+ const { empty } = require('../assert/empty')
14
+ const { truth } = require('../assert/truth')
15
+ const {
15
16
  xpathLocator,
16
17
  ucfirst,
17
18
  fileExists,
@@ -23,40 +24,44 @@ import {
23
24
  clearString,
24
25
  requireWithFallback,
25
26
  normalizeSpacesInString,
26
- } from '../utils.js';
27
-
28
- import { isColorProperty, convertColorToRGBA } from '../colorUtils.js';
29
- import ElementNotFound from './errors/ElementNotFound.js';
30
- import RemoteBrowserConnectionRefused from './errors/RemoteBrowserConnectionRefused.js';
31
- import Popup from './extras/Popup.js';
32
- import Console from './extras/Console.js';
33
- import { findByPlaywrightLocator, findReact, findVue } from './extras/PlaywrightReactVueLocator.js';
34
-
35
- import {
36
- setRestartStrategy, restartsSession, restartsContext, restartsBrowser,
37
- } from './extras/PlaywrightRestartOpts.js';
38
- import { createValueEngine, createDisabledEngine } from './extras/PlaywrightPropEngine.js';
39
-
40
- import {
27
+ } = require('../utils')
28
+ const { isColorProperty, convertColorToRGBA } = require('../colorUtils')
29
+ const ElementNotFound = require('./errors/ElementNotFound')
30
+ const RemoteBrowserConnectionRefused = require('./errors/RemoteBrowserConnectionRefused')
31
+ const Popup = require('./extras/Popup')
32
+ const Console = require('./extras/Console')
33
+ const { findReact, findVue, findByPlaywrightLocator } = require('./extras/PlaywrightReactVueLocator')
34
+
35
+ let playwright
36
+ let perfTiming
37
+ let defaultSelectorEnginesInitialized = false
38
+
39
+ const popupStore = new Popup()
40
+ const consoleLogStore = new Console()
41
+ const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron']
42
+
43
+ const {
44
+ setRestartStrategy,
45
+ restartsSession,
46
+ restartsContext,
47
+ restartsBrowser,
48
+ } = require('./extras/PlaywrightRestartOpts')
49
+ const { createValueEngine, createDisabledEngine } = require('./extras/PlaywrightPropEngine')
50
+ const {
41
51
  seeElementError,
42
52
  dontSeeElementError,
43
53
  dontSeeElementInDOMError,
44
54
  seeElementInDOMError,
45
- } from './errors/ElementAssertion.js';
46
-
47
- import {
48
- dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics,
49
- } from './network/actions.js';
50
-
51
- let playwright;
52
- let perfTiming;
53
- let defaultSelectorEnginesInitialized = false;
55
+ } = require('./errors/ElementAssertion')
56
+ const {
57
+ dontSeeTraffic,
58
+ seeTraffic,
59
+ grabRecordedNetworkTraffics,
60
+ stopRecordingTraffic,
61
+ flushNetworkTraffics,
62
+ } = require('./network/actions')
54
63
 
55
- const popupStore = new Popup();
56
- const consoleLogStore = new Console();
57
- const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron'];
58
-
59
- const pathSeparator = path.sep;
64
+ const pathSeparator = path.sep
60
65
 
61
66
  /**
62
67
  * ## Configuration
@@ -105,7 +110,7 @@ const pathSeparator = path.sep;
105
110
  * @prop {object} [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
106
111
  * @prop {string} [testIdAttribute=data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
107
112
  */
108
- const config = {};
113
+ const config = {}
109
114
 
110
115
  /**
111
116
  * Uses [Playwright](https://github.com/microsoft/playwright) library to run tests inside:
@@ -327,34 +332,34 @@ const config = {};
327
332
  */
328
333
  class Playwright extends Helper {
329
334
  constructor(config) {
330
- super(config);
335
+ super(config)
331
336
 
332
- playwright = requireWithFallback('playwright', 'playwright-core');
337
+ playwright = requireWithFallback('playwright', 'playwright-core')
333
338
 
334
339
  // set defaults
335
- this.isRemoteBrowser = false;
336
- this.isRunning = false;
337
- this.isAuthenticated = false;
338
- this.sessionPages = {};
339
- this.activeSessionName = '';
340
- this.isElectron = false;
341
- this.isCDPConnection = false;
342
- this.electronSessions = [];
343
- this.storageState = null;
340
+ this.isRemoteBrowser = false
341
+ this.isRunning = false
342
+ this.isAuthenticated = false
343
+ this.sessionPages = {}
344
+ this.activeSessionName = ''
345
+ this.isElectron = false
346
+ this.isCDPConnection = false
347
+ this.electronSessions = []
348
+ this.storageState = null
344
349
 
345
350
  // for network stuff
346
- this.requests = [];
347
- this.recording = false;
348
- this.recordedAtLeastOnce = false;
351
+ this.requests = []
352
+ this.recording = false
353
+ this.recordedAtLeastOnce = false
349
354
 
350
355
  // for websocket messages
351
- this.webSocketMessages = [];
352
- this.recordingWebSocketMessages = false;
353
- this.recordedWebSocketMessagesAtLeastOnce = false;
354
- this.cdpSession = null;
356
+ this.webSocketMessages = []
357
+ this.recordingWebSocketMessages = false
358
+ this.recordedWebSocketMessagesAtLeastOnce = false
359
+ this.cdpSession = null
355
360
 
356
361
  // override defaults with config
357
- this._setConfig(config);
362
+ this._setConfig(config)
358
363
  }
359
364
 
360
365
  _validateConfig(config) {
@@ -381,54 +386,65 @@ class Playwright extends Helper {
381
386
  use: { actionTimeout: 0 },
382
387
  ignoreHTTPSErrors: false, // Adding it here o that context can be set up to ignore the SSL errors,
383
388
  highlightElement: false,
384
- };
389
+ }
385
390
 
386
- process.env.testIdAttribute = 'data-testid';
387
- config = Object.assign(defaults, config);
391
+ process.env.testIdAttribute = 'data-testid'
392
+ config = Object.assign(defaults, config)
388
393
 
389
394
  if (availableBrowsers.indexOf(config.browser) < 0) {
390
- throw new Error(`Invalid config. Can't use browser "${config.browser}". Accepted values: ${availableBrowsers.join(', ')}`);
395
+ throw new Error(
396
+ `Invalid config. Can't use browser "${config.browser}". Accepted values: ${availableBrowsers.join(', ')}`,
397
+ )
391
398
  }
392
399
 
393
- return config;
400
+ return config
394
401
  }
395
402
 
396
403
  _getOptionsForBrowser(config) {
397
404
  if (config[config.browser]) {
398
405
  if (config[config.browser].browserWSEndpoint && config[config.browser].browserWSEndpoint.wsEndpoint) {
399
- config[config.browser].browserWSEndpoint = config[config.browser].browserWSEndpoint.wsEndpoint;
406
+ config[config.browser].browserWSEndpoint = config[config.browser].browserWSEndpoint.wsEndpoint
400
407
  }
401
408
  return {
402
409
  ...config[config.browser],
403
410
  wsEndpoint: config[config.browser].browserWSEndpoint,
404
- };
411
+ }
405
412
  }
406
- return {};
413
+ return {}
407
414
  }
408
415
 
409
416
  _setConfig(config) {
410
- this.options = this._validateConfig(config);
411
- setRestartStrategy(this.options);
417
+ this.options = this._validateConfig(config)
418
+ setRestartStrategy(this.options)
412
419
  this.playwrightOptions = {
413
420
  headless: !this.options.show,
414
421
  ...this._getOptionsForBrowser(config),
415
- };
422
+ }
416
423
 
417
424
  if (this.options.channel && this.options.browser === 'chromium') {
418
- this.playwrightOptions.channel = this.options.channel;
425
+ this.playwrightOptions.channel = this.options.channel
419
426
  }
420
427
 
421
428
  if (this.options.video) {
422
- this.options.recordVideo = { size: parseWindowSize(this.options.windowSize) };
429
+ // set the video resolution with window size
430
+ let size = parseWindowSize(this.options.windowSize)
431
+
432
+ // if the video resolution is passed, set the record resoultion with that resolution
433
+ if (this.options.recordVideo && this.options.recordVideo.size) {
434
+ size = parseWindowSize(this.options.recordVideo.size)
435
+ }
436
+ this.options.recordVideo = { size }
423
437
  }
424
438
  if (this.options.recordVideo && !this.options.recordVideo.dir) {
425
- this.options.recordVideo.dir = `${global.output_dir}/videos/`;
439
+ this.options.recordVideo.dir = `${global.output_dir}/videos/`
426
440
  }
427
- this.isRemoteBrowser = !!this.playwrightOptions.browserWSEndpoint;
428
- this.isElectron = this.options.browser === 'electron';
429
- this.userDataDir = this.playwrightOptions.userDataDir ? `${this.playwrightOptions.userDataDir}_${Date.now().toString()}` : undefined;
430
- this.isCDPConnection = this.playwrightOptions.cdpConnection;
431
- popupStore.defaultAction = this.options.defaultPopupAction;
441
+ this.isRemoteBrowser = !!this.playwrightOptions.browserWSEndpoint
442
+ this.isElectron = this.options.browser === 'electron'
443
+ this.userDataDir = this.playwrightOptions.userDataDir
444
+ ? `${this.playwrightOptions.userDataDir}_${Date.now().toString()}`
445
+ : undefined
446
+ this.isCDPConnection = this.playwrightOptions.cdpConnection
447
+ popupStore.defaultAction = this.options.defaultPopupAction
432
448
  }
433
449
 
434
450
  static _config() {
@@ -451,216 +467,222 @@ class Playwright extends Helper {
451
467
  type: 'confirm',
452
468
  when: (answers) => answers.Playwright_browser !== 'electron',
453
469
  },
454
- ];
470
+ ]
455
471
  }
456
472
 
457
473
  static _checkRequirements() {
458
474
  try {
459
- requireWithFallback('playwright', 'playwright-core');
475
+ requireWithFallback('playwright', 'playwright-core')
460
476
  } catch (e) {
461
- return ['playwright@^1.18'];
477
+ return ['playwright@^1.18']
462
478
  }
463
479
  }
464
480
 
465
481
  async _init() {
466
482
  // register an internal selector engine for reading value property of elements in a selector
467
- if (defaultSelectorEnginesInitialized) return;
468
- defaultSelectorEnginesInitialized = true;
483
+ if (defaultSelectorEnginesInitialized) return
484
+ defaultSelectorEnginesInitialized = true
469
485
  try {
470
- await playwright.selectors.register('__value', createValueEngine);
471
- await playwright.selectors.register('__disabled', createDisabledEngine);
472
- if (process.env.testIdAttribute) await playwright.selectors.setTestIdAttribute(process.env.testIdAttribute);
486
+ await playwright.selectors.register('__value', createValueEngine)
487
+ await playwright.selectors.register('__disabled', createDisabledEngine)
488
+ if (process.env.testIdAttribute) await playwright.selectors.setTestIdAttribute(process.env.testIdAttribute)
473
489
  } catch (e) {
474
- console.warn(e);
490
+ console.warn(e)
475
491
  }
476
492
  }
477
493
 
478
494
  _beforeSuite() {
479
495
  if ((restartsSession() || restartsContext()) && !this.options.manualStart && !this.isRunning) {
480
- this.debugSection('Session', 'Starting singleton browser session');
481
- return this._startBrowser();
496
+ this.debugSection('Session', 'Starting singleton browser session')
497
+ return this._startBrowser()
482
498
  }
483
499
  }
484
500
 
485
501
  async _before(test) {
486
- this.currentRunningTest = test;
502
+ this.currentRunningTest = test
487
503
  recorder.retry({
488
504
  retries: process.env.FAILED_STEP_RETRIES || 3,
489
- when: err => {
490
- if (!err || typeof (err.message) !== 'string') {
491
- return false;
505
+ when: (err) => {
506
+ if (!err || typeof err.message !== 'string') {
507
+ return false
492
508
  }
493
509
  // ignore context errors
494
- return err.message.includes('context');
510
+ return err.message.includes('context')
495
511
  },
496
- });
512
+ })
497
513
 
498
- if (restartsBrowser() && !this.options.manualStart) await this._startBrowser();
499
- if (!this.isRunning && !this.options.manualStart) await this._startBrowser();
514
+ if (restartsBrowser() && !this.options.manualStart) await this._startBrowser()
515
+ if (!this.isRunning && !this.options.manualStart) await this._startBrowser()
500
516
 
501
- this.isAuthenticated = false;
517
+ this.isAuthenticated = false
502
518
  if (this.isElectron) {
503
- this.browserContext = this.browser.context();
519
+ this.browserContext = this.browser.context()
504
520
  } else if (this.playwrightOptions.userDataDir) {
505
- this.browserContext = this.browser;
521
+ this.browserContext = this.browser
506
522
  } else {
507
523
  const contextOptions = {
508
524
  ignoreHTTPSErrors: this.options.ignoreHTTPSErrors,
509
525
  acceptDownloads: true,
510
526
  ...this.options.emulate,
511
- };
527
+ }
512
528
  if (this.options.basicAuth) {
513
- contextOptions.httpCredentials = this.options.basicAuth;
514
- this.isAuthenticated = true;
529
+ contextOptions.httpCredentials = this.options.basicAuth
530
+ this.isAuthenticated = true
515
531
  }
516
- if (this.options.bypassCSP) contextOptions.bypassCSP = this.options.bypassCSP;
517
- if (this.options.recordVideo) contextOptions.recordVideo = this.options.recordVideo;
532
+ if (this.options.bypassCSP) contextOptions.bypassCSP = this.options.bypassCSP
533
+ if (this.options.recordVideo) contextOptions.recordVideo = this.options.recordVideo
518
534
  if (this.options.recordHar) {
519
- const harExt = this.options.recordHar.content && this.options.recordHar.content === 'attach' ? 'zip' : 'har';
520
- const fileName = `${`${global.output_dir}${path.sep}har${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.${harExt}`;
521
- const dir = path.dirname(fileName);
522
- if (!fileExists(dir)) fs.mkdirSync(dir);
523
- this.options.recordHar.path = fileName;
524
- this.currentRunningTest.artifacts.har = fileName;
525
- contextOptions.recordHar = this.options.recordHar;
535
+ const harExt = this.options.recordHar.content && this.options.recordHar.content === 'attach' ? 'zip' : 'har'
536
+ const fileName = `${`${global.output_dir}${path.sep}har${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.${harExt}`
537
+ const dir = path.dirname(fileName)
538
+ if (!fileExists(dir)) fs.mkdirSync(dir)
539
+ this.options.recordHar.path = fileName
540
+ this.currentRunningTest.artifacts.har = fileName
541
+ contextOptions.recordHar = this.options.recordHar
526
542
  }
527
- if (this.storageState) contextOptions.storageState = this.storageState;
528
- if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent;
529
- if (this.options.locale) contextOptions.locale = this.options.locale;
530
- if (this.options.colorScheme) contextOptions.colorScheme = this.options.colorScheme;
531
- this.contextOptions = contextOptions;
543
+ if (this.storageState) contextOptions.storageState = this.storageState
544
+ if (this.options.userAgent) contextOptions.userAgent = this.options.userAgent
545
+ if (this.options.locale) contextOptions.locale = this.options.locale
546
+ if (this.options.colorScheme) contextOptions.colorScheme = this.options.colorScheme
547
+ this.contextOptions = contextOptions
532
548
  if (!this.browserContext || !restartsSession()) {
533
- this.browserContext = await this.browser.newContext(this.contextOptions); // Adding the HTTPSError ignore in the context so that we can ignore those errors
549
+ this.browserContext = await this.browser.newContext(this.contextOptions) // Adding the HTTPSError ignore in the context so that we can ignore those errors
534
550
  }
535
551
  }
536
552
 
537
- let mainPage;
553
+ let mainPage
538
554
  if (this.isElectron) {
539
- mainPage = await this.browser.firstWindow();
555
+ mainPage = await this.browser.firstWindow()
540
556
  } else {
541
557
  try {
542
- const existingPages = await this.browserContext.pages();
543
- mainPage = existingPages[0] || (await this.browserContext.newPage());
558
+ const existingPages = await this.browserContext.pages()
559
+ mainPage = existingPages[0] || (await this.browserContext.newPage())
544
560
  } catch (e) {
545
561
  if (this.playwrightOptions.userDataDir) {
546
- this.browser = await playwright[this.options.browser].launchPersistentContext(this.userDataDir, this.playwrightOptions);
547
- this.browserContext = this.browser;
548
- const existingPages = await this.browserContext.pages();
549
- mainPage = existingPages[0];
562
+ this.browser = await playwright[this.options.browser].launchPersistentContext(
563
+ this.userDataDir,
564
+ this.playwrightOptions,
565
+ )
566
+ this.browserContext = this.browser
567
+ const existingPages = await this.browserContext.pages()
568
+ mainPage = existingPages[0]
550
569
  }
551
570
  }
552
571
  }
553
- await targetCreatedHandler.call(this, mainPage);
572
+ await targetCreatedHandler.call(this, mainPage)
554
573
 
555
- await this._setPage(mainPage);
574
+ await this._setPage(mainPage)
556
575
 
557
- if (this.options.trace) await this.browserContext.tracing.start({ screenshots: true, snapshots: true });
576
+ if (this.options.trace) await this.browserContext.tracing.start({ screenshots: true, snapshots: true })
558
577
 
559
- return this.browser;
578
+ return this.browser
560
579
  }
561
580
 
562
581
  async _after() {
563
- if (!this.isRunning) return;
582
+ if (!this.isRunning) return
564
583
 
565
584
  if (this.isElectron) {
566
- this.browser.close();
567
- this.electronSessions.forEach(session => session.close());
568
- return;
585
+ this.browser.close()
586
+ this.electronSessions.forEach((session) => session.close())
587
+ return
569
588
  }
570
589
 
571
590
  if (restartsSession()) {
572
- return refreshContextSession.bind(this)();
591
+ return refreshContextSession.bind(this)()
573
592
  }
574
593
 
575
594
  if (restartsBrowser()) {
576
- this.isRunning = false;
577
- return this._stopBrowser();
595
+ this.isRunning = false
596
+ return this._stopBrowser()
578
597
  }
579
598
 
580
599
  // close other sessions
581
600
  try {
582
601
  if ((await this.browser)._type === 'Browser') {
583
- const contexts = await this.browser.contexts();
584
- const currentContext = contexts[0];
602
+ const contexts = await this.browser.contexts()
603
+ const currentContext = contexts[0]
585
604
  if (currentContext && (this.options.keepCookies || this.options.keepBrowserState)) {
586
- this.storageState = await currentContext.storageState();
605
+ this.storageState = await currentContext.storageState()
587
606
  }
588
607
 
589
- await Promise.all(contexts.map(c => c.close()));
608
+ await Promise.all(contexts.map((c) => c.close()))
590
609
  }
591
610
  } catch (e) {
592
- console.log(e);
611
+ console.log(e)
593
612
  }
594
613
 
595
614
  // await this.closeOtherTabs();
596
- return this.browser;
615
+ return this.browser
597
616
  }
598
617
 
599
618
  _afterSuite() {}
600
619
 
601
620
  async _finishTest() {
602
- if ((restartsSession() || restartsContext()) && this.isRunning) return this._stopBrowser();
621
+ if ((restartsSession() || restartsContext()) && this.isRunning) return this._stopBrowser()
603
622
  }
604
623
 
605
624
  _session() {
606
- const defaultContext = this.browserContext;
625
+ const defaultContext = this.browserContext
607
626
  return {
608
627
  start: async (sessionName = '', config) => {
609
- this.debugSection('New Context', config ? JSON.stringify(config) : 'opened');
610
- this.activeSessionName = sessionName;
628
+ this.debugSection('New Context', config ? JSON.stringify(config) : 'opened')
629
+ this.activeSessionName = sessionName
611
630
 
612
- let browserContext;
613
- let page;
631
+ let browserContext
632
+ let page
614
633
  if (this.isElectron) {
615
- const browser = await playwright._electron.launch(this.playwrightOptions);
616
- this.electronSessions.push(browser);
617
- browserContext = browser.context();
618
- page = await browser.firstWindow();
634
+ const browser = await playwright._electron.launch(this.playwrightOptions)
635
+ this.electronSessions.push(browser)
636
+ browserContext = browser.context()
637
+ page = await browser.firstWindow()
619
638
  } else {
620
639
  try {
621
- browserContext = await this.browser.newContext(Object.assign(this.contextOptions, config));
622
- page = await browserContext.newPage();
640
+ browserContext = await this.browser.newContext(Object.assign(this.contextOptions, config))
641
+ page = await browserContext.newPage()
623
642
  } catch (e) {
624
643
  if (this.playwrightOptions.userDataDir) {
625
- browserContext = await playwright[this.options.browser].launchPersistentContext(`${this.userDataDir}_${this.activeSessionName}`, this.playwrightOptions);
626
- this.browser = browserContext;
627
- page = await browserContext.pages()[0];
644
+ browserContext = await playwright[this.options.browser].launchPersistentContext(
645
+ `${this.userDataDir}_${this.activeSessionName}`,
646
+ this.playwrightOptions,
647
+ )
648
+ this.browser = browserContext
649
+ page = await browserContext.pages()[0]
628
650
  }
629
651
  }
630
652
  }
631
653
 
632
- if (this.options.trace) await browserContext.tracing.start({ screenshots: true, snapshots: true });
633
- await targetCreatedHandler.call(this, page);
634
- await this._setPage(page);
654
+ if (this.options.trace) await browserContext.tracing.start({ screenshots: true, snapshots: true })
655
+ await targetCreatedHandler.call(this, page)
656
+ await this._setPage(page)
635
657
  // Create a new page inside context.
636
- return browserContext;
658
+ return browserContext
637
659
  },
638
660
  stop: async () => {
639
661
  // is closed by _after
640
662
  },
641
663
  loadVars: async (context) => {
642
664
  if (context) {
643
- this.browserContext = context;
644
- const existingPages = await context.pages();
645
- this.sessionPages[this.activeSessionName] = existingPages[0];
646
- return this._setPage(this.sessionPages[this.activeSessionName]);
665
+ this.browserContext = context
666
+ const existingPages = await context.pages()
667
+ this.sessionPages[this.activeSessionName] = existingPages[0]
668
+ return this._setPage(this.sessionPages[this.activeSessionName])
647
669
  }
648
670
  },
649
671
  restoreVars: async (session) => {
650
- this.withinLocator = null;
651
- this.browserContext = defaultContext;
672
+ this.withinLocator = null
673
+ this.browserContext = defaultContext
652
674
 
653
675
  if (!session) {
654
- this.activeSessionName = '';
676
+ this.activeSessionName = ''
655
677
  } else {
656
- this.activeSessionName = session;
678
+ this.activeSessionName = session
657
679
  }
658
- const existingPages = await this.browserContext.pages();
659
- await this._setPage(existingPages[0]);
680
+ const existingPages = await this.browserContext.pages()
681
+ await this._setPage(existingPages[0])
660
682
 
661
- return this._waitForAction();
683
+ return this._waitForAction()
662
684
  },
663
- };
685
+ }
664
686
  }
665
687
 
666
688
  /**
@@ -681,7 +703,7 @@ class Playwright extends Helper {
681
703
  * @param {function} fn async function that executed with Playwright helper as arguments
682
704
  */
683
705
  usePlaywrightTo(description, fn) {
684
- return this._useTo(...arguments);
706
+ return this._useTo(...arguments)
685
707
  }
686
708
 
687
709
  /**
@@ -695,7 +717,7 @@ class Playwright extends Helper {
695
717
  * ```
696
718
  */
697
719
  amAcceptingPopups() {
698
- popupStore.actionType = 'accept';
720
+ popupStore.actionType = 'accept'
699
721
  }
700
722
 
701
723
  /**
@@ -704,7 +726,7 @@ class Playwright extends Helper {
704
726
  * libraries](http://jster.net/category/windows-modals-popups).
705
727
  */
706
728
  acceptPopup() {
707
- popupStore.assertPopupActionType('accept');
729
+ popupStore.assertPopupActionType('accept')
708
730
  }
709
731
 
710
732
  /**
@@ -718,23 +740,23 @@ class Playwright extends Helper {
718
740
  * ```
719
741
  */
720
742
  amCancellingPopups() {
721
- popupStore.actionType = 'cancel';
743
+ popupStore.actionType = 'cancel'
722
744
  }
723
745
 
724
746
  /**
725
747
  * Dismisses the active JavaScript popup, as created by window.alert|window.confirm|window.prompt.
726
748
  */
727
749
  cancelPopup() {
728
- popupStore.assertPopupActionType('cancel');
750
+ popupStore.assertPopupActionType('cancel')
729
751
  }
730
752
 
731
753
  /**
732
754
  * {{> seeInPopup }}
733
755
  */
734
756
  async seeInPopup(text) {
735
- popupStore.assertPopupVisible();
736
- const popupText = await popupStore.popup.message();
737
- stringIncludes('text in popup').assert(text, popupText);
757
+ popupStore.assertPopupVisible()
758
+ const popupText = await popupStore.popup.message()
759
+ stringIncludes('text in popup').assert(text, popupText)
738
760
  }
739
761
 
740
762
  /**
@@ -742,21 +764,21 @@ class Playwright extends Helper {
742
764
  * @param {object} page page to set
743
765
  */
744
766
  async _setPage(page) {
745
- page = await page;
746
- this._addPopupListener(page);
747
- this.page = page;
748
- if (!page) return;
749
- this.browserContext.setDefaultTimeout(0);
750
- page.setDefaultNavigationTimeout(this.options.getPageTimeout);
751
- page.setDefaultTimeout(this.options.timeout);
767
+ page = await page
768
+ this._addPopupListener(page)
769
+ this.page = page
770
+ if (!page) return
771
+ this.browserContext.setDefaultTimeout(0)
772
+ page.setDefaultNavigationTimeout(this.options.getPageTimeout)
773
+ page.setDefaultTimeout(this.options.timeout)
752
774
 
753
775
  page.on('crash', async () => {
754
- console.log('ERROR: Page has crashed, closing page!');
755
- await page.close();
756
- });
757
- this.context = await this.page;
758
- this.contextLocator = null;
759
- await page.bringToFront();
776
+ console.log('ERROR: Page has crashed, closing page!')
777
+ await page.close()
778
+ })
779
+ this.context = await this.page
780
+ this.contextLocator = null
781
+ await page.bringToFront()
760
782
  }
761
783
 
762
784
  /**
@@ -768,33 +790,33 @@ class Playwright extends Helper {
768
790
  */
769
791
  _addPopupListener(page) {
770
792
  if (!page) {
771
- return;
793
+ return
772
794
  }
773
- page.removeAllListeners('dialog');
795
+ page.removeAllListeners('dialog')
774
796
  page.on('dialog', async (dialog) => {
775
- popupStore.popup = dialog;
776
- const action = popupStore.actionType || this.options.defaultPopupAction;
777
- await this._waitForAction();
797
+ popupStore.popup = dialog
798
+ const action = popupStore.actionType || this.options.defaultPopupAction
799
+ await this._waitForAction()
778
800
 
779
801
  switch (action) {
780
802
  case 'accept':
781
- return dialog.accept();
803
+ return dialog.accept()
782
804
 
783
805
  case 'cancel':
784
- return dialog.dismiss();
806
+ return dialog.dismiss()
785
807
 
786
808
  default: {
787
- throw new Error('Unknown popup action type. Only "accept" or "cancel" are accepted');
809
+ throw new Error('Unknown popup action type. Only "accept" or "cancel" are accepted')
788
810
  }
789
811
  }
790
- });
812
+ })
791
813
  }
792
814
 
793
815
  /**
794
816
  * Gets page URL including hash.
795
817
  */
796
818
  async _getPageUrl() {
797
- return this.executeScript(() => window.location.href);
819
+ return this.executeScript(() => window.location.href)
798
820
  }
799
821
 
800
822
  /**
@@ -807,45 +829,48 @@ class Playwright extends Helper {
807
829
  */
808
830
  async grabPopupText() {
809
831
  if (popupStore.popup) {
810
- return popupStore.popup.message();
832
+ return popupStore.popup.message()
811
833
  }
812
- return null;
834
+ return null
813
835
  }
814
836
 
815
837
  async _startBrowser() {
816
838
  if (this.isElectron) {
817
- this.browser = await playwright._electron.launch(this.playwrightOptions);
839
+ this.browser = await playwright._electron.launch(this.playwrightOptions)
818
840
  } else if (this.isRemoteBrowser && this.isCDPConnection) {
819
841
  try {
820
- this.browser = await playwright[this.options.browser].connectOverCDP(this.playwrightOptions);
842
+ this.browser = await playwright[this.options.browser].connectOverCDP(this.playwrightOptions)
821
843
  } catch (err) {
822
844
  if (err.toString().indexOf('ECONNREFUSED')) {
823
- throw new RemoteBrowserConnectionRefused(err);
845
+ throw new RemoteBrowserConnectionRefused(err)
824
846
  }
825
- throw err;
847
+ throw err
826
848
  }
827
849
  } else if (this.isRemoteBrowser) {
828
850
  try {
829
- this.browser = await playwright[this.options.browser].connect(this.playwrightOptions);
851
+ this.browser = await playwright[this.options.browser].connect(this.playwrightOptions)
830
852
  } catch (err) {
831
853
  if (err.toString().indexOf('ECONNREFUSED')) {
832
- throw new RemoteBrowserConnectionRefused(err);
854
+ throw new RemoteBrowserConnectionRefused(err)
833
855
  }
834
- throw err;
856
+ throw err
835
857
  }
836
858
  } else if (this.playwrightOptions.userDataDir) {
837
- this.browser = await playwright[this.options.browser].launchPersistentContext(this.userDataDir, this.playwrightOptions);
859
+ this.browser = await playwright[this.options.browser].launchPersistentContext(
860
+ this.userDataDir,
861
+ this.playwrightOptions,
862
+ )
838
863
  } else {
839
- this.browser = await playwright[this.options.browser].launch(this.playwrightOptions);
864
+ this.browser = await playwright[this.options.browser].launch(this.playwrightOptions)
840
865
  }
841
866
 
842
867
  // works only for Chromium
843
868
  this.browser.on('targetchanged', (target) => {
844
- this.debugSection('Url', target.url());
845
- });
869
+ this.debugSection('Url', target.url())
870
+ })
846
871
 
847
- this.isRunning = true;
848
- return this.browser;
872
+ this.isRunning = true
873
+ return this.browser
849
874
  }
850
875
 
851
876
  /**
@@ -854,72 +879,72 @@ class Playwright extends Helper {
854
879
  * @param {object} [contextOptions] See https://playwright.dev/docs/api/class-browser#browser-new-context
855
880
  */
856
881
  async _createContextPage(contextOptions) {
857
- this.browserContext = await this.browser.newContext(contextOptions);
858
- const page = await this.browserContext.newPage();
859
- targetCreatedHandler.call(this, page);
860
- await this._setPage(page);
882
+ this.browserContext = await this.browser.newContext(contextOptions)
883
+ const page = await this.browserContext.newPage()
884
+ targetCreatedHandler.call(this, page)
885
+ await this._setPage(page)
861
886
  }
862
887
 
863
888
  _getType() {
864
- return this.browser._type;
889
+ return this.browser._type
865
890
  }
866
891
 
867
892
  async _stopBrowser() {
868
- this.withinLocator = null;
869
- await this._setPage(null);
870
- this.context = null;
871
- this.frame = null;
872
- popupStore.clear();
873
- if (this.options.recordHar) await this.browserContext.close();
874
- await this.browser.close();
893
+ this.withinLocator = null
894
+ await this._setPage(null)
895
+ this.context = null
896
+ this.frame = null
897
+ popupStore.clear()
898
+ if (this.options.recordHar) await this.browserContext.close()
899
+ await this.browser.close()
875
900
  }
876
901
 
877
902
  async _evaluateHandeInContext(...args) {
878
- const context = await this._getContext();
879
- return context.evaluateHandle(...args);
903
+ const context = await this._getContext()
904
+ return context.evaluateHandle(...args)
880
905
  }
881
906
 
882
907
  async _withinBegin(locator) {
883
908
  if (this.withinLocator) {
884
- throw new Error('Can\'t start within block inside another within block');
909
+ throw new Error("Can't start within block inside another within block")
885
910
  }
886
911
 
887
- const frame = isFrameLocator(locator);
912
+ const frame = isFrameLocator(locator)
888
913
 
889
914
  if (frame) {
890
915
  if (Array.isArray(frame)) {
891
- await this.switchTo(null);
892
- return frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve());
916
+ await this.switchTo(null)
917
+ return frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve())
893
918
  }
894
- await this.switchTo(frame);
895
- this.withinLocator = new Locator(frame);
896
- return;
919
+ await this.switchTo(frame)
920
+ this.withinLocator = new Locator(frame)
921
+ return
897
922
  }
898
923
 
899
- const el = await this._locateElement(locator);
900
- assertElementExists(el, locator);
901
- this.context = el;
902
- this.contextLocator = locator;
924
+ const el = await this._locateElement(locator)
925
+ assertElementExists(el, locator)
926
+ this.context = el
927
+ this.contextLocator = locator
903
928
 
904
- this.withinLocator = new Locator(locator);
929
+ this.withinLocator = new Locator(locator)
905
930
  }
906
931
 
907
932
  async _withinEnd() {
908
- this.withinLocator = null;
909
- this.context = await this.page;
910
- this.contextLocator = null;
911
- this.frame = null;
933
+ this.withinLocator = null
934
+ this.context = await this.page
935
+ this.contextLocator = null
936
+ this.frame = null
912
937
  }
913
938
 
914
939
  _extractDataFromPerformanceTiming(timing, ...dataNames) {
915
- const navigationStart = timing.navigationStart;
940
+ const navigationStart = timing.navigationStart
916
941
 
917
- const extractedData = {};
942
+ const extractedData = {}
918
943
  dataNames.forEach((name) => {
919
- extractedData[name] = timing[name] - navigationStart;
920
- });
944
+ extractedData[name] = timing[name] - navigationStart
945
+ })
921
946
 
922
- return extractedData;
947
+ return extractedData
923
948
  }
924
949
 
925
950
  /**
@@ -927,22 +952,22 @@ class Playwright extends Helper {
927
952
  */
928
953
  async amOnPage(url) {
929
954
  if (this.isElectron) {
930
- throw new Error('Cannot open pages inside an Electron container');
955
+ throw new Error('Cannot open pages inside an Electron container')
931
956
  }
932
- if (!(/^\w+\:(\/\/|.+)/.test(url))) {
933
- url = this.options.url + (url.startsWith('/') ? url : `/${url}`);
957
+ if (!/^\w+\:(\/\/|.+)/.test(url)) {
958
+ url = this.options.url + (url.startsWith('/') ? url : `/${url}`)
934
959
  }
935
960
 
936
- if (this.options.basicAuth && (this.isAuthenticated !== true)) {
961
+ if (this.options.basicAuth && this.isAuthenticated !== true) {
937
962
  if (url.includes(this.options.url)) {
938
- await this.browserContext.setHTTPCredentials(this.options.basicAuth);
939
- this.isAuthenticated = true;
963
+ await this.browserContext.setHTTPCredentials(this.options.basicAuth)
964
+ this.isAuthenticated = true
940
965
  }
941
966
  }
942
967
 
943
- await this.page.goto(url, { waitUntil: this.options.waitForNavigation });
968
+ await this.page.goto(url, { waitUntil: this.options.waitForNavigation })
944
969
 
945
- const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)));
970
+ const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing)))
946
971
 
947
972
  perfTiming = this._extractDataFromPerformanceTiming(
948
973
  performanceTiming,
@@ -950,9 +975,9 @@ class Playwright extends Helper {
950
975
  'domInteractive',
951
976
  'domContentLoadedEventEnd',
952
977
  'loadEventEnd',
953
- );
978
+ )
954
979
 
955
- return this._waitForAction();
980
+ return this._waitForAction()
956
981
  }
957
982
 
958
983
  /**
@@ -973,11 +998,11 @@ class Playwright extends Helper {
973
998
  */
974
999
  async resizeWindow(width, height) {
975
1000
  if (width === 'maximize') {
976
- throw new Error('Playwright can\'t control windows, so it can\'t maximize it');
1001
+ throw new Error("Playwright can't control windows, so it can't maximize it")
977
1002
  }
978
1003
 
979
- await this.page.setViewportSize({ width, height });
980
- return this._waitForAction();
1004
+ await this.page.setViewportSize({ width, height })
1005
+ return this._waitForAction()
981
1006
  }
982
1007
 
983
1008
  /**
@@ -993,9 +1018,9 @@ class Playwright extends Helper {
993
1018
  */
994
1019
  async setPlaywrightRequestHeaders(customHeaders) {
995
1020
  if (!customHeaders) {
996
- throw new Error('Cannot send empty headers.');
1021
+ throw new Error('Cannot send empty headers.')
997
1022
  }
998
- return this.browserContext.setExtraHTTPHeaders(customHeaders);
1023
+ return this.browserContext.setExtraHTTPHeaders(customHeaders)
999
1024
  }
1000
1025
 
1001
1026
  /**
@@ -1003,13 +1028,13 @@ class Playwright extends Helper {
1003
1028
  *
1004
1029
  */
1005
1030
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
1006
- const el = await this._locateElement(locator);
1007
- assertElementExists(el, locator);
1031
+ const el = await this._locateElement(locator)
1032
+ assertElementExists(el, locator)
1008
1033
 
1009
1034
  // Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
1010
- const { x, y } = await clickablePoint(el);
1011
- await this.page.mouse.move(x + offsetX, y + offsetY);
1012
- return this._waitForAction();
1035
+ const { x, y } = await clickablePoint(el)
1036
+ await this.page.mouse.move(x + offsetX, y + offsetY)
1037
+ return this._waitForAction()
1013
1038
  }
1014
1039
 
1015
1040
  /**
@@ -1017,11 +1042,11 @@ class Playwright extends Helper {
1017
1042
  *
1018
1043
  */
1019
1044
  async focus(locator, options = {}) {
1020
- const el = await this._locateElement(locator);
1021
- assertElementExists(el, locator, 'Element to focus');
1045
+ const el = await this._locateElement(locator)
1046
+ assertElementExists(el, locator, 'Element to focus')
1022
1047
 
1023
- await el.focus(options);
1024
- return this._waitForAction();
1048
+ await el.focus(options)
1049
+ return this._waitForAction()
1025
1050
  }
1026
1051
 
1027
1052
  /**
@@ -1029,11 +1054,11 @@ class Playwright extends Helper {
1029
1054
  *
1030
1055
  */
1031
1056
  async blur(locator, options = {}) {
1032
- const el = await this._locateElement(locator);
1033
- assertElementExists(el, locator, 'Element to blur');
1057
+ const el = await this._locateElement(locator)
1058
+ assertElementExists(el, locator, 'Element to blur')
1034
1059
 
1035
- await el.blur(options);
1036
- return this._waitForAction();
1060
+ await el.blur(options)
1061
+ return this._waitForAction()
1037
1062
  }
1038
1063
  /**
1039
1064
  * Return the checked status of given element.
@@ -1045,14 +1070,14 @@ class Playwright extends Helper {
1045
1070
  */
1046
1071
 
1047
1072
  async grabCheckedElementStatus(locator, options = {}) {
1048
- const supportedTypes = ['checkbox', 'radio'];
1049
- const el = await this._locateElement(locator);
1050
- const type = await el.getAttribute('type');
1073
+ const supportedTypes = ['checkbox', 'radio']
1074
+ const el = await this._locateElement(locator)
1075
+ const type = await el.getAttribute('type')
1051
1076
 
1052
1077
  if (supportedTypes.includes(type)) {
1053
- return el.isChecked(options);
1078
+ return el.isChecked(options)
1054
1079
  }
1055
- throw new Error(`Element is not a ${supportedTypes.join(' or ')} input`);
1080
+ throw new Error(`Element is not a ${supportedTypes.join(' or ')} input`)
1056
1081
  }
1057
1082
  /**
1058
1083
  * Return the disabled status of given element.
@@ -1064,8 +1089,8 @@ class Playwright extends Helper {
1064
1089
  */
1065
1090
 
1066
1091
  async grabDisabledElementStatus(locator, options = {}) {
1067
- const el = await this._locateElement(locator);
1068
- return el.isDisabled(options);
1092
+ const el = await this._locateElement(locator)
1093
+ return el.isDisabled(options)
1069
1094
  }
1070
1095
 
1071
1096
  /**
@@ -1082,24 +1107,24 @@ class Playwright extends Helper {
1082
1107
  *
1083
1108
  */
1084
1109
  async dragAndDrop(srcElement, destElement, options) {
1085
- const src = new Locator(srcElement);
1086
- const dst = new Locator(destElement);
1110
+ const src = new Locator(srcElement)
1111
+ const dst = new Locator(destElement)
1087
1112
 
1088
1113
  if (options) {
1089
- return this.page.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options);
1114
+ return this.page.dragAndDrop(buildLocatorString(src), buildLocatorString(dst), options)
1090
1115
  }
1091
1116
 
1092
- const _smallWaitInMs = 600;
1093
- await this.page.locator(buildLocatorString(src)).hover();
1094
- await this.page.mouse.down();
1095
- await this.page.waitForTimeout(_smallWaitInMs);
1117
+ const _smallWaitInMs = 600
1118
+ await this.page.locator(buildLocatorString(src)).hover()
1119
+ await this.page.mouse.down()
1120
+ await this.page.waitForTimeout(_smallWaitInMs)
1096
1121
 
1097
- const destElBox = await this.page.locator(buildLocatorString(dst)).boundingBox();
1122
+ const destElBox = await this.page.locator(buildLocatorString(dst)).boundingBox()
1098
1123
 
1099
- await this.page.mouse.move(destElBox.x + destElBox.width / 2, destElBox.y + destElBox.height / 2);
1100
- await this.page.locator(buildLocatorString(dst)).hover({ position: { x: 10, y: 10 } });
1101
- await this.page.waitForTimeout(_smallWaitInMs);
1102
- await this.page.mouse.up();
1124
+ await this.page.mouse.move(destElBox.x + destElBox.width / 2, destElBox.y + destElBox.height / 2)
1125
+ await this.page.locator(buildLocatorString(dst)).hover({ position: { x: 10, y: 10 } })
1126
+ await this.page.waitForTimeout(_smallWaitInMs)
1127
+ await this.page.mouse.up()
1103
1128
  }
1104
1129
 
1105
1130
  /**
@@ -1117,16 +1142,16 @@ class Playwright extends Helper {
1117
1142
  * @param {object} [contextOptions] [Options for browser context](https://playwright.dev/docs/api/class-browser#browser-new-context) when starting new browser
1118
1143
  */
1119
1144
  async restartBrowser(contextOptions) {
1120
- await this._stopBrowser();
1121
- await this._startBrowser();
1122
- await this._createContextPage(contextOptions);
1145
+ await this._stopBrowser()
1146
+ await this._startBrowser()
1147
+ await this._createContextPage(contextOptions)
1123
1148
  }
1124
1149
 
1125
1150
  /**
1126
1151
  * {{> refreshPage }}
1127
1152
  */
1128
1153
  async refreshPage() {
1129
- return this.page.reload({ timeout: this.options.getPageTimeout, waitUntil: this.options.waitForNavigation });
1154
+ return this.page.reload({ timeout: this.options.getPageTimeout, waitUntil: this.options.waitForNavigation })
1130
1155
  }
1131
1156
 
1132
1157
  /**
@@ -1147,13 +1172,13 @@ class Playwright extends Helper {
1147
1172
  * @returns Promise<void>
1148
1173
  */
1149
1174
  async replayFromHar(harFilePath, opts) {
1150
- const file = path.join(global.codecept_dir, harFilePath);
1175
+ const file = path.join(global.codecept_dir, harFilePath)
1151
1176
 
1152
1177
  if (!fileExists(file)) {
1153
- throw new Error(`File at ${file} cannot be found on local system`);
1178
+ throw new Error(`File at ${file} cannot be found on local system`)
1154
1179
  }
1155
1180
 
1156
- await this.page.routeFromHAR(harFilePath, opts);
1181
+ await this.page.routeFromHAR(harFilePath, opts)
1157
1182
  }
1158
1183
 
1159
1184
  /**
@@ -1161,8 +1186,8 @@ class Playwright extends Helper {
1161
1186
  */
1162
1187
  scrollPageToTop() {
1163
1188
  return this.executeScript(() => {
1164
- window.scrollTo(0, 0);
1165
- });
1189
+ window.scrollTo(0, 0)
1190
+ })
1166
1191
  }
1167
1192
 
1168
1193
  /**
@@ -1170,16 +1195,13 @@ class Playwright extends Helper {
1170
1195
  */
1171
1196
  async scrollPageToBottom() {
1172
1197
  return this.executeScript(() => {
1173
- const body = document.body;
1174
- const html = document.documentElement;
1175
- window.scrollTo(0, Math.max(
1176
- body.scrollHeight,
1177
- body.offsetHeight,
1178
- html.clientHeight,
1179
- html.scrollHeight,
1180
- html.offsetHeight,
1181
- ));
1182
- });
1198
+ const body = document.body
1199
+ const html = document.documentElement
1200
+ window.scrollTo(
1201
+ 0,
1202
+ Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
1203
+ )
1204
+ })
1183
1205
  }
1184
1206
 
1185
1207
  /**
@@ -1187,29 +1209,32 @@ class Playwright extends Helper {
1187
1209
  */
1188
1210
  async scrollTo(locator, offsetX = 0, offsetY = 0) {
1189
1211
  if (typeof locator === 'number' && typeof offsetX === 'number') {
1190
- offsetY = offsetX;
1191
- offsetX = locator;
1192
- locator = null;
1212
+ offsetY = offsetX
1213
+ offsetX = locator
1214
+ locator = null
1193
1215
  }
1194
1216
 
1195
1217
  if (locator) {
1196
- const el = await this._locateElement(locator);
1197
- assertElementExists(el, locator, 'Element');
1198
- await el.scrollIntoViewIfNeeded();
1199
- const elementCoordinates = await clickablePoint(el);
1200
- await this.executeScript((offsetX, offsetY) => window.scrollBy(offsetX, offsetY), { offsetX: elementCoordinates.x + offsetX, offsetY: elementCoordinates.y + offsetY });
1218
+ const el = await this._locateElement(locator)
1219
+ assertElementExists(el, locator, 'Element')
1220
+ await el.scrollIntoViewIfNeeded()
1221
+ const elementCoordinates = await clickablePoint(el)
1222
+ await this.executeScript((offsetX, offsetY) => window.scrollBy(offsetX, offsetY), {
1223
+ offsetX: elementCoordinates.x + offsetX,
1224
+ offsetY: elementCoordinates.y + offsetY,
1225
+ })
1201
1226
  } else {
1202
- await this.executeScript(({ offsetX, offsetY }) => window.scrollTo(offsetX, offsetY), { offsetX, offsetY });
1227
+ await this.executeScript(({ offsetX, offsetY }) => window.scrollTo(offsetX, offsetY), { offsetX, offsetY })
1203
1228
  }
1204
- return this._waitForAction();
1229
+ return this._waitForAction()
1205
1230
  }
1206
1231
 
1207
1232
  /**
1208
1233
  * {{> seeInTitle }}
1209
1234
  */
1210
1235
  async seeInTitle(text) {
1211
- const title = await this.page.title();
1212
- stringIncludes('web page title').assert(text, title);
1236
+ const title = await this.page.title()
1237
+ stringIncludes('web page title').assert(text, title)
1213
1238
  }
1214
1239
 
1215
1240
  /**
@@ -1220,34 +1245,34 @@ class Playwright extends Helper {
1220
1245
  function getScrollPosition() {
1221
1246
  return {
1222
1247
  x: window.pageXOffset,
1223
- y: window.pageYOffset
1224
- };
1248
+ y: window.pageYOffset,
1249
+ }
1225
1250
  }
1226
1251
  /* eslint-enable comma-dangle */
1227
- return this.executeScript(getScrollPosition);
1252
+ return this.executeScript(getScrollPosition)
1228
1253
  }
1229
1254
 
1230
1255
  /**
1231
1256
  * {{> seeTitleEquals }}
1232
1257
  */
1233
1258
  async seeTitleEquals(text) {
1234
- const title = await this.page.title();
1235
- return equals('web page title').assert(title, text);
1259
+ const title = await this.page.title()
1260
+ return equals('web page title').assert(title, text)
1236
1261
  }
1237
1262
 
1238
1263
  /**
1239
1264
  * {{> dontSeeInTitle }}
1240
1265
  */
1241
1266
  async dontSeeInTitle(text) {
1242
- const title = await this.page.title();
1243
- stringIncludes('web page title').negate(text, title);
1267
+ const title = await this.page.title()
1268
+ stringIncludes('web page title').negate(text, title)
1244
1269
  }
1245
1270
 
1246
1271
  /**
1247
1272
  * {{> grabTitle }}
1248
1273
  */
1249
1274
  async grabTitle() {
1250
- return this.page.title();
1275
+ return this.page.title()
1251
1276
  }
1252
1277
 
1253
1278
  /**
@@ -1259,11 +1284,11 @@ class Playwright extends Helper {
1259
1284
  * ```
1260
1285
  */
1261
1286
  async _locate(locator) {
1262
- const context = (await this.context) || (await this._getContext());
1287
+ const context = (await this.context) || (await this._getContext())
1263
1288
 
1264
- if (this.frame) return findElements(this.frame, locator);
1289
+ if (this.frame) return findElements(this.frame, locator)
1265
1290
 
1266
- return findElements(context, locator);
1291
+ return findElements(context, locator)
1267
1292
  }
1268
1293
 
1269
1294
  /**
@@ -1275,8 +1300,8 @@ class Playwright extends Helper {
1275
1300
  * ```
1276
1301
  */
1277
1302
  async _locateElement(locator) {
1278
- const context = (await this.context) || (await this._getContext());
1279
- return findElement(context, locator);
1303
+ const context = (await this.context) || (await this._getContext())
1304
+ return findElement(context, locator)
1280
1305
  }
1281
1306
 
1282
1307
  /**
@@ -1288,10 +1313,10 @@ class Playwright extends Helper {
1288
1313
  * ```
1289
1314
  */
1290
1315
  async _locateCheckable(locator, providedContext = null) {
1291
- const context = providedContext || (await this._getContext());
1292
- const els = await findCheckable.call(this, locator, context);
1293
- assertElementExists(els[0], locator, 'Checkbox or radio');
1294
- return els[0];
1316
+ const context = providedContext || (await this._getContext())
1317
+ const els = await findCheckable.call(this, locator, context)
1318
+ assertElementExists(els[0], locator, 'Checkbox or radio')
1319
+ return els[0]
1295
1320
  }
1296
1321
 
1297
1322
  /**
@@ -1302,8 +1327,8 @@ class Playwright extends Helper {
1302
1327
  * ```
1303
1328
  */
1304
1329
  async _locateClickable(locator) {
1305
- const context = await this._getContext();
1306
- return findClickable.call(this, context, locator);
1330
+ const context = await this._getContext()
1331
+ return findClickable.call(this, context, locator)
1307
1332
  }
1308
1333
 
1309
1334
  /**
@@ -1314,7 +1339,7 @@ class Playwright extends Helper {
1314
1339
  * ```
1315
1340
  */
1316
1341
  async _locateFields(locator) {
1317
- return findFields.call(this, locator);
1342
+ return findFields.call(this, locator)
1318
1343
  }
1319
1344
 
1320
1345
  /**
@@ -1322,7 +1347,7 @@ class Playwright extends Helper {
1322
1347
  *
1323
1348
  */
1324
1349
  async grabWebElements(locator) {
1325
- return this._locate(locator);
1350
+ return this._locate(locator)
1326
1351
  }
1327
1352
 
1328
1353
  /**
@@ -1330,7 +1355,7 @@ class Playwright extends Helper {
1330
1355
  *
1331
1356
  */
1332
1357
  async grabWebElement(locator) {
1333
- return this._locateElement(locator);
1358
+ return this._locateElement(locator)
1334
1359
  }
1335
1360
 
1336
1361
  /**
@@ -1345,20 +1370,20 @@ class Playwright extends Helper {
1345
1370
  */
1346
1371
  async switchToNextTab(num = 1) {
1347
1372
  if (this.isElectron) {
1348
- throw new Error('Cannot switch tabs inside an Electron container');
1373
+ throw new Error('Cannot switch tabs inside an Electron container')
1349
1374
  }
1350
- const pages = await this.browserContext.pages();
1375
+ const pages = await this.browserContext.pages()
1351
1376
 
1352
- const index = pages.indexOf(this.page);
1353
- this.withinLocator = null;
1354
- const page = pages[index + num];
1377
+ const index = pages.indexOf(this.page)
1378
+ this.withinLocator = null
1379
+ const page = pages[index + num]
1355
1380
 
1356
1381
  if (!page) {
1357
- throw new Error(`There is no ability to switch to next tab with offset ${num}`);
1382
+ throw new Error(`There is no ability to switch to next tab with offset ${num}`)
1358
1383
  }
1359
- await targetCreatedHandler.call(this, page);
1360
- await this._setPage(page);
1361
- return this._waitForAction();
1384
+ await targetCreatedHandler.call(this, page)
1385
+ await this._setPage(page)
1386
+ return this._waitForAction()
1362
1387
  }
1363
1388
 
1364
1389
  /**
@@ -1372,19 +1397,19 @@ class Playwright extends Helper {
1372
1397
  */
1373
1398
  async switchToPreviousTab(num = 1) {
1374
1399
  if (this.isElectron) {
1375
- throw new Error('Cannot switch tabs inside an Electron container');
1400
+ throw new Error('Cannot switch tabs inside an Electron container')
1376
1401
  }
1377
- const pages = await this.browserContext.pages();
1378
- const index = pages.indexOf(this.page);
1379
- this.withinLocator = null;
1380
- const page = pages[index - num];
1402
+ const pages = await this.browserContext.pages()
1403
+ const index = pages.indexOf(this.page)
1404
+ this.withinLocator = null
1405
+ const page = pages[index - num]
1381
1406
 
1382
1407
  if (!page) {
1383
- throw new Error(`There is no ability to switch to previous tab with offset ${num}`);
1408
+ throw new Error(`There is no ability to switch to previous tab with offset ${num}`)
1384
1409
  }
1385
1410
 
1386
- await this._setPage(page);
1387
- return this._waitForAction();
1411
+ await this._setPage(page)
1412
+ return this._waitForAction()
1388
1413
  }
1389
1414
 
1390
1415
  /**
@@ -1396,12 +1421,12 @@ class Playwright extends Helper {
1396
1421
  */
1397
1422
  async closeCurrentTab() {
1398
1423
  if (this.isElectron) {
1399
- throw new Error('Cannot close current tab inside an Electron container');
1424
+ throw new Error('Cannot close current tab inside an Electron container')
1400
1425
  }
1401
- const oldPage = this.page;
1402
- await this.switchToPreviousTab();
1403
- await oldPage.close();
1404
- return this._waitForAction();
1426
+ const oldPage = this.page
1427
+ await this.switchToPreviousTab()
1428
+ await oldPage.close()
1429
+ return this._waitForAction()
1405
1430
  }
1406
1431
 
1407
1432
  /**
@@ -1412,13 +1437,13 @@ class Playwright extends Helper {
1412
1437
  * ```
1413
1438
  */
1414
1439
  async closeOtherTabs() {
1415
- const pages = await this.browserContext.pages();
1416
- const otherPages = pages.filter(page => page !== this.page);
1440
+ const pages = await this.browserContext.pages()
1441
+ const otherPages = pages.filter((page) => page !== this.page)
1417
1442
  if (otherPages.length) {
1418
- this.debug(`Closing ${otherPages.length} tabs`);
1419
- return Promise.all(otherPages.map(p => p.close()));
1443
+ this.debug(`Closing ${otherPages.length} tabs`)
1444
+ return Promise.all(otherPages.map((p) => p.close()))
1420
1445
  }
1421
- return Promise.resolve();
1446
+ return Promise.resolve()
1422
1447
  }
1423
1448
 
1424
1449
  /**
@@ -1437,20 +1462,20 @@ class Playwright extends Helper {
1437
1462
  */
1438
1463
  async openNewTab(options) {
1439
1464
  if (this.isElectron) {
1440
- throw new Error('Cannot open new tabs inside an Electron container');
1465
+ throw new Error('Cannot open new tabs inside an Electron container')
1441
1466
  }
1442
- const page = await this.browserContext.newPage(options);
1443
- await targetCreatedHandler.call(this, page);
1444
- await this._setPage(page);
1445
- return this._waitForAction();
1467
+ const page = await this.browserContext.newPage(options)
1468
+ await targetCreatedHandler.call(this, page)
1469
+ await this._setPage(page)
1470
+ return this._waitForAction()
1446
1471
  }
1447
1472
 
1448
1473
  /**
1449
1474
  * {{> grabNumberOfOpenTabs }}
1450
1475
  */
1451
1476
  async grabNumberOfOpenTabs() {
1452
- const pages = await this.browserContext.pages();
1453
- return pages.length;
1477
+ const pages = await this.browserContext.pages()
1478
+ return pages.length
1454
1479
  }
1455
1480
 
1456
1481
  /**
@@ -1458,12 +1483,12 @@ class Playwright extends Helper {
1458
1483
  *
1459
1484
  */
1460
1485
  async seeElement(locator) {
1461
- let els = await this._locate(locator);
1462
- els = await Promise.all(els.map(el => el.isVisible()));
1486
+ let els = await this._locate(locator)
1487
+ els = await Promise.all(els.map((el) => el.isVisible()))
1463
1488
  try {
1464
- return empty('visible elements').negate(els.filter(v => v).fill('ELEMENT'));
1489
+ return empty('visible elements').negate(els.filter((v) => v).fill('ELEMENT'))
1465
1490
  } catch (e) {
1466
- dontSeeElementError(locator);
1491
+ dontSeeElementError(locator)
1467
1492
  }
1468
1493
  }
1469
1494
 
@@ -1472,12 +1497,12 @@ class Playwright extends Helper {
1472
1497
  *
1473
1498
  */
1474
1499
  async dontSeeElement(locator) {
1475
- let els = await this._locate(locator);
1476
- els = await Promise.all(els.map(el => el.isVisible()));
1500
+ let els = await this._locate(locator)
1501
+ els = await Promise.all(els.map((el) => el.isVisible()))
1477
1502
  try {
1478
- return empty('visible elements').assert(els.filter(v => v).fill('ELEMENT'));
1503
+ return empty('visible elements').assert(els.filter((v) => v).fill('ELEMENT'))
1479
1504
  } catch (e) {
1480
- seeElementError(locator);
1505
+ seeElementError(locator)
1481
1506
  }
1482
1507
  }
1483
1508
 
@@ -1485,11 +1510,11 @@ class Playwright extends Helper {
1485
1510
  * {{> seeElementInDOM }}
1486
1511
  */
1487
1512
  async seeElementInDOM(locator) {
1488
- const els = await this._locate(locator);
1513
+ const els = await this._locate(locator)
1489
1514
  try {
1490
- return empty('elements on page').negate(els.filter(v => v).fill('ELEMENT'));
1515
+ return empty('elements on page').negate(els.filter((v) => v).fill('ELEMENT'))
1491
1516
  } catch (e) {
1492
- dontSeeElementInDOMError(locator);
1517
+ dontSeeElementInDOMError(locator)
1493
1518
  }
1494
1519
  }
1495
1520
 
@@ -1497,11 +1522,11 @@ class Playwright extends Helper {
1497
1522
  * {{> dontSeeElementInDOM }}
1498
1523
  */
1499
1524
  async dontSeeElementInDOM(locator) {
1500
- const els = await this._locate(locator);
1525
+ const els = await this._locate(locator)
1501
1526
  try {
1502
- return empty('elements on a page').assert(els.filter(v => v).fill('ELEMENT'));
1527
+ return empty('elements on a page').assert(els.filter((v) => v).fill('ELEMENT'))
1503
1528
  } catch (e) {
1504
- seeElementInDOMError(locator);
1529
+ seeElementInDOMError(locator)
1505
1530
  }
1506
1531
  }
1507
1532
 
@@ -1524,18 +1549,18 @@ class Playwright extends Helper {
1524
1549
  */
1525
1550
  async handleDownloads(fileName) {
1526
1551
  this.page.waitForEvent('download').then(async (download) => {
1527
- const filePath = await download.path();
1528
- fileName = fileName || `downloads/${path.basename(filePath)}`;
1552
+ const filePath = await download.path()
1553
+ fileName = fileName || `downloads/${path.basename(filePath)}`
1529
1554
 
1530
- const downloadPath = path.join(global.output_dir, fileName);
1555
+ const downloadPath = path.join(global.output_dir, fileName)
1531
1556
  if (!fs.existsSync(path.dirname(downloadPath))) {
1532
- fs.mkdirSync(path.dirname(downloadPath), '0777');
1557
+ fs.mkdirSync(path.dirname(downloadPath), '0777')
1533
1558
  }
1534
- fs.copyFileSync(filePath, downloadPath);
1535
- this.debug('Download completed');
1536
- this.debugSection('Downloaded From', await download.url());
1537
- this.debugSection('Downloaded To', downloadPath);
1538
- });
1559
+ fs.copyFileSync(filePath, downloadPath)
1560
+ this.debug('Download completed')
1561
+ this.debugSection('Downloaded From', await download.url())
1562
+ this.debugSection('Downloaded To', downloadPath)
1563
+ })
1539
1564
  }
1540
1565
 
1541
1566
  /**
@@ -1555,37 +1580,37 @@ class Playwright extends Helper {
1555
1580
  *
1556
1581
  */
1557
1582
  async click(locator, context = null, options = {}) {
1558
- return proceedClick.call(this, locator, context, options);
1583
+ return proceedClick.call(this, locator, context, options)
1559
1584
  }
1560
1585
 
1561
1586
  /**
1562
1587
  * Clicks link and waits for navigation (deprecated)
1563
1588
  */
1564
1589
  async clickLink(locator, context = null) {
1565
- console.log('clickLink deprecated: Playwright automatically waits for navigation to happen.');
1566
- console.log('Replace I.clickLink with I.click');
1567
- return this.click(locator, context);
1590
+ console.log('clickLink deprecated: Playwright automatically waits for navigation to happen.')
1591
+ console.log('Replace I.clickLink with I.click')
1592
+ return this.click(locator, context)
1568
1593
  }
1569
1594
 
1570
1595
  /**
1571
1596
  * {{> forceClick }}
1572
1597
  */
1573
1598
  async forceClick(locator, context = null) {
1574
- return proceedClick.call(this, locator, context, { force: true });
1599
+ return proceedClick.call(this, locator, context, { force: true })
1575
1600
  }
1576
1601
 
1577
1602
  /**
1578
1603
  * {{> doubleClick }}
1579
1604
  */
1580
1605
  async doubleClick(locator, context = null) {
1581
- return proceedClick.call(this, locator, context, { clickCount: 2 });
1606
+ return proceedClick.call(this, locator, context, { clickCount: 2 })
1582
1607
  }
1583
1608
 
1584
1609
  /**
1585
1610
  * {{> rightClick }}
1586
1611
  */
1587
1612
  async rightClick(locator, context = null) {
1588
- return proceedClick.call(this, locator, context, { button: 'right' });
1613
+ return proceedClick.call(this, locator, context, { button: 'right' })
1589
1614
  }
1590
1615
 
1591
1616
  /**
@@ -1604,9 +1629,9 @@ class Playwright extends Helper {
1604
1629
  *
1605
1630
  */
1606
1631
  async checkOption(field, context = null, options = { force: true }) {
1607
- const elm = await this._locateCheckable(field, context);
1608
- await elm.check(options);
1609
- return this._waitForAction();
1632
+ const elm = await this._locateCheckable(field, context)
1633
+ await elm.check(options)
1634
+ return this._waitForAction()
1610
1635
  }
1611
1636
 
1612
1637
  /**
@@ -1624,41 +1649,41 @@ class Playwright extends Helper {
1624
1649
  * {{> uncheckOption }}
1625
1650
  */
1626
1651
  async uncheckOption(field, context = null, options = { force: true }) {
1627
- const elm = await this._locateCheckable(field, context);
1628
- await elm.uncheck(options);
1629
- return this._waitForAction();
1652
+ const elm = await this._locateCheckable(field, context)
1653
+ await elm.uncheck(options)
1654
+ return this._waitForAction()
1630
1655
  }
1631
1656
 
1632
1657
  /**
1633
1658
  * {{> seeCheckboxIsChecked }}
1634
1659
  */
1635
1660
  async seeCheckboxIsChecked(field) {
1636
- return proceedIsChecked.call(this, 'assert', field);
1661
+ return proceedIsChecked.call(this, 'assert', field)
1637
1662
  }
1638
1663
 
1639
1664
  /**
1640
1665
  * {{> dontSeeCheckboxIsChecked }}
1641
1666
  */
1642
1667
  async dontSeeCheckboxIsChecked(field) {
1643
- return proceedIsChecked.call(this, 'negate', field);
1668
+ return proceedIsChecked.call(this, 'negate', field)
1644
1669
  }
1645
1670
 
1646
1671
  /**
1647
1672
  * {{> pressKeyDown }}
1648
1673
  */
1649
1674
  async pressKeyDown(key) {
1650
- key = getNormalizedKey.call(this, key);
1651
- await this.page.keyboard.down(key);
1652
- return this._waitForAction();
1675
+ key = getNormalizedKey.call(this, key)
1676
+ await this.page.keyboard.down(key)
1677
+ return this._waitForAction()
1653
1678
  }
1654
1679
 
1655
1680
  /**
1656
1681
  * {{> pressKeyUp }}
1657
1682
  */
1658
1683
  async pressKeyUp(key) {
1659
- key = getNormalizedKey.call(this, key);
1660
- await this.page.keyboard.up(key);
1661
- return this._waitForAction();
1684
+ key = getNormalizedKey.call(this, key)
1685
+ await this.page.keyboard.up(key)
1686
+ return this._waitForAction()
1662
1687
  }
1663
1688
 
1664
1689
  /**
@@ -1668,28 +1693,28 @@ class Playwright extends Helper {
1668
1693
  * {{> pressKeyWithKeyNormalization }}
1669
1694
  */
1670
1695
  async pressKey(key) {
1671
- const modifiers = [];
1696
+ const modifiers = []
1672
1697
  if (Array.isArray(key)) {
1673
1698
  for (let k of key) {
1674
- k = getNormalizedKey.call(this, k);
1699
+ k = getNormalizedKey.call(this, k)
1675
1700
  if (isModifierKey(k)) {
1676
- modifiers.push(k);
1701
+ modifiers.push(k)
1677
1702
  } else {
1678
- key = k;
1679
- break;
1703
+ key = k
1704
+ break
1680
1705
  }
1681
1706
  }
1682
1707
  } else {
1683
- key = getNormalizedKey.call(this, key);
1708
+ key = getNormalizedKey.call(this, key)
1684
1709
  }
1685
1710
  for (const modifier of modifiers) {
1686
- await this.page.keyboard.down(modifier);
1711
+ await this.page.keyboard.down(modifier)
1687
1712
  }
1688
- await this.page.keyboard.press(key);
1713
+ await this.page.keyboard.press(key)
1689
1714
  for (const modifier of modifiers) {
1690
- await this.page.keyboard.up(modifier);
1715
+ await this.page.keyboard.up(modifier)
1691
1716
  }
1692
- return this._waitForAction();
1717
+ return this._waitForAction()
1693
1718
  }
1694
1719
 
1695
1720
  /**
@@ -1697,13 +1722,13 @@ class Playwright extends Helper {
1697
1722
  */
1698
1723
  async type(keys, delay = null) {
1699
1724
  if (!Array.isArray(keys)) {
1700
- keys = keys.toString();
1701
- keys = keys.split('');
1725
+ keys = keys.toString()
1726
+ keys = keys.split('')
1702
1727
  }
1703
1728
 
1704
1729
  for (const key of keys) {
1705
- await this.page.keyboard.press(key);
1706
- if (delay) await this.wait(delay / 1000);
1730
+ await this.page.keyboard.press(key)
1731
+ if (delay) await this.wait(delay / 1000)
1707
1732
  }
1708
1733
  }
1709
1734
 
@@ -1712,75 +1737,75 @@ class Playwright extends Helper {
1712
1737
  *
1713
1738
  */
1714
1739
  async fillField(field, value) {
1715
- const els = await findFields.call(this, field);
1716
- assertElementExists(els, field, 'Field');
1717
- const el = els[0];
1740
+ const els = await findFields.call(this, field)
1741
+ assertElementExists(els, field, 'Field')
1742
+ const el = els[0]
1718
1743
 
1719
- await el.clear();
1744
+ await el.clear()
1720
1745
 
1721
- await highlightActiveElement.call(this, el);
1746
+ await highlightActiveElement.call(this, el)
1722
1747
 
1723
- await el.type(value.toString(), { delay: this.options.pressKeyDelay });
1748
+ await el.type(value.toString(), { delay: this.options.pressKeyDelay })
1724
1749
 
1725
- return this._waitForAction();
1750
+ return this._waitForAction()
1726
1751
  }
1727
1752
 
1728
1753
  /**
1729
1754
  * Clears the text input element: `<input>`, `<textarea>` or `[contenteditable]` .
1730
1755
  *
1731
- *
1732
- * Examples:
1733
- *
1734
- * ```js
1735
- * I.clearField('.text-area')
1736
- *
1737
- * // if this doesn't work use force option
1738
- * I.clearField('#submit', { force: true })
1739
- * ```
1740
- * Use `force` to bypass the [actionability](https://playwright.dev/docs/actionability) checks.
1741
- *
1756
+ *
1757
+ * Examples:
1758
+ *
1759
+ * ```js
1760
+ * I.clearField('.text-area')
1761
+ *
1762
+ * // if this doesn't work use force option
1763
+ * I.clearField('#submit', { force: true })
1764
+ * ```
1765
+ * Use `force` to bypass the [actionability](https://playwright.dev/docs/actionability) checks.
1766
+ *
1742
1767
  * @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
1743
1768
  * @param {any} [options] [Additional options](https://playwright.dev/docs/api/class-locator#locator-clear) for available options object as 2nd argument.
1744
1769
  */
1745
1770
  async clearField(locator, options = {}) {
1746
- const els = await findFields.call(this, locator);
1747
- assertElementExists(els, locator, 'Field to clear');
1771
+ const els = await findFields.call(this, locator)
1772
+ assertElementExists(els, locator, 'Field to clear')
1748
1773
 
1749
- const el = els[0];
1774
+ const el = els[0]
1750
1775
 
1751
- await highlightActiveElement.call(this, el);
1776
+ await highlightActiveElement.call(this, el)
1752
1777
 
1753
- await el.clear();
1778
+ await el.clear()
1754
1779
 
1755
- return this._waitForAction();
1780
+ return this._waitForAction()
1756
1781
  }
1757
1782
 
1758
1783
  /**
1759
1784
  * {{> appendField }}
1760
1785
  */
1761
1786
  async appendField(field, value) {
1762
- const els = await findFields.call(this, field);
1763
- assertElementExists(els, field, 'Field');
1764
- await highlightActiveElement.call(this, els[0]);
1765
- await els[0].press('End');
1766
- await els[0].type(value.toString(), { delay: this.options.pressKeyDelay });
1767
- return this._waitForAction();
1787
+ const els = await findFields.call(this, field)
1788
+ assertElementExists(els, field, 'Field')
1789
+ await highlightActiveElement.call(this, els[0])
1790
+ await els[0].press('End')
1791
+ await els[0].type(value.toString(), { delay: this.options.pressKeyDelay })
1792
+ return this._waitForAction()
1768
1793
  }
1769
1794
 
1770
1795
  /**
1771
1796
  * {{> seeInField }}
1772
1797
  */
1773
1798
  async seeInField(field, value) {
1774
- const _value = (typeof value === 'boolean') ? value : value.toString();
1775
- return proceedSeeInField.call(this, 'assert', field, _value);
1799
+ const _value = typeof value === 'boolean' ? value : value.toString()
1800
+ return proceedSeeInField.call(this, 'assert', field, _value)
1776
1801
  }
1777
1802
 
1778
1803
  /**
1779
1804
  * {{> dontSeeInField }}
1780
1805
  */
1781
1806
  async dontSeeInField(field, value) {
1782
- const _value = (typeof value === 'boolean') ? value : value.toString();
1783
- return proceedSeeInField.call(this, 'negate', field, _value);
1807
+ const _value = typeof value === 'boolean' ? value : value.toString()
1808
+ return proceedSeeInField.call(this, 'negate', field, _value)
1784
1809
  }
1785
1810
 
1786
1811
  /**
@@ -1788,38 +1813,38 @@ class Playwright extends Helper {
1788
1813
  *
1789
1814
  */
1790
1815
  async attachFile(locator, pathToFile) {
1791
- const file = path.join(global.codecept_dir, pathToFile);
1816
+ const file = path.join(global.codecept_dir, pathToFile)
1792
1817
 
1793
1818
  if (!fileExists(file)) {
1794
- throw new Error(`File at ${file} can not be found on local system`);
1819
+ throw new Error(`File at ${file} can not be found on local system`)
1795
1820
  }
1796
- const els = await findFields.call(this, locator);
1797
- assertElementExists(els, locator, 'Field');
1798
- await els[0].setInputFiles(file);
1799
- return this._waitForAction();
1821
+ const els = await findFields.call(this, locator)
1822
+ assertElementExists(els, locator, 'Field')
1823
+ await els[0].setInputFiles(file)
1824
+ return this._waitForAction()
1800
1825
  }
1801
1826
 
1802
1827
  /**
1803
1828
  * {{> selectOption }}
1804
1829
  */
1805
1830
  async selectOption(select, option) {
1806
- const els = await findFields.call(this, select);
1807
- assertElementExists(els, select, 'Selectable field');
1808
- const el = els[0];
1831
+ const els = await findFields.call(this, select)
1832
+ assertElementExists(els, select, 'Selectable field')
1833
+ const el = els[0]
1809
1834
 
1810
- await highlightActiveElement.call(this, el);
1811
- let optionToSelect = '';
1835
+ await highlightActiveElement.call(this, el)
1836
+ let optionToSelect = ''
1812
1837
 
1813
1838
  try {
1814
- optionToSelect = (await el.locator('option', { hasText: option }).textContent()).trim();
1839
+ optionToSelect = (await el.locator('option', { hasText: option }).textContent()).trim()
1815
1840
  } catch (e) {
1816
- optionToSelect = option;
1841
+ optionToSelect = option
1817
1842
  }
1818
1843
 
1819
- if (!Array.isArray(option)) option = [optionToSelect];
1844
+ if (!Array.isArray(option)) option = [optionToSelect]
1820
1845
 
1821
- await el.selectOption(option);
1822
- return this._waitForAction();
1846
+ await el.selectOption(option)
1847
+ return this._waitForAction()
1823
1848
  }
1824
1849
 
1825
1850
  /**
@@ -1827,37 +1852,37 @@ class Playwright extends Helper {
1827
1852
  *
1828
1853
  */
1829
1854
  async grabNumberOfVisibleElements(locator) {
1830
- let els = await this._locate(locator);
1831
- els = await Promise.all(els.map(el => el.isVisible()));
1832
- return els.filter(v => v).length;
1855
+ let els = await this._locate(locator)
1856
+ els = await Promise.all(els.map((el) => el.isVisible()))
1857
+ return els.filter((v) => v).length
1833
1858
  }
1834
1859
 
1835
1860
  /**
1836
1861
  * {{> seeInCurrentUrl }}
1837
1862
  */
1838
1863
  async seeInCurrentUrl(url) {
1839
- stringIncludes('url').assert(url, await this._getPageUrl());
1864
+ stringIncludes('url').assert(url, await this._getPageUrl())
1840
1865
  }
1841
1866
 
1842
1867
  /**
1843
1868
  * {{> dontSeeInCurrentUrl }}
1844
1869
  */
1845
1870
  async dontSeeInCurrentUrl(url) {
1846
- stringIncludes('url').negate(url, await this._getPageUrl());
1871
+ stringIncludes('url').negate(url, await this._getPageUrl())
1847
1872
  }
1848
1873
 
1849
1874
  /**
1850
1875
  * {{> seeCurrentUrlEquals }}
1851
1876
  */
1852
1877
  async seeCurrentUrlEquals(url) {
1853
- urlEquals(this.options.url).assert(url, await this._getPageUrl());
1878
+ urlEquals(this.options.url).assert(url, await this._getPageUrl())
1854
1879
  }
1855
1880
 
1856
1881
  /**
1857
1882
  * {{> dontSeeCurrentUrlEquals }}
1858
1883
  */
1859
1884
  async dontSeeCurrentUrlEquals(url) {
1860
- urlEquals(this.options.url).negate(url, await this._getPageUrl());
1885
+ urlEquals(this.options.url).negate(url, await this._getPageUrl())
1861
1886
  }
1862
1887
 
1863
1888
  /**
@@ -1866,14 +1891,14 @@ class Playwright extends Helper {
1866
1891
  *
1867
1892
  */
1868
1893
  async see(text, context = null) {
1869
- return proceedSee.call(this, 'assert', text, context);
1894
+ return proceedSee.call(this, 'assert', text, context)
1870
1895
  }
1871
1896
 
1872
1897
  /**
1873
1898
  * {{> seeTextEquals }}
1874
1899
  */
1875
1900
  async seeTextEquals(text, context = null) {
1876
- return proceedSee.call(this, 'assert', text, context, true);
1901
+ return proceedSee.call(this, 'assert', text, context, true)
1877
1902
  }
1878
1903
 
1879
1904
  /**
@@ -1882,14 +1907,14 @@ class Playwright extends Helper {
1882
1907
  *
1883
1908
  */
1884
1909
  async dontSee(text, context = null) {
1885
- return proceedSee.call(this, 'negate', text, context);
1910
+ return proceedSee.call(this, 'negate', text, context)
1886
1911
  }
1887
1912
 
1888
1913
  /**
1889
1914
  * {{> grabSource }}
1890
1915
  */
1891
1916
  async grabSource() {
1892
- return this.page.content();
1917
+ return this.page.content()
1893
1918
  }
1894
1919
 
1895
1920
  /**
@@ -1904,32 +1929,32 @@ class Playwright extends Helper {
1904
1929
  * @return {Promise<any[]>}
1905
1930
  */
1906
1931
  async grabBrowserLogs() {
1907
- const logs = consoleLogStore.entries;
1908
- consoleLogStore.clear();
1909
- return logs;
1932
+ const logs = consoleLogStore.entries
1933
+ consoleLogStore.clear()
1934
+ return logs
1910
1935
  }
1911
1936
 
1912
1937
  /**
1913
1938
  * {{> grabCurrentUrl }}
1914
1939
  */
1915
1940
  async grabCurrentUrl() {
1916
- return this._getPageUrl();
1941
+ return this._getPageUrl()
1917
1942
  }
1918
1943
 
1919
1944
  /**
1920
1945
  * {{> seeInSource }}
1921
1946
  */
1922
1947
  async seeInSource(text) {
1923
- const source = await this.page.content();
1924
- stringIncludes('HTML source of a page').assert(text, source);
1948
+ const source = await this.page.content()
1949
+ stringIncludes('HTML source of a page').assert(text, source)
1925
1950
  }
1926
1951
 
1927
1952
  /**
1928
1953
  * {{> dontSeeInSource }}
1929
1954
  */
1930
1955
  async dontSeeInSource(text) {
1931
- const source = await this.page.content();
1932
- stringIncludes('HTML source of a page').negate(text, source);
1956
+ const source = await this.page.content()
1957
+ stringIncludes('HTML source of a page').negate(text, source)
1933
1958
  }
1934
1959
 
1935
1960
  /**
@@ -1938,8 +1963,10 @@ class Playwright extends Helper {
1938
1963
  *
1939
1964
  */
1940
1965
  async seeNumberOfElements(locator, num) {
1941
- const elements = await this._locate(locator);
1942
- return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
1966
+ const elements = await this._locate(locator)
1967
+ return equals(
1968
+ `expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`,
1969
+ ).assert(elements.length, num)
1943
1970
  }
1944
1971
 
1945
1972
  /**
@@ -1948,8 +1975,11 @@ class Playwright extends Helper {
1948
1975
  *
1949
1976
  */
1950
1977
  async seeNumberOfVisibleElements(locator, num) {
1951
- const res = await this.grabNumberOfVisibleElements(locator);
1952
- return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
1978
+ const res = await this.grabNumberOfVisibleElements(locator)
1979
+ return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(
1980
+ res,
1981
+ num,
1982
+ )
1953
1983
  }
1954
1984
 
1955
1985
  /**
@@ -1957,9 +1987,9 @@ class Playwright extends Helper {
1957
1987
  */
1958
1988
  async setCookie(cookie) {
1959
1989
  if (Array.isArray(cookie)) {
1960
- return this.browserContext.addCookies(cookie);
1990
+ return this.browserContext.addCookies(cookie)
1961
1991
  }
1962
- return this.browserContext.addCookies([cookie]);
1992
+ return this.browserContext.addCookies([cookie])
1963
1993
  }
1964
1994
 
1965
1995
  /**
@@ -1967,16 +1997,16 @@ class Playwright extends Helper {
1967
1997
  *
1968
1998
  */
1969
1999
  async seeCookie(name) {
1970
- const cookies = await this.browserContext.cookies();
1971
- empty(`cookie ${name} to be set`).negate(cookies.filter(c => c.name === name));
2000
+ const cookies = await this.browserContext.cookies()
2001
+ empty(`cookie ${name} to be set`).negate(cookies.filter((c) => c.name === name))
1972
2002
  }
1973
2003
 
1974
2004
  /**
1975
2005
  * {{> dontSeeCookie }}
1976
2006
  */
1977
2007
  async dontSeeCookie(name) {
1978
- const cookies = await this.browserContext.cookies();
1979
- empty(`cookie ${name} to be set`).assert(cookies.filter(c => c.name === name));
2008
+ const cookies = await this.browserContext.cookies()
2009
+ empty(`cookie ${name} not to be set`).assert(cookies.filter((c) => c.name === name))
1980
2010
  }
1981
2011
 
1982
2012
  /**
@@ -1985,10 +2015,10 @@ class Playwright extends Helper {
1985
2015
  * {{> grabCookie }}
1986
2016
  */
1987
2017
  async grabCookie(name) {
1988
- const cookies = await this.browserContext.cookies();
1989
- if (!name) return cookies;
1990
- const cookie = cookies.filter(c => c.name === name);
1991
- if (cookie[0]) return cookie[0];
2018
+ const cookies = await this.browserContext.cookies()
2019
+ if (!name) return cookies
2020
+ const cookie = cookies.filter((c) => c.name === name)
2021
+ if (cookie[0]) return cookie[0]
1992
2022
  }
1993
2023
 
1994
2024
  /**
@@ -1997,8 +2027,8 @@ class Playwright extends Helper {
1997
2027
  async clearCookie() {
1998
2028
  // Playwright currently doesn't support to delete a certain cookie
1999
2029
  // https://github.com/microsoft/playwright/blob/main/docs/src/api/class-browsercontext.md#async-method-browsercontextclearcookies
2000
- if (!this.browserContext) return;
2001
- return this.browserContext.clearCookies();
2030
+ if (!this.browserContext) return
2031
+ return this.browserContext.clearCookies()
2002
2032
  }
2003
2033
 
2004
2034
  /**
@@ -2028,9 +2058,9 @@ class Playwright extends Helper {
2028
2058
  async executeScript(fn, arg) {
2029
2059
  if (this.context && this.context.constructor.name === 'FrameLocator') {
2030
2060
  // switching to iframe context
2031
- return this.context.locator(':root').evaluate(fn, arg);
2061
+ return this.context.locator(':root').evaluate(fn, arg)
2032
2062
  }
2033
- return this.page.evaluate.apply(this.page, [fn, arg]);
2063
+ return this.page.evaluate.apply(this.page, [fn, arg])
2034
2064
  }
2035
2065
 
2036
2066
  /**
@@ -2039,14 +2069,14 @@ class Playwright extends Helper {
2039
2069
  * @param {*} locator
2040
2070
  */
2041
2071
  _contextLocator(locator) {
2042
- locator = buildLocatorString(new Locator(locator, 'css'));
2072
+ locator = buildLocatorString(new Locator(locator, 'css'))
2043
2073
 
2044
2074
  if (this.contextLocator) {
2045
- const contextLocator = buildLocatorString(new Locator(this.contextLocator, 'css'));
2046
- locator = `${contextLocator} >> ${locator}`;
2075
+ const contextLocator = buildLocatorString(new Locator(this.contextLocator, 'css'))
2076
+ locator = `${contextLocator} >> ${locator}`
2047
2077
  }
2048
2078
 
2049
- return locator;
2079
+ return locator
2050
2080
  }
2051
2081
 
2052
2082
  /**
@@ -2054,11 +2084,11 @@ class Playwright extends Helper {
2054
2084
  *
2055
2085
  */
2056
2086
  async grabTextFrom(locator) {
2057
- locator = this._contextLocator(locator);
2058
- const text = await this.page.textContent(locator);
2059
- assertElementExists(text, locator);
2060
- this.debugSection('Text', text);
2061
- return text;
2087
+ locator = this._contextLocator(locator)
2088
+ const text = await this.page.textContent(locator)
2089
+ assertElementExists(text, locator)
2090
+ this.debugSection('Text', text)
2091
+ return text
2062
2092
  }
2063
2093
 
2064
2094
  /**
@@ -2066,51 +2096,51 @@ class Playwright extends Helper {
2066
2096
  *
2067
2097
  */
2068
2098
  async grabTextFromAll(locator) {
2069
- const els = await this._locate(locator);
2070
- const texts = [];
2099
+ const els = await this._locate(locator)
2100
+ const texts = []
2071
2101
  for (const el of els) {
2072
- texts.push(await (await el.innerText()));
2102
+ texts.push(await await el.innerText())
2073
2103
  }
2074
- this.debug(`Matched ${els.length} elements`);
2075
- return texts;
2104
+ this.debug(`Matched ${els.length} elements`)
2105
+ return texts
2076
2106
  }
2077
2107
 
2078
2108
  /**
2079
2109
  * {{> grabValueFrom }}
2080
2110
  */
2081
2111
  async grabValueFrom(locator) {
2082
- const values = await this.grabValueFromAll(locator);
2083
- assertElementExists(values, locator);
2084
- this.debugSection('Value', values[0]);
2085
- return values[0];
2112
+ const values = await this.grabValueFromAll(locator)
2113
+ assertElementExists(values, locator)
2114
+ this.debugSection('Value', values[0])
2115
+ return values[0]
2086
2116
  }
2087
2117
 
2088
2118
  /**
2089
2119
  * {{> grabValueFromAll }}
2090
2120
  */
2091
2121
  async grabValueFromAll(locator) {
2092
- const els = await findFields.call(this, locator);
2093
- this.debug(`Matched ${els.length} elements`);
2094
- return Promise.all(els.map(el => el.inputValue()));
2122
+ const els = await findFields.call(this, locator)
2123
+ this.debug(`Matched ${els.length} elements`)
2124
+ return Promise.all(els.map((el) => el.inputValue()))
2095
2125
  }
2096
2126
 
2097
2127
  /**
2098
2128
  * {{> grabHTMLFrom }}
2099
2129
  */
2100
2130
  async grabHTMLFrom(locator) {
2101
- const html = await this.grabHTMLFromAll(locator);
2102
- assertElementExists(html, locator);
2103
- this.debugSection('HTML', html[0]);
2104
- return html[0];
2131
+ const html = await this.grabHTMLFromAll(locator)
2132
+ assertElementExists(html, locator)
2133
+ this.debugSection('HTML', html[0])
2134
+ return html[0]
2105
2135
  }
2106
2136
 
2107
2137
  /**
2108
2138
  * {{> grabHTMLFromAll }}
2109
2139
  */
2110
2140
  async grabHTMLFromAll(locator) {
2111
- const els = await this._locate(locator);
2112
- this.debug(`Matched ${els.length} elements`);
2113
- return Promise.all(els.map(el => el.innerHTML()));
2141
+ const els = await this._locate(locator)
2142
+ this.debug(`Matched ${els.length} elements`)
2143
+ return Promise.all(els.map((el) => el.innerHTML()))
2114
2144
  }
2115
2145
 
2116
2146
  /**
@@ -2118,10 +2148,10 @@ class Playwright extends Helper {
2118
2148
  *
2119
2149
  */
2120
2150
  async grabCssPropertyFrom(locator, cssProperty) {
2121
- const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty);
2122
- assertElementExists(cssValues, locator);
2123
- this.debugSection('CSS', cssValues[0]);
2124
- return cssValues[0];
2151
+ const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
2152
+ assertElementExists(cssValues, locator)
2153
+ this.debugSection('CSS', cssValues[0])
2154
+ return cssValues[0]
2125
2155
  }
2126
2156
 
2127
2157
  /**
@@ -2129,11 +2159,15 @@ class Playwright extends Helper {
2129
2159
  *
2130
2160
  */
2131
2161
  async grabCssPropertyFromAll(locator, cssProperty) {
2132
- const els = await this._locate(locator);
2133
- this.debug(`Matched ${els.length} elements`);
2134
- const cssValues = await Promise.all(els.map(el => el.evaluate((el, cssProperty) => getComputedStyle(el).getPropertyValue(cssProperty), cssProperty)));
2162
+ const els = await this._locate(locator)
2163
+ this.debug(`Matched ${els.length} elements`)
2164
+ const cssValues = await Promise.all(
2165
+ els.map((el) =>
2166
+ el.evaluate((el, cssProperty) => getComputedStyle(el).getPropertyValue(cssProperty), cssProperty),
2167
+ ),
2168
+ )
2135
2169
 
2136
- return cssValues;
2170
+ return cssValues
2137
2171
  }
2138
2172
 
2139
2173
  /**
@@ -2141,35 +2175,37 @@ class Playwright extends Helper {
2141
2175
  *
2142
2176
  */
2143
2177
  async seeCssPropertiesOnElements(locator, cssProperties) {
2144
- const res = await this._locate(locator);
2145
- assertElementExists(res, locator);
2178
+ const res = await this._locate(locator)
2179
+ assertElementExists(res, locator)
2146
2180
 
2147
- const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
2148
- const elemAmount = res.length;
2149
- let props = [];
2181
+ const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties)
2182
+ const elemAmount = res.length
2183
+ let props = []
2150
2184
 
2151
2185
  for (const element of res) {
2152
2186
  for (const prop of Object.keys(cssProperties)) {
2153
- const cssProp = await this.grabCssPropertyFrom(locator, prop);
2187
+ const cssProp = await this.grabCssPropertyFrom(locator, prop)
2154
2188
  if (isColorProperty(prop)) {
2155
- props.push(convertColorToRGBA(cssProp));
2189
+ props.push(convertColorToRGBA(cssProp))
2156
2190
  } else {
2157
- props.push(cssProp);
2191
+ props.push(cssProp)
2158
2192
  }
2159
2193
  }
2160
2194
  }
2161
2195
 
2162
- const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
2163
- if (!Array.isArray(props)) props = [props];
2164
- let chunked = chunkArray(props, values.length);
2196
+ const values = Object.keys(cssPropertiesCamelCase).map((key) => cssPropertiesCamelCase[key])
2197
+ if (!Array.isArray(props)) props = [props]
2198
+ let chunked = chunkArray(props, values.length)
2165
2199
  chunked = chunked.filter((val) => {
2166
2200
  for (let i = 0; i < val.length; ++i) {
2167
2201
  // eslint-disable-next-line eqeqeq
2168
- if (val[i] != values[i]) return false;
2202
+ if (val[i] != values[i]) return false
2169
2203
  }
2170
- return true;
2171
- });
2172
- return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
2204
+ return true
2205
+ })
2206
+ return equals(
2207
+ `all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
2208
+ ).assert(chunked.length, elemAmount)
2173
2209
  }
2174
2210
 
2175
2211
  /**
@@ -2177,31 +2213,33 @@ class Playwright extends Helper {
2177
2213
  *
2178
2214
  */
2179
2215
  async seeAttributesOnElements(locator, attributes) {
2180
- const res = await this._locate(locator);
2181
- assertElementExists(res, locator);
2216
+ const res = await this._locate(locator)
2217
+ assertElementExists(res, locator)
2182
2218
 
2183
- const elemAmount = res.length;
2184
- const commands = [];
2219
+ const elemAmount = res.length
2220
+ const commands = []
2185
2221
  res.forEach((el) => {
2186
2222
  Object.keys(attributes).forEach((prop) => {
2187
- commands.push(el
2188
- .evaluate((el, attr) => el[attr] || el.getAttribute(attr), prop));
2189
- });
2190
- });
2191
- let attrs = await Promise.all(commands);
2192
- const values = Object.keys(attributes).map(key => attributes[key]);
2193
- if (!Array.isArray(attrs)) attrs = [attrs];
2194
- let chunked = chunkArray(attrs, values.length);
2223
+ commands.push(el.evaluate((el, attr) => el[attr] || el.getAttribute(attr), prop))
2224
+ })
2225
+ })
2226
+ let attrs = await Promise.all(commands)
2227
+ const values = Object.keys(attributes).map((key) => attributes[key])
2228
+ if (!Array.isArray(attrs)) attrs = [attrs]
2229
+ let chunked = chunkArray(attrs, values.length)
2195
2230
  chunked = chunked.filter((val) => {
2196
2231
  for (let i = 0; i < val.length; ++i) {
2197
2232
  // the attribute could be a boolean
2198
- if (typeof val[i] === 'boolean') return val[i] === values[i];
2233
+ if (typeof val[i] === 'boolean') return val[i] === values[i]
2199
2234
  // if the attribute doesn't exist, returns false as well
2200
- if (!val[i] || !val[i].includes(values[i])) return false;
2235
+ if (!val[i] || !val[i].includes(values[i])) return false
2201
2236
  }
2202
- return true;
2203
- });
2204
- return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`).assert(chunked.length, elemAmount);
2237
+ return true
2238
+ })
2239
+ return equals(`all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`).assert(
2240
+ chunked.length,
2241
+ elemAmount,
2242
+ )
2205
2243
  }
2206
2244
 
2207
2245
  /**
@@ -2209,21 +2247,21 @@ class Playwright extends Helper {
2209
2247
  *
2210
2248
  */
2211
2249
  async dragSlider(locator, offsetX = 0) {
2212
- const src = await this._locateElement(locator);
2213
- assertElementExists(src, locator, 'Slider Element');
2250
+ const src = await this._locateElement(locator)
2251
+ assertElementExists(src, locator, 'Slider Element')
2214
2252
 
2215
2253
  // Note: Using clickablePoint private api because the .BoundingBox does not take into account iframe offsets!
2216
- const sliderSource = await clickablePoint(src);
2254
+ const sliderSource = await clickablePoint(src)
2217
2255
 
2218
2256
  // Drag start point
2219
- await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 });
2220
- await this.page.mouse.down();
2257
+ await this.page.mouse.move(sliderSource.x, sliderSource.y, { steps: 5 })
2258
+ await this.page.mouse.down()
2221
2259
 
2222
2260
  // Drag destination
2223
- await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 });
2224
- await this.page.mouse.up();
2261
+ await this.page.mouse.move(sliderSource.x + offsetX, sliderSource.y, { steps: 5 })
2262
+ await this.page.mouse.up()
2225
2263
 
2226
- return this._waitForAction();
2264
+ return this._waitForAction()
2227
2265
  }
2228
2266
 
2229
2267
  /**
@@ -2231,10 +2269,10 @@ class Playwright extends Helper {
2231
2269
  *
2232
2270
  */
2233
2271
  async grabAttributeFrom(locator, attr) {
2234
- const attrs = await this.grabAttributeFromAll(locator, attr);
2235
- assertElementExists(attrs, locator);
2236
- this.debugSection('Attribute', attrs[0]);
2237
- return attrs[0];
2272
+ const attrs = await this.grabAttributeFromAll(locator, attr)
2273
+ assertElementExists(attrs, locator)
2274
+ this.debugSection('Attribute', attrs[0])
2275
+ return attrs[0]
2238
2276
  }
2239
2277
 
2240
2278
  /**
@@ -2242,15 +2280,15 @@ class Playwright extends Helper {
2242
2280
  *
2243
2281
  */
2244
2282
  async grabAttributeFromAll(locator, attr) {
2245
- const els = await this._locate(locator);
2246
- this.debug(`Matched ${els.length} elements`);
2247
- const array = [];
2283
+ const els = await this._locate(locator)
2284
+ this.debug(`Matched ${els.length} elements`)
2285
+ const array = []
2248
2286
 
2249
2287
  for (let index = 0; index < els.length; index++) {
2250
- array.push(await els[index].getAttribute(attr));
2288
+ array.push(await els[index].getAttribute(attr))
2251
2289
  }
2252
2290
 
2253
- return array;
2291
+ return array
2254
2292
  }
2255
2293
 
2256
2294
  /**
@@ -2258,43 +2296,43 @@ class Playwright extends Helper {
2258
2296
  *
2259
2297
  */
2260
2298
  async saveElementScreenshot(locator, fileName) {
2261
- const outputFile = screenshotOutputFolder(fileName);
2299
+ const outputFile = screenshotOutputFolder(fileName)
2262
2300
 
2263
- const res = await this._locateElement(locator);
2264
- assertElementExists(res, locator);
2265
- const elem = res;
2266
- this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
2267
- return elem.screenshot({ path: outputFile, type: 'png' });
2301
+ const res = await this._locateElement(locator)
2302
+ assertElementExists(res, locator)
2303
+ const elem = res
2304
+ this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
2305
+ return elem.screenshot({ path: outputFile, type: 'png' })
2268
2306
  }
2269
2307
 
2270
2308
  /**
2271
2309
  * {{> saveScreenshot }}
2272
2310
  */
2273
2311
  async saveScreenshot(fileName, fullPage) {
2274
- const fullPageOption = fullPage || this.options.fullPageScreenshots;
2275
- let outputFile = screenshotOutputFolder(fileName);
2312
+ const fullPageOption = fullPage || this.options.fullPageScreenshots
2313
+ let outputFile = screenshotOutputFolder(fileName)
2276
2314
 
2277
- this.debug(`Screenshot is saving to ${outputFile}`);
2315
+ this.debug(`Screenshot is saving to ${outputFile}`)
2278
2316
 
2279
2317
  await this.page.screenshot({
2280
2318
  path: outputFile,
2281
2319
  fullPage: fullPageOption,
2282
2320
  type: 'png',
2283
- });
2321
+ })
2284
2322
 
2285
2323
  if (this.activeSessionName) {
2286
2324
  for (const sessionName in this.sessionPages) {
2287
- const activeSessionPage = this.sessionPages[sessionName];
2288
- outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`);
2325
+ const activeSessionPage = this.sessionPages[sessionName]
2326
+ outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`)
2289
2327
 
2290
- this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`);
2328
+ this.debug(`${sessionName} - Screenshot is saving to ${outputFile}`)
2291
2329
 
2292
2330
  if (activeSessionPage) {
2293
2331
  await activeSessionPage.screenshot({
2294
2332
  path: outputFile,
2295
2333
  fullPage: fullPageOption,
2296
2334
  type: 'png',
2297
- });
2335
+ })
2298
2336
  }
2299
2337
  }
2300
2338
  }
@@ -2318,20 +2356,23 @@ class Playwright extends Helper {
2318
2356
  * @returns {Promise<object>} response
2319
2357
  */
2320
2358
  async makeApiRequest(method, url, options) {
2321
- method = method.toLowerCase();
2322
- const allowedMethods = ['get', 'post', 'patch', 'head', 'fetch', 'delete'];
2359
+ method = method.toLowerCase()
2360
+ const allowedMethods = ['get', 'post', 'patch', 'head', 'fetch', 'delete']
2323
2361
  if (!allowedMethods.includes(method)) {
2324
- throw new Error(`Method ${method} is not allowed, use the one from a list ${allowedMethods} or switch to using REST helper`);
2362
+ throw new Error(
2363
+ `Method ${method} is not allowed, use the one from a list ${allowedMethods} or switch to using REST helper`,
2364
+ )
2325
2365
  }
2326
2366
 
2327
- if (url.startsWith('/')) { // local url
2328
- url = this.options.url + url;
2329
- this.debugSection('URL', url);
2367
+ if (url.startsWith('/')) {
2368
+ // local url
2369
+ url = this.options.url + url
2370
+ this.debugSection('URL', url)
2330
2371
  }
2331
2372
 
2332
- const response = await this.page.request[method](url, options);
2333
- this.debugSection('Status', response.status());
2334
- this.debugSection('Response', await response.text());
2373
+ const response = await this.page.request[method](url, options)
2374
+ this.debugSection('Status', response.status())
2375
+ this.debugSection('Response', await response.text())
2335
2376
 
2336
2377
  // hook to allow JSON response handle this
2337
2378
  if (this.config.onResponse) {
@@ -2340,68 +2381,83 @@ class Playwright extends Helper {
2340
2381
  status: response.status(),
2341
2382
  statusText: response.statusText(),
2342
2383
  headers: response.headers(),
2343
- };
2344
- this.config.onResponse(axiosResponse);
2384
+ }
2385
+ this.config.onResponse(axiosResponse)
2345
2386
  }
2346
2387
 
2347
- return response;
2388
+ return response
2348
2389
  }
2349
2390
 
2350
2391
  async _failed(test) {
2351
- await this._withinEnd();
2392
+ await this._withinEnd()
2352
2393
 
2353
2394
  if (!test.artifacts) {
2354
- test.artifacts = {};
2395
+ test.artifacts = {}
2355
2396
  }
2356
2397
 
2357
2398
  if (this.options.recordVideo && this.page && this.page.video()) {
2358
- test.artifacts.video = await saveVideoForPage(this.page, `${test.title}.failed`);
2399
+ test.artifacts.video = saveVideoForPage(this.page, `${test.title}.failed`)
2359
2400
  for (const sessionName in this.sessionPages) {
2360
- test.artifacts[`video_${sessionName}`] = await saveVideoForPage(this.sessionPages[sessionName], `${test.title}_${sessionName}.failed`);
2401
+ test.artifacts[`video_${sessionName}`] = saveVideoForPage(
2402
+ this.sessionPages[sessionName],
2403
+ `${test.title}_${sessionName}.failed`,
2404
+ )
2361
2405
  }
2362
2406
  }
2363
2407
 
2364
2408
  if (this.options.trace) {
2365
- test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.failed`);
2409
+ test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.failed`)
2366
2410
  for (const sessionName in this.sessionPages) {
2367
- if (!this.sessionPages[sessionName].context) continue;
2368
- test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(this.sessionPages[sessionName].context, `${test.title}_${sessionName}.failed`);
2411
+ if (!this.sessionPages[sessionName].context) continue
2412
+ test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(
2413
+ this.sessionPages[sessionName].context,
2414
+ `${test.title}_${sessionName}.failed`,
2415
+ )
2369
2416
  }
2370
2417
  }
2371
2418
 
2372
2419
  if (this.options.recordHar) {
2373
- test.artifacts.har = this.currentRunningTest.artifacts.har;
2420
+ test.artifacts.har = this.currentRunningTest.artifacts.har
2374
2421
  }
2375
2422
  }
2376
2423
 
2377
2424
  async _passed(test) {
2378
2425
  if (this.options.recordVideo && this.page && this.page.video()) {
2379
2426
  if (this.options.keepVideoForPassedTests) {
2380
- test.artifacts.video = await saveVideoForPage(this.page, `${test.title}.passed`);
2427
+ test.artifacts.video = saveVideoForPage(this.page, `${test.title}.passed`)
2381
2428
  for (const sessionName of Object.keys(this.sessionPages)) {
2382
- test.artifacts[`video_${sessionName}`] = await saveVideoForPage(this.sessionPages[sessionName], `${test.title}_${sessionName}.passed`);
2429
+ test.artifacts[`video_${sessionName}`] = saveVideoForPage(
2430
+ this.sessionPages[sessionName],
2431
+ `${test.title}_${sessionName}.passed`,
2432
+ )
2383
2433
  }
2384
2434
  } else {
2385
- this.page.video().delete().catch(e => {});
2435
+ this.page
2436
+ .video()
2437
+ .delete()
2438
+ .catch((e) => {})
2386
2439
  }
2387
2440
  }
2388
2441
 
2389
2442
  if (this.options.trace) {
2390
2443
  if (this.options.keepTraceForPassedTests) {
2391
2444
  if (this.options.trace) {
2392
- test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.passed`);
2445
+ test.artifacts.trace = await saveTraceForContext(this.browserContext, `${test.title}.passed`)
2393
2446
  for (const sessionName in this.sessionPages) {
2394
- if (!this.sessionPages[sessionName].context) continue;
2395
- test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(this.sessionPages[sessionName].context, `${test.title}_${sessionName}.passed`);
2447
+ if (!this.sessionPages[sessionName].context) continue
2448
+ test.artifacts[`trace_${sessionName}`] = await saveTraceForContext(
2449
+ this.sessionPages[sessionName].context,
2450
+ `${test.title}_${sessionName}.passed`,
2451
+ )
2396
2452
  }
2397
2453
  }
2398
2454
  } else {
2399
- await this.browserContext.tracing.stop();
2455
+ await this.browserContext.tracing.stop()
2400
2456
  }
2401
2457
  }
2402
2458
 
2403
2459
  if (this.options.recordHar) {
2404
- test.artifacts.har = this.currentRunningTest.artifacts.har;
2460
+ test.artifacts.har = this.currentRunningTest.artifacts.har
2405
2461
  }
2406
2462
  }
2407
2463
 
@@ -2409,62 +2465,99 @@ class Playwright extends Helper {
2409
2465
  * {{> wait }}
2410
2466
  */
2411
2467
  async wait(sec) {
2412
- return new Promise(((done) => {
2413
- setTimeout(done, sec * 1000);
2414
- }));
2468
+ return new Promise((done) => {
2469
+ setTimeout(done, sec * 1000)
2470
+ })
2415
2471
  }
2416
2472
 
2417
2473
  /**
2418
2474
  * {{> waitForEnabled }}
2419
2475
  */
2420
2476
  async waitForEnabled(locator, sec) {
2421
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2422
- locator = new Locator(locator, 'css');
2423
- const matcher = await this.context;
2424
- let waiter;
2425
- const context = await this._getContext();
2477
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2478
+ locator = new Locator(locator, 'css')
2479
+
2480
+ let waiter
2481
+ const context = await this._getContext()
2426
2482
  if (!locator.isXPath()) {
2427
2483
  const valueFn = function ([locator]) {
2428
- return Array.from(document.querySelectorAll(locator)).filter(el => !el.disabled).length > 0;
2429
- };
2430
- waiter = context.waitForFunction(valueFn, [locator.value], { timeout: waitTimeout });
2484
+ return Array.from(document.querySelectorAll(locator)).filter((el) => !el.disabled).length > 0
2485
+ }
2486
+ waiter = context.waitForFunction(valueFn, [locator.value], { timeout: waitTimeout })
2431
2487
  } else {
2432
2488
  const enabledFn = function ([locator, $XPath]) {
2433
- eval($XPath); // eslint-disable-line no-eval
2434
- return $XPath(null, locator).filter(el => !el.disabled).length > 0;
2435
- };
2436
- waiter = context.waitForFunction(enabledFn, [locator.value, $XPath.toString()], { timeout: waitTimeout });
2489
+ eval($XPath) // eslint-disable-line no-eval
2490
+ return $XPath(null, locator).filter((el) => !el.disabled).length > 0
2491
+ }
2492
+ waiter = context.waitForFunction(enabledFn, [locator.value, $XPath.toString()], { timeout: waitTimeout })
2493
+ }
2494
+ return waiter.catch((err) => {
2495
+ throw new Error(
2496
+ `element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`,
2497
+ )
2498
+ })
2499
+ }
2500
+
2501
+ /**
2502
+ * {{> waitForDisabled }}
2503
+ */
2504
+ async waitForDisabled(locator, sec) {
2505
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2506
+ locator = new Locator(locator, 'css')
2507
+
2508
+ let waiter
2509
+ const context = await this._getContext()
2510
+ if (!locator.isXPath()) {
2511
+ const valueFn = function ([locator]) {
2512
+ return Array.from(document.querySelectorAll(locator)).filter((el) => el.disabled).length > 0
2513
+ }
2514
+ waiter = context.waitForFunction(valueFn, [locator.value], { timeout: waitTimeout })
2515
+ } else {
2516
+ const disabledFn = function ([locator, $XPath]) {
2517
+ eval($XPath) // eslint-disable-line no-eval
2518
+ return $XPath(null, locator).filter((el) => el.disabled).length > 0
2519
+ }
2520
+ waiter = context.waitForFunction(disabledFn, [locator.value, $XPath.toString()], { timeout: waitTimeout })
2437
2521
  }
2438
2522
  return waiter.catch((err) => {
2439
- throw new Error(`element (${locator.toString()}) still not enabled after ${waitTimeout / 1000} sec\n${err.message}`);
2440
- });
2523
+ throw new Error(
2524
+ `element (${locator.toString()}) is still enabled after ${waitTimeout / 1000} sec\n${err.message}`,
2525
+ )
2526
+ })
2441
2527
  }
2442
2528
 
2443
2529
  /**
2444
2530
  * {{> waitForValue }}
2445
2531
  */
2446
2532
  async waitForValue(field, value, sec) {
2447
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2448
- const locator = new Locator(field, 'css');
2449
- const matcher = await this.context;
2450
- let waiter;
2451
- const context = await this._getContext();
2533
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2534
+ const locator = new Locator(field, 'css')
2535
+ const matcher = await this.context
2536
+ let waiter
2537
+ const context = await this._getContext()
2452
2538
  if (!locator.isXPath()) {
2453
2539
  const valueFn = function ([locator, value]) {
2454
- return Array.from(document.querySelectorAll(locator)).filter(el => (el.value || '').indexOf(value) !== -1).length > 0;
2455
- };
2456
- waiter = context.waitForFunction(valueFn, [locator.value, value], { timeout: waitTimeout });
2540
+ return (
2541
+ Array.from(document.querySelectorAll(locator)).filter((el) => (el.value || '').indexOf(value) !== -1).length >
2542
+ 0
2543
+ )
2544
+ }
2545
+ waiter = context.waitForFunction(valueFn, [locator.value, value], { timeout: waitTimeout })
2457
2546
  } else {
2458
2547
  const valueFn = function ([locator, $XPath, value]) {
2459
- eval($XPath); // eslint-disable-line no-eval
2460
- return $XPath(null, locator).filter(el => (el.value || '').indexOf(value) !== -1).length > 0;
2461
- };
2462
- waiter = context.waitForFunction(valueFn, [locator.value, $XPath.toString(), value], { timeout: waitTimeout });
2548
+ eval($XPath) // eslint-disable-line no-eval
2549
+ return $XPath(null, locator).filter((el) => (el.value || '').indexOf(value) !== -1).length > 0
2550
+ }
2551
+ waiter = context.waitForFunction(valueFn, [locator.value, $XPath.toString(), value], {
2552
+ timeout: waitTimeout,
2553
+ })
2463
2554
  }
2464
2555
  return waiter.catch((err) => {
2465
- const loc = locator.toString();
2466
- 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}`);
2467
- });
2556
+ const loc = locator.toString()
2557
+ throw new Error(
2558
+ `element (${loc}) is not in DOM or there is no element(${loc}) with value "${value}" after ${waitTimeout / 1000} sec\n${err.message}`,
2559
+ )
2560
+ })
2468
2561
  }
2469
2562
 
2470
2563
  /**
@@ -2472,38 +2565,44 @@ class Playwright extends Helper {
2472
2565
  *
2473
2566
  */
2474
2567
  async waitNumberOfVisibleElements(locator, num, sec) {
2475
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2476
- locator = new Locator(locator, 'css');
2568
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2569
+ locator = new Locator(locator, 'css')
2477
2570
 
2478
- let waiter;
2479
- const context = await this._getContext();
2571
+ let waiter
2572
+ const context = await this._getContext()
2480
2573
  if (locator.isCSS()) {
2481
2574
  const visibleFn = function ([locator, num]) {
2482
- const els = document.querySelectorAll(locator);
2575
+ const els = document.querySelectorAll(locator)
2483
2576
  if (!els || els.length === 0) {
2484
- return false;
2577
+ return false
2485
2578
  }
2486
- return Array.prototype.filter.call(els, el => el.offsetParent !== null).length === num;
2487
- };
2488
- waiter = context.waitForFunction(visibleFn, [locator.value, num], { timeout: waitTimeout });
2579
+ return Array.prototype.filter.call(els, (el) => el.offsetParent !== null).length === num
2580
+ }
2581
+ waiter = context.waitForFunction(visibleFn, [locator.value, num], { timeout: waitTimeout })
2489
2582
  } else {
2490
2583
  const visibleFn = function ([locator, $XPath, num]) {
2491
- eval($XPath); // eslint-disable-line no-eval
2492
- return $XPath(null, locator).filter(el => el.offsetParent !== null).length === num;
2493
- };
2494
- waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString(), num], { timeout: waitTimeout });
2584
+ eval($XPath) // eslint-disable-line no-eval
2585
+ return $XPath(null, locator).filter((el) => el.offsetParent !== null).length === num
2586
+ }
2587
+ waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString(), num], {
2588
+ timeout: waitTimeout,
2589
+ })
2495
2590
  }
2496
2591
  return waiter.catch((err) => {
2497
- throw new Error(`The number of elements (${locator.toString()}) is not ${num} after ${waitTimeout / 1000} sec\n${err.message}`);
2498
- });
2592
+ throw new Error(
2593
+ `The number of elements (${locator.toString()}) is not ${num} after ${waitTimeout / 1000} sec\n${err.message}`,
2594
+ )
2595
+ })
2499
2596
  }
2500
2597
 
2501
2598
  /**
2502
2599
  * {{> waitForClickable }}
2503
2600
  */
2504
2601
  async waitForClickable(locator, waitTimeout) {
2505
- console.log('I.waitForClickable is DEPRECATED: This is no longer needed, Playwright automatically waits for element to be clickable');
2506
- console.log('Remove usage of this function');
2602
+ console.log(
2603
+ 'I.waitForClickable is DEPRECATED: This is no longer needed, Playwright automatically waits for element to be clickable',
2604
+ )
2605
+ console.log('Remove usage of this function')
2507
2606
  }
2508
2607
 
2509
2608
  /**
@@ -2511,14 +2610,16 @@ class Playwright extends Helper {
2511
2610
  *
2512
2611
  */
2513
2612
  async waitForElement(locator, sec) {
2514
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2515
- locator = new Locator(locator, 'css');
2613
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2614
+ locator = new Locator(locator, 'css')
2516
2615
 
2517
- const context = await this._getContext();
2616
+ const context = await this._getContext()
2518
2617
  try {
2519
- await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'attached' });
2618
+ await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'attached' })
2520
2619
  } catch (e) {
2521
- throw new Error(`element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${e.message}`);
2620
+ throw new Error(
2621
+ `element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${e.message}`,
2622
+ )
2522
2623
  }
2523
2624
  }
2524
2625
 
@@ -2528,28 +2629,28 @@ class Playwright extends Helper {
2528
2629
  * {{> waitForVisible }}
2529
2630
  */
2530
2631
  async waitForVisible(locator, sec) {
2531
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2532
- locator = new Locator(locator, 'css');
2533
- const context = await this._getContext();
2534
- let count = 0;
2632
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2633
+ locator = new Locator(locator, 'css')
2634
+ const context = await this._getContext()
2635
+ let count = 0
2535
2636
 
2536
2637
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2537
- let waiter;
2638
+ let waiter
2538
2639
  if (this.frame) {
2539
2640
  do {
2540
- waiter = await this.frame.locator(buildLocatorString(locator)).first().isVisible();
2541
- await this.wait(1);
2542
- count += 1000;
2543
- if (waiter) break;
2544
- } while (count <= waitTimeout);
2641
+ waiter = await this.frame.locator(buildLocatorString(locator)).first().isVisible()
2642
+ await this.wait(1)
2643
+ count += 1000
2644
+ if (waiter) break
2645
+ } while (count <= waitTimeout)
2545
2646
 
2546
- if (!waiter) throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec.`);
2647
+ if (!waiter) throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec.`)
2547
2648
  }
2548
2649
 
2549
2650
  try {
2550
- await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'visible' });
2651
+ await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'visible' })
2551
2652
  } catch (e) {
2552
- throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${e.message}`);
2653
+ throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${e.message}`)
2553
2654
  }
2554
2655
  }
2555
2656
 
@@ -2557,29 +2658,29 @@ class Playwright extends Helper {
2557
2658
  * {{> waitForInvisible }}
2558
2659
  */
2559
2660
  async waitForInvisible(locator, sec) {
2560
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2561
- locator = new Locator(locator, 'css');
2562
- const context = await this._getContext();
2563
- let waiter;
2564
- let count = 0;
2661
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2662
+ locator = new Locator(locator, 'css')
2663
+ const context = await this._getContext()
2664
+ let waiter
2665
+ let count = 0
2565
2666
 
2566
2667
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2567
2668
  if (this.frame) {
2568
2669
  do {
2569
- waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
2570
- await this.wait(1);
2571
- count += 1000;
2572
- if (waiter) break;
2573
- } while (count <= waitTimeout);
2670
+ waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden()
2671
+ await this.wait(1)
2672
+ count += 1000
2673
+ if (waiter) break
2674
+ } while (count <= waitTimeout)
2574
2675
 
2575
- if (!waiter) throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec.`);
2576
- return;
2676
+ if (!waiter) throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec.`)
2677
+ return
2577
2678
  }
2578
2679
 
2579
2680
  try {
2580
- await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' });
2681
+ await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' })
2581
2682
  } catch (e) {
2582
- throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${e.message}`);
2683
+ throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${e.message}`)
2583
2684
  }
2584
2685
  }
2585
2686
 
@@ -2587,143 +2688,168 @@ class Playwright extends Helper {
2587
2688
  * {{> waitToHide }}
2588
2689
  */
2589
2690
  async waitToHide(locator, sec) {
2590
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2591
- locator = new Locator(locator, 'css');
2592
- const context = await this._getContext();
2593
- let waiter;
2594
- let count = 0;
2691
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2692
+ locator = new Locator(locator, 'css')
2693
+ const context = await this._getContext()
2694
+ let waiter
2695
+ let count = 0
2595
2696
 
2596
2697
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2597
2698
  if (this.frame) {
2598
2699
  do {
2599
- waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
2600
- await this.wait(1);
2601
- count += 1000;
2602
- if (waiter) break;
2603
- } while (count <= waitTimeout);
2700
+ waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden()
2701
+ await this.wait(1)
2702
+ count += 1000
2703
+ if (waiter) break
2704
+ } while (count <= waitTimeout)
2604
2705
 
2605
- if (!waiter) throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec.`);
2606
- return;
2706
+ if (!waiter) throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec.`)
2707
+ return
2607
2708
  }
2608
2709
 
2609
- return context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' }).catch((err) => {
2610
- throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`);
2611
- });
2710
+ return context
2711
+ .locator(buildLocatorString(locator))
2712
+ .first()
2713
+ .waitFor({ timeout: waitTimeout, state: 'hidden' })
2714
+ .catch((err) => {
2715
+ throw new Error(
2716
+ `element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`,
2717
+ )
2718
+ })
2612
2719
  }
2613
2720
 
2614
2721
  /**
2615
2722
  * {{> waitForNumberOfTabs }}
2616
2723
  */
2617
2724
  async waitForNumberOfTabs(expectedTabs, sec) {
2618
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2619
- let currentTabs;
2620
- let count = 0;
2725
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2726
+ let currentTabs
2727
+ let count = 0
2621
2728
 
2622
2729
  do {
2623
- currentTabs = await this.grabNumberOfOpenTabs();
2624
- await this.wait(1);
2625
- count += 1000;
2626
- if (currentTabs >= expectedTabs) return;
2627
- } while (count <= waitTimeout);
2730
+ currentTabs = await this.grabNumberOfOpenTabs()
2731
+ await this.wait(1)
2732
+ count += 1000
2733
+ if (currentTabs >= expectedTabs) return
2734
+ } while (count <= waitTimeout)
2628
2735
 
2629
- throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`);
2736
+ throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`)
2630
2737
  }
2631
2738
 
2632
2739
  async _getContext() {
2633
2740
  if (this.context && this.context.constructor.name === 'FrameLocator') {
2634
- return this.context;
2741
+ return this.context
2635
2742
  }
2636
- return this.page;
2743
+ return this.page
2637
2744
  }
2638
2745
 
2639
2746
  /**
2640
2747
  * {{> waitInUrl }}
2641
2748
  */
2642
2749
  async waitInUrl(urlPart, sec = null) {
2643
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2644
-
2645
- return this.page.waitForFunction((urlPart) => {
2646
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
2647
- return currUrl.indexOf(urlPart) > -1;
2648
- }, urlPart, { timeout: waitTimeout }).catch(async (e) => {
2649
- const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
2650
- if (/Timeout/i.test(e.message)) {
2651
- throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
2652
- } else {
2653
- throw e;
2654
- }
2655
- });
2750
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2751
+
2752
+ return this.page
2753
+ .waitForFunction(
2754
+ (urlPart) => {
2755
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2756
+ return currUrl.indexOf(urlPart) > -1
2757
+ },
2758
+ urlPart,
2759
+ { timeout: waitTimeout },
2760
+ )
2761
+ .catch(async (e) => {
2762
+ const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2763
+ if (/Timeout/i.test(e.message)) {
2764
+ throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
2765
+ } else {
2766
+ throw e
2767
+ }
2768
+ })
2656
2769
  }
2657
2770
 
2658
2771
  /**
2659
2772
  * {{> waitUrlEquals }}
2660
2773
  */
2661
2774
  async waitUrlEquals(urlPart, sec = null) {
2662
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2775
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2663
2776
 
2664
- const baseUrl = this.options.url;
2777
+ const baseUrl = this.options.url
2665
2778
  if (urlPart.indexOf('http') < 0) {
2666
- urlPart = baseUrl + urlPart;
2667
- }
2668
-
2669
- return this.page.waitForFunction((urlPart) => {
2670
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
2671
- return currUrl.indexOf(urlPart) > -1;
2672
- }, urlPart, { timeout: waitTimeout }).catch(async (e) => {
2673
- const currUrl = await this._getPageUrl(); // Required because the waitForFunction can't return data.
2674
- if (/Timeout/i.test(e.message)) {
2675
- throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
2676
- } else {
2677
- throw e;
2678
- }
2679
- });
2779
+ urlPart = baseUrl + urlPart
2780
+ }
2781
+
2782
+ return this.page
2783
+ .waitForFunction(
2784
+ (urlPart) => {
2785
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
2786
+ return currUrl.indexOf(urlPart) > -1
2787
+ },
2788
+ urlPart,
2789
+ { timeout: waitTimeout },
2790
+ )
2791
+ .catch(async (e) => {
2792
+ const currUrl = await this._getPageUrl() // Required because the waitForFunction can't return data.
2793
+ if (/Timeout/i.test(e.message)) {
2794
+ throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
2795
+ } else {
2796
+ throw e
2797
+ }
2798
+ })
2680
2799
  }
2681
2800
 
2682
2801
  /**
2683
2802
  * {{> waitForText }}
2684
2803
  */
2685
2804
  async waitForText(text, sec = null, context = null) {
2686
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2687
- const errorMessage = `Text "${text}" was not found on page after ${waitTimeout / 1000} sec.`;
2688
- let waiter;
2805
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2806
+ const errorMessage = `Text "${text}" was not found on page after ${waitTimeout / 1000} sec.`
2807
+ let waiter
2689
2808
 
2690
- const contextObject = await this._getContext();
2809
+ const contextObject = await this._getContext()
2691
2810
 
2692
2811
  if (context) {
2693
- const locator = new Locator(context, 'css');
2812
+ const locator = new Locator(context, 'css')
2694
2813
  if (!locator.isXPath()) {
2695
2814
  try {
2696
- await contextObject.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`).first().waitFor({ timeout: waitTimeout, state: 'visible' });
2815
+ await contextObject
2816
+ .locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`)
2817
+ .first()
2818
+ .waitFor({ timeout: waitTimeout, state: 'visible' })
2697
2819
  } catch (e) {
2698
- throw new Error(`${errorMessage}\n${e.message}`);
2820
+ throw new Error(`${errorMessage}\n${e.message}`)
2699
2821
  }
2700
2822
  }
2701
2823
 
2702
2824
  if (locator.isXPath()) {
2703
2825
  try {
2704
- await contextObject.waitForFunction(([locator, text, $XPath]) => {
2705
- eval($XPath); // eslint-disable-line no-eval
2706
- const el = $XPath(null, locator);
2707
- if (!el.length) return false;
2708
- return el[0].innerText.indexOf(text) > -1;
2709
- }, [locator.value, text, $XPath.toString()], { timeout: waitTimeout });
2826
+ await contextObject.waitForFunction(
2827
+ ([locator, text, $XPath]) => {
2828
+ eval($XPath) // eslint-disable-line no-eval
2829
+ const el = $XPath(null, locator)
2830
+ if (!el.length) return false
2831
+ return el[0].innerText.indexOf(text) > -1
2832
+ },
2833
+ [locator.value, text, $XPath.toString()],
2834
+ { timeout: waitTimeout },
2835
+ )
2710
2836
  } catch (e) {
2711
- throw new Error(`${errorMessage}\n${e.message}`);
2837
+ throw new Error(`${errorMessage}\n${e.message}`)
2712
2838
  }
2713
2839
  }
2714
2840
  } else {
2715
2841
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2716
2842
  // eslint-disable-next-line no-lonely-if
2717
- const _contextObject = this.frame ? this.frame : contextObject;
2718
- let count = 0;
2843
+ const _contextObject = this.frame ? this.frame : contextObject
2844
+ let count = 0
2719
2845
  do {
2720
- waiter = await _contextObject.locator(`:has-text("${text}")`).first().isVisible();
2721
- if (waiter) break;
2722
- await this.wait(1);
2723
- count += 1000;
2724
- } while (count <= waitTimeout);
2846
+ waiter = await _contextObject.locator(`:has-text("${text}")`).first().isVisible()
2847
+ if (waiter) break
2848
+ await this.wait(1)
2849
+ count += 1000
2850
+ } while (count <= waitTimeout)
2725
2851
 
2726
- if (!waiter) throw new Error(`${errorMessage}`);
2852
+ if (!waiter) throw new Error(`${errorMessage}`)
2727
2853
  }
2728
2854
  }
2729
2855
 
@@ -2739,8 +2865,8 @@ class Playwright extends Helper {
2739
2865
  * @param {?number} [sec=null] seconds to wait
2740
2866
  */
2741
2867
  async waitForRequest(urlOrPredicate, sec = null) {
2742
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2743
- return this.page.waitForRequest(urlOrPredicate, { timeout });
2868
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2869
+ return this.page.waitForRequest(urlOrPredicate, { timeout })
2744
2870
  }
2745
2871
 
2746
2872
  /**
@@ -2755,8 +2881,8 @@ class Playwright extends Helper {
2755
2881
  * @param {?number} [sec=null] number of seconds to wait
2756
2882
  */
2757
2883
  async waitForResponse(urlOrPredicate, sec = null) {
2758
- const timeout = sec ? sec * 1000 : this.options.waitForTimeout;
2759
- return this.page.waitForResponse(urlOrPredicate, { timeout });
2884
+ const timeout = sec ? sec * 1000 : this.options.waitForTimeout
2885
+ return this.page.waitForResponse(urlOrPredicate, { timeout })
2760
2886
  }
2761
2887
 
2762
2888
  /**
@@ -2766,51 +2892,51 @@ class Playwright extends Helper {
2766
2892
  if (Number.isInteger(locator)) {
2767
2893
  // Select by frame index of current context
2768
2894
 
2769
- let childFrames = null;
2895
+ let childFrames = null
2770
2896
  if (this.context && typeof this.context.childFrames === 'function') {
2771
- childFrames = this.context.childFrames();
2897
+ childFrames = this.context.childFrames()
2772
2898
  } else {
2773
- childFrames = this.page.mainFrame().childFrames();
2899
+ childFrames = this.page.mainFrame().childFrames()
2774
2900
  }
2775
2901
 
2776
2902
  if (locator >= 0 && locator < childFrames.length) {
2777
- this.context = await this.page.frameLocator('iframe').nth(locator);
2778
- this.contextLocator = locator;
2903
+ this.context = await this.page.frameLocator('iframe').nth(locator)
2904
+ this.contextLocator = locator
2779
2905
  } else {
2780
- throw new Error('Element #invalidIframeSelector was not found by text|CSS|XPath');
2906
+ throw new Error('Element #invalidIframeSelector was not found by text|CSS|XPath')
2781
2907
  }
2782
- return;
2908
+ return
2783
2909
  }
2784
2910
 
2785
2911
  if (!locator) {
2786
- this.context = this.page;
2787
- this.contextLocator = null;
2788
- this.frame = null;
2789
- return;
2912
+ this.context = this.page
2913
+ this.contextLocator = null
2914
+ this.frame = null
2915
+ return
2790
2916
  }
2791
2917
 
2792
2918
  // iframe by selector
2793
- locator = buildLocatorString(new Locator(locator, 'css'));
2794
- const frame = await this._locateElement(locator);
2919
+ locator = buildLocatorString(new Locator(locator, 'css'))
2920
+ const frame = await this._locateElement(locator)
2795
2921
 
2796
2922
  if (!frame) {
2797
- throw new Error(`Frame ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
2923
+ throw new Error(`Frame ${JSON.stringify(locator)} was not found by text|CSS|XPath`)
2798
2924
  }
2799
2925
 
2800
2926
  if (this.frame) {
2801
- this.frame = await this.frame.frameLocator(locator);
2927
+ this.frame = await this.frame.frameLocator(locator)
2802
2928
  } else {
2803
- this.frame = await this.page.frameLocator(locator);
2929
+ this.frame = await this.page.frameLocator(locator)
2804
2930
  }
2805
2931
 
2806
- const contentFrame = this.frame;
2932
+ const contentFrame = this.frame
2807
2933
 
2808
2934
  if (contentFrame) {
2809
- this.context = contentFrame;
2810
- this.contextLocator = null;
2935
+ this.context = contentFrame
2936
+ this.contextLocator = null
2811
2937
  } else {
2812
- this.context = this.page.frame(this.page.frames()[1].name());
2813
- this.contextLocator = locator;
2938
+ this.context = this.page.frame(this.page.frames()[1].name())
2939
+ this.contextLocator = locator
2814
2940
  }
2815
2941
  }
2816
2942
 
@@ -2818,17 +2944,17 @@ class Playwright extends Helper {
2818
2944
  * {{> waitForFunction }}
2819
2945
  */
2820
2946
  async waitForFunction(fn, argsOrSec = null, sec = null) {
2821
- let args = [];
2947
+ let args = []
2822
2948
  if (argsOrSec) {
2823
2949
  if (Array.isArray(argsOrSec)) {
2824
- args = argsOrSec;
2950
+ args = argsOrSec
2825
2951
  } else if (typeof argsOrSec === 'number') {
2826
- sec = argsOrSec;
2952
+ sec = argsOrSec
2827
2953
  }
2828
2954
  }
2829
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2830
- const context = await this._getContext();
2831
- return context.waitForFunction(fn, args, { timeout: waitTimeout });
2955
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2956
+ const context = await this._getContext()
2957
+ return context.waitForFunction(fn, args, { timeout: waitTimeout })
2832
2958
  }
2833
2959
 
2834
2960
  /**
@@ -2840,13 +2966,13 @@ class Playwright extends Helper {
2840
2966
  */
2841
2967
  async waitForNavigation(options = {}) {
2842
2968
  console.log(`waitForNavigation deprecated:
2843
- * This method is inherently racy, please use 'waitForURL' instead.`);
2969
+ * This method is inherently racy, please use 'waitForURL' instead.`)
2844
2970
  options = {
2845
2971
  timeout: this.options.getPageTimeout,
2846
2972
  waitUntil: this.options.waitForNavigation,
2847
2973
  ...options,
2848
- };
2849
- return this.page.waitForNavigation(options);
2974
+ }
2975
+ return this.page.waitForNavigation(options)
2850
2976
  }
2851
2977
 
2852
2978
  /**
@@ -2862,41 +2988,44 @@ class Playwright extends Helper {
2862
2988
  timeout: this.options.getPageTimeout,
2863
2989
  waitUntil: this.options.waitForNavigation,
2864
2990
  ...options,
2865
- };
2866
- return this.page.waitForURL(url, options);
2991
+ }
2992
+ return this.page.waitForURL(url, options)
2867
2993
  }
2868
2994
 
2869
2995
  async waitUntilExists(locator, sec) {
2870
2996
  console.log(`waitUntilExists deprecated:
2871
2997
  * use 'waitForElement' to wait for element to be attached
2872
- * use 'waitForDetached to wait for element to be removed'`);
2873
- return this.waitForDetached(locator, sec);
2998
+ * use 'waitForDetached to wait for element to be removed'`)
2999
+ return this.waitForDetached(locator, sec)
2874
3000
  }
2875
3001
 
2876
3002
  /**
2877
3003
  * {{> waitForDetached }}
2878
3004
  */
2879
3005
  async waitForDetached(locator, sec) {
2880
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2881
- locator = new Locator(locator, 'css');
3006
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
3007
+ locator = new Locator(locator, 'css')
2882
3008
 
2883
- let waiter;
2884
- const context = await this._getContext();
3009
+ let waiter
3010
+ const context = await this._getContext()
2885
3011
  if (!locator.isXPath()) {
2886
3012
  try {
2887
- await context.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()}`).first().waitFor({ timeout: waitTimeout, state: 'detached' });
3013
+ await context
3014
+ .locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()}`)
3015
+ .first()
3016
+ .waitFor({ timeout: waitTimeout, state: 'detached' })
2888
3017
  } catch (e) {
2889
- throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${e.message}`);
3018
+ throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${e.message}`)
2890
3019
  }
2891
3020
  } else {
2892
3021
  const visibleFn = function ([locator, $XPath]) {
2893
- eval($XPath); // eslint-disable-line no-eval
2894
- return $XPath(null, locator).length === 0;
2895
- };
2896
- waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString()], { timeout: waitTimeout });
3022
+ eval($XPath) // eslint-disable-line no-eval
3023
+ return $XPath(null, locator).length === 0
3024
+ }
3025
+ waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString()], { timeout: waitTimeout })
2897
3026
  return waiter.catch((err) => {
2898
- throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
2899
- });
3027
+ throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`)
3028
+ })
2900
3029
  }
2901
3030
  }
2902
3031
 
@@ -2905,53 +3034,56 @@ class Playwright extends Helper {
2905
3034
  */
2906
3035
  async waitForCookie(name, sec) {
2907
3036
  // by default, we will retry 3 times
2908
- let retries = 3;
2909
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
3037
+ let retries = 3
3038
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
2910
3039
 
2911
3040
  if (sec) {
2912
- retries = sec;
3041
+ retries = sec
2913
3042
  } else {
2914
- retries = Math.ceil(waitTimeout / 1000) - 1;
3043
+ retries = Math.ceil(waitTimeout / 1000) - 1
2915
3044
  }
2916
3045
 
2917
- return promiseRetry(async (retry, number) => {
2918
- const _grabCookie = async (name) => {
2919
- const cookies = await this.browserContext.cookies();
2920
- const cookie = cookies.filter(c => c.name === name);
2921
- if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
2922
- };
3046
+ return promiseRetry(
3047
+ async (retry, number) => {
3048
+ const _grabCookie = async (name) => {
3049
+ const cookies = await this.browserContext.cookies()
3050
+ const cookie = cookies.filter((c) => c.name === name)
3051
+ if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
3052
+ }
2923
3053
 
2924
- this.debugSection('Wait for cookie: ', name);
2925
- if (number > 1) this.debugSection('Retrying... Attempt #', number);
3054
+ this.debugSection('Wait for cookie: ', name)
3055
+ if (number > 1) this.debugSection('Retrying... Attempt #', number)
2926
3056
 
2927
- try {
2928
- await _grabCookie(name);
2929
- } catch (e) {
2930
- retry(e);
2931
- }
2932
- }, { retries, maxTimeout: 1000 });
3057
+ try {
3058
+ await _grabCookie(name)
3059
+ } catch (e) {
3060
+ retry(e)
3061
+ }
3062
+ },
3063
+ { retries, maxTimeout: 1000 },
3064
+ )
2933
3065
  }
2934
3066
 
2935
3067
  async _waitForAction() {
2936
- return this.wait(this.options.waitForAction / 1000);
3068
+ return this.wait(this.options.waitForAction / 1000)
2937
3069
  }
2938
3070
 
2939
3071
  /**
2940
3072
  * {{> grabDataFromPerformanceTiming }}
2941
3073
  */
2942
3074
  async grabDataFromPerformanceTiming() {
2943
- return perfTiming;
3075
+ return perfTiming
2944
3076
  }
2945
3077
 
2946
3078
  /**
2947
3079
  * {{> grabElementBoundingRect }}
2948
3080
  */
2949
3081
  async grabElementBoundingRect(locator, prop) {
2950
- const el = await this._locateElement(locator);
2951
- assertElementExists(el, locator);
2952
- const rect = await el.boundingBox();
2953
- if (prop) return rect[prop];
2954
- return rect;
3082
+ const el = await this._locateElement(locator)
3083
+ assertElementExists(el, locator)
3084
+ const rect = await el.boundingBox()
3085
+ if (prop) return rect[prop]
3086
+ return rect
2955
3087
  }
2956
3088
 
2957
3089
  /**
@@ -2966,7 +3098,7 @@ class Playwright extends Helper {
2966
3098
  * @param {function} [handler] a function to process request
2967
3099
  */
2968
3100
  async mockRoute(url, handler) {
2969
- return this.browserContext.route(...arguments);
3101
+ return this.browserContext.route(...arguments)
2970
3102
  }
2971
3103
 
2972
3104
  /**
@@ -2982,17 +3114,17 @@ class Playwright extends Helper {
2982
3114
  * @param {function} [handler] a function to process request
2983
3115
  */
2984
3116
  async stopMockingRoute(url, handler) {
2985
- return this.browserContext.unroute(...arguments);
3117
+ return this.browserContext.unroute(...arguments)
2986
3118
  }
2987
3119
 
2988
3120
  /**
2989
- * {{> flushNetworkTraffics }}
3121
+ * {{> startRecordingTraffic }}
2990
3122
  *
2991
3123
  */
2992
3124
  startRecordingTraffic() {
2993
- this.flushNetworkTraffics();
2994
- this.recording = true;
2995
- this.recordedAtLeastOnce = true;
3125
+ this.flushNetworkTraffics()
3126
+ this.recording = true
3127
+ this.recordedAtLeastOnce = true
2996
3128
 
2997
3129
  this.page.on('requestfinished', async (request) => {
2998
3130
  const information = {
@@ -3001,16 +3133,16 @@ class Playwright extends Helper {
3001
3133
  requestHeaders: request.headers(),
3002
3134
  requestPostData: request.postData(),
3003
3135
  response: request.response(),
3004
- };
3136
+ }
3005
3137
 
3006
- this.debugSection('REQUEST: ', JSON.stringify(information));
3138
+ this.debugSection('REQUEST: ', JSON.stringify(information))
3007
3139
 
3008
3140
  if (typeof information.requestPostData === 'object') {
3009
- information.requestPostData = JSON.parse(information.requestPostData);
3141
+ information.requestPostData = JSON.parse(information.requestPostData)
3010
3142
  }
3011
3143
 
3012
- this.requests.push(information);
3013
- });
3144
+ this.requests.push(information)
3145
+ })
3014
3146
  }
3015
3147
 
3016
3148
  /**
@@ -3033,21 +3165,21 @@ class Playwright extends Helper {
3033
3165
  */
3034
3166
  blockTraffic(urls) {
3035
3167
  if (Array.isArray(urls)) {
3036
- urls.forEach(url => {
3168
+ urls.forEach((url) => {
3037
3169
  this.page.route(url, (route) => {
3038
3170
  route
3039
3171
  .abort()
3040
3172
  // Sometimes it happens that browser has been closed in the meantime. It is ok to ignore error then.
3041
- .catch((e) => {});
3042
- });
3043
- });
3173
+ .catch((e) => {})
3174
+ })
3175
+ })
3044
3176
  } else {
3045
3177
  this.page.route(urls, (route) => {
3046
3178
  route
3047
3179
  .abort()
3048
3180
  // Sometimes it happens that browser has been closed in the meantime. It is ok to ignore error then.
3049
- .catch((e) => {});
3050
- });
3181
+ .catch((e) => {})
3182
+ })
3051
3183
  }
3052
3184
  }
3053
3185
 
@@ -3069,10 +3201,10 @@ class Playwright extends Helper {
3069
3201
  */
3070
3202
  mockTraffic(urls, responseString, contentType = 'application/json') {
3071
3203
  // Required to mock cross-domain requests
3072
- const headers = { 'access-control-allow-origin': '*' };
3204
+ const headers = { 'access-control-allow-origin': '*' }
3073
3205
 
3074
3206
  if (typeof urls === 'string') {
3075
- urls = [urls];
3207
+ urls = [urls]
3076
3208
  }
3077
3209
 
3078
3210
  urls.forEach((url) => {
@@ -3080,15 +3212,15 @@ class Playwright extends Helper {
3080
3212
  if (this.page.isClosed()) {
3081
3213
  // Sometimes it happens that browser has been closed in the meantime.
3082
3214
  // In this case we just don't fulfill to prevent error in test scenario.
3083
- return;
3215
+ return
3084
3216
  }
3085
3217
  route.fulfill({
3086
3218
  contentType,
3087
3219
  headers,
3088
3220
  body: responseString,
3089
- });
3090
- });
3091
- });
3221
+ })
3222
+ })
3223
+ })
3092
3224
  }
3093
3225
 
3094
3226
  /**
@@ -3096,7 +3228,7 @@ class Playwright extends Helper {
3096
3228
  * {{> flushNetworkTraffics }}
3097
3229
  */
3098
3230
  flushNetworkTraffics() {
3099
- flushNetworkTraffics.call(this);
3231
+ flushNetworkTraffics.call(this)
3100
3232
  }
3101
3233
 
3102
3234
  /**
@@ -3104,14 +3236,12 @@ class Playwright extends Helper {
3104
3236
  * {{> stopRecordingTraffic }}
3105
3237
  */
3106
3238
  stopRecordingTraffic() {
3107
- stopRecordingTraffic.call(this);
3239
+ stopRecordingTraffic.call(this)
3108
3240
  }
3109
3241
 
3110
3242
  /**
3111
3243
  * Returns full URL of request matching parameter "urlMatch".
3112
3244
  *
3113
- * @param {string|RegExp} urlMatch Expected URL of request in network traffic. Can be a string or a regular expression.
3114
- *
3115
3245
  * Examples:
3116
3246
  *
3117
3247
  * ```js
@@ -3119,25 +3249,28 @@ class Playwright extends Helper {
3119
3249
  * I.grabTrafficUrl(/session.*start/);
3120
3250
  * ```
3121
3251
  *
3252
+ * @param {string|RegExp} urlMatch Expected URL of request in network traffic. Can be a string or a regular expression.
3122
3253
  * @return {Promise<*>}
3123
3254
  */
3124
3255
  grabTrafficUrl(urlMatch) {
3125
3256
  if (!this.recordedAtLeastOnce) {
3126
- throw new Error('Failure in test automation. You use "I.grabTrafficUrl", but "I.startRecordingTraffic" was never called before.');
3257
+ throw new Error(
3258
+ 'Failure in test automation. You use "I.grabTrafficUrl", but "I.startRecordingTraffic" was never called before.',
3259
+ )
3127
3260
  }
3128
3261
 
3129
3262
  for (const i in this.requests) {
3130
3263
  // eslint-disable-next-line no-prototype-builtins
3131
3264
  if (this.requests.hasOwnProperty(i)) {
3132
- const request = this.requests[i];
3265
+ const request = this.requests[i]
3133
3266
 
3134
3267
  if (request.url && request.url.match(new RegExp(urlMatch))) {
3135
- return request.url;
3268
+ return request.url
3136
3269
  }
3137
3270
  }
3138
3271
  }
3139
3272
 
3140
- assert.fail(`Method "getTrafficUrl" failed: No request found in traffic that matches ${urlMatch}`);
3273
+ assert.fail(`Method "getTrafficUrl" failed: No request found in traffic that matches ${urlMatch}`)
3141
3274
  }
3142
3275
 
3143
3276
  /**
@@ -3145,17 +3278,15 @@ class Playwright extends Helper {
3145
3278
  * {{> grabRecordedNetworkTraffics }}
3146
3279
  */
3147
3280
  async grabRecordedNetworkTraffics() {
3148
- return grabRecordedNetworkTraffics.call(this);
3281
+ return grabRecordedNetworkTraffics.call(this)
3149
3282
  }
3150
3283
 
3151
3284
  /**
3152
3285
  *
3153
3286
  * {{> seeTraffic }}
3154
3287
  */
3155
- async seeTraffic({
3156
- name, url, parameters, requestPostData, timeout = 10,
3157
- }) {
3158
- await seeTraffic.call(this, ...arguments);
3288
+ async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) {
3289
+ await seeTraffic.call(this, ...arguments)
3159
3290
  }
3160
3291
 
3161
3292
  /**
@@ -3164,51 +3295,42 @@ class Playwright extends Helper {
3164
3295
  *
3165
3296
  */
3166
3297
  dontSeeTraffic({ name, url }) {
3167
- dontSeeTraffic.call(this, ...arguments);
3298
+ dontSeeTraffic.call(this, ...arguments)
3168
3299
  }
3169
3300
 
3170
3301
  /**
3171
3302
  * {{> startRecordingWebSocketMessages }}
3172
3303
  */
3173
3304
  async startRecordingWebSocketMessages() {
3174
- this.flushWebSocketMessages();
3175
- this.recordingWebSocketMessages = true;
3176
- this.recordedWebSocketMessagesAtLeastOnce = true;
3177
-
3178
- this.cdpSession = await this.getNewCDPSession();
3179
- await this.cdpSession.send('Network.enable');
3180
- await this.cdpSession.send('Page.enable');
3181
-
3182
- this.cdpSession.on(
3183
- 'Network.webSocketFrameReceived',
3184
- (payload) => {
3185
- this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload));
3186
- },
3187
- );
3305
+ this.flushWebSocketMessages()
3306
+ this.recordingWebSocketMessages = true
3307
+ this.recordedWebSocketMessagesAtLeastOnce = true
3188
3308
 
3189
- this.cdpSession.on(
3190
- 'Network.webSocketFrameSent',
3191
- (payload) => {
3192
- this._logWebsocketMessages(this._getWebSocketLog('SENT', payload));
3193
- },
3194
- );
3309
+ this.cdpSession = await this.getNewCDPSession()
3310
+ await this.cdpSession.send('Network.enable')
3311
+ await this.cdpSession.send('Page.enable')
3195
3312
 
3196
- this.cdpSession.on(
3197
- 'Network.webSocketFrameError',
3198
- (payload) => {
3199
- this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload));
3200
- },
3201
- );
3313
+ this.cdpSession.on('Network.webSocketFrameReceived', (payload) => {
3314
+ this._logWebsocketMessages(this._getWebSocketLog('RECEIVED', payload))
3315
+ })
3316
+
3317
+ this.cdpSession.on('Network.webSocketFrameSent', (payload) => {
3318
+ this._logWebsocketMessages(this._getWebSocketLog('SENT', payload))
3319
+ })
3320
+
3321
+ this.cdpSession.on('Network.webSocketFrameError', (payload) => {
3322
+ this._logWebsocketMessages(this._getWebSocketLog('ERROR', payload))
3323
+ })
3202
3324
  }
3203
3325
 
3204
3326
  /**
3205
3327
  * {{> stopRecordingWebSocketMessages }}
3206
3328
  */
3207
3329
  async stopRecordingWebSocketMessages() {
3208
- await this.cdpSession.send('Network.disable');
3209
- await this.cdpSession.send('Page.disable');
3210
- this.page.removeAllListeners('Network');
3211
- this.recordingWebSocketMessages = false;
3330
+ await this.cdpSession.send('Network.disable')
3331
+ await this.cdpSession.send('Page.disable')
3332
+ this.page.removeAllListeners('Network')
3333
+ this.recordingWebSocketMessages = false
3212
3334
  }
3213
3335
 
3214
3336
  /**
@@ -3220,17 +3342,19 @@ class Playwright extends Helper {
3220
3342
  grabWebSocketMessages() {
3221
3343
  if (!this.recordingWebSocketMessages) {
3222
3344
  if (!this.recordedWebSocketMessagesAtLeastOnce) {
3223
- throw new Error('Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.');
3345
+ throw new Error(
3346
+ 'Failure in test automation. You use "I.grabWebSocketMessages", but "I.startRecordingWebSocketMessages" was never called before.',
3347
+ )
3224
3348
  }
3225
3349
  }
3226
- return this.webSocketMessages;
3350
+ return this.webSocketMessages
3227
3351
  }
3228
3352
 
3229
3353
  /**
3230
3354
  * Resets all recorded WS messages.
3231
3355
  */
3232
3356
  flushWebSocketMessages() {
3233
- this.webSocketMessages = [];
3357
+ this.webSocketMessages = []
3234
3358
  }
3235
3359
 
3236
3360
  /**
@@ -3288,426 +3412,444 @@ class Playwright extends Helper {
3288
3412
  * @return {Promise<Array<Object>>}
3289
3413
  */
3290
3414
  async grabMetrics() {
3291
- const client = await this.page.context().newCDPSession(this.page);
3292
- await client.send('Performance.enable');
3293
- const perfMetricObject = await client.send('Performance.getMetrics');
3294
- return perfMetricObject?.metrics;
3415
+ const client = await this.page.context().newCDPSession(this.page)
3416
+ await client.send('Performance.enable')
3417
+ const perfMetricObject = await client.send('Performance.getMetrics')
3418
+ return perfMetricObject?.metrics
3295
3419
  }
3296
3420
 
3297
3421
  _getWebSocketMessage(payload) {
3298
3422
  if (payload.errorMessage) {
3299
- return payload.errorMessage;
3423
+ return payload.errorMessage
3300
3424
  }
3301
3425
 
3302
- return payload.response.payloadData;
3426
+ return payload.response.payloadData
3303
3427
  }
3304
3428
 
3305
3429
  _getWebSocketLog(prefix, payload) {
3306
- return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`;
3430
+ return `${prefix} ID: ${payload.requestId} TIMESTAMP: ${payload.timestamp} (${new Date().toISOString()})\n\n${this._getWebSocketMessage(payload)}\n\n`
3307
3431
  }
3308
3432
 
3309
3433
  async getNewCDPSession() {
3310
- return this.page.context().newCDPSession(this.page);
3434
+ return this.page.context().newCDPSession(this.page)
3311
3435
  }
3312
3436
 
3313
3437
  _logWebsocketMessages(message) {
3314
- this.webSocketMessages += message;
3438
+ this.webSocketMessages.push(message)
3315
3439
  }
3316
3440
  }
3317
3441
 
3318
- export default Playwright;
3442
+ module.exports = Playwright
3319
3443
 
3320
3444
  function buildLocatorString(locator) {
3321
3445
  if (locator.isCustom()) {
3322
- return `${locator.type}=${locator.value}`;
3323
- } if (locator.isXPath()) {
3324
- return `xpath=${locator.value}`;
3446
+ return `${locator.type}=${locator.value}`
3447
+ }
3448
+ if (locator.isXPath()) {
3449
+ return `xpath=${locator.value}`
3325
3450
  }
3326
- return locator.simplify();
3451
+ return locator.simplify()
3327
3452
  }
3328
3453
 
3329
3454
  async function findElements(matcher, locator) {
3330
- if (locator.react) return findReact(matcher, locator);
3331
- if (locator.vue) return findVue(matcher, locator);
3332
- if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator);
3333
- locator = new Locator(locator, 'css');
3455
+ if (locator.react) return findReact(matcher, locator)
3456
+ if (locator.vue) return findVue(matcher, locator)
3457
+ if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator)
3458
+ locator = new Locator(locator, 'css')
3334
3459
 
3335
- return matcher.locator(buildLocatorString(locator)).all();
3460
+ return matcher.locator(buildLocatorString(locator)).all()
3336
3461
  }
3337
3462
 
3338
3463
  async function findElement(matcher, locator) {
3339
- if (locator.react) return findReact(matcher, locator);
3340
- if (locator.vue) return findVue(matcher, locator);
3341
- if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator);
3342
- locator = new Locator(locator, 'css');
3464
+ if (locator.react) return findReact(matcher, locator)
3465
+ if (locator.vue) return findVue(matcher, locator)
3466
+ if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator)
3467
+ locator = new Locator(locator, 'css')
3343
3468
 
3344
- return matcher.locator(buildLocatorString(locator)).first();
3469
+ return matcher.locator(buildLocatorString(locator)).first()
3345
3470
  }
3346
3471
 
3347
3472
  async function getVisibleElements(elements) {
3348
- const visibleElements = [];
3473
+ const visibleElements = []
3349
3474
  for (const element of elements) {
3350
3475
  if (await element.isVisible()) {
3351
- visibleElements.push(element);
3476
+ visibleElements.push(element)
3352
3477
  }
3353
3478
  }
3354
3479
  if (visibleElements.length === 0) {
3355
- return elements;
3480
+ return elements
3356
3481
  }
3357
- return visibleElements;
3482
+ return visibleElements
3358
3483
  }
3359
3484
 
3360
3485
  async function proceedClick(locator, context = null, options = {}) {
3361
- let matcher = await this._getContext();
3486
+ let matcher = await this._getContext()
3362
3487
  if (context) {
3363
- const els = await this._locate(context);
3364
- assertElementExists(els, context);
3365
- matcher = els[0];
3488
+ const els = await this._locate(context)
3489
+ assertElementExists(els, context)
3490
+ matcher = els[0]
3366
3491
  }
3367
- const els = await findClickable.call(this, matcher, locator);
3492
+ const els = await findClickable.call(this, matcher, locator)
3368
3493
  if (context) {
3369
- assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
3494
+ assertElementExists(
3495
+ els,
3496
+ locator,
3497
+ 'Clickable element',
3498
+ `was not found inside element ${new Locator(context).toString()}`,
3499
+ )
3370
3500
  } else {
3371
- assertElementExists(els, locator, 'Clickable element');
3501
+ assertElementExists(els, locator, 'Clickable element')
3372
3502
  }
3373
3503
 
3374
- await highlightActiveElement.call(this, els[0]);
3504
+ await highlightActiveElement.call(this, els[0])
3375
3505
 
3376
3506
  /*
3377
3507
  using the force true options itself but instead dispatching a click
3378
3508
  */
3379
3509
  if (options.force) {
3380
- await els[0].dispatchEvent('click');
3510
+ await els[0].dispatchEvent('click')
3381
3511
  } else {
3382
- const element = els.length > 1 ? (await getVisibleElements(els))[0] : els[0];
3383
- await element.click(options);
3512
+ const element = els.length > 1 ? (await getVisibleElements(els))[0] : els[0]
3513
+ await element.click(options)
3384
3514
  }
3385
- const promises = [];
3515
+ const promises = []
3386
3516
  if (options.waitForNavigation) {
3387
- promises.push(this.waitForURL(/.*/, { waitUntil: options.waitForNavigation }));
3517
+ promises.push(this.waitForURL(/.*/, { waitUntil: options.waitForNavigation }))
3388
3518
  }
3389
- promises.push(this._waitForAction());
3519
+ promises.push(this._waitForAction())
3390
3520
 
3391
- return Promise.all(promises);
3521
+ return Promise.all(promises)
3392
3522
  }
3393
3523
 
3394
3524
  async function findClickable(matcher, locator) {
3395
- if (locator.react) return findReact(matcher, locator);
3396
- if (locator.vue) return findVue(matcher, locator);
3397
- if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator);
3525
+ if (locator.react) return findReact(matcher, locator)
3526
+ if (locator.vue) return findVue(matcher, locator)
3527
+ if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator)
3398
3528
 
3399
- locator = new Locator(locator);
3400
- if (!locator.isFuzzy()) return findElements.call(this, matcher, locator);
3529
+ locator = new Locator(locator)
3530
+ if (!locator.isFuzzy()) return findElements.call(this, matcher, locator)
3401
3531
 
3402
- let els;
3403
- const literal = xpathLocator.literal(locator.value);
3532
+ let els
3533
+ const literal = xpathLocator.literal(locator.value)
3404
3534
 
3405
- els = await findElements.call(this, matcher, Locator.clickable.narrow(literal));
3406
- if (els.length) return els;
3535
+ els = await findElements.call(this, matcher, Locator.clickable.narrow(literal))
3536
+ if (els.length) return els
3407
3537
 
3408
- els = await findElements.call(this, matcher, Locator.clickable.wide(literal));
3409
- if (els.length) return els;
3538
+ els = await findElements.call(this, matcher, Locator.clickable.wide(literal))
3539
+ if (els.length) return els
3410
3540
 
3411
3541
  try {
3412
- els = await findElements.call(this, matcher, Locator.clickable.self(literal));
3413
- if (els.length) return els;
3542
+ els = await findElements.call(this, matcher, Locator.clickable.self(literal))
3543
+ if (els.length) return els
3414
3544
  } catch (err) {
3415
3545
  // Do nothing
3416
3546
  }
3417
3547
 
3418
- return findElements.call(this, matcher, locator.value); // by css or xpath
3548
+ return findElements.call(this, matcher, locator.value) // by css or xpath
3419
3549
  }
3420
3550
 
3421
3551
  async function proceedSee(assertType, text, context, strict = false) {
3422
- let description;
3423
- let allText;
3552
+ let description
3553
+ let allText
3424
3554
 
3425
3555
  if (!context) {
3426
- const el = await this.context;
3556
+ const el = await this.context
3427
3557
 
3428
- allText = el.constructor.name !== 'Locator' ? [await el.locator('body').innerText()] : [await el.innerText()];
3558
+ allText = el.constructor.name !== 'Locator' ? [await el.locator('body').innerText()] : [await el.innerText()]
3429
3559
 
3430
- description = 'web application';
3560
+ description = 'web application'
3431
3561
  } else {
3432
- const locator = new Locator(context, 'css');
3433
- description = `element ${locator.toString()}`;
3434
- const els = await this._locate(locator);
3435
- assertElementExists(els, locator.toString());
3436
- allText = await Promise.all(els.map(el => el.innerText()));
3562
+ const locator = new Locator(context, 'css')
3563
+ description = `element ${locator.toString()}`
3564
+ const els = await this._locate(locator)
3565
+ assertElementExists(els, locator.toString())
3566
+ allText = await Promise.all(els.map((el) => el.innerText()))
3437
3567
  }
3438
3568
 
3439
3569
  if (strict) {
3440
- return allText.map(elText => equals(description)[assertType](text, elText));
3570
+ return allText.map((elText) => equals(description)[assertType](text, elText))
3441
3571
  }
3442
- return stringIncludes(description)[assertType](normalizeSpacesInString(text), normalizeSpacesInString(allText.join(' | ')));
3572
+ return stringIncludes(description)[assertType](
3573
+ normalizeSpacesInString(text),
3574
+ normalizeSpacesInString(allText.join(' | ')),
3575
+ )
3443
3576
  }
3444
3577
 
3445
3578
  async function findCheckable(locator, context) {
3446
- let contextEl = await this.context;
3579
+ let contextEl = await this.context
3447
3580
  if (typeof context === 'string') {
3448
- contextEl = await findElements.call(this, contextEl, (new Locator(context, 'css')).simplify());
3449
- contextEl = contextEl[0];
3581
+ contextEl = await findElements.call(this, contextEl, new Locator(context, 'css').simplify())
3582
+ contextEl = contextEl[0]
3450
3583
  }
3451
3584
 
3452
- const matchedLocator = new Locator(locator);
3585
+ const matchedLocator = new Locator(locator)
3453
3586
  if (!matchedLocator.isFuzzy()) {
3454
- return findElements.call(this, contextEl, matchedLocator.simplify());
3587
+ return findElements.call(this, contextEl, matchedLocator.simplify())
3455
3588
  }
3456
3589
 
3457
- const literal = xpathLocator.literal(locator);
3458
- let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal));
3590
+ const literal = xpathLocator.literal(locator)
3591
+ let els = await findElements.call(this, contextEl, Locator.checkable.byText(literal))
3459
3592
  if (els.length) {
3460
- return els;
3593
+ return els
3461
3594
  }
3462
- els = await findElements.call(this, contextEl, Locator.checkable.byName(literal));
3595
+ els = await findElements.call(this, contextEl, Locator.checkable.byName(literal))
3463
3596
  if (els.length) {
3464
- return els;
3597
+ return els
3465
3598
  }
3466
- return findElements.call(this, contextEl, locator);
3599
+ return findElements.call(this, contextEl, locator)
3467
3600
  }
3468
3601
 
3469
3602
  async function proceedIsChecked(assertType, option) {
3470
- let els = await findCheckable.call(this, option);
3471
- assertElementExists(els, option, 'Checkable');
3472
- els = await Promise.all(els.map(el => el.isChecked()));
3473
- const selected = els.reduce((prev, cur) => prev || cur);
3474
- return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
3603
+ let els = await findCheckable.call(this, option)
3604
+ assertElementExists(els, option, 'Checkable')
3605
+ els = await Promise.all(els.map((el) => el.isChecked()))
3606
+ const selected = els.reduce((prev, cur) => prev || cur)
3607
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
3475
3608
  }
3476
3609
 
3477
3610
  async function findFields(locator) {
3478
- const matchedLocator = new Locator(locator);
3611
+ const matchedLocator = new Locator(locator)
3479
3612
  if (!matchedLocator.isFuzzy()) {
3480
- return this._locate(matchedLocator);
3613
+ return this._locate(matchedLocator)
3481
3614
  }
3482
- const literal = xpathLocator.literal(locator);
3615
+ const literal = xpathLocator.literal(locator)
3483
3616
 
3484
- let els = await this._locate({ xpath: Locator.field.labelEquals(literal) });
3617
+ let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
3485
3618
  if (els.length) {
3486
- return els;
3619
+ return els
3487
3620
  }
3488
3621
 
3489
- els = await this._locate({ xpath: Locator.field.labelContains(literal) });
3622
+ els = await this._locate({ xpath: Locator.field.labelContains(literal) })
3490
3623
  if (els.length) {
3491
- return els;
3624
+ return els
3492
3625
  }
3493
- els = await this._locate({ xpath: Locator.field.byName(literal) });
3626
+ els = await this._locate({ xpath: Locator.field.byName(literal) })
3494
3627
  if (els.length) {
3495
- return els;
3628
+ return els
3496
3629
  }
3497
- return this._locate({ css: locator });
3630
+ return this._locate({ css: locator })
3498
3631
  }
3499
3632
 
3500
3633
  async function proceedSeeInField(assertType, field, value) {
3501
- const els = await findFields.call(this, field);
3502
- assertElementExists(els, field, 'Field');
3503
- const el = els[0];
3504
- const tag = await el.evaluate(e => e.tagName);
3505
- const fieldType = await el.getAttribute('type');
3634
+ const els = await findFields.call(this, field)
3635
+ assertElementExists(els, field, 'Field')
3636
+ const el = els[0]
3637
+ const tag = await el.evaluate((e) => e.tagName)
3638
+ const fieldType = await el.getAttribute('type')
3506
3639
 
3507
3640
  const proceedMultiple = async (elements) => {
3508
- const fields = Array.isArray(elements) ? elements : [elements];
3641
+ const fields = Array.isArray(elements) ? elements : [elements]
3509
3642
 
3510
- const elementValues = [];
3643
+ const elementValues = []
3511
3644
  for (const element of fields) {
3512
- elementValues.push(await element.inputValue());
3645
+ elementValues.push(await element.inputValue())
3513
3646
  }
3514
3647
 
3515
3648
  if (typeof value === 'boolean') {
3516
- equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length);
3649
+ equals(`no. of items matching > 0: ${field}`)[assertType](value, !!elementValues.length)
3517
3650
  } else {
3518
3651
  if (assertType === 'assert') {
3519
- equals(`select option by ${field}`)[assertType](true, elementValues.length > 0);
3652
+ equals(`select option by ${field}`)[assertType](true, elementValues.length > 0)
3520
3653
  }
3521
- elementValues.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val));
3654
+ elementValues.forEach((val) => stringIncludes(`fields by ${field}`)[assertType](value, val))
3522
3655
  }
3523
- };
3656
+ }
3524
3657
 
3525
3658
  if (tag === 'SELECT') {
3526
3659
  if (await el.getAttribute('multiple')) {
3527
- const selectedOptions = await el.all('option:checked');
3528
- if (!selectedOptions.length) return null;
3660
+ const selectedOptions = await el.all('option:checked')
3661
+ if (!selectedOptions.length) return null
3529
3662
 
3530
- const options = await filterFieldsByValue(selectedOptions, value, true);
3531
- return proceedMultiple(options);
3663
+ const options = await filterFieldsByValue(selectedOptions, value, true)
3664
+ return proceedMultiple(options)
3532
3665
  }
3533
3666
 
3534
- return el.inputValue();
3667
+ return el.inputValue()
3535
3668
  }
3536
3669
 
3537
3670
  if (tag === 'INPUT') {
3538
3671
  if (fieldType === 'checkbox' || fieldType === 'radio') {
3539
3672
  if (typeof value === 'boolean') {
3540
3673
  // Filter by values
3541
- const options = await filterFieldsBySelectionState(els, true);
3542
- return proceedMultiple(options);
3674
+ const options = await filterFieldsBySelectionState(els, true)
3675
+ return proceedMultiple(options)
3543
3676
  }
3544
3677
 
3545
- const options = await filterFieldsByValue(els, value, true);
3546
- return proceedMultiple(options);
3678
+ const options = await filterFieldsByValue(els, value, true)
3679
+ return proceedMultiple(options)
3547
3680
  }
3548
- return proceedMultiple(els[0]);
3681
+ return proceedMultiple(els[0])
3549
3682
  }
3550
3683
 
3551
- let fieldVal;
3684
+ let fieldVal
3552
3685
 
3553
3686
  try {
3554
- fieldVal = await el.inputValue();
3687
+ fieldVal = await el.inputValue()
3555
3688
  } catch (e) {
3556
3689
  if (e.message.includes('Error: Node is not an <input>, <textarea> or <select> element')) {
3557
- fieldVal = await el.innerText();
3690
+ fieldVal = await el.innerText()
3558
3691
  }
3559
3692
  }
3560
3693
 
3561
- return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal);
3694
+ return stringIncludes(`fields by ${field}`)[assertType](value, fieldVal)
3562
3695
  }
3563
3696
 
3564
3697
  async function filterFieldsByValue(elements, value, onlySelected) {
3565
- const matches = [];
3698
+ const matches = []
3566
3699
  for (const element of elements) {
3567
- const val = await element.getAttribute('value');
3568
- let isSelected = true;
3700
+ const val = await element.getAttribute('value')
3701
+ let isSelected = true
3569
3702
  if (onlySelected) {
3570
- isSelected = await elementSelected(element);
3703
+ isSelected = await elementSelected(element)
3571
3704
  }
3572
3705
  if ((value == null || val.indexOf(value) > -1) && isSelected) {
3573
- matches.push(element);
3706
+ matches.push(element)
3574
3707
  }
3575
3708
  }
3576
- return matches;
3709
+ return matches
3577
3710
  }
3578
3711
 
3579
3712
  async function filterFieldsBySelectionState(elements, state) {
3580
- const matches = [];
3713
+ const matches = []
3581
3714
  for (const element of elements) {
3582
- const isSelected = await elementSelected(element);
3715
+ const isSelected = await elementSelected(element)
3583
3716
  if (isSelected === state) {
3584
- matches.push(element);
3717
+ matches.push(element)
3585
3718
  }
3586
3719
  }
3587
- return matches;
3720
+ return matches
3588
3721
  }
3589
3722
 
3590
3723
  async function elementSelected(element) {
3591
- const type = await element.getAttribute('type');
3724
+ const type = await element.getAttribute('type')
3592
3725
 
3593
3726
  if (type === 'checkbox' || type === 'radio') {
3594
- return element.isChecked();
3727
+ return element.isChecked()
3595
3728
  }
3596
- return element.getAttribute('selected');
3729
+ return element.getAttribute('selected')
3597
3730
  }
3598
3731
 
3599
3732
  function isFrameLocator(locator) {
3600
- locator = new Locator(locator);
3733
+ locator = new Locator(locator)
3601
3734
  if (locator.isFrame()) {
3602
- return locator.value;
3735
+ return locator.value
3603
3736
  }
3604
- return false;
3737
+ return false
3605
3738
  }
3606
3739
 
3607
3740
  function assertElementExists(res, locator, prefix, suffix) {
3608
3741
  if (!res || res.length === 0) {
3609
- throw new ElementNotFound(locator, prefix, suffix);
3742
+ throw new ElementNotFound(locator, prefix, suffix)
3610
3743
  }
3611
3744
  }
3612
3745
 
3613
3746
  function $XPath(element, selector) {
3614
- const found = document.evaluate(selector, element || document.body, null, 5, null);
3615
- const res = [];
3616
- let current = null;
3617
- while (current = found.iterateNext()) {
3618
- res.push(current);
3747
+ const found = document.evaluate(selector, element || document.body, null, 5, null)
3748
+ const res = []
3749
+ let current = null
3750
+ while ((current = found.iterateNext())) {
3751
+ res.push(current)
3619
3752
  }
3620
- return res;
3753
+ return res
3621
3754
  }
3622
3755
 
3623
3756
  async function targetCreatedHandler(page) {
3624
- if (!page) return;
3625
- this.withinLocator = null;
3757
+ if (!page) return
3758
+ this.withinLocator = null
3626
3759
  page.on('load', () => {
3627
- page.$('body')
3760
+ page
3761
+ .$('body')
3628
3762
  .catch(() => null)
3629
3763
  .then(async () => {
3630
3764
  if (this.context && this.context._type === 'Frame') {
3631
3765
  // we are inside iframe?
3632
- const frameEl = await this.context.frameElement();
3633
- this.context = await frameEl.contentFrame();
3634
- this.contextLocator = null;
3635
- return;
3766
+ const frameEl = await this.context.frameElement()
3767
+ this.context = await frameEl.contentFrame()
3768
+ this.contextLocator = null
3769
+ return
3636
3770
  }
3637
3771
  // if context element was in iframe - keep it
3638
3772
  // if (await this.context.ownerFrame()) return;
3639
- this.context = page;
3640
- this.contextLocator = null;
3641
- });
3642
- });
3773
+ this.context = page
3774
+ this.contextLocator = null
3775
+ })
3776
+ })
3643
3777
  page.on('console', (msg) => {
3644
3778
  if (!consoleLogStore.includes(msg) && this.options.ignoreLog && !this.options.ignoreLog.includes(msg.type())) {
3645
- this.debugSection(`Browser:${ucfirst(msg.type())}`, (msg.text && msg.text() || msg._text || '') + msg.args().join(' '));
3779
+ this.debugSection(
3780
+ `Browser:${ucfirst(msg.type())}`,
3781
+ ((msg.text && msg.text()) || msg._text || '') + msg.args().join(' '),
3782
+ )
3646
3783
  }
3647
- consoleLogStore.add(msg);
3648
- });
3784
+ consoleLogStore.add(msg)
3785
+ })
3649
3786
 
3650
3787
  if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && this._getType() === 'Browser') {
3651
3788
  try {
3652
- await page.setViewportSize(parseWindowSize(this.options.windowSize));
3789
+ await page.setViewportSize(parseWindowSize(this.options.windowSize))
3653
3790
  } catch (err) {
3654
- this.debug('Target can be already closed, ignoring...');
3791
+ this.debug('Target can be already closed, ignoring...')
3655
3792
  }
3656
3793
  }
3657
3794
  }
3658
3795
 
3659
3796
  function parseWindowSize(windowSize) {
3660
- if (!windowSize) return { width: 800, height: 600 };
3661
- const dimensions = windowSize.split('x');
3797
+ if (!windowSize) return { width: 800, height: 600 }
3798
+
3799
+ if (windowSize.width && windowSize.height) {
3800
+ return { width: parseInt(windowSize.width, 10), height: parseInt(windowSize.height, 10) }
3801
+ }
3802
+
3803
+ const dimensions = windowSize.split('x')
3662
3804
  if (dimensions.length < 2 || windowSize === 'maximize') {
3663
- console.log('Invalid window size, setting window to default values');
3664
- return { width: 800, height: 600 }; // invalid size
3805
+ console.log('Invalid window size, setting window to default values')
3806
+ return { width: 800, height: 600 } // invalid size
3665
3807
  }
3666
- const width = parseInt(dimensions[0], 10);
3667
- const height = parseInt(dimensions[1], 10);
3668
- return { width, height };
3808
+ const width = parseInt(dimensions[0], 10)
3809
+ const height = parseInt(dimensions[1], 10)
3810
+ return { width, height }
3669
3811
  }
3670
3812
 
3671
3813
  // List of key values to key definitions
3672
3814
  // https://github.com/puppeteer/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3673
3815
  const keyDefinitionMap = {
3674
3816
  /* eslint-disable quote-props */
3675
- '0': 'Digit0',
3676
- '1': 'Digit1',
3677
- '2': 'Digit2',
3678
- '3': 'Digit3',
3679
- '4': 'Digit4',
3680
- '5': 'Digit5',
3681
- '6': 'Digit6',
3682
- '7': 'Digit7',
3683
- '8': 'Digit8',
3684
- '9': 'Digit9',
3685
- 'a': 'KeyA',
3686
- 'b': 'KeyB',
3687
- 'c': 'KeyC',
3688
- 'd': 'KeyD',
3689
- 'e': 'KeyE',
3690
- 'f': 'KeyF',
3691
- 'g': 'KeyG',
3692
- 'h': 'KeyH',
3693
- 'i': 'KeyI',
3694
- 'j': 'KeyJ',
3695
- 'k': 'KeyK',
3696
- 'l': 'KeyL',
3697
- 'm': 'KeyM',
3698
- 'n': 'KeyN',
3699
- 'o': 'KeyO',
3700
- 'p': 'KeyP',
3701
- 'q': 'KeyQ',
3702
- 'r': 'KeyR',
3703
- 's': 'KeyS',
3704
- 't': 'KeyT',
3705
- 'u': 'KeyU',
3706
- 'v': 'KeyV',
3707
- 'w': 'KeyW',
3708
- 'x': 'KeyX',
3709
- 'y': 'KeyY',
3710
- 'z': 'KeyZ',
3817
+ 0: 'Digit0',
3818
+ 1: 'Digit1',
3819
+ 2: 'Digit2',
3820
+ 3: 'Digit3',
3821
+ 4: 'Digit4',
3822
+ 5: 'Digit5',
3823
+ 6: 'Digit6',
3824
+ 7: 'Digit7',
3825
+ 8: 'Digit8',
3826
+ 9: 'Digit9',
3827
+ a: 'KeyA',
3828
+ b: 'KeyB',
3829
+ c: 'KeyC',
3830
+ d: 'KeyD',
3831
+ e: 'KeyE',
3832
+ f: 'KeyF',
3833
+ g: 'KeyG',
3834
+ h: 'KeyH',
3835
+ i: 'KeyI',
3836
+ j: 'KeyJ',
3837
+ k: 'KeyK',
3838
+ l: 'KeyL',
3839
+ m: 'KeyM',
3840
+ n: 'KeyN',
3841
+ o: 'KeyO',
3842
+ p: 'KeyP',
3843
+ q: 'KeyQ',
3844
+ r: 'KeyR',
3845
+ s: 'KeyS',
3846
+ t: 'KeyT',
3847
+ u: 'KeyU',
3848
+ v: 'KeyV',
3849
+ w: 'KeyW',
3850
+ x: 'KeyX',
3851
+ y: 'KeyY',
3852
+ z: 'KeyZ',
3711
3853
  ';': 'Semicolon',
3712
3854
  '=': 'Equal',
3713
3855
  ',': 'Comma',
@@ -3718,89 +3860,92 @@ const keyDefinitionMap = {
3718
3860
  '[': 'BracketLeft',
3719
3861
  '\\': 'Backslash',
3720
3862
  ']': 'BracketRight',
3721
- '\'': 'Quote',
3863
+ "'": 'Quote',
3722
3864
  /* eslint-enable quote-props */
3723
- };
3865
+ }
3724
3866
 
3725
3867
  function getNormalizedKey(key) {
3726
- const normalizedKey = getNormalizedKeyAttributeValue(key);
3868
+ const normalizedKey = getNormalizedKeyAttributeValue(key)
3727
3869
  if (key !== normalizedKey) {
3728
- this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`);
3870
+ this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`)
3729
3871
  }
3730
3872
  // Use key definition to ensure correct key is displayed when Shift modifier is active
3731
3873
  if (Object.prototype.hasOwnProperty.call(keyDefinitionMap, normalizedKey)) {
3732
- return keyDefinitionMap[normalizedKey];
3874
+ return keyDefinitionMap[normalizedKey]
3733
3875
  }
3734
- return normalizedKey;
3876
+ return normalizedKey
3735
3877
  }
3736
3878
 
3737
3879
  async function clickablePoint(el) {
3738
- const rect = await el.boundingBox();
3739
- if (!rect) throw new ElementNotFound(el);
3740
- const {
3741
- x, y, width, height,
3742
- } = rect;
3743
- return { x: x + width / 2, y: y + height / 2 };
3880
+ const rect = await el.boundingBox()
3881
+ if (!rect) throw new ElementNotFound(el)
3882
+ const { x, y, width, height } = rect
3883
+ return { x: x + width / 2, y: y + height / 2 }
3744
3884
  }
3745
3885
 
3746
3886
  async function refreshContextSession() {
3747
3887
  // close other sessions
3748
3888
  try {
3749
- const contexts = await this.browser.contexts();
3750
- contexts.shift();
3889
+ const contexts = await this.browser.contexts()
3890
+ contexts.shift()
3751
3891
 
3752
- await Promise.all(contexts.map(c => c.close()));
3892
+ await Promise.all(contexts.map((c) => c.close()))
3753
3893
  } catch (e) {
3754
- console.log(e);
3894
+ console.log(e)
3755
3895
  }
3756
3896
 
3757
3897
  if (this.page) {
3758
- const existingPages = await this.browserContext.pages();
3759
- await this._setPage(existingPages[0]);
3898
+ const existingPages = await this.browserContext.pages()
3899
+ await this._setPage(existingPages[0])
3760
3900
  }
3761
3901
 
3762
- if (this.options.keepBrowserState) return;
3902
+ if (this.options.keepBrowserState) return
3763
3903
 
3764
3904
  if (!this.options.keepCookies) {
3765
- this.debugSection('Session', 'cleaning cookies and localStorage');
3766
- await this.clearCookie();
3905
+ this.debugSection('Session', 'cleaning cookies and localStorage')
3906
+ await this.clearCookie()
3767
3907
  }
3768
- const currentUrl = await this.grabCurrentUrl();
3908
+ const currentUrl = await this.grabCurrentUrl()
3769
3909
 
3770
3910
  if (currentUrl.startsWith('http')) {
3771
3911
  await this.executeScript('localStorage.clear();').catch((err) => {
3772
- if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
3773
- });
3912
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
3913
+ })
3774
3914
  await this.executeScript('sessionStorage.clear();').catch((err) => {
3775
- if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
3776
- });
3915
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
3916
+ })
3777
3917
  }
3778
3918
  }
3779
3919
 
3780
- async function saveVideoForPage(page, name) {
3781
- if (!page.video()) return null;
3782
- const fileName = `${`${global.output_dir}${pathSeparator}videos${pathSeparator}${uuidv4()}_${clearString(name)}`.slice(0, 245)}.webm`;
3783
- page.video().saveAs(fileName).then(() => {
3784
- if (!page) return;
3785
- page.video().delete().catch(e => {});
3786
- });
3787
- return fileName;
3920
+ function saveVideoForPage(page, name) {
3921
+ if (!page.video()) return null
3922
+ const fileName = `${`${global.output_dir}${pathSeparator}videos${pathSeparator}${uuidv4()}_${clearString(name)}`.slice(0, 245)}.webm`
3923
+ page
3924
+ .video()
3925
+ .saveAs(fileName)
3926
+ .then(() => {
3927
+ if (!page) return
3928
+ page
3929
+ .video()
3930
+ .delete()
3931
+ .catch(() => {})
3932
+ })
3933
+ return fileName
3788
3934
  }
3789
-
3790
3935
  async function saveTraceForContext(context, name) {
3791
- if (!context) return;
3792
- if (!context.tracing) return;
3793
- const fileName = `${`${global.output_dir}${pathSeparator}trace${pathSeparator}${uuidv4()}_${clearString(name)}`.slice(0, 245)}.zip`;
3794
- await context.tracing.stop({ path: fileName });
3795
- return fileName;
3936
+ if (!context) return
3937
+ if (!context.tracing) return
3938
+ const fileName = `${`${global.output_dir}${pathSeparator}trace${pathSeparator}${uuidv4()}_${clearString(name)}`.slice(0, 245)}.zip`
3939
+ await context.tracing.stop({ path: fileName })
3940
+ return fileName
3796
3941
  }
3797
3942
 
3798
3943
  async function highlightActiveElement(element) {
3799
3944
  if (this.options.highlightElement && global.debugMode) {
3800
- await element.evaluate(el => {
3801
- const prevStyle = el.style.boxShadow;
3802
- el.style.boxShadow = '0px 0px 4px 3px rgba(255, 0, 0, 0.7)';
3803
- setTimeout(() => el.style.boxShadow = prevStyle, 2000);
3804
- });
3945
+ await element.evaluate((el) => {
3946
+ const prevStyle = el.style.boxShadow
3947
+ el.style.boxShadow = '0px 0px 4px 3px rgba(255, 0, 0, 0.7)'
3948
+ setTimeout(() => (el.style.boxShadow = prevStyle), 2000)
3949
+ })
3805
3950
  }
3806
3951
  }