codeceptjs 3.6.7 → 4.0.0-beta.2

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