@telefonica/acceptance-testing 3.0.0-beta9 → 4.0.0

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.
@@ -11,6 +11,7 @@ var pptrTestingLibrary = require('pptr-testing-library');
11
11
  var jestImageSnapshot = require('jest-image-snapshot');
12
12
  var globToRegExp = _interopDefault(require('glob-to-regexp'));
13
13
  var child_process = require('child_process');
14
+ var istanbul = _interopDefault(require('istanbul-lib-coverage'));
14
15
 
15
16
  function _regeneratorRuntime() {
16
17
  _regeneratorRuntime = function () {
@@ -370,6 +371,27 @@ function _objectWithoutPropertiesLoose(source, excluded) {
370
371
  return target;
371
372
  }
372
373
 
374
+ /**
375
+ * Debug function that logs to the console if the DEBUG_ACCEPTANCE_TESTING environment variable is set
376
+ */
377
+ var debug = function debug() {
378
+ if (process.env.DEBUG_ACCEPTANCE_TESTING) {
379
+ var _console;
380
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
381
+ args[_key] = arguments[_key];
382
+ }
383
+ (_console = console).debug.apply(_console, ['[acceptance-testing]'].concat(args));
384
+ }
385
+ };
386
+ /**
387
+ * Returns true if the current path matches the spied path, including parameters
388
+ */
389
+ var matchPath = function matchPath(spiedPath, currentPath) {
390
+ var normalizedCurrentPath = path.normalize(currentPath);
391
+ var pattern = globToRegExp(spiedPath);
392
+ return pattern.test(normalizedCurrentPath);
393
+ };
394
+
373
395
  var getGlobalPage = function getGlobalPage() {
374
396
  return global.page;
375
397
  };
@@ -380,90 +402,159 @@ var getRootPath = function getRootPath() {
380
402
  }
381
403
  return rootPath;
382
404
  };
383
- /**
384
- * We want to clear coverage files from previous runs, but at this point it is not easy because each
385
- * worker runs a different instance of this script, so we can't just clear the coverage folder at
386
- * the beginning of the test run.
387
- *
388
- * The solution is to remove the coverage folder when the stored ppid (parent process id) is
389
- * different from the current one
405
+ /**
406
+ * We want to clear coverage files from previous runs, but at this point it is not easy because each
407
+ * worker runs a different instance of this script, so we can't just clear the coverage folder at
408
+ * the beginning of the test run.
409
+ *
410
+ * The solution is to remove the coverage folder when the stored ppid (parent process id) is
411
+ * different from the current one
390
412
  */
391
413
  var prepareCoverageReportPath = function prepareCoverageReportPath(_ref) {
392
414
  var coveragePath = _ref.coveragePath;
393
415
  var ppidFile = path.join(coveragePath, '.ppid');
416
+ var nycOutputPath = path.join(coveragePath, '.nyc_output');
394
417
  var ppid = process.ppid.toString();
395
418
  if (!fs.existsSync(ppidFile) || fs.readFileSync(ppidFile, 'utf-8') !== ppid) {
396
419
  // the condition is just to make sure we don't remove files outside the repo
397
420
  if (getRootPath() === process.cwd() && path.normalize(coveragePath).startsWith(process.cwd())) {
398
- fs.rmSync(coveragePath, {
421
+ fs.rmSync(nycOutputPath, {
399
422
  recursive: true,
400
423
  force: true
401
424
  });
402
425
  }
403
- fs.mkdirSync(coveragePath, {
426
+ fs.mkdirSync(nycOutputPath, {
404
427
  recursive: true
405
428
  });
406
429
  fs.writeFileSync(ppidFile, ppid);
407
430
  }
408
431
  };
409
- /**
410
- * Asumes the code was instrumented with istanbul and the coverage report stored in `window.__coverage__`.
411
- * If not, this function does nothing.
432
+ var workerId = process.env.JEST_WORKER_ID || '0';
433
+ /**
434
+ * Writes the coverage reports into single files, one per each coverage object (path). This makes it easier to merge them.
435
+ * The `workerId` from jest is used to avoid race conditions when multiple workers are running in parallel.
436
+ */
437
+ var writeCombinedCoverage = function writeCombinedCoverage(nycOutputPath, coverage) {
438
+ Object.values(coverage).forEach(function (value) {
439
+ if (value && value.path && value.hash) {
440
+ var _currentCoverage;
441
+ var filename = path.join(nycOutputPath, value.hash + "-" + workerId + ".json");
442
+ var currentCoverage = (_currentCoverage = {}, _currentCoverage[value.path] = value, _currentCoverage);
443
+ var previousCoverage = fs.existsSync(filename) ? JSON.parse(fs.readFileSync(filename, 'utf8')) : {};
444
+ var mergedCoverage = istanbul.createCoverageMap(previousCoverage);
445
+ mergedCoverage.merge(currentCoverage);
446
+ debug('Writing merged coverage:', value.path, value.hash);
447
+ fs.writeFileSync(filename, JSON.stringify(mergedCoverage.toJSON(), null, 2));
448
+ } else {
449
+ debug('Skip write coverage. Missing path or hash:', value);
450
+ }
451
+ });
452
+ };
453
+ /**
454
+ * Assumes the code was instrumented with istanbul/nyc and the coverage report stored in `window.__coverage__`.
455
+ * If not, this function does nothing.
412
456
  */
413
- var collectCoverageIfAvailable = /*#__PURE__*/function () {
457
+ var collectFrontendCoverage = /*#__PURE__*/function () {
414
458
  var _ref3 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref2) {
415
- var coveragePath, coverage, nycOutputPath;
459
+ var coveragePath, nycOutputPath, coverage;
416
460
  return _regeneratorRuntime().wrap(function _callee$(_context) {
417
461
  while (1) switch (_context.prev = _context.next) {
418
462
  case 0:
419
463
  coveragePath = _ref2.coveragePath;
420
- _context.next = 3;
464
+ nycOutputPath = path.join(coveragePath, '.nyc_output');
465
+ _context.next = 4;
421
466
  return getGlobalPage().evaluate(function () {
422
467
  return window.__coverage__;
423
468
  });
424
- case 3:
469
+ case 4:
425
470
  coverage = _context.sent;
426
471
  if (coverage) {
427
- _context.next = 6;
472
+ _context.next = 8;
428
473
  break;
429
474
  }
475
+ debug('Skipping coverage collection. No coverage found.');
430
476
  return _context.abrupt("return");
431
- case 6:
477
+ case 8:
478
+ debug('Frontend coverage found');
432
479
  prepareCoverageReportPath({
433
480
  coveragePath: coveragePath
434
481
  });
435
- nycOutputPath = path.join(coveragePath, '.nyc_output');
436
482
  fs.mkdirSync(nycOutputPath, {
437
483
  recursive: true
438
484
  });
439
- Object.values(coverage).forEach(function (cov) {
440
- if (cov && cov.path && cov.hash) {
441
- var _JSON$stringify;
442
- fs.writeFileSync(path.join(nycOutputPath, cov.hash + '.json'), JSON.stringify((_JSON$stringify = {}, _JSON$stringify[cov.path] = cov, _JSON$stringify)));
443
- }
444
- });
445
- case 10:
485
+ writeCombinedCoverage(nycOutputPath, coverage);
486
+ case 12:
446
487
  case "end":
447
488
  return _context.stop();
448
489
  }
449
490
  }, _callee);
450
491
  }));
451
- return function collectCoverageIfAvailable(_x) {
492
+ return function collectFrontendCoverage(_x) {
452
493
  return _ref3.apply(this, arguments);
453
494
  };
454
495
  }();
455
-
456
- /**
457
- * Returns true if the current path matches the spied path, including parameters
458
- */
459
- var matchPath = function matchPath(spiedPath, currentPath) {
460
- var normalizedCurrentPath = path.normalize(currentPath);
461
- var pattern = globToRegExp(spiedPath);
462
- return pattern.test(normalizedCurrentPath);
496
+ var writeCoverage = function writeCoverage(nycOutputPath, nameSuffix, coverage) {
497
+ Object.values(coverage).forEach(function (value) {
498
+ if (value && value.path && value.hash) {
499
+ var _JSON$stringify;
500
+ var filename = path.join(nycOutputPath, "" + value.hash + nameSuffix + ".json");
501
+ debug('Writing coverage:', value.path, value.hash);
502
+ fs.writeFileSync(filename, JSON.stringify((_JSON$stringify = {}, _JSON$stringify[value.path] = value, _JSON$stringify), null, 2));
503
+ } else {
504
+ debug('Skip write coverage. Missing path or hash:', value);
505
+ }
506
+ });
463
507
  };
508
+ /**
509
+ * Collects backend coverage reports from the provided URLs and stores them in the coverage folder
510
+ */
511
+ var collectBackendCoverage = /*#__PURE__*/function () {
512
+ var _ref5 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref4) {
513
+ var coveragePath, coverageUrls, nycOutputPath, serverReports;
514
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
515
+ while (1) switch (_context2.prev = _context2.next) {
516
+ case 0:
517
+ coveragePath = _ref4.coveragePath, coverageUrls = _ref4.coverageUrls;
518
+ nycOutputPath = path.join(coveragePath, '.nyc_output');
519
+ debug('Collecting backend coverage reports', coverageUrls);
520
+ _context2.next = 5;
521
+ return Promise.all(coverageUrls.map(function (url) {
522
+ return fetch(url).then(function (res) {
523
+ var _res$headers$get;
524
+ if (res.ok && res.status === 200 && (_res$headers$get = res.headers.get('content-type')) != null && _res$headers$get.includes('application/json')) {
525
+ return res.json();
526
+ }
527
+ debug('Error fetching coverage report:', {
528
+ url: url,
529
+ status: res.status
530
+ });
531
+ return null;
532
+ })["catch"](function () {
533
+ debug('Error fetching coverage report:', {
534
+ url: url
535
+ });
536
+ return null;
537
+ });
538
+ }));
539
+ case 5:
540
+ serverReports = _context2.sent;
541
+ serverReports.forEach(function (report, index) {
542
+ writeCoverage(nycOutputPath, "-backend" + index, report.coverage);
543
+ });
544
+ case 7:
545
+ case "end":
546
+ return _context2.stop();
547
+ }
548
+ }, _callee2);
549
+ }));
550
+ return function collectBackendCoverage(_x2) {
551
+ return _ref5.apply(this, arguments);
552
+ };
553
+ }();
464
554
 
465
- var _excluded = ["userAgent", "isDarkMode", "viewport", "cookies"];
466
- var _pkg$acceptanceTests, _ref, _projectConfig$covera;
555
+ var _excluded = ["captureBeyondViewport"],
556
+ _excluded2 = ["userAgent", "isDarkMode", "viewport", "cookies"];
557
+ var _pkg$acceptanceTests, _ref, _projectConfig$covera, _projectConfig$covera2;
467
558
  var LINUX_DOCKER_HOST_IP = '172.17.0.1';
468
559
  var getGlobalBrowser = function getGlobalBrowser() {
469
560
  return global.browser;
@@ -472,7 +563,7 @@ var getGlobalPage$1 = function getGlobalPage() {
472
563
  return global.page;
473
564
  };
474
565
  var isCi = /*#__PURE__*/process.argv.includes('--ci') || process.env.CI;
475
- var isUsingDockerizedChromium = !!isCi || /*#__PURE__*/new URL( /*#__PURE__*/getGlobalBrowser().wsEndpoint()).port === '9223';
566
+ var isUsingDockerizedChromium = isCi || /*#__PURE__*/new URL( /*#__PURE__*/getGlobalBrowser().wsEndpoint()).port === '9223';
476
567
  /** Check if running inside WSL */
477
568
  var isWsl = function isWsl() {
478
569
  if (process.platform !== 'linux') {
@@ -535,15 +626,17 @@ var serverHostName = /*#__PURE__*/function () {
535
626
  var rootDir = /*#__PURE__*/findRoot( /*#__PURE__*/process.cwd());
536
627
  var pkg = /*#__PURE__*/JSON.parse( /*#__PURE__*/fs.readFileSync( /*#__PURE__*/path.join(rootDir, 'package.json'), 'utf-8'));
537
628
  var projectConfig = (_pkg$acceptanceTests = pkg.acceptanceTests) != null ? _pkg$acceptanceTests : {};
629
+ debug('Project config:', projectConfig);
538
630
  var server = (_ref = isCi ? projectConfig.ciServer : projectConfig.devServer) != null ? _ref : projectConfig.server;
539
631
  var coveragePath = /*#__PURE__*/path.join(rootDir, (_projectConfig$covera = projectConfig.coveragePath) != null ? _projectConfig$covera : 'reports/coverage-acceptance');
632
+ var coverageUrls = (_projectConfig$covera2 = projectConfig.coverageUrls) != null ? _projectConfig$covera2 : [];
540
633
  var serverPort = server == null ? void 0 : server.port;
541
634
  var toMatchImageSnapshot = /*#__PURE__*/jestImageSnapshot.configureToMatchImageSnapshot({
542
635
  failureThreshold: 0,
543
636
  failureThresholdType: 'percent',
544
637
  customSnapshotIdentifier: function customSnapshotIdentifier(_ref2) {
545
638
  var defaultIdentifier = _ref2.defaultIdentifier;
546
- return defaultIdentifier + '-snap';
639
+ return defaultIdentifier;
547
640
  }
548
641
  });
549
642
  var calledToMatchImageSnapshotOutsideDocker = false;
@@ -633,15 +726,18 @@ var waitForPaintEnd = /*#__PURE__*/function () {
633
726
  return _ref3.apply(this, arguments);
634
727
  };
635
728
  }();
636
- var normalizeSreenshotOptions = function normalizeSreenshotOptions(options) {
637
- return options;
729
+ var normalizeSreenshotOptions = function normalizeSreenshotOptions(_temp2) {
730
+ var _ref5 = _temp2 === void 0 ? {} : _temp2,
731
+ _ref5$captureBeyondVi = _ref5.captureBeyondViewport,
732
+ captureBeyondViewport = _ref5$captureBeyondVi === void 0 ? false : _ref5$captureBeyondVi,
733
+ options = _objectWithoutPropertiesLoose(_ref5, _excluded);
734
+ // Puppeter default for captureBeyondViewport is true, but we think false is a better default.
735
+ // When this is true, the fixed elements (like fixed footers) are relative to the original page
736
+ // viewport, not to the full page, so those elements look weird in fullPage screenshots.
737
+ return _extends({}, options, {
738
+ captureBeyondViewport: captureBeyondViewport
739
+ });
638
740
  };
639
- // const normalizeSreenshotOptions = ({captureBeyondViewport = false, ...options}: ScreenshotOptions = {}) => {
640
- // // Puppeter default for captureBeyondViewport is true, but we think false is a better default.
641
- // // When this is true, the fixed elements (like fixed footers) are relative to the original page
642
- // // viewport, not to the full page, so those elements look weird in fullPage screenshots.
643
- // return {...options, captureBeyondViewport};
644
- // };
645
741
  // Puppeteer already calls scrollIntoViewIfNeeded before clicking an element. But it doesn't work in all situations
646
742
  // For example, when there is a fixed footer in the page and the element to click is under it, the browser won't scroll
647
743
  // because the element is already in the viewport (the ifNeeded part is important here). By forcing the scroll to the
@@ -654,238 +750,144 @@ var scrollIntoView = function scrollIntoView(el) {
654
750
  });
655
751
  };
656
752
  var getPageApi = function getPageApi(page) {
657
- return {
658
- type: function () {
659
- var _type = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(elementHandle, text, options) {
660
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
661
- while (1) switch (_context2.prev = _context2.next) {
662
- case 0:
663
- _context2.next = 2;
664
- return scrollIntoView(elementHandle);
665
- case 2:
666
- return _context2.abrupt("return", elementHandle.type(text, options));
667
- case 3:
668
- case "end":
669
- return _context2.stop();
670
- }
671
- }, _callee2);
672
- }));
673
- function type(_x3, _x4, _x5) {
674
- return _type.apply(this, arguments);
675
- }
676
- return type;
677
- }(),
678
- click: function () {
679
- var _click = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(elementHandle, options) {
680
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
681
- while (1) switch (_context3.prev = _context3.next) {
682
- case 0:
683
- _context3.next = 2;
684
- return scrollIntoView(elementHandle);
685
- case 2:
686
- return _context3.abrupt("return", elementHandle.click(options));
687
- case 3:
688
- case "end":
689
- return _context3.stop();
690
- }
691
- }, _callee3);
692
- }));
693
- function click(_x6, _x7) {
694
- return _click.apply(this, arguments);
695
- }
696
- return click;
697
- }(),
698
- select: function () {
699
- var _select = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(elementHandle) {
700
- var _len,
701
- values,
702
- _key,
703
- _args4 = arguments;
704
- return _regeneratorRuntime().wrap(function _callee4$(_context4) {
705
- while (1) switch (_context4.prev = _context4.next) {
706
- case 0:
707
- _context4.next = 2;
708
- return scrollIntoView(elementHandle);
709
- case 2:
710
- for (_len = _args4.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
711
- values[_key - 1] = _args4[_key];
712
- }
713
- return _context4.abrupt("return", elementHandle.select.apply(elementHandle, values));
714
- case 4:
715
- case "end":
716
- return _context4.stop();
717
- }
718
- }, _callee4);
719
- }));
720
- function select(_x8) {
721
- return _select.apply(this, arguments);
722
- }
723
- return select;
724
- }(),
725
- screenshot: function () {
726
- var _screenshot = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(options) {
727
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
728
- while (1) switch (_context5.prev = _context5.next) {
729
- case 0:
730
- if (options != null && options.skipNetworkWait) {
731
- _context5.next = 3;
732
- break;
733
- }
753
+ var api = Object.create(page);
754
+ api.type = /*#__PURE__*/function () {
755
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(elementHandle, text, options) {
756
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
757
+ while (1) switch (_context2.prev = _context2.next) {
758
+ case 0:
759
+ _context2.next = 2;
760
+ return scrollIntoView(elementHandle);
761
+ case 2:
762
+ return _context2.abrupt("return", elementHandle.type(text, options));
763
+ case 3:
764
+ case "end":
765
+ return _context2.stop();
766
+ }
767
+ }, _callee2);
768
+ }));
769
+ return function (_x3, _x4, _x5) {
770
+ return _ref6.apply(this, arguments);
771
+ };
772
+ }();
773
+ api.click = /*#__PURE__*/function () {
774
+ var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(elementHandle, options) {
775
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
776
+ while (1) switch (_context3.prev = _context3.next) {
777
+ case 0:
778
+ _context3.next = 2;
779
+ return scrollIntoView(elementHandle);
780
+ case 2:
781
+ return _context3.abrupt("return", elementHandle.click(options));
782
+ case 3:
783
+ case "end":
784
+ return _context3.stop();
785
+ }
786
+ }, _callee3);
787
+ }));
788
+ return function (_x6, _x7) {
789
+ return _ref7.apply(this, arguments);
790
+ };
791
+ }();
792
+ api.select = /*#__PURE__*/function () {
793
+ var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(elementHandle) {
794
+ var _len,
795
+ values,
796
+ _key,
797
+ _args4 = arguments;
798
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
799
+ while (1) switch (_context4.prev = _context4.next) {
800
+ case 0:
801
+ _context4.next = 2;
802
+ return scrollIntoView(elementHandle);
803
+ case 2:
804
+ for (_len = _args4.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
805
+ values[_key - 1] = _args4[_key];
806
+ }
807
+ return _context4.abrupt("return", elementHandle.select.apply(elementHandle, values));
808
+ case 4:
809
+ case "end":
810
+ return _context4.stop();
811
+ }
812
+ }, _callee4);
813
+ }));
814
+ return function (_x8) {
815
+ return _ref8.apply(this, arguments);
816
+ };
817
+ }();
818
+ api.screenshot = /*#__PURE__*/function () {
819
+ var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(options) {
820
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
821
+ while (1) switch (_context5.prev = _context5.next) {
822
+ case 0:
823
+ if (options != null && options.skipNetworkWait) {
734
824
  _context5.next = 3;
735
- return page.waitForNetworkIdle();
736
- case 3:
737
- _context5.next = 5;
738
- return waitForPaintEnd(page, options);
739
- case 5:
740
- return _context5.abrupt("return", page.screenshot(normalizeSreenshotOptions(options)));
741
- case 6:
742
- case "end":
743
- return _context5.stop();
744
- }
745
- }, _callee5);
746
- }));
747
- function screenshot(_x9) {
748
- return _screenshot.apply(this, arguments);
749
- }
750
- return screenshot;
751
- }(),
752
- clear: function () {
753
- var _clear = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(elementHandle) {
754
- return _regeneratorRuntime().wrap(function _callee6$(_context6) {
755
- while (1) switch (_context6.prev = _context6.next) {
756
- case 0:
757
- _context6.next = 2;
758
- return elementHandle.click({
759
- clickCount: 3
760
- });
761
- case 2:
762
- _context6.next = 4;
763
- return elementHandle.press('Delete');
764
- case 4:
765
- case "end":
766
- return _context6.stop();
767
- }
768
- }, _callee6);
769
- }));
770
- function clear(_x10) {
771
- return _clear.apply(this, arguments);
772
- }
773
- return clear;
774
- }(),
775
- // For some reason, puppeteer browserContext.overridePermissions doesn't work with newer chrome versions.
776
- // This workaround polyfills the browser geolocation api to return the mocked position
777
- setGeolocation: function setGeolocation(position) {
778
- return page.evaluate(function (position) {
779
- window.navigator.geolocation.getCurrentPosition = function (callback) {
780
- // @ts-expect-error - puppeteer's setGeoLocation does not expect a timestamp to be passed
781
- callback({
782
- coords: position
783
- });
784
- };
785
- }, position);
786
- },
787
- $: page.$.bind(page),
788
- $$: page.$$.bind(page),
789
- $$eval: page.$$eval.bind(page),
790
- $eval: page.$eval.bind(page),
791
- accessibility: page.accessibility,
792
- addScriptTag: page.addScriptTag.bind(page),
793
- addStyleTag: page.addStyleTag.bind(page),
794
- authenticate: page.authenticate.bind(page),
795
- bringToFront: page.bringToFront.bind(page),
796
- browser: page.browser.bind(page),
797
- browserContext: page.browserContext.bind(page),
798
- close: page.close.bind(page),
799
- content: page.content,
800
- cookies: page.cookies.bind(page),
801
- coverage: page.coverage,
802
- createCDPSession: page.createCDPSession.bind(page),
803
- createPDFStream: page.createPDFStream.bind(page),
804
- deleteCookie: page.deleteCookie.bind(page),
805
- emit: page.emit.bind(page),
806
- emulate: page.emulate.bind(page),
807
- emulateCPUThrottling: page.emulateCPUThrottling.bind(page),
808
- emulateIdleState: page.emulateIdleState.bind(page),
809
- emulateMediaFeatures: page.emulateMediaFeatures.bind(page),
810
- emulateMediaType: page.emulateMediaType.bind(page),
811
- emulateNetworkConditions: page.emulateNetworkConditions.bind(page),
812
- emulateTimezone: page.emulateTimezone.bind(page),
813
- emulateVisionDeficiency: page.emulateVisionDeficiency.bind(page),
814
- evaluate: page.evaluate.bind(page),
815
- evaluateHandle: page.evaluateHandle.bind(page),
816
- evaluateOnNewDocument: page.evaluateOnNewDocument.bind(page),
817
- exposeFunction: page.exposeFunction.bind(page),
818
- focus: page.focus.bind(page),
819
- frames: page.frames.bind(page),
820
- getDefaultTimeout: page.getDefaultTimeout.bind(page),
821
- goBack: page.goBack.bind(page),
822
- goForward: page.goForward.bind(page),
823
- "goto": page["goto"].bind(page),
824
- hover: page.hover.bind(page),
825
- isClosed: page.isClosed.bind(page),
826
- isDragInterceptionEnabled: page.isDragInterceptionEnabled.bind(page),
827
- isJavaScriptEnabled: page.isJavaScriptEnabled.bind(page),
828
- isServiceWorkerBypassed: page.isServiceWorkerBypassed.bind(page),
829
- keyboard: page.keyboard,
830
- listenerCount: page.listenerCount.bind(page),
831
- locator: page.locator.bind(page),
832
- mainFrame: page.mainFrame.bind(page),
833
- metrics: page.metrics.bind(page),
834
- mouse: page.mouse,
835
- off: page.off.bind(page),
836
- on: page.on.bind(page),
837
- once: page.once.bind(page),
838
- pdf: page.pdf,
839
- queryObjects: page.queryObjects.bind(page),
840
- reload: page.reload.bind(page),
841
- removeAllListeners: page.removeAllListeners.bind(page),
842
- removeExposedFunction: page.removeExposedFunction.bind(page),
843
- removeScriptToEvaluateOnNewDocument: page.removeScriptToEvaluateOnNewDocument.bind(page),
844
- screencast: page.screencast,
845
- setBypassCSP: page.setBypassCSP.bind(page),
846
- setBypassServiceWorker: page.setBypassServiceWorker.bind(page),
847
- setCacheEnabled: page.setCacheEnabled.bind(page),
848
- setContent: page.setContent.bind(page),
849
- setCookie: page.setCookie.bind(page),
850
- setDefaultNavigationTimeout: page.setDefaultNavigationTimeout.bind(page),
851
- setDefaultTimeout: page.setDefaultTimeout.bind(page),
852
- setDragInterception: page.setDragInterception.bind(page),
853
- setExtraHTTPHeaders: page.setExtraHTTPHeaders.bind(page),
854
- setJavaScriptEnabled: page.setJavaScriptEnabled.bind(page),
855
- setOfflineMode: page.setOfflineMode.bind(page),
856
- setRequestInterception: page.setRequestInterception.bind(page),
857
- setUserAgent: page.setUserAgent.bind(page),
858
- setViewport: page.setViewport.bind(page),
859
- tap: page.tap.bind(page),
860
- target: page.target.bind(page),
861
- title: page.title,
862
- touchscreen: page.touchscreen,
863
- tracing: page.tracing,
864
- url: page.url,
865
- viewport: page.viewport,
866
- waitForDevicePrompt: page.waitForDevicePrompt.bind(page),
867
- waitForFileChooser: page.waitForFileChooser.bind(page),
868
- waitForFrame: page.waitForFrame.bind(page),
869
- waitForFunction: page.waitForFunction.bind(page),
870
- waitForNavigation: page.waitForNavigation.bind(page),
871
- waitForNetworkIdle: page.waitForNetworkIdle.bind(page),
872
- waitForRequest: page.waitForRequest.bind(page),
873
- waitForResponse: page.waitForResponse.bind(page),
874
- waitForSelector: page.waitForSelector.bind(page),
875
- workers: page.workers
825
+ break;
826
+ }
827
+ _context5.next = 3;
828
+ return page.waitForNetworkIdle();
829
+ case 3:
830
+ _context5.next = 5;
831
+ return waitForPaintEnd(page, options);
832
+ case 5:
833
+ return _context5.abrupt("return", page.screenshot(normalizeSreenshotOptions(options)));
834
+ case 6:
835
+ case "end":
836
+ return _context5.stop();
837
+ }
838
+ }, _callee5);
839
+ }));
840
+ return function (_x9) {
841
+ return _ref9.apply(this, arguments);
842
+ };
843
+ }();
844
+ api.clear = /*#__PURE__*/function () {
845
+ var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(elementHandle) {
846
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
847
+ while (1) switch (_context6.prev = _context6.next) {
848
+ case 0:
849
+ _context6.next = 2;
850
+ return elementHandle.click({
851
+ clickCount: 3
852
+ });
853
+ case 2:
854
+ _context6.next = 4;
855
+ return elementHandle.press('Delete');
856
+ case 4:
857
+ case "end":
858
+ return _context6.stop();
859
+ }
860
+ }, _callee6);
861
+ }));
862
+ return function (_x10) {
863
+ return _ref10.apply(this, arguments);
864
+ };
865
+ }();
866
+ // For some reason, puppeteer browserContext.overridePermissions doesn't work with newer chrome versions.
867
+ // This workaround polyfills the browser geolocation api to return the mocked position
868
+ api.setGeolocation = function (position) {
869
+ return page.evaluate(function (position) {
870
+ window.navigator.geolocation.getCurrentPosition = function (callback) {
871
+ // @ts-expect-error - puppeteer's setGeoLocation does not expect a timestamp to be passed
872
+ callback({
873
+ coords: position
874
+ });
875
+ };
876
+ }, position);
876
877
  };
878
+ return api;
877
879
  };
878
880
  var needsRequestInterception = false;
879
881
  var requestHandlers = [];
880
882
  var requestInterceptor = function requestInterceptor(req) {
881
883
  var _requestHandlers$find;
882
- var _ref5 = (_requestHandlers$find = requestHandlers.find(function (_ref6) {
883
- var matcher = _ref6.matcher;
884
+ var _ref11 = (_requestHandlers$find = requestHandlers.find(function (_ref12) {
885
+ var matcher = _ref12.matcher;
884
886
  return matcher(req);
885
887
  })) != null ? _requestHandlers$find : {
886
888
  handler: null
887
889
  },
888
- handler = _ref5.handler;
890
+ handler = _ref11.handler;
889
891
  if (!handler) {
890
892
  req["continue"]();
891
893
  return;
@@ -902,12 +904,12 @@ var interceptRequest = function interceptRequest(matcher) {
902
904
  });
903
905
  return spy;
904
906
  };
905
- var createApiEndpointMock = function createApiEndpointMock(_temp2) {
906
- var _ref8;
907
- var _ref7 = _temp2 === void 0 ? {} : _temp2,
908
- origin = _ref7.origin,
909
- baseUrl = _ref7.baseUrl;
910
- var originRegExp = globToRegExp((_ref8 = origin != null ? origin : baseUrl) != null ? _ref8 : '*');
907
+ var createApiEndpointMock = function createApiEndpointMock(_temp3) {
908
+ var _ref14;
909
+ var _ref13 = _temp3 === void 0 ? {} : _temp3,
910
+ origin = _ref13.origin,
911
+ baseUrl = _ref13.baseUrl;
912
+ var originRegExp = globToRegExp((_ref14 = origin != null ? origin : baseUrl) != null ? _ref14 : '*');
911
913
  interceptRequest(function (req) {
912
914
  var _URL = new URL(req.url()),
913
915
  origin = _URL.origin;
@@ -955,12 +957,12 @@ var createApiEndpointMock = function createApiEndpointMock(_temp2) {
955
957
  };
956
958
  };
957
959
  var openPage = /*#__PURE__*/function () {
958
- var _ref10 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(_ref9) {
960
+ var _ref16 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(_ref15) {
959
961
  var userAgent, isDarkMode, viewport, cookies, urlConfig, url, currentUserAgent, page, connectionError;
960
962
  return _regeneratorRuntime().wrap(function _callee7$(_context7) {
961
963
  while (1) switch (_context7.prev = _context7.next) {
962
964
  case 0:
963
- userAgent = _ref9.userAgent, isDarkMode = _ref9.isDarkMode, viewport = _ref9.viewport, cookies = _ref9.cookies, urlConfig = /*#__PURE__*/_objectWithoutPropertiesLoose(_ref9, _excluded);
965
+ userAgent = _ref15.userAgent, isDarkMode = _ref15.isDarkMode, viewport = _ref15.viewport, cookies = _ref15.cookies, urlConfig = /*#__PURE__*/_objectWithoutPropertiesLoose(_ref15, _excluded2);
964
966
  url = function () {
965
967
  if (urlConfig.url !== undefined) {
966
968
  return urlConfig.url;
@@ -979,45 +981,46 @@ var openPage = /*#__PURE__*/function () {
979
981
  }
980
982
  return protocol + "://" + hostname + ":" + port + path;
981
983
  }();
984
+ debug('Opening page:', url);
982
985
  _context7.t0 = userAgent;
983
986
  if (_context7.t0) {
984
- _context7.next = 7;
987
+ _context7.next = 8;
985
988
  break;
986
989
  }
987
- _context7.next = 6;
990
+ _context7.next = 7;
988
991
  return getGlobalBrowser().userAgent();
989
- case 6:
990
- _context7.t0 = _context7.sent;
991
992
  case 7:
993
+ _context7.t0 = _context7.sent;
994
+ case 8:
992
995
  currentUserAgent = _context7.t0;
993
996
  page = getGlobalPage$1();
994
- _context7.next = 11;
997
+ _context7.next = 12;
995
998
  return page.bringToFront();
996
- case 11:
999
+ case 12:
997
1000
  if (!viewport) {
998
- _context7.next = 14;
1001
+ _context7.next = 15;
999
1002
  break;
1000
1003
  }
1001
- _context7.next = 14;
1004
+ _context7.next = 15;
1002
1005
  return page.setViewport(viewport);
1003
- case 14:
1006
+ case 15:
1004
1007
  if (!cookies) {
1005
- _context7.next = 17;
1008
+ _context7.next = 18;
1006
1009
  break;
1007
1010
  }
1008
- _context7.next = 17;
1011
+ _context7.next = 18;
1009
1012
  return page.setCookie.apply(page, cookies);
1010
- case 17:
1011
- _context7.next = 19;
1013
+ case 18:
1014
+ _context7.next = 20;
1012
1015
  return page.setUserAgent(currentUserAgent + " acceptance-test");
1013
- case 19:
1014
- _context7.next = 21;
1016
+ case 20:
1017
+ _context7.next = 22;
1015
1018
  return page.emulateMediaFeatures([{
1016
1019
  name: 'prefers-color-scheme',
1017
1020
  value: isDarkMode ? 'dark' : 'light'
1018
1021
  }]);
1019
- case 21:
1020
- _context7.next = 23;
1022
+ case 22:
1023
+ _context7.next = 24;
1021
1024
  return page.evaluateOnNewDocument(function (viewport) {
1022
1025
  var _viewport$safeAreaIns;
1023
1026
  var overriddenSafeAreaInsets = !viewport ? [] : Object.keys((_viewport$safeAreaIns = viewport == null ? void 0 : viewport.safeAreaInset) != null ? _viewport$safeAreaIns : {}).map(function (key) {
@@ -1031,53 +1034,53 @@ var openPage = /*#__PURE__*/function () {
1031
1034
  document.head.appendChild(style);
1032
1035
  });
1033
1036
  }, viewport);
1034
- case 23:
1037
+ case 24:
1035
1038
  if (!needsRequestInterception) {
1036
- _context7.next = 27;
1039
+ _context7.next = 28;
1037
1040
  break;
1038
1041
  }
1039
- _context7.next = 26;
1042
+ _context7.next = 27;
1040
1043
  return page.setRequestInterception(true);
1041
- case 26:
1042
- page.on('request', requestInterceptor);
1043
1044
  case 27:
1044
- _context7.prev = 27;
1045
- _context7.next = 30;
1045
+ page.on('request', requestInterceptor);
1046
+ case 28:
1047
+ _context7.prev = 28;
1048
+ _context7.next = 31;
1046
1049
  return page["goto"](url);
1047
- case 30:
1048
- _context7.next = 41;
1050
+ case 31:
1051
+ _context7.next = 42;
1049
1052
  break;
1050
- case 32:
1051
- _context7.prev = 32;
1052
- _context7.t1 = _context7["catch"](27);
1053
+ case 33:
1054
+ _context7.prev = 33;
1055
+ _context7.t1 = _context7["catch"](28);
1053
1056
  if (!_context7.t1.message.includes('net::ERR_CONNECTION_REFUSED')) {
1054
- _context7.next = 40;
1057
+ _context7.next = 41;
1055
1058
  break;
1056
1059
  }
1057
1060
  connectionError = new Error("Could not connect to " + url + ". Is the server running?");
1058
1061
  Error.captureStackTrace(connectionError, openPage);
1059
1062
  throw connectionError;
1060
- case 40:
1061
- throw _context7.t1;
1062
1063
  case 41:
1063
- _context7.next = 43;
1064
+ throw _context7.t1;
1065
+ case 42:
1066
+ _context7.next = 44;
1064
1067
  return page.waitForFunction('document.fonts.status === "loaded"');
1065
- case 43:
1066
- return _context7.abrupt("return", getPageApi(page));
1067
1068
  case 44:
1069
+ return _context7.abrupt("return", getPageApi(page));
1070
+ case 45:
1068
1071
  case "end":
1069
1072
  return _context7.stop();
1070
1073
  }
1071
- }, _callee7, null, [[27, 32]]);
1074
+ }, _callee7, null, [[28, 33]]);
1072
1075
  }));
1073
1076
  return function openPage(_x11) {
1074
- return _ref10.apply(this, arguments);
1077
+ return _ref16.apply(this, arguments);
1075
1078
  };
1076
1079
  }();
1077
- var buildQueryMethods = function buildQueryMethods(_temp3) {
1078
- var _ref11 = _temp3 === void 0 ? {} : _temp3,
1079
- page = _ref11.page,
1080
- element = _ref11.element;
1080
+ var buildQueryMethods = function buildQueryMethods(_temp4) {
1081
+ var _ref17 = _temp4 === void 0 ? {} : _temp4,
1082
+ page = _ref17.page,
1083
+ element = _ref17.element;
1081
1084
  var boundQueries = {};
1082
1085
  var _loop = function _loop() {
1083
1086
  var _Object$entries$_i = _Object$entries[_i],
@@ -1122,7 +1125,7 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
1122
1125
  elementHandle = _context12.sent;
1123
1126
  newElementHandle = Object.create(elementHandle);
1124
1127
  newElementHandle.screenshot = /*#__PURE__*/function () {
1125
- var _ref13 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(options) {
1128
+ var _ref19 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(options) {
1126
1129
  return _regeneratorRuntime().wrap(function _callee8$(_context8) {
1127
1130
  while (1) switch (_context8.prev = _context8.next) {
1128
1131
  case 0:
@@ -1146,11 +1149,11 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
1146
1149
  }, _callee8);
1147
1150
  }));
1148
1151
  return function (_x12) {
1149
- return _ref13.apply(this, arguments);
1152
+ return _ref19.apply(this, arguments);
1150
1153
  };
1151
1154
  }();
1152
1155
  newElementHandle.click = /*#__PURE__*/function () {
1153
- var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(options) {
1156
+ var _ref20 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(options) {
1154
1157
  return _regeneratorRuntime().wrap(function _callee9$(_context9) {
1155
1158
  while (1) switch (_context9.prev = _context9.next) {
1156
1159
  case 0:
@@ -1165,11 +1168,11 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
1165
1168
  }, _callee9);
1166
1169
  }));
1167
1170
  return function (_x13) {
1168
- return _ref14.apply(this, arguments);
1171
+ return _ref20.apply(this, arguments);
1169
1172
  };
1170
1173
  }();
1171
1174
  newElementHandle.type = /*#__PURE__*/function () {
1172
- var _ref15 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(text, options) {
1175
+ var _ref21 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(text, options) {
1173
1176
  return _regeneratorRuntime().wrap(function _callee10$(_context10) {
1174
1177
  while (1) switch (_context10.prev = _context10.next) {
1175
1178
  case 0:
@@ -1184,7 +1187,7 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
1184
1187
  }, _callee10);
1185
1188
  }));
1186
1189
  return function (_x14, _x15) {
1187
- return _ref15.apply(this, arguments);
1190
+ return _ref21.apply(this, arguments);
1188
1191
  };
1189
1192
  }();
1190
1193
  newElementHandle.select = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11() {
@@ -1246,39 +1249,62 @@ afterEach( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().ma
1246
1249
  return _regeneratorRuntime().wrap(function _callee14$(_context14) {
1247
1250
  while (1) switch (_context14.prev = _context14.next) {
1248
1251
  case 0:
1249
- _context14.next = 2;
1250
- return collectCoverageIfAvailable({
1252
+ if (!process.env.COLLECT_ACCEPTANCE_COVERAGE) {
1253
+ _context14.next = 3;
1254
+ break;
1255
+ }
1256
+ _context14.next = 3;
1257
+ return collectFrontendCoverage({
1251
1258
  coveragePath: coveragePath
1252
1259
  });
1253
- case 2:
1254
- _context14.prev = 2;
1260
+ case 3:
1261
+ _context14.prev = 3;
1255
1262
  page = getGlobalPage$1();
1256
1263
  requestHandlers = [];
1257
1264
  needsRequestInterception = false;
1258
1265
  page.off('request', requestInterceptor);
1259
1266
  // clear tab, this way we clear the DOM and stop js execution or pending requests
1260
- _context14.next = 9;
1267
+ _context14.next = 10;
1261
1268
  return page["goto"]('about:blank');
1262
- case 9:
1263
- _context14.next = 13;
1269
+ case 10:
1270
+ _context14.next = 14;
1264
1271
  break;
1265
- case 11:
1266
- _context14.prev = 11;
1267
- _context14.t0 = _context14["catch"](2);
1268
- case 13:
1272
+ case 12:
1273
+ _context14.prev = 12;
1274
+ _context14.t0 = _context14["catch"](3);
1275
+ case 14:
1269
1276
  case "end":
1270
1277
  return _context14.stop();
1271
1278
  }
1272
- }, _callee14, null, [[2, 11]]);
1279
+ }, _callee14, null, [[3, 12]]);
1280
+ })));
1281
+ afterAll( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
1282
+ return _regeneratorRuntime().wrap(function _callee15$(_context15) {
1283
+ while (1) switch (_context15.prev = _context15.next) {
1284
+ case 0:
1285
+ if (!process.env.COLLECT_ACCEPTANCE_COVERAGE) {
1286
+ _context15.next = 3;
1287
+ break;
1288
+ }
1289
+ _context15.next = 3;
1290
+ return collectBackendCoverage({
1291
+ coveragePath: coveragePath,
1292
+ coverageUrls: coverageUrls
1293
+ });
1294
+ case 3:
1295
+ case "end":
1296
+ return _context15.stop();
1297
+ }
1298
+ }, _callee15);
1273
1299
  })));
1274
- /**
1275
- * Returns a new path to the file that can be used by chromium in acceptance tests
1276
- *
1277
- * To be able to use `element.uploadFile()` in a dockerized chromium, the file must exist in the
1278
- * host and the docker, and both sides must use the same path.
1279
- *
1280
- * To workaround this bug or limitation, this function prepares the file by copying it to /tmp in
1281
- * the host and the container.
1300
+ /**
1301
+ * Returns a new path to the file that can be used by chromium in acceptance tests
1302
+ *
1303
+ * To be able to use `element.uploadFile()` in a dockerized chromium, the file must exist in the
1304
+ * host and the docker, and both sides must use the same path.
1305
+ *
1306
+ * To workaround this bug or limitation, this function prepares the file by copying it to /tmp in
1307
+ * the host and the container.
1282
1308
  */
1283
1309
  var prepareFile = function prepareFile(filepath) {
1284
1310
  var isLocal = !isCi;
@@ -1298,8 +1324,8 @@ var prepareFile = function prepareFile(filepath) {
1298
1324
  return filepath;
1299
1325
  }
1300
1326
  };
1301
- /**
1302
- * A convenience method to defer an expectation
1327
+ /**
1328
+ * A convenience method to defer an expectation
1303
1329
  */
1304
1330
  var wait = function wait(expectation, timeout, interval) {
1305
1331
  if (timeout === void 0) {
@@ -1345,44 +1371,44 @@ var waitForElementToBeRemoved = function waitForElementToBeRemoved(element, time
1345
1371
  }
1346
1372
  var startStack = new Error().stack;
1347
1373
  var wait = /*#__PURE__*/function () {
1348
- var _ref19 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
1374
+ var _ref26 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
1349
1375
  var t0, box;
1350
- return _regeneratorRuntime().wrap(function _callee15$(_context15) {
1351
- while (1) switch (_context15.prev = _context15.next) {
1376
+ return _regeneratorRuntime().wrap(function _callee16$(_context16) {
1377
+ while (1) switch (_context16.prev = _context16.next) {
1352
1378
  case 0:
1353
1379
  t0 = Date.now();
1354
1380
  case 1:
1355
1381
  if (!(Date.now() - t0 < timeout)) {
1356
- _context15.next = 11;
1382
+ _context16.next = 11;
1357
1383
  break;
1358
1384
  }
1359
- _context15.next = 4;
1385
+ _context16.next = 4;
1360
1386
  return element.boundingBox();
1361
1387
  case 4:
1362
- box = _context15.sent;
1388
+ box = _context16.sent;
1363
1389
  if (box) {
1364
- _context15.next = 7;
1390
+ _context16.next = 7;
1365
1391
  break;
1366
1392
  }
1367
- return _context15.abrupt("return");
1393
+ return _context16.abrupt("return");
1368
1394
  case 7:
1369
- _context15.next = 9;
1395
+ _context16.next = 9;
1370
1396
  return new Promise(function (resolve) {
1371
1397
  return setTimeout(resolve, interval);
1372
1398
  });
1373
1399
  case 9:
1374
- _context15.next = 1;
1400
+ _context16.next = 1;
1375
1401
  break;
1376
1402
  case 11:
1377
1403
  throw new Error('Element not removed');
1378
1404
  case 12:
1379
1405
  case "end":
1380
- return _context15.stop();
1406
+ return _context16.stop();
1381
1407
  }
1382
- }, _callee15);
1408
+ }, _callee16);
1383
1409
  }));
1384
1410
  return function wait() {
1385
- return _ref19.apply(this, arguments);
1411
+ return _ref26.apply(this, arguments);
1386
1412
  };
1387
1413
  }();
1388
1414
  return wait()["catch"](function (error) {