@smoothdeploy/playwright 1.60.1 → 1.62.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.
@@ -56,7 +56,7 @@ var import_events2 = __toESM(require("events"));
56
56
  var import_fs13 = __toESM(require("fs"));
57
57
  var import_path17 = __toESM(require("path"));
58
58
  var import_coreBundle2 = require("playwright-core/lib/coreBundle");
59
- var import_common9 = require("../common");
59
+ var import_common10 = require("../common");
60
60
 
61
61
  // packages/playwright/src/runner/fsWatcher.ts
62
62
  var chokidar = require("playwright-core/lib/utilsBundle").chokidar;
@@ -432,6 +432,18 @@ var TeleSuite = class {
432
432
  suite.parent = this;
433
433
  this._entries.push(suite);
434
434
  }
435
+ skip(_reason) {
436
+ throw new Error("Disposition methods are not supported on a TeleSuite (read-only).");
437
+ }
438
+ fixme(_reason) {
439
+ throw new Error("Disposition methods are not supported on a TeleSuite (read-only).");
440
+ }
441
+ fail(_reason) {
442
+ throw new Error("Disposition methods are not supported on a TeleSuite (read-only).");
443
+ }
444
+ exclude() {
445
+ throw new Error("Disposition methods are not supported on a TeleSuite (read-only).");
446
+ }
435
447
  };
436
448
  var TeleTestCase = class {
437
449
  constructor(id, title, location, repeatEachIndex) {
@@ -467,6 +479,18 @@ var TeleTestCase = class {
467
479
  this.results.push(result);
468
480
  return result;
469
481
  }
482
+ skip(_reason) {
483
+ throw new Error("Disposition methods are not supported on a TeleTestCase (read-only).");
484
+ }
485
+ fixme(_reason) {
486
+ throw new Error("Disposition methods are not supported on a TeleTestCase (read-only).");
487
+ }
488
+ fail(_reason) {
489
+ throw new Error("Disposition methods are not supported on a TeleTestCase (read-only).");
490
+ }
491
+ exclude() {
492
+ throw new Error("Disposition methods are not supported on a TeleTestCase (read-only).");
493
+ }
470
494
  };
471
495
  var TeleTestStep = class {
472
496
  constructor(payload, parentStep, location, result) {
@@ -525,6 +549,8 @@ var TeleTestResult = class {
525
549
  }
526
550
  };
527
551
  var baseFullConfig = {
552
+ argv: [],
553
+ failOnFlakyTests: false,
528
554
  forbidOnly: false,
529
555
  fullyParallel: false,
530
556
  globalSetup: null,
@@ -704,15 +730,14 @@ async function gitCommitInfo(gitDir) {
704
730
  // committer name
705
731
  "%ce",
706
732
  // committer email
707
- "%ct",
733
+ "%ct"
708
734
  // committer date, UNIX timestamp
709
- ""
710
- // branch
711
735
  ];
712
- const output = await runGit(`git log -1 --pretty=format:"${tokens.join(separator2)}" && git rev-parse --abbrev-ref HEAD`, gitDir);
713
- if (!output)
736
+ const logOutput = await runGit(["log", "-1", `--pretty=format:${tokens.join(separator2)}`], gitDir);
737
+ if (!logOutput)
714
738
  return void 0;
715
- const [hash, shortHash, subject, body, authorName, authorEmail, authorTime, committerName, committerEmail, committerTime, branch] = output.split(separator2);
739
+ const branchOutput = await runGit(["rev-parse", "--abbrev-ref", "HEAD"], gitDir);
740
+ const [hash, shortHash, subject, body, authorName, authorEmail, authorTime, committerName, committerEmail, committerTime] = logOutput.split(separator2);
716
741
  return {
717
742
  shortHash,
718
743
  hash,
@@ -728,38 +753,38 @@ async function gitCommitInfo(gitDir) {
728
753
  email: committerEmail,
729
754
  time: +committerTime * 1e3
730
755
  },
731
- branch: branch.trim()
756
+ branch: branchOutput?.trim() ?? ""
732
757
  };
733
758
  }
734
759
  async function gitDiff(gitDir, ci) {
735
760
  const diffLimit = 1e5;
736
761
  if (ci?.prBaseHash) {
737
- await runGit(`git fetch origin ${ci.prBaseHash} --depth=1 --no-auto-maintenance --no-auto-gc --no-tags --no-recurse-submodules`, gitDir);
738
- const diff3 = await runGit(`git diff ${ci.prBaseHash} HEAD`, gitDir);
762
+ await runGit(["fetch", "origin", ci.prBaseHash, "--depth=1", "--no-auto-maintenance", "--no-auto-gc", "--no-tags", "--no-recurse-submodules"], gitDir);
763
+ const diff3 = await runGit(["diff", ci.prBaseHash, "HEAD"], gitDir);
739
764
  if (diff3)
740
765
  return diff3.substring(0, diffLimit);
741
766
  }
742
767
  if (ci)
743
768
  return;
744
- const uncommitted = await runGit("git diff", gitDir);
769
+ const uncommitted = await runGit(["diff"], gitDir);
745
770
  if (uncommitted === void 0) {
746
771
  return;
747
772
  }
748
773
  if (uncommitted)
749
774
  return uncommitted.substring(0, diffLimit);
750
- const diff2 = await runGit("git diff HEAD~1", gitDir);
775
+ const diff2 = await runGit(["diff", "HEAD~1"], gitDir);
751
776
  return diff2?.substring(0, diffLimit);
752
777
  }
753
- async function runGit(command, cwd) {
754
- debug(`running "${command}"`);
778
+ async function runGit(args, cwd) {
779
+ debug(`running "git ${args.join(" ")}"`);
755
780
  const start = monotonicTime();
756
781
  const result = await spawnAsync(
757
- command,
758
- [],
759
- { stdio: "pipe", cwd, timeout: GIT_OPERATIONS_TIMEOUT_MS, shell: true }
782
+ "git",
783
+ args,
784
+ { stdio: "pipe", cwd, timeout: GIT_OPERATIONS_TIMEOUT_MS }
760
785
  );
761
786
  if (monotonicTime() - start > GIT_OPERATIONS_TIMEOUT_MS) {
762
- print(`timeout of ${GIT_OPERATIONS_TIMEOUT_MS}ms exceeded while running "${command}"`);
787
+ print(`timeout of ${GIT_OPERATIONS_TIMEOUT_MS}ms exceeded while running "git ${args.join(" ")}"`);
763
788
  return;
764
789
  }
765
790
  if (result.code)
@@ -774,6 +799,7 @@ ${result.stderr}`);
774
799
  // packages/playwright/src/plugins/webServerPlugin.ts
775
800
  var import_net = __toESM(require("net"));
776
801
  var import_path = __toESM(require("path"));
802
+ var import_util = require("util");
777
803
  var colors = require("playwright-core/lib/utilsBundle").colors;
778
804
  var debug2 = require("playwright-core/lib/utilsBundle").debug;
779
805
  var { ManualPromise } = require("playwright-core/lib/coreBundle").iso;
@@ -882,7 +908,7 @@ var WebServerPlugin = class {
882
908
  launchedProcess[stdio].on("data", (data) => {
883
909
  if (!this._options.wait?.[stdio] || stdioWaitCollectors[stdio] === void 0)
884
910
  return;
885
- stdioWaitCollectors[stdio] += data.toString();
911
+ stdioWaitCollectors[stdio] += (0, import_util.stripVTControlCharacters)(data.toString());
886
912
  this._options.wait[stdio].lastIndex = 0;
887
913
  const result = this._options.wait[stdio].exec(stdioWaitCollectors[stdio]);
888
914
  if (result) {
@@ -1004,18 +1030,29 @@ __export(base_exports, {
1004
1030
  terminalScreen: () => terminalScreen
1005
1031
  });
1006
1032
  var import_path2 = __toESM(require("path"));
1007
- var import_util = require("../util");
1033
+ var import_stream = require("stream");
1034
+ var import_util2 = require("../util");
1008
1035
  var realColors = require("playwright-core/lib/utilsBundle").colors;
1009
1036
  var { noColors } = require("playwright-core/lib/coreBundle").iso;
1010
1037
  var { msToString } = require("playwright-core/lib/coreBundle").iso;
1011
- var { parseErrorStack } = require("playwright-core/lib/coreBundle").iso;
1038
+ var { parseErrorStack } = require("playwright-core/lib/coreBundle").utils;
1012
1039
  var { getPackageManagerExecCommand } = require("playwright-core/lib/coreBundle").utils;
1013
1040
  var { fitToWidth } = require("playwright-core/lib/coreBundle").utils;
1014
- var kOutputSymbol = Symbol("output");
1041
+ var kOutputSymbol = /* @__PURE__ */ Symbol("output");
1015
1042
  var DEFAULT_TTY_WIDTH = 100;
1016
1043
  var DEFAULT_TTY_HEIGHT = 40;
1017
1044
  var originalProcessStdout = process.stdout;
1018
1045
  var originalProcessStderr = process.stderr;
1046
+ var StripAnsiStream = class extends import_stream.Writable {
1047
+ constructor(target) {
1048
+ super();
1049
+ this._target = target;
1050
+ }
1051
+ write(chunk, encodingOrCallback, callback) {
1052
+ const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
1053
+ return this._target.write((0, import_util2.stripAnsiEscapes)(chunk.toString()), cb);
1054
+ }
1055
+ };
1019
1056
  var terminalScreen = (() => {
1020
1057
  let isTTY = !!originalProcessStdout.isTTY;
1021
1058
  let ttyWidth = originalProcessStdout.columns || 0;
@@ -1044,7 +1081,7 @@ var terminalScreen = (() => {
1044
1081
  ttyHeight = DEFAULT_TTY_HEIGHT;
1045
1082
  }
1046
1083
  let useColors = isTTY;
1047
- if (process.env.DEBUG_COLORS === "0" || process.env.DEBUG_COLORS === "false" || process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false")
1084
+ if (process.env.DEBUG_COLORS === "0" || process.env.DEBUG_COLORS === "false" || process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false" || process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "")
1048
1085
  useColors = false;
1049
1086
  else if (process.env.DEBUG_COLORS || process.env.FORCE_COLOR)
1050
1087
  useColors = true;
@@ -1055,8 +1092,8 @@ var terminalScreen = (() => {
1055
1092
  ttyWidth,
1056
1093
  ttyHeight,
1057
1094
  colors: colors7,
1058
- stdout: originalProcessStdout,
1059
- stderr: originalProcessStderr
1095
+ stdout: useColors ? originalProcessStdout : new StripAnsiStream(originalProcessStdout),
1096
+ stderr: useColors ? originalProcessStderr : new StripAnsiStream(originalProcessStderr)
1060
1097
  };
1061
1098
  })();
1062
1099
  var nonTerminalScreen = {
@@ -1361,7 +1398,7 @@ function quotePathIfNeeded(path21) {
1361
1398
  return `"${path21}"`;
1362
1399
  return path21;
1363
1400
  }
1364
- var kReportedSymbol = Symbol("reported");
1401
+ var kReportedSymbol = /* @__PURE__ */ Symbol("reported");
1365
1402
  function markErrorsAsReported(result) {
1366
1403
  result[kReportedSymbol] = result.errors.length;
1367
1404
  }
@@ -1444,7 +1481,7 @@ function formatError(screen, error) {
1444
1481
  if (error.snippet) {
1445
1482
  let snippet = error.snippet;
1446
1483
  if (!screen.colors.enabled)
1447
- snippet = (0, import_util.stripAnsiEscapes)(snippet);
1484
+ snippet = (0, import_util2.stripAnsiEscapes)(snippet);
1448
1485
  tokens.push("");
1449
1486
  tokens.push(snippet);
1450
1487
  }
@@ -1464,13 +1501,13 @@ function separator(screen, text = "") {
1464
1501
  if (text)
1465
1502
  text += " ";
1466
1503
  const columns = Math.min(100, screen.ttyWidth || 100);
1467
- return text + screen.colors.dim("\u2500".repeat(Math.max(0, columns - (0, import_util.stripAnsiEscapes)(text).length)));
1504
+ return text + screen.colors.dim("\u2500".repeat(Math.max(0, columns - (0, import_util2.stripAnsiEscapes)(text).length)));
1468
1505
  }
1469
1506
  function indent(lines, tab) {
1470
1507
  return lines.replace(/^(?=.+$)/gm, tab);
1471
1508
  }
1472
1509
  function prepareErrorStack(stack) {
1473
- return parseErrorStack(stack, import_path2.default.sep, !!process.env.PWDEBUGIMPL);
1510
+ return parseErrorStack(stack);
1474
1511
  }
1475
1512
  function resolveFromEnv(name) {
1476
1513
  const value = process.env[name];
@@ -1489,7 +1526,7 @@ function resolveOutputFile(reporterName, options) {
1489
1526
  if (!outputDir && options.outputDir)
1490
1527
  outputDir = import_path2.default.resolve(options.configDir, options.outputDir);
1491
1528
  if (!outputDir && options.default)
1492
- outputDir = (0, import_util.resolveReporterOutputPath)(options.default.outputDir, options.configDir, void 0);
1529
+ outputDir = (0, import_util2.resolveReporterOutputPath)(options.default.outputDir, options.configDir, void 0);
1493
1530
  if (!outputDir)
1494
1531
  outputDir = options.configDir;
1495
1532
  const reportName = process.env[`PLAYWRIGHT_${name}_OUTPUT_NAME`] ?? options.fileName ?? options.default?.fileName;
@@ -1534,52 +1571,61 @@ function groupAttachments(attachments) {
1534
1571
  var import_fs = __toESM(require("fs"));
1535
1572
 
1536
1573
  // packages/playwright/src/reporters/multiplexer.ts
1574
+ var import_util3 = require("../util");
1537
1575
  var Multiplexer = class {
1538
1576
  constructor(reporters) {
1577
+ this._hasReporterErrors = false;
1539
1578
  this._reporters = reporters;
1540
1579
  }
1541
1580
  version() {
1542
1581
  return "v2";
1543
1582
  }
1583
+ hasReporterErrors() {
1584
+ return this._hasReporterErrors;
1585
+ }
1544
1586
  onConfigure(config2) {
1545
1587
  for (const reporter of this._reporters)
1546
- wrap(() => reporter.onConfigure?.(config2));
1588
+ this._wrap(() => reporter.onConfigure?.(config2));
1589
+ }
1590
+ async preprocess(params) {
1591
+ for (const reporter of this._reporters)
1592
+ await reporter.preprocess?.(params);
1547
1593
  }
1548
1594
  onBegin(suite) {
1549
1595
  for (const reporter of this._reporters)
1550
- wrap(() => reporter.onBegin?.(suite));
1596
+ this._wrap(() => reporter.onBegin?.(suite));
1551
1597
  }
1552
1598
  onTestBegin(test, result) {
1553
1599
  for (const reporter of this._reporters)
1554
- wrap(() => reporter.onTestBegin?.(test, result));
1600
+ this._wrap(() => reporter.onTestBegin?.(test, result));
1555
1601
  }
1556
1602
  onStdOut(chunk, test, result) {
1557
1603
  for (const reporter of this._reporters)
1558
- wrap(() => reporter.onStdOut?.(chunk, test, result));
1604
+ this._wrap(() => reporter.onStdOut?.(chunk, test, result));
1559
1605
  }
1560
1606
  onStdErr(chunk, test, result) {
1561
1607
  for (const reporter of this._reporters)
1562
- wrap(() => reporter.onStdErr?.(chunk, test, result));
1608
+ this._wrap(() => reporter.onStdErr?.(chunk, test, result));
1563
1609
  }
1564
1610
  async onTestPaused(test, result) {
1565
1611
  for (const reporter of this._reporters)
1566
- await wrapAsync(() => reporter.onTestPaused?.(test, result));
1612
+ await this._wrapAsync(() => reporter.onTestPaused?.(test, result));
1567
1613
  }
1568
1614
  onTestEnd(test, result) {
1569
1615
  for (const reporter of this._reporters)
1570
- wrap(() => reporter.onTestEnd?.(test, result));
1616
+ this._wrap(() => reporter.onTestEnd?.(test, result));
1571
1617
  }
1572
1618
  onReportConfigure(params) {
1573
1619
  for (const reporter of this._reporters)
1574
- wrap(() => reporter.onReportConfigure?.(params));
1620
+ this._wrap(() => reporter.onReportConfigure?.(params));
1575
1621
  }
1576
1622
  onReportEnd(params) {
1577
1623
  for (const reporter of this._reporters)
1578
- wrap(() => reporter.onReportEnd?.(params));
1624
+ this._wrap(() => reporter.onReportEnd?.(params));
1579
1625
  }
1580
1626
  async onEnd(result) {
1581
1627
  for (const reporter of this._reporters) {
1582
- const outResult = await wrapAsync(() => reporter.onEnd?.(result));
1628
+ const outResult = await this._wrapAsync(() => reporter.onEnd?.(result));
1583
1629
  if (outResult?.status)
1584
1630
  result.status = outResult.status;
1585
1631
  }
@@ -1587,42 +1633,45 @@ var Multiplexer = class {
1587
1633
  }
1588
1634
  async onExit() {
1589
1635
  for (const reporter of this._reporters)
1590
- await wrapAsync(() => reporter.onExit?.());
1636
+ await this._wrapAsync(() => reporter.onExit?.());
1591
1637
  }
1592
1638
  onError(error, workerInfo) {
1593
1639
  for (const reporter of this._reporters)
1594
- wrap(() => reporter.onError?.(error, workerInfo));
1640
+ this._wrap(() => reporter.onError?.(error, workerInfo), false);
1595
1641
  }
1596
1642
  onStepBegin(test, result, step) {
1597
1643
  for (const reporter of this._reporters)
1598
- wrap(() => reporter.onStepBegin?.(test, result, step));
1644
+ this._wrap(() => reporter.onStepBegin?.(test, result, step));
1599
1645
  }
1600
1646
  onStepEnd(test, result, step) {
1601
1647
  for (const reporter of this._reporters)
1602
- wrap(() => reporter.onStepEnd?.(test, result, step));
1648
+ this._wrap(() => reporter.onStepEnd?.(test, result, step));
1603
1649
  }
1604
1650
  printsToStdio() {
1605
1651
  return this._reporters.some((r) => {
1606
1652
  let prints = false;
1607
- wrap(() => prints = r.printsToStdio ? r.printsToStdio() : true);
1653
+ this._wrap(() => prints = r.printsToStdio ? r.printsToStdio() : true, false);
1608
1654
  return prints;
1609
1655
  });
1610
1656
  }
1611
- };
1612
- async function wrapAsync(callback) {
1613
- try {
1614
- return await callback();
1615
- } catch (e) {
1616
- console.error("Error in reporter", e);
1657
+ _wrap(callback, redispatch = true) {
1658
+ try {
1659
+ callback();
1660
+ } catch (e) {
1661
+ this._hasReporterErrors = true;
1662
+ if (redispatch)
1663
+ this.onError((0, import_util3.serializeError)(e));
1664
+ }
1617
1665
  }
1618
- }
1619
- function wrap(callback) {
1620
- try {
1621
- callback();
1622
- } catch (e) {
1623
- console.error("Error in reporter", e);
1666
+ async _wrapAsync(callback) {
1667
+ try {
1668
+ return await callback();
1669
+ } catch (e) {
1670
+ this._hasReporterErrors = true;
1671
+ this.onError((0, import_util3.serializeError)(e));
1672
+ }
1624
1673
  }
1625
- }
1674
+ };
1626
1675
 
1627
1676
  // packages/playwright/src/reporters/internalReporter.ts
1628
1677
  var import_common = require("../common");
@@ -1648,6 +1697,9 @@ var ReporterV2Wrapper = class {
1648
1697
  onConfigure(config2) {
1649
1698
  this._config = config2;
1650
1699
  }
1700
+ preprocess(params) {
1701
+ return this._reporter.preprocess?.(params);
1702
+ }
1651
1703
  onBegin(suite) {
1652
1704
  this._reporter.onBegin?.(this._config, suite);
1653
1705
  const deferred = this._deferred;
@@ -1715,12 +1767,18 @@ var InternalReporter = class {
1715
1767
  version() {
1716
1768
  return "v2";
1717
1769
  }
1770
+ hasReporterErrors() {
1771
+ return this._reporter.hasReporterErrors();
1772
+ }
1718
1773
  onConfigure(config2) {
1719
1774
  this._config = config2;
1720
1775
  this._startTime = /* @__PURE__ */ new Date();
1721
1776
  this._monotonicStartTime = monotonicTime3();
1722
1777
  this._reporter.onConfigure?.(config2);
1723
1778
  }
1779
+ async preprocess(params) {
1780
+ await this._reporter.preprocess(params);
1781
+ }
1724
1782
  onBegin(suite) {
1725
1783
  this._didBegin = true;
1726
1784
  this._reporter.onBegin?.(suite);
@@ -1767,7 +1825,7 @@ var InternalReporter = class {
1767
1825
  this._reporter.onStepEnd?.(test, result, step);
1768
1826
  }
1769
1827
  printsToStdio() {
1770
- return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;
1828
+ return this._reporter.printsToStdio?.() ?? true;
1771
1829
  }
1772
1830
  _addSnippetToTestErrors(test, result) {
1773
1831
  for (const error of result.errors)
@@ -1801,7 +1859,7 @@ function addLocationAndSnippetToError(config2, error, file) {
1801
1859
  }
1802
1860
 
1803
1861
  // packages/playwright/src/runner/testRunner.ts
1804
- var import_util13 = require("../util");
1862
+ var import_util15 = require("../util");
1805
1863
 
1806
1864
  // packages/playwright/src/runner/reporters.ts
1807
1865
  var reporters_exports = {};
@@ -1997,7 +2055,7 @@ var InProcessLoaderHost = class {
1997
2055
  return result;
1998
2056
  }
1999
2057
  async stop() {
2000
- await import_common2.esm.incorporateCompilationCache();
2058
+ await import_common2.transform.incorporateCompilationCache();
2001
2059
  }
2002
2060
  };
2003
2061
  var OutOfProcessLoaderHost = class {
@@ -2028,7 +2086,7 @@ var OutOfProcessLoaderHost = class {
2028
2086
  };
2029
2087
 
2030
2088
  // packages/playwright/src/runner/loadUtils.ts
2031
- var import_util4 = require("../util");
2089
+ var import_util6 = require("../util");
2032
2090
 
2033
2091
  // packages/playwright/src/runner/projectUtils.ts
2034
2092
  var projectUtils_exports = {};
@@ -2042,12 +2100,12 @@ __export(projectUtils_exports, {
2042
2100
  });
2043
2101
  var import_fs2 = __toESM(require("fs"));
2044
2102
  var import_path3 = __toESM(require("path"));
2045
- var import_util2 = require("util");
2046
- var import_util3 = require("../util");
2047
- var minimatch = require("playwright-core/lib/utilsBundle").minimatch;
2103
+ var import_util4 = require("util");
2104
+ var import_util5 = require("../util");
2105
+ var { minimatch } = require("playwright-core/lib/utilsBundle");
2048
2106
  var { escapeRegExp } = require("playwright-core/lib/coreBundle").iso;
2049
- var readFileAsync = (0, import_util2.promisify)(import_fs2.default.readFile);
2050
- var readDirAsync = (0, import_util2.promisify)(import_fs2.default.readdir);
2107
+ var readFileAsync = (0, import_util4.promisify)(import_fs2.default.readFile);
2108
+ var readDirAsync = (0, import_util4.promisify)(import_fs2.default.readdir);
2051
2109
  function wildcardPatternToRegExp(pattern) {
2052
2110
  return new RegExp("^" + pattern.split("*").map(escapeRegExp).join(".*") + "$", "ig");
2053
2111
  }
@@ -2152,8 +2210,8 @@ async function collectFilesForProject(project, fsCache = /* @__PURE__ */ new Map
2152
2210
  const extensions = /* @__PURE__ */ new Set([".js", ".ts", ".mjs", ".mts", ".cjs", ".cts", ".jsx", ".tsx", ".mjsx", ".mtsx", ".cjsx", ".ctsx"]);
2153
2211
  const testFileExtension = (file) => extensions.has(import_path3.default.extname(file));
2154
2212
  const allFiles = await cachedCollectFiles(project.project.testDir, project.respectGitIgnore, fsCache);
2155
- const testMatch = (0, import_util3.createFileMatcher)(project.project.testMatch);
2156
- const testIgnore = (0, import_util3.createFileMatcher)(project.project.testIgnore);
2213
+ const testMatch = (0, import_util5.createFileMatcher)(project.project.testMatch);
2214
+ const testIgnore = (0, import_util5.createFileMatcher)(project.project.testIgnore);
2157
2215
  const testFiles = allFiles.filter((file) => {
2158
2216
  if (!testFileExtension(file))
2159
2217
  return false;
@@ -2235,6 +2293,65 @@ async function collectFiles(testDir, respectGitIgnore) {
2235
2293
  return files;
2236
2294
  }
2237
2295
 
2296
+ // packages/playwright/src/runner/reporterTestRun.ts
2297
+ var import_common3 = require("../common");
2298
+ var ReporterTestRunImpl = class {
2299
+ constructor(_rootSuite, _readonlyProjectSuites) {
2300
+ this._rootSuite = _rootSuite;
2301
+ this._readonlyProjectSuites = _readonlyProjectSuites;
2302
+ this._active = true;
2303
+ this._skipSharding = false;
2304
+ this.skip = import_common3.transform.wrapFunctionWithLocation((location, target, reason) => this._modifier("skip", location, target, reason));
2305
+ this.fixme = import_common3.transform.wrapFunctionWithLocation((location, target, reason) => this._modifier("fixme", location, target, reason));
2306
+ this.fail = import_common3.transform.wrapFunctionWithLocation((location, target, reason) => this._modifier("fail", location, target, reason));
2307
+ }
2308
+ close() {
2309
+ this._active = false;
2310
+ }
2311
+ shouldSkipSharding() {
2312
+ return this._skipSharding;
2313
+ }
2314
+ skipSharding() {
2315
+ if (!this._active)
2316
+ throw new Error(`TestRun.skipSharding() can only be called from Reporter.preprocess().`);
2317
+ if (this._skipSharding)
2318
+ throw new Error(`Multiple reporters called 'skipSharding'. Only one reporter may handle sharding.`);
2319
+ this._skipSharding = true;
2320
+ }
2321
+ exclude(target) {
2322
+ if (!this._active)
2323
+ throw new Error(`TestRun.exclude() can only be called from Reporter.preprocess().`);
2324
+ const internalTarget = target;
2325
+ this._checkTarget("exclude", internalTarget);
2326
+ internalTarget.parent._detach(internalTarget);
2327
+ }
2328
+ _modifier(type, location, _target, reason) {
2329
+ if (!this._active)
2330
+ throw new Error(`TestRun.${type}() can only be called from Reporter.preprocess().`);
2331
+ const target = _target;
2332
+ this._checkTarget(type, target);
2333
+ const annotation = { type, description: reason, location };
2334
+ if (target instanceof import_common3.test.Suite) {
2335
+ for (const test of target.allTests())
2336
+ test._applyPlanAnnotation(annotation);
2337
+ } else {
2338
+ target._applyPlanAnnotation(annotation);
2339
+ }
2340
+ }
2341
+ _checkTarget(method, target) {
2342
+ if (target === this._rootSuite)
2343
+ throw new Error(`TestRun.${method}() cannot be called on the root suite.`);
2344
+ let suite = target instanceof import_common3.test.Suite ? target : target.parent;
2345
+ while (suite) {
2346
+ if (this._readonlyProjectSuites.has(suite)) {
2347
+ const targetType = target instanceof import_common3.test.TestCase ? " test" : "";
2348
+ throw new Error(`TestRun.${method}() cannot be called on a setup or teardown project${targetType}; these always run in full.`);
2349
+ }
2350
+ suite = suite.parent;
2351
+ }
2352
+ }
2353
+ };
2354
+
2238
2355
  // packages/playwright/src/runner/testGroups.ts
2239
2356
  function createTestGroups(projectSuite, expectedParallelism) {
2240
2357
  const groups = /* @__PURE__ */ new Map();
@@ -2334,7 +2451,7 @@ function filterForShard(shard, weights, testGroups) {
2334
2451
  }
2335
2452
 
2336
2453
  // packages/playwright/src/runner/loadUtils.ts
2337
- var import_common3 = require("../common");
2454
+ var import_common4 = require("../common");
2338
2455
  var sourceMapSupport = require("playwright-core/lib/utilsBundle").sourceMapSupport;
2339
2456
  var { toPosixPath } = require("playwright-core/lib/coreBundle").utils;
2340
2457
  async function collectProjectsAndTestFiles(testRun, doNotRunTestsOutsideProjectFilter) {
@@ -2387,7 +2504,7 @@ async function loadFileSuites(testRun, mode, errors) {
2387
2504
  await loaderHost.stop();
2388
2505
  }
2389
2506
  for (const file of allTestFiles) {
2390
- for (const dependency of import_common3.cc.dependenciesForTestFile(file)) {
2507
+ for (const dependency of import_common4.cc.dependenciesForTestFile(file)) {
2391
2508
  if (allTestFiles.has(dependency)) {
2392
2509
  const importer = import_path4.default.relative(config2.config.rootDir, file);
2393
2510
  const importee = import_path4.default.relative(config2.config.rootDir, dependency);
@@ -2405,7 +2522,7 @@ async function loadFileSuites(testRun, mode, errors) {
2405
2522
  }
2406
2523
  async function createRootSuite(testRun, errors, shouldFilterOnly) {
2407
2524
  const config2 = testRun.config;
2408
- const rootSuite = new import_common3.test.Suite("", "root");
2525
+ const rootSuite = new import_common4.test.Suite("", "root");
2409
2526
  const projectSuites = /* @__PURE__ */ new Map();
2410
2527
  const filteredProjectSuites = /* @__PURE__ */ new Map();
2411
2528
  {
@@ -2417,10 +2534,10 @@ async function createRootSuite(testRun, errors, shouldFilterOnly) {
2417
2534
  }
2418
2535
  }
2419
2536
  if (shouldFilterOnly) {
2420
- const filteredRoot = new import_common3.test.Suite("", "root");
2537
+ const filteredRoot = new import_common4.test.Suite("", "root");
2421
2538
  for (const filteredProjectSuite of filteredProjectSuites.values())
2422
2539
  filteredRoot._addSuite(filteredProjectSuite);
2423
- import_common3.suiteUtils.filterOnly(filteredRoot);
2540
+ import_common4.suiteUtils.filterOnly(filteredRoot);
2424
2541
  for (const [project, filteredProjectSuite] of filteredProjectSuites) {
2425
2542
  if (!filteredRoot.suites.includes(filteredProjectSuite))
2426
2543
  filteredProjectSuites.delete(project);
@@ -2440,7 +2557,24 @@ async function createRootSuite(testRun, errors, shouldFilterOnly) {
2440
2557
  errors.push(...createForbidOnlyErrors(onlyTestsAndSuites, config2.configCLIOverrides.forbidOnly, configFilePath));
2441
2558
  }
2442
2559
  }
2443
- if (config2.config.shard) {
2560
+ const dependencySuites = /* @__PURE__ */ new Map();
2561
+ for (const [project, type] of projectClosure) {
2562
+ if (type !== "dependency")
2563
+ continue;
2564
+ const dependencySuite = buildProjectSuite(project, projectSuites.get(project));
2565
+ dependencySuites.set(project, dependencySuite);
2566
+ rootSuite._prependSuite(dependencySuite);
2567
+ }
2568
+ const reporterTestRun = new ReporterTestRunImpl(rootSuite, new Set(dependencySuites.values()));
2569
+ await testRun.reporter.preprocess({
2570
+ config: config2.config,
2571
+ suite: rootSuite,
2572
+ testRun: reporterTestRun
2573
+ });
2574
+ reporterTestRun.close();
2575
+ for (const dependencySuite of dependencySuites.values())
2576
+ rootSuite._detach(dependencySuite);
2577
+ if (config2.config.shard && !reporterTestRun.shouldSkipSharding()) {
2444
2578
  const testGroups = [];
2445
2579
  for (const projectSuite of rootSuite.suites) {
2446
2580
  for (const group of createTestGroups(projectSuite, config2.config.shard.total))
@@ -2452,30 +2586,31 @@ async function createRootSuite(testRun, errors, shouldFilterOnly) {
2452
2586
  for (const test of group.tests)
2453
2587
  testsInThisShard.add(test);
2454
2588
  }
2455
- import_common3.suiteUtils.filterTestsRemoveEmptySuites(rootSuite, (test) => testsInThisShard.has(test));
2589
+ import_common4.suiteUtils.filterTestsRemoveEmptySuites(rootSuite, (test) => testsInThisShard.has(test));
2456
2590
  }
2457
2591
  if (testRun.postShardTestFilters.length)
2458
- import_common3.suiteUtils.filterTestsRemoveEmptySuites(rootSuite, (test) => testRun.postShardTestFilters.every((filter) => filter(test)));
2592
+ import_common4.suiteUtils.filterTestsRemoveEmptySuites(rootSuite, (test) => testRun.postShardTestFilters.every((filter) => filter(test)));
2459
2593
  const topLevelProjects = [];
2460
2594
  {
2461
- const projectClosure2 = new Map(buildProjectsClosure(rootSuite.suites.map((suite) => suite._fullProject)));
2462
- for (const [project, level] of projectClosure2.entries()) {
2463
- if (level === "dependency")
2464
- rootSuite._prependSuite(buildProjectSuite(project, projectSuites.get(project)));
2595
+ const finalProjectClosure = buildProjectsClosure(rootSuite.suites.map((suite) => suite._fullProject));
2596
+ for (const [project, type] of finalProjectClosure) {
2597
+ if (type === "dependency")
2598
+ rootSuite._addSuite(dependencySuites.get(project));
2465
2599
  else
2466
2600
  topLevelProjects.push(project);
2467
2601
  }
2468
2602
  }
2603
+ rootSuite._entries.sort((a, b) => config2.projects.indexOf(a._fullProject) - config2.projects.indexOf(b._fullProject));
2469
2604
  testRun.rootSuite = rootSuite;
2470
2605
  testRun.topLevelProjects = topLevelProjects;
2471
2606
  }
2472
2607
  function createProjectSuite(project, fileSuites) {
2473
- const projectSuite = new import_common3.test.Suite(project.project.name, "project");
2608
+ const projectSuite = new import_common4.test.Suite(project.project.name, "project");
2474
2609
  for (const fileSuite of fileSuites)
2475
- projectSuite._addSuite(import_common3.suiteUtils.bindFileSuiteToProject(project, fileSuite));
2476
- const grepMatcher = (0, import_util4.createTitleMatcher)(project.project.grep);
2477
- const grepInvertMatcher = project.project.grepInvert ? (0, import_util4.createTitleMatcher)(project.project.grepInvert) : null;
2478
- import_common3.suiteUtils.filterTestsRemoveEmptySuites(projectSuite, (test) => {
2610
+ projectSuite._addSuite(import_common4.suiteUtils.bindFileSuiteToProject(project, fileSuite));
2611
+ const grepMatcher = (0, import_util6.createTitleMatcher)(project.project.grep);
2612
+ const grepInvertMatcher = project.project.grepInvert ? (0, import_util6.createTitleMatcher)(project.project.grepInvert) : null;
2613
+ import_common4.suiteUtils.filterTestsRemoveEmptySuites(projectSuite, (test) => {
2479
2614
  const grepTitle = test._grepTitleWithTags();
2480
2615
  if (grepInvertMatcher?.(grepTitle))
2481
2616
  return false;
@@ -2487,11 +2622,11 @@ function filterProjectSuite(projectSuite, testFilters) {
2487
2622
  if (!testFilters.length)
2488
2623
  return projectSuite;
2489
2624
  const result = projectSuite._deepClone();
2490
- import_common3.suiteUtils.filterTestsRemoveEmptySuites(result, (test) => testFilters.every((filter) => filter(test)));
2625
+ import_common4.suiteUtils.filterTestsRemoveEmptySuites(result, (test) => testFilters.every((filter) => filter(test)));
2491
2626
  return result;
2492
2627
  }
2493
2628
  function buildProjectSuite(project, projectSuite) {
2494
- const result = new import_common3.test.Suite(project.project.name, "project");
2629
+ const result = new import_common4.test.Suite(project.project.name, "project");
2495
2630
  result._fullProject = project;
2496
2631
  if (project.fullyParallel)
2497
2632
  result._parallelMode = "parallel";
@@ -2499,7 +2634,7 @@ function buildProjectSuite(project, projectSuite) {
2499
2634
  result._addSuite(fileSuite);
2500
2635
  for (let repeatEachIndex = 1; repeatEachIndex < project.project.repeatEach; repeatEachIndex++) {
2501
2636
  const clone = fileSuite._deepClone();
2502
- import_common3.suiteUtils.applyRepeatEachIndex(project, clone, repeatEachIndex);
2637
+ import_common4.suiteUtils.applyRepeatEachIndex(project, clone, repeatEachIndex);
2503
2638
  result._addSuite(clone);
2504
2639
  }
2505
2640
  }
@@ -2542,11 +2677,11 @@ function buildItemLocation(rootDir, testOrSuite) {
2542
2677
  return `${import_path4.default.relative(rootDir, testOrSuite.location.file)}:${testOrSuite.location.line}`;
2543
2678
  }
2544
2679
  async function requireOrImportDefaultFunction(file, expectConstructor) {
2545
- let func = await import_common3.transform.requireOrImport(file);
2680
+ let func = await import_common4.transform.requireOrImport(file);
2546
2681
  if (func && typeof func === "object" && "default" in func)
2547
2682
  func = func["default"];
2548
2683
  if (typeof func !== "function")
2549
- throw (0, import_util4.errorWithFile)(file, `file must export a single ${expectConstructor ? "class" : "function"}.`);
2684
+ throw (0, import_util6.errorWithFile)(file, `file must export a single ${expectConstructor ? "class" : "function"}.`);
2550
2685
  return func;
2551
2686
  }
2552
2687
  function loadGlobalHook(config2, file) {
@@ -2585,7 +2720,7 @@ async function loadTestList(config2, filePath) {
2585
2720
  project = tokens[0].substring(1, tokens[0].length - 1);
2586
2721
  tokens.shift();
2587
2722
  }
2588
- return { project, file: toPosixPath((0, import_util4.parseLocationArg)(tokens[0]).file), titlePath: tokens.slice(1) };
2723
+ return { project, file: toPosixPath((0, import_util6.parseLocationArg)(tokens[0]).file), titlePath: tokens.slice(1) };
2589
2724
  });
2590
2725
  const testFilter = (test) => descriptions.some((d) => {
2591
2726
  const [projectName, , ...titles] = test.titlePath();
@@ -2602,14 +2737,14 @@ async function loadTestList(config2, filePath) {
2602
2737
  };
2603
2738
  return { testFilter, fileFilter };
2604
2739
  } catch (e) {
2605
- throw (0, import_util4.errorWithFile)(filePath, "Cannot read test list file: " + e.message);
2740
+ throw (0, import_util6.errorWithFile)(filePath, "Cannot read test list file: " + e.message);
2606
2741
  }
2607
2742
  }
2608
2743
 
2609
2744
  // packages/playwright/src/reporters/blob.ts
2610
2745
  var import_fs4 = __toESM(require("fs"));
2611
2746
  var import_path6 = __toESM(require("path"));
2612
- var import_stream = require("stream");
2747
+ var import_stream2 = require("stream");
2613
2748
  var import_coreBundle = require("playwright-core/lib/coreBundle");
2614
2749
 
2615
2750
  // packages/playwright/src/reporters/teleEmitter.ts
@@ -2621,7 +2756,7 @@ var TeleReporterEmitter = class {
2621
2756
  this._resultKnownErrorCounts = /* @__PURE__ */ new Map();
2622
2757
  // In case there is blob reporter and UI mode, make sure one doesn't override
2623
2758
  // the id assigned by the other.
2624
- this._idSymbol = Symbol("id");
2759
+ this._idSymbol = /* @__PURE__ */ Symbol("id");
2625
2760
  this._messageSink = messageSink;
2626
2761
  this._emitterOptions = options;
2627
2762
  }
@@ -2762,7 +2897,8 @@ var TeleReporterEmitter = class {
2762
2897
  globalSetup: config2.globalSetup,
2763
2898
  globalTeardown: config2.globalTeardown,
2764
2899
  tags: config2.tags,
2765
- webServer: config2.webServer
2900
+ webServer: config2.webServer,
2901
+ failOnFlakyTests: config2.failOnFlakyTests
2766
2902
  };
2767
2903
  }
2768
2904
  _serializeProject(suite) {
@@ -2955,7 +3091,7 @@ var BlobReporter = class extends TeleReporterEmitter {
2955
3091
  zipFile.addFile(originalPath, zipEntryPath);
2956
3092
  }
2957
3093
  const lines = this._messages.map((m) => JSON.stringify(m) + "\n");
2958
- const content = import_stream.Readable.from(lines);
3094
+ const content = import_stream2.Readable.from(lines);
2959
3095
  zipFile.addReadStream(content, "report.jsonl");
2960
3096
  zipFile.end();
2961
3097
  await finishPromise;
@@ -3089,14 +3225,17 @@ var empty_default = EmptyReporter;
3089
3225
 
3090
3226
  // packages/playwright/src/reporters/github.ts
3091
3227
  var import_path7 = __toESM(require("path"));
3092
- var import_util5 = require("../util");
3228
+ var import_util7 = require("../util");
3093
3229
  var { noColors: noColors2 } = require("playwright-core/lib/coreBundle").iso;
3094
3230
  var { msToString: msToString2 } = require("playwright-core/lib/coreBundle").iso;
3095
3231
  var GitHubLogger = class {
3232
+ newLine() {
3233
+ process.stdout.write("\n");
3234
+ }
3096
3235
  _log(message, type = "notice", options = {}) {
3097
3236
  message = message.replace(/\n/g, "%0A");
3098
3237
  const configs = Object.entries(options).map(([key, option]) => `${key}=${option}`).join(",");
3099
- process.stdout.write((0, import_util5.stripAnsiEscapes)(`::${type} ${configs}::${message}
3238
+ process.stdout.write((0, import_util7.stripAnsiEscapes)(`::${type} ${configs}::${message}
3100
3239
  `));
3101
3240
  }
3102
3241
  debug(message, options) {
@@ -3129,6 +3268,7 @@ var GitHubReporter = class extends TerminalReporter {
3129
3268
  if (!this._shouldPrintFailureAnnotations(test))
3130
3269
  return;
3131
3270
  this._failedTestCount++;
3271
+ this.githubLogger.newLine();
3132
3272
  for (const r of test.results)
3133
3273
  this._printFailureAnnotation(test, r, this._failedTestCount);
3134
3274
  }
@@ -3203,9 +3343,9 @@ __export(html_exports, {
3203
3343
  var import_fs5 = __toESM(require("fs"));
3204
3344
  var import_os = __toESM(require("os"));
3205
3345
  var import_path8 = __toESM(require("path"));
3206
- var import_stream2 = require("stream");
3346
+ var import_stream3 = require("stream");
3207
3347
  var babel2 = __toESM(require("../transform/babelBundle"));
3208
- var import_util6 = require("../util");
3348
+ var import_util8 = require("../util");
3209
3349
  var colors2 = require("playwright-core/lib/utilsBundle").colors;
3210
3350
  var mime2 = require("playwright-core/lib/utilsBundle").mime;
3211
3351
  var open = require("playwright-core/lib/utilsBundle").open;
@@ -3263,7 +3403,7 @@ var HtmlReporter = class {
3263
3403
  this.suite = suite;
3264
3404
  }
3265
3405
  _resolveOptions() {
3266
- const outputFolder = reportFolderFromEnv() ?? (0, import_util6.resolveReporterOutputPath)("playwright-report", this._options.configDir, this._options.outputFolder);
3406
+ const outputFolder = reportFolderFromEnv() ?? (0, import_util8.resolveReporterOutputPath)("playwright-report", this._options.configDir, this._options.outputFolder);
3267
3407
  return {
3268
3408
  outputFolder,
3269
3409
  open: getHtmlReportOptionProcessEnv() || this._options.open || "on-failure",
@@ -3293,10 +3433,12 @@ var HtmlReporter = class {
3293
3433
  const noSnippets = parseBooleanEnvVar("PLAYWRIGHT_HTML_NO_SNIPPETS") ?? this._options.noSnippets;
3294
3434
  const noCopyPrompt = parseBooleanEnvVar("PLAYWRIGHT_HTML_NO_COPY_PROMPT") ?? this._options.noCopyPrompt;
3295
3435
  const doNotInlineAssets = parseBooleanEnvVar("PLAYWRIGHT_HTML_DO_NOT_INLINE_ASSETS") ?? this._options.doNotInlineAssets ?? false;
3436
+ const mergeFiles = parseBooleanEnvVar("PLAYWRIGHT_HTML_MERGE_FILES") ?? this._options.mergeFiles;
3296
3437
  const builder = new HtmlBuilder(yazl2, this.config, this._outputFolder, this._attachmentsBaseURL, doNotInlineAssets, {
3297
3438
  title: process.env.PLAYWRIGHT_HTML_TITLE || this._options.title,
3298
3439
  noSnippets,
3299
- noCopyPrompt
3440
+ noCopyPrompt,
3441
+ mergeFiles
3300
3442
  });
3301
3443
  this._buildResult = await builder.build(this.config.metadata, projectSuites, result, this._topLevelErrors, this._machines);
3302
3444
  }
@@ -3343,7 +3485,7 @@ function parseBooleanEnvVar(name) {
3343
3485
  return void 0;
3344
3486
  }
3345
3487
  function standaloneDefaultFolder() {
3346
- return reportFolderFromEnv() ?? (0, import_util6.resolveReporterOutputPath)("playwright-report", process.cwd(), void 0);
3488
+ return reportFolderFromEnv() ?? (0, import_util8.resolveReporterOutputPath)("playwright-report", process.cwd(), void 0);
3347
3489
  }
3348
3490
  async function resolveReportFolder(reportPath) {
3349
3491
  const stat = await import_fs5.default.promises.stat(reportPath).catch(() => null);
@@ -3520,9 +3662,9 @@ var HtmlBuilder = class {
3520
3662
  }
3521
3663
  async _writeReportData(filePath) {
3522
3664
  import_fs5.default.appendFileSync(filePath, '<template id="playwrightReportBase64">data:application/zip;base64,');
3523
- await new Promise((f) => {
3665
+ await new Promise((resolve, reject) => {
3524
3666
  this._dataZipFile.end(void 0, () => {
3525
- this._dataZipFile.outputStream.pipe(new Base64Encoder()).pipe(import_fs5.default.createWriteStream(filePath, { flags: "a" })).on("close", f);
3667
+ this._dataZipFile.outputStream.pipe(new Base64Encoder()).pipe(import_fs5.default.createWriteStream(filePath, { flags: "a" })).on("close", resolve).on("error", reject);
3526
3668
  });
3527
3669
  });
3528
3670
  import_fs5.default.appendFileSync(filePath, "</template>");
@@ -3608,10 +3750,10 @@ var HtmlBuilder = class {
3608
3750
  this._hasTraces = true;
3609
3751
  if ((a.name === "stdout" || a.name === "stderr") && a.contentType === "text/plain") {
3610
3752
  if (lastAttachment && lastAttachment.name === a.name && lastAttachment.contentType === a.contentType) {
3611
- lastAttachment.body += (0, import_util6.stripAnsiEscapes)(a.body);
3753
+ lastAttachment.body += (0, import_util8.stripAnsiEscapes)(a.body);
3612
3754
  return null;
3613
3755
  }
3614
- a.body = (0, import_util6.stripAnsiEscapes)(a.body);
3756
+ a.body = (0, import_util8.stripAnsiEscapes)(a.body);
3615
3757
  lastAttachment = a;
3616
3758
  return a;
3617
3759
  }
@@ -3751,7 +3893,7 @@ var addStats = (stats, delta) => {
3751
3893
  stats.ok = stats.ok && delta.ok;
3752
3894
  return stats;
3753
3895
  };
3754
- var Base64Encoder = class extends import_stream2.Transform {
3896
+ var Base64Encoder = class extends import_stream3.Transform {
3755
3897
  _transform(chunk, encoding, callback) {
3756
3898
  if (this._remainder) {
3757
3899
  chunk = Buffer.concat([this._remainder, chunk]);
@@ -3842,7 +3984,7 @@ function createErrorCodeframe(message, location) {
3842
3984
  highlightCode: false,
3843
3985
  linesAbove: 100,
3844
3986
  linesBelow: 100,
3845
- message: (0, import_util6.stripAnsiEscapes)(message).split("\n")[0] || void 0
3987
+ message: (0, import_util8.stripAnsiEscapes)(message).split("\n")[0] || void 0
3846
3988
  }
3847
3989
  );
3848
3990
  }
@@ -3854,7 +3996,7 @@ var html_default = HtmlReporter;
3854
3996
  // packages/playwright/src/reporters/json.ts
3855
3997
  var import_fs6 = __toESM(require("fs"));
3856
3998
  var import_path9 = __toESM(require("path"));
3857
- var import_common4 = require("../common");
3999
+ var import_common5 = require("../common");
3858
4000
  var { MultiMap: MultiMap2 } = require("playwright-core/lib/coreBundle").iso;
3859
4001
  var { toPosixPath: toPosixPath3 } = require("playwright-core/lib/coreBundle").utils;
3860
4002
  var JSONReporter = class {
@@ -3891,7 +4033,7 @@ var JSONReporter = class {
3891
4033
  repeatEach: project.repeatEach,
3892
4034
  retries: project.retries,
3893
4035
  metadata: project.metadata,
3894
- id: import_common4.config.getProjectId(project),
4036
+ id: import_common5.config.getProjectId(project),
3895
4037
  name: project.name,
3896
4038
  testDir: toPosixPath3(project.testDir),
3897
4039
  testIgnore: serializePatterns(project.testIgnore),
@@ -3918,7 +4060,7 @@ var JSONReporter = class {
3918
4060
  _mergeSuites(suites) {
3919
4061
  const fileSuites = new MultiMap2();
3920
4062
  for (const projectSuite of suites) {
3921
- const projectId = import_common4.config.getProjectId(projectSuite.project());
4063
+ const projectId = import_common5.config.getProjectId(projectSuite.project());
3922
4064
  const projectName = projectSuite.project().name;
3923
4065
  for (const fileSuite of projectSuite.suites) {
3924
4066
  const file = fileSuite.location.file;
@@ -4072,7 +4214,7 @@ var json_default = JSONReporter;
4072
4214
  // packages/playwright/src/reporters/junit.ts
4073
4215
  var import_fs7 = __toESM(require("fs"));
4074
4216
  var import_path10 = __toESM(require("path"));
4075
- var import_util7 = require("../util");
4217
+ var import_util9 = require("../util");
4076
4218
  var { getAsBooleanFromENV } = require("playwright-core/lib/coreBundle").utils;
4077
4219
  var JUnitReporter = class {
4078
4220
  constructor(options) {
@@ -4238,7 +4380,7 @@ var JUnitReporter = class {
4238
4380
  entry.children.push({
4239
4381
  name: errorInfo.elementName,
4240
4382
  attributes: { message: errorInfo.message, type: errorInfo.type },
4241
- text: (0, import_util7.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4383
+ text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4242
4384
  });
4243
4385
  return errorInfo.elementName;
4244
4386
  }
@@ -4248,7 +4390,7 @@ var JUnitReporter = class {
4248
4390
  message: `${import_path10.default.basename(test.location.file)}:${test.location.line}:${test.location.column} ${test.title}`,
4249
4391
  type: "FAILURE"
4250
4392
  },
4251
- text: (0, import_util7.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4393
+ text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4252
4394
  });
4253
4395
  return "failure";
4254
4396
  }
@@ -4295,7 +4437,7 @@ Warning: attachment ${attachmentPath} is missing`);
4295
4437
  children: []
4296
4438
  };
4297
4439
  const stackTrace = result.error?.stack || result.error?.message || result.error?.value || "";
4298
- entry.children.push({ name: "stackTrace", text: (0, import_util7.stripAnsiEscapes)(stackTrace) });
4440
+ entry.children.push({ name: "stackTrace", text: (0, import_util9.stripAnsiEscapes)(stackTrace) });
4299
4441
  await this._appendStdIO(entry, [result]);
4300
4442
  return entry;
4301
4443
  }
@@ -4304,7 +4446,7 @@ function classifyResultError(result) {
4304
4446
  const error = result.error;
4305
4447
  if (!error)
4306
4448
  return null;
4307
- const rawMessage = (0, import_util7.stripAnsiEscapes)(error.message || error.value || "");
4449
+ const rawMessage = (0, import_util9.stripAnsiEscapes)(error.message || error.value || "");
4308
4450
  const nameMatch = rawMessage.match(/^(\w+): /);
4309
4451
  const errorName = nameMatch ? nameMatch[1] : "";
4310
4452
  const messageBody = nameMatch ? rawMessage.slice(nameMatch[0].length) : rawMessage;
@@ -4346,7 +4488,7 @@ function serializeXML(entry, tokens, stripANSIControlSequences) {
4346
4488
  var discouragedXMLCharacters = /[\u0000-\u0008\u000b-\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f]/g;
4347
4489
  function escape(text, stripANSIControlSequences, isCharacterData) {
4348
4490
  if (stripANSIControlSequences)
4349
- text = (0, import_util7.stripAnsiEscapes)(text);
4491
+ text = (0, import_util9.stripAnsiEscapes)(text);
4350
4492
  if (isCharacterData) {
4351
4493
  text = "<![CDATA[" + text.replace(/]]>/g, "]]&gt;") + "]]>";
4352
4494
  } else {
@@ -4468,7 +4610,7 @@ var LineReporter = class extends TerminalReporter {
4468
4610
  var line_default = LineReporter;
4469
4611
 
4470
4612
  // packages/playwright/src/reporters/list.ts
4471
- var import_util8 = require("../util");
4613
+ var import_util10 = require("../util");
4472
4614
  var { msToString: msToString3 } = require("playwright-core/lib/coreBundle").iso;
4473
4615
  var { getAsBooleanFromENV: getAsBooleanFromENV2 } = require("playwright-core/lib/coreBundle").utils;
4474
4616
  var DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === "win32" && process.env.TERM_PROGRAM !== "vscode" && !process.env.WT_SESSION;
@@ -4484,8 +4626,10 @@ var ListReporter = class extends TerminalReporter {
4484
4626
  this._resultIndex = /* @__PURE__ */ new Map();
4485
4627
  this._stepIndex = /* @__PURE__ */ new Map();
4486
4628
  this._needNewLine = false;
4629
+ this._failureIndex = 0;
4487
4630
  this._paused = /* @__PURE__ */ new Set();
4488
4631
  this._printSteps = getAsBooleanFromENV2("PLAYWRIGHT_LIST_PRINT_STEPS", options?.printSteps);
4632
+ this._printFailuresInline = getAsBooleanFromENV2("PLAYWRIGHT_LIST_PRINT_FAILURES_INLINE", options?.printFailuresInline);
4489
4633
  }
4490
4634
  onBegin(suite) {
4491
4635
  super.onBegin(suite);
@@ -4612,6 +4756,15 @@ var ListReporter = class extends TerminalReporter {
4612
4756
  const wasPaused = this._paused.delete(result);
4613
4757
  if (!wasPaused)
4614
4758
  this._updateTestLine(test, result);
4759
+ const isFailure = result.status !== "skipped" && result.status !== test.expectedStatus;
4760
+ if (!wasPaused && this._printFailuresInline && isFailure)
4761
+ this._printFailure(test);
4762
+ }
4763
+ _printFailure(test) {
4764
+ this._maybeWriteNewLine();
4765
+ const message = "\n" + this.formatFailure(test, ++this._failureIndex) + "\n";
4766
+ this._updateLineCountAndNewLineFlagForOutput(message);
4767
+ this.screen.stdout.write(message);
4615
4768
  }
4616
4769
  _updateTestLine(test, result) {
4617
4770
  const title = this.formatTestTitle(test);
@@ -4675,7 +4828,7 @@ var ListReporter = class extends TerminalReporter {
4675
4828
  this.screen.stdout.write(`\x1B[${this._lastRow - row}E`);
4676
4829
  }
4677
4830
  _testPrefix(index, statusMark) {
4678
- const statusMarkLength = (0, import_util8.stripAnsiEscapes)(statusMark).length;
4831
+ const statusMarkLength = (0, import_util10.stripAnsiEscapes)(statusMark).length;
4679
4832
  const indexLength = Math.ceil(Math.log10(this.totalTestCount + 1));
4680
4833
  return " " + statusMark + " ".repeat(3 - statusMarkLength) + this.screen.colors.dim(index.padStart(indexLength) + " ");
4681
4834
  }
@@ -4692,10 +4845,10 @@ var ListReporter = class extends TerminalReporter {
4692
4845
  async onEnd(result) {
4693
4846
  await super.onEnd(result);
4694
4847
  this.screen.stdout.write("\n");
4695
- this.epilogue(true);
4848
+ this.epilogue(!this._printFailuresInline);
4696
4849
  }
4697
4850
  };
4698
- var lastStepOrdinalSymbol = Symbol("lastStepOrdinal");
4851
+ var lastStepOrdinalSymbol = /* @__PURE__ */ Symbol("lastStepOrdinal");
4699
4852
  var list_default = ListReporter;
4700
4853
 
4701
4854
  // packages/playwright/src/reporters/listModeReporter.ts
@@ -5130,7 +5283,7 @@ function computeCommandHash(config2, runOptions) {
5130
5283
  // packages/playwright/src/runner/tasks.ts
5131
5284
  var import_fs11 = __toESM(require("fs"));
5132
5285
  var import_path15 = __toESM(require("path"));
5133
- var import_util11 = require("util");
5286
+ var import_util13 = require("util");
5134
5287
 
5135
5288
  // packages/playwright/src/runner/rebase.ts
5136
5289
  var import_fs9 = __toESM(require("fs"));
@@ -5284,7 +5437,7 @@ function applyPatchWithConflictMarkers(oldText, newText) {
5284
5437
  // packages/playwright/src/runner/workerHost.ts
5285
5438
  var import_fs10 = __toESM(require("fs"));
5286
5439
  var import_path13 = __toESM(require("path"));
5287
- var import_common5 = require("../common");
5440
+ var import_common6 = require("../common");
5288
5441
 
5289
5442
  // packages/playwright/src/isomorphic/folders.ts
5290
5443
  function artifactsFolderName(workerIndex) {
@@ -5320,8 +5473,8 @@ var WorkerHost = class extends ProcessHost {
5320
5473
  async start() {
5321
5474
  await import_fs10.default.promises.mkdir(this._params.artifactsDir, { recursive: true });
5322
5475
  return await this.startRunner(this._params, {
5323
- onStdOut: (chunk) => this.emit("stdOut", import_common5.ipc.stdioChunkToParams(chunk)),
5324
- onStdErr: (chunk) => this.emit("stdErr", import_common5.ipc.stdioChunkToParams(chunk))
5476
+ onStdOut: (chunk) => this.emit("stdOut", import_common6.ipc.stdioChunkToParams(chunk)),
5477
+ onStdErr: (chunk) => this.emit("stdErr", import_common6.ipc.stdioChunkToParams(chunk))
5325
5478
  });
5326
5479
  }
5327
5480
  async onExit() {
@@ -5353,16 +5506,17 @@ var WorkerHost = class extends ProcessHost {
5353
5506
  };
5354
5507
 
5355
5508
  // packages/playwright/src/runner/dispatcher.ts
5356
- var import_common6 = require("../common");
5357
- var import_util9 = require("../util");
5509
+ var import_common7 = require("../common");
5510
+ var import_util11 = require("../util");
5358
5511
  var colors4 = require("playwright-core/lib/utilsBundle").colors;
5359
5512
  var { ManualPromise: ManualPromise3 } = require("playwright-core/lib/coreBundle").iso;
5360
5513
  var { eventsHelper } = require("playwright-core/lib/coreBundle").utils;
5361
5514
  var Dispatcher = class {
5362
- constructor(testRun) {
5515
+ constructor(testRun, options = {}) {
5363
5516
  // Worker slot is claimed when it has jobDispatcher assigned.
5364
5517
  this._workerSlots = [];
5365
5518
  this._queue = [];
5519
+ this._isolatedJobs = /* @__PURE__ */ new Set();
5366
5520
  this._workerLimitPerProjectId = /* @__PURE__ */ new Map();
5367
5521
  this._queuedOrRunningHashCount = /* @__PURE__ */ new Map();
5368
5522
  this._finished = new ManualPromise3();
@@ -5370,6 +5524,7 @@ var Dispatcher = class {
5370
5524
  this._extraEnvByProjectId = /* @__PURE__ */ new Map();
5371
5525
  this._producedEnvByProjectId = /* @__PURE__ */ new Map();
5372
5526
  this._testRun = testRun;
5527
+ this._ignoreMaxFailures = !!options.ignoreMaxFailures;
5373
5528
  for (const project of testRun.config.projects) {
5374
5529
  if (project.workers)
5375
5530
  this._workerLimitPerProjectId.set(project.id, project.workers);
@@ -5378,6 +5533,8 @@ var Dispatcher = class {
5378
5533
  _findFirstJobToRun() {
5379
5534
  for (let index = 0; index < this._queue.length; index++) {
5380
5535
  const job = this._queue[index];
5536
+ if (this._isolatedJobs.has(job) && this._workerSlots.some((w) => !!w.jobDispatcher))
5537
+ continue;
5381
5538
  const projectIdWorkerLimit = this._workerLimitPerProjectId.get(job.projectId);
5382
5539
  if (!projectIdWorkerLimit)
5383
5540
  return index;
@@ -5401,7 +5558,7 @@ var Dispatcher = class {
5401
5558
  return;
5402
5559
  }
5403
5560
  this._queue.splice(jobIndex, 1);
5404
- const jobDispatcher = new JobDispatcher(job, this._testRun, () => this.stop().catch(() => {
5561
+ const jobDispatcher = new JobDispatcher(job, this._testRun, this._ignoreMaxFailures ? void 0 : () => this.stop().catch(() => {
5405
5562
  }));
5406
5563
  this._workerSlots[workerIndex].jobDispatcher = jobDispatcher;
5407
5564
  void this._runJobInWorker(workerIndex, jobDispatcher).then(() => {
@@ -5423,7 +5580,7 @@ var Dispatcher = class {
5423
5580
  }
5424
5581
  let startError;
5425
5582
  if (!worker) {
5426
- worker = this._createWorker(job, index, import_common6.ipc.serializeConfig(this._testRun.config, true));
5583
+ worker = this._createWorker(job, index, import_common7.ipc.serializeConfig(this._testRun.config, true));
5427
5584
  this._workerSlots[index].worker = worker;
5428
5585
  worker.on("exit", () => this._workerSlots[index].worker = void 0);
5429
5586
  startError = await worker.start();
@@ -5443,9 +5600,16 @@ var Dispatcher = class {
5443
5600
  );
5444
5601
  else if (this._isWorkerRedundant(worker))
5445
5602
  void worker.stop();
5446
- if (!this._isStopped && result.newJob) {
5447
- this._queue.unshift(result.newJob);
5448
- this._updateCounterForWorkerHash(result.newJob.workerHash, 1);
5603
+ if (!this._isStopped) {
5604
+ if (result.remainingJob) {
5605
+ this._queue.unshift(result.remainingJob);
5606
+ this._updateCounterForWorkerHash(result.remainingJob.workerHash, 1);
5607
+ }
5608
+ if (result.isolatedRetriesJob) {
5609
+ this._isolatedJobs.add(result.isolatedRetriesJob);
5610
+ this._queue.push(result.isolatedRetriesJob);
5611
+ this._updateCounterForWorkerHash(result.isolatedRetriesJob.workerHash, 1);
5612
+ }
5449
5613
  }
5450
5614
  }
5451
5615
  _checkFinished() {
@@ -5475,7 +5639,7 @@ var Dispatcher = class {
5475
5639
  this._updateCounterForWorkerHash(group.workerHash, 1);
5476
5640
  this._isStopped = false;
5477
5641
  this._workerSlots = [];
5478
- if (this._testRun.hasReachedMaxFailures())
5642
+ if (!this._ignoreMaxFailures && this._testRun.hasReachedMaxFailures())
5479
5643
  void this.stop();
5480
5644
  for (let i = 0; i < this._testRun.config.config.workers; i++)
5481
5645
  this._workerSlots.push({});
@@ -5548,7 +5712,7 @@ var Dispatcher = class {
5548
5712
  }
5549
5713
  };
5550
5714
  var JobDispatcher = class {
5551
- constructor(job, testRun, stopCallback) {
5715
+ constructor(job, testRun, onMaxFailuresReached) {
5552
5716
  this.jobResult = new ManualPromise3();
5553
5717
  this._listeners = [];
5554
5718
  this._failedTests = /* @__PURE__ */ new Set();
@@ -5559,9 +5723,12 @@ var JobDispatcher = class {
5559
5723
  this._workerIndex = 0;
5560
5724
  this.job = job;
5561
5725
  this._testRun = testRun;
5562
- this._stopCallback = stopCallback;
5726
+ this._onMaxFailuresReached = onMaxFailuresReached;
5563
5727
  this._remainingByTestId = new Map(this.job.tests.map((e) => [e.id, e]));
5564
5728
  }
5729
+ _isStoppedByMaxFailures() {
5730
+ return !!this._onMaxFailuresReached && this._testRun.hasReachedMaxFailures();
5731
+ }
5565
5732
  _onTestBegin(params) {
5566
5733
  const test = this._remainingByTestId.get(params.testId);
5567
5734
  if (!test) {
@@ -5576,7 +5743,7 @@ var JobDispatcher = class {
5576
5743
  this._currentlyRunning = { test, result };
5577
5744
  }
5578
5745
  _onTestEnd(params) {
5579
- if (this._testRun.hasReachedMaxFailures()) {
5746
+ if (this._isStoppedByMaxFailures()) {
5580
5747
  params.status = "interrupted";
5581
5748
  params.errors = [];
5582
5749
  }
@@ -5696,7 +5863,7 @@ var JobDispatcher = class {
5696
5863
  for (const test of this._remainingByTestId.values()) {
5697
5864
  if (!testIds.has(test.id))
5698
5865
  continue;
5699
- if (!this._testRun.hasReachedMaxFailures()) {
5866
+ if (!this._isStoppedByMaxFailures()) {
5700
5867
  this._failTestWithErrors(test, errors);
5701
5868
  errors = [];
5702
5869
  }
@@ -5755,12 +5922,18 @@ var JobDispatcher = class {
5755
5922
  serialSuite.allTests().forEach((test) => retryCandidates.add(test));
5756
5923
  }
5757
5924
  const remaining = [...this._remainingByTestId.values()];
5925
+ const isolatedRetries = [];
5758
5926
  for (const test of retryCandidates) {
5759
- if (test.results.length < test.retries + 1)
5760
- remaining.push(test);
5927
+ if (test.results.length < test.retries + 1) {
5928
+ if (this._testRun.config.retryStrategy === "immediate")
5929
+ remaining.push(test);
5930
+ else
5931
+ isolatedRetries.push(test);
5932
+ }
5761
5933
  }
5762
- const newJob = remaining.length ? { ...this.job, tests: remaining } : void 0;
5763
- this._finished({ didFail: true, newJob });
5934
+ const remainingJob = remaining.length ? { ...this.job, tests: remaining } : void 0;
5935
+ const isolatedRetriesJob = isolatedRetries.length ? { ...this.job, tests: isolatedRetries } : void 0;
5936
+ this._finished({ didFail: true, remainingJob, isolatedRetriesJob });
5764
5937
  }
5765
5938
  onExit(data) {
5766
5939
  const unexpectedExitError = data.unexpectedly ? {
@@ -5778,7 +5951,7 @@ var JobDispatcher = class {
5778
5951
  const runPayload = {
5779
5952
  file: this.job.requireFile,
5780
5953
  entries: this.job.tests.map((test) => {
5781
- return { testId: test.id, retry: test.results.length };
5954
+ return { testId: test.id, retry: test.results.length, planAnnotations: test._planAnnotations };
5782
5955
  })
5783
5956
  };
5784
5957
  worker.runTestGroup(runPayload);
@@ -5807,7 +5980,7 @@ var JobDispatcher = class {
5807
5980
  addLocationAndSnippetToError(this._testRun.config.config, response.error);
5808
5981
  return response;
5809
5982
  } catch (e) {
5810
- const error = (0, import_util9.serializeError)(e);
5983
+ const error = (0, import_util11.serializeError)(e);
5811
5984
  addLocationAndSnippetToError(this._testRun.config.config, error);
5812
5985
  return { response: void 0, error };
5813
5986
  }
@@ -5822,7 +5995,7 @@ var JobDispatcher = class {
5822
5995
  }
5823
5996
  skipWholeJob() {
5824
5997
  const allTestsSkipped = this.job.tests.every((test) => test.expectedStatus === "skipped");
5825
- if (allTestsSkipped && !this._testRun.hasReachedMaxFailures()) {
5998
+ if (allTestsSkipped && !this._isStoppedByMaxFailures()) {
5826
5999
  for (const test of this.job.tests) {
5827
6000
  const result = test._appendTestResult();
5828
6001
  this._testRun.reporter.onTestBegin?.(test, result);
@@ -5839,11 +6012,11 @@ var JobDispatcher = class {
5839
6012
  }
5840
6013
  _reportTestEnd(test, result) {
5841
6014
  this._testRun.reporter.onTestEnd?.(test, result);
5842
- const hadMaxFailures = this._testRun.hasReachedMaxFailures();
6015
+ const hadMaxFailures = this._isStoppedByMaxFailures();
5843
6016
  if (test.outcome() === "unexpected" && test.results.length > test.retries)
5844
6017
  ++this._testRun.failedTestCount;
5845
- if (!hadMaxFailures && this._testRun.hasReachedMaxFailures()) {
5846
- this._stopCallback();
6018
+ if (!hadMaxFailures && this._isStoppedByMaxFailures()) {
6019
+ this._onMaxFailuresReached?.();
5847
6020
  this._testRun.reporter.onError?.({ message: colors4.red(`Testing stopped early after ${this._testRun.config.config.maxFailures} maximum allowed failures.`) });
5848
6021
  }
5849
6022
  }
@@ -5926,7 +6099,7 @@ var FixedNodeSIGINTHandler = class {
5926
6099
  };
5927
6100
 
5928
6101
  // packages/playwright/src/runner/taskRunner.ts
5929
- var import_util10 = require("../util");
6102
+ var import_util12 = require("../util");
5930
6103
  var colors5 = require("playwright-core/lib/utilsBundle").colors;
5931
6104
  var debug4 = require("playwright-core/lib/utilsBundle").debug;
5932
6105
  var { ManualPromise: ManualPromise4 } = require("playwright-core/lib/coreBundle").iso;
@@ -5967,7 +6140,7 @@ var TaskRunner = class _TaskRunner {
5967
6140
  await task.setup?.(context, errors, softErrors);
5968
6141
  } catch (e) {
5969
6142
  debug4("pw:test:task")(`error in "${task.title}": `, e);
5970
- errors.push((0, import_util10.serializeError)(e));
6143
+ errors.push((0, import_util12.serializeError)(e));
5971
6144
  } finally {
5972
6145
  for (const error of [...softErrors, ...errors])
5973
6146
  this._reporter.onError?.(error);
@@ -6030,7 +6203,7 @@ var TimeoutWatcher = class {
6030
6203
  // packages/playwright/src/runner/vcs.ts
6031
6204
  var import_child_process2 = __toESM(require("child_process"));
6032
6205
  var import_path14 = __toESM(require("path"));
6033
- var import_common7 = require("../common");
6206
+ var import_common8 = require("../common");
6034
6207
  async function detectChangedTestFiles(baseCommit, configDir) {
6035
6208
  function gitFileList(args) {
6036
6209
  try {
@@ -6062,17 +6235,17 @@ async function detectChangedTestFiles(baseCommit, configDir) {
6062
6235
  const untrackedFiles = gitFileList(["ls-files", "--others", "--exclude-standard"]).map((file) => import_path14.default.join(configDir, file));
6063
6236
  const [gitRoot] = gitFileList(["rev-parse", "--show-toplevel"]);
6064
6237
  const trackedFilesWithChanges = gitFileList(["diff", baseCommit, "--name-only"]).map((file) => import_path14.default.join(gitRoot, file));
6065
- return new Set(import_common7.cc.affectedTestFiles([...untrackedFiles, ...trackedFilesWithChanges]));
6238
+ return new Set(import_common8.cc.affectedTestFiles([...untrackedFiles, ...trackedFilesWithChanges]));
6066
6239
  }
6067
6240
 
6068
6241
  // packages/playwright/src/runner/tasks.ts
6069
- var import_common8 = require("../common");
6070
- var import_util12 = require("../util");
6242
+ var import_common9 = require("../common");
6243
+ var import_util14 = require("../util");
6071
6244
  var debug5 = require("playwright-core/lib/utilsBundle").debug;
6072
6245
  var { ManualPromise: ManualPromise5 } = require("playwright-core/lib/coreBundle").iso;
6073
6246
  var { monotonicTime: monotonicTime6 } = require("playwright-core/lib/coreBundle").iso;
6074
6247
  var { removeFolders: removeFolders4 } = require("playwright-core/lib/coreBundle").utils;
6075
- var readDirAsync2 = (0, import_util11.promisify)(import_fs11.default.readdir);
6248
+ var readDirAsync2 = (0, import_util13.promisify)(import_fs11.default.readdir);
6076
6249
  var TestRun = class {
6077
6250
  constructor(config2, reporter, options) {
6078
6251
  this.rootSuite = void 0;
@@ -6100,7 +6273,7 @@ var TestRun = class {
6100
6273
  result() {
6101
6274
  const hasFailedTests = this.rootSuite?.allTests().some((test) => !test.ok());
6102
6275
  const hasFlakyTests = this.rootSuite?.allTests().some((test) => test.outcome() === "flaky");
6103
- return this.hasWorkerErrors || this.hasReachedMaxFailures() || hasFailedTests || this.config.failOnFlakyTests && hasFlakyTests ? "failed" : "passed";
6276
+ return this.hasWorkerErrors || this.reporter.hasReporterErrors() || this.hasReachedMaxFailures() || hasFailedTests || this.config.config.failOnFlakyTests && hasFlakyTests ? "failed" : "passed";
6104
6277
  }
6105
6278
  };
6106
6279
  async function runTasks(testRun, tasks, globalTimeout, cancelPromise) {
@@ -6127,6 +6300,8 @@ async function finishTaskRun(testRun, status) {
6127
6300
  if (modifiedResult && modifiedResult.status)
6128
6301
  status = modifiedResult.status;
6129
6302
  await testRun.reporter.onExit();
6303
+ if (status === "passed" && testRun.reporter.hasReporterErrors())
6304
+ status = "failed";
6130
6305
  return status;
6131
6306
  }
6132
6307
  function createGlobalSetupTasks(config2) {
@@ -6149,7 +6324,7 @@ function createClearCacheTask(config2) {
6149
6324
  return {
6150
6325
  title: "clear cache",
6151
6326
  setup: async () => {
6152
- await (0, import_util12.removeDirAndLogToConsole)(import_common8.cc.cacheDir);
6327
+ await (0, import_util14.removeDirAndLogToConsole)(import_common9.cc.cacheDir);
6153
6328
  for (const plugin of config2.plugins)
6154
6329
  await plugin.instance?.clearCache?.();
6155
6330
  }
@@ -6248,12 +6423,12 @@ function createListFilesTask() {
6248
6423
  await createRootSuite(testRun, errors, false);
6249
6424
  await collectProjectsAndTestFiles(testRun, false);
6250
6425
  for (const [project, files] of testRun.projectFiles) {
6251
- const projectSuite = new import_common8.test.Suite(project.project.name, "project");
6426
+ const projectSuite = new import_common9.test.Suite(project.project.name, "project");
6252
6427
  projectSuite._fullProject = project;
6253
6428
  testRun.rootSuite._addSuite(projectSuite);
6254
6429
  const suites = files.map((file) => {
6255
6430
  const title = import_path15.default.relative(testRun.config.config.rootDir, file);
6256
- const suite = new import_common8.test.Suite(title, "file");
6431
+ const suite = new import_common9.test.Suite(title, "file");
6257
6432
  suite.location = { file, line: 0, column: 0 };
6258
6433
  projectSuite._addSuite(suite);
6259
6434
  return suite;
@@ -6268,7 +6443,7 @@ function createLoadTask(mode, options) {
6268
6443
  title: "load tests",
6269
6444
  setup: async (testRun, errors, softErrors) => {
6270
6445
  if (testRun.options.locations?.length) {
6271
- const { testFilter, fileFilter } = import_common8.suiteUtils.createFiltersFromArguments(testRun.options.locations);
6446
+ const { testFilter, fileFilter } = import_common9.suiteUtils.createFiltersFromArguments(testRun.options.locations);
6272
6447
  testRun.loadFileFilters.push(fileFilter);
6273
6448
  testRun.preOnlyTestFilters.push(testFilter);
6274
6449
  }
@@ -6282,14 +6457,14 @@ function createLoadTask(mode, options) {
6282
6457
  testRun.preOnlyTestFilters.push((test) => !testFilter(test));
6283
6458
  }
6284
6459
  if (testRun.options.grep || testRun.options.grepInvert) {
6285
- const grepMatcher = testRun.options.grep ? (0, import_util12.createTitleMatcher)((0, import_util12.forceRegExp)(testRun.options.grep)) : () => true;
6286
- const grepInvertMatcher = testRun.options.grepInvert ? (0, import_util12.createTitleMatcher)((0, import_util12.forceRegExp)(testRun.options.grepInvert)) : () => false;
6460
+ const grepMatcher = testRun.options.grep ? (0, import_util14.createTitleMatcher)((0, import_util14.forceRegExp)(testRun.options.grep)) : () => true;
6461
+ const grepInvertMatcher = testRun.options.grepInvert ? (0, import_util14.createTitleMatcher)((0, import_util14.forceRegExp)(testRun.options.grepInvert)) : () => false;
6287
6462
  testRun.preOnlyTestFilters.push((test) => {
6288
6463
  const grepTitle = test._grepTitleWithTags();
6289
6464
  return !grepInvertMatcher(grepTitle) && grepMatcher(grepTitle);
6290
6465
  });
6291
6466
  }
6292
- if (testRun.options.lastFailedTestIds?.length) {
6467
+ if (testRun.options.lastFailedTestIds) {
6293
6468
  const failedTestIds = new Set(testRun.options.lastFailedTestIds);
6294
6469
  testRun.postShardTestFilters.push((test) => failedTestIds.has(test.id));
6295
6470
  }
@@ -6337,6 +6512,7 @@ function createPhasesTask() {
6337
6512
  const projectToSuite = new Map(testRun.rootSuite.suites.map((suite) => [suite._fullProject, suite]));
6338
6513
  const allProjects = [...projectToSuite.keys()];
6339
6514
  const teardownToSetups = buildTeardownToSetupsMap(allProjects);
6515
+ const ignoreMaxFailuresProjectIds = new Set(testRun.config.config.maxFailures > 0 ? [...teardownToSetups.keys()].map((project) => project.id) : []);
6340
6516
  const teardownToSetupsDependents = /* @__PURE__ */ new Map();
6341
6517
  for (const [teardown, setups] of teardownToSetups) {
6342
6518
  const closure = buildDependentProjects(setups, allProjects);
@@ -6355,11 +6531,14 @@ function createPhasesTask() {
6355
6531
  }
6356
6532
  for (const project of phaseProjects)
6357
6533
  processed.add(project);
6358
- if (phaseProjects.length) {
6534
+ for (const ignoreMaxFailures of [false, true]) {
6535
+ const projects = phaseProjects.filter((project) => ignoreMaxFailuresProjectIds.has(project.id) === ignoreMaxFailures);
6536
+ if (!projects.length)
6537
+ continue;
6359
6538
  let testGroupsInPhase = 0;
6360
- const phase = { dispatcher: new Dispatcher(testRun), projects: [] };
6539
+ const phase = { dispatcher: new Dispatcher(testRun, { ignoreMaxFailures }), projects: [] };
6361
6540
  testRun.phases.push(phase);
6362
- for (const project of phaseProjects) {
6541
+ for (const project of projects) {
6363
6542
  const projectSuite = projectToSuite.get(project);
6364
6543
  const testGroups = createTestGroups(projectSuite, testRun.config.config.workers);
6365
6544
  phase.projects.push({ project, projectSuite, testGroups });
@@ -6421,20 +6600,25 @@ function createRunTestsTask() {
6421
6600
  var import_fs12 = __toESM(require("fs"));
6422
6601
  var import_path16 = __toESM(require("path"));
6423
6602
  var LastRunReporter = class {
6424
- constructor(filteredProjects, listMode) {
6603
+ constructor(filteredProjects, listMode, lastFailedFileOverride) {
6425
6604
  this._listMode = !!listMode;
6426
- const [project] = filteredProjects;
6427
- if (project)
6428
- this._lastRunFile = import_path16.default.join(project.project.outputDir, ".last-run.json");
6605
+ const override = lastFailedFileOverride ?? process.env.PLAYWRIGHT_LAST_RUN_OUTPUT_FILE;
6606
+ if (override) {
6607
+ this._lastRunFile = import_path16.default.resolve(process.cwd(), override);
6608
+ } else {
6609
+ const [project] = filteredProjects;
6610
+ if (project)
6611
+ this._lastRunFile = import_path16.default.join(project.project.outputDir, ".last-run.json");
6612
+ }
6429
6613
  }
6430
6614
  async filterLastFailed() {
6431
6615
  if (!this._lastRunFile)
6432
- return [];
6616
+ return void 0;
6433
6617
  try {
6434
6618
  const lastRunInfo = JSON.parse(await import_fs12.default.promises.readFile(this._lastRunFile, "utf8"));
6435
6619
  return lastRunInfo.failedTests;
6436
6620
  } catch {
6437
- return [];
6621
+ return void 0;
6438
6622
  }
6439
6623
  }
6440
6624
  version() {
@@ -6480,7 +6664,7 @@ var TestRunner = class extends import_events2.default {
6480
6664
  this._configCLIOverrides = configCLIOverrides;
6481
6665
  this._watcher = new FSWatcher((events) => {
6482
6666
  const collector = /* @__PURE__ */ new Set();
6483
- events.forEach((f) => import_common9.cc.collectAffectedTestFiles(f.file, collector));
6667
+ events.forEach((f) => import_common10.cc.collectAffectedTestFiles(f.file, collector));
6484
6668
  this.emit(TestRunnerEvent.TestFilesChanged, [...collector]);
6485
6669
  });
6486
6670
  }
@@ -6649,7 +6833,8 @@ var TestRunner = class extends import_events2.default {
6649
6833
  },
6650
6834
  ...params.updateSnapshots ? { updateSnapshots: params.updateSnapshots } : {},
6651
6835
  ...params.updateSourceMethod ? { updateSourceMethod: params.updateSourceMethod } : {},
6652
- ...params.workers ? { workers: params.workers } : {}
6836
+ ...params.workers ? { workers: params.workers } : {},
6837
+ ...params.maxFailures ? { maxFailures: params.maxFailures } : {}
6653
6838
  };
6654
6839
  const config2 = await this._loadConfigOrReportError(new InternalReporter([userReporter]), overrides);
6655
6840
  if (!config2)
@@ -6689,7 +6874,7 @@ var TestRunner = class extends import_events2.default {
6689
6874
  this._watchedTestDependencies = /* @__PURE__ */ new Set();
6690
6875
  for (const fileName of fileNames) {
6691
6876
  this._watchedTestDependencies.add(fileName);
6692
- import_common9.cc.dependenciesForTestFile(fileName).forEach((file) => this._watchedTestDependencies.add(file));
6877
+ import_common10.cc.dependenciesForTestFile(fileName).forEach((file) => this._watchedTestDependencies.add(file));
6693
6878
  }
6694
6879
  await this._updateWatcher(true);
6695
6880
  }
@@ -6705,7 +6890,7 @@ var TestRunner = class extends import_events2.default {
6705
6890
  ]);
6706
6891
  if (status !== "passed")
6707
6892
  return { errors: errorReporter.errors(), testFiles: [] };
6708
- return { testFiles: import_common9.cc.affectedTestFiles(files) };
6893
+ return { testFiles: import_common10.cc.affectedTestFiles(files) };
6709
6894
  }
6710
6895
  async stopTests() {
6711
6896
  this._testRun?.stop?.resolve();
@@ -6719,7 +6904,7 @@ var TestRunner = class extends import_events2.default {
6719
6904
  }
6720
6905
  async _loadConfig(overrides) {
6721
6906
  try {
6722
- const config2 = await import_common9.configLoader.loadConfig(this.configLocation, overrides);
6907
+ const config2 = await import_common10.configLoader.loadConfig(this.configLocation, overrides);
6723
6908
  if (!this._plugins) {
6724
6909
  webServerPluginsForConfig(config2).forEach((p) => config2.plugins.push({ factory: p }));
6725
6910
  addGitCommitInfoPlugin(config2);
@@ -6727,11 +6912,15 @@ var TestRunner = class extends import_events2.default {
6727
6912
  } else {
6728
6913
  config2.plugins.splice(0, config2.plugins.length, ...this._plugins);
6729
6914
  }
6915
+ this._lastLoadedConfig = config2;
6730
6916
  return { config: config2 };
6731
6917
  } catch (e) {
6732
- return { config: null, error: (0, import_util13.serializeError)(e) };
6918
+ return { config: null, error: (0, import_util15.serializeError)(e) };
6733
6919
  }
6734
6920
  }
6921
+ lastLoadedConfig() {
6922
+ return this._lastLoadedConfig;
6923
+ }
6735
6924
  async _loadConfigOrReportError(reporter, overrides) {
6736
6925
  const { config: config2, error } = await this._loadConfig(overrides);
6737
6926
  if (config2)
@@ -6764,10 +6953,10 @@ async function runAllTestsWithConfig(config2, options) {
6764
6953
  webServerPluginsForConfig(config2).forEach((p) => config2.plugins.push({ factory: p }));
6765
6954
  const filteredProjects = filterProjects(config2.projects, options.projectFilter);
6766
6955
  const reporters = await createReporters(config2, options.listMode ? "list" : "test", void 0, options);
6767
- const lastRun = new LastRunReporter(filteredProjects, options.listMode);
6956
+ const lastRun = new LastRunReporter(filteredProjects, options.listMode, options.lastFailedFile);
6768
6957
  if (options.lastFailed) {
6769
6958
  const lastFailedTestIds = await lastRun.filterLastFailed();
6770
- if (lastFailedTestIds.length)
6959
+ if (lastFailedTestIds)
6771
6960
  options = { ...options, lastFailedTestIds };
6772
6961
  }
6773
6962
  const reporter = new InternalReporter([...reporters, lastRun]);
@@ -6794,9 +6983,9 @@ __export(testServer_exports, {
6794
6983
  runTestServer: () => runTestServer,
6795
6984
  runUIMode: () => runUIMode
6796
6985
  });
6797
- var import_util14 = __toESM(require("util"));
6986
+ var import_util16 = __toESM(require("util"));
6798
6987
  var import_coreBundle3 = require("playwright-core/lib/coreBundle");
6799
- var import_common10 = require("../common");
6988
+ var import_common11 = require("../common");
6800
6989
 
6801
6990
  // packages/playwright/src/runner/uiModeReporter.ts
6802
6991
  var UIModeReporter = class extends TeleReporterEmitter {
@@ -6824,7 +7013,23 @@ var TestServer = class {
6824
7013
  }
6825
7014
  async start(options) {
6826
7015
  this._dispatcher = new TestServerDispatcher(this._configLocation, this._configCLIOverrides);
6827
- return await import_coreBundle3.server.startTraceViewerServer({ ...options, transport: this._dispatcher.transport });
7016
+ return await import_coreBundle3.server.startTraceViewerServer({
7017
+ host: options.host,
7018
+ port: options.port,
7019
+ allowedFileRoots: () => this._allowedFileRoots(),
7020
+ transport: this._dispatcher.transport
7021
+ });
7022
+ }
7023
+ _allowedFileRoots() {
7024
+ const roots = /* @__PURE__ */ new Set([process.cwd(), this._configLocation.configDir]);
7025
+ const config2 = this._dispatcher?._testRunner.lastLoadedConfig();
7026
+ if (config2) {
7027
+ for (const project of config2.projects) {
7028
+ roots.add(project.project.outputDir);
7029
+ roots.add(project.project.testDir);
7030
+ }
7031
+ }
7032
+ return [...roots];
6828
7033
  }
6829
7034
  async stop() {
6830
7035
  await this._dispatcher?.stop();
@@ -6938,7 +7143,7 @@ var TestServerDispatcher = class {
6938
7143
  if (interceptStdio) {
6939
7144
  if (debug6.log === originalDebugLog) {
6940
7145
  debug6.log = (...args) => {
6941
- const string = import_util14.default.format(...args) + "\n";
7146
+ const string = import_util16.default.format(...args) + "\n";
6942
7147
  return originalStderrWrite.apply(process.stderr, [string]);
6943
7148
  };
6944
7149
  }
@@ -6962,7 +7167,7 @@ var TestServerDispatcher = class {
6962
7167
  }
6963
7168
  };
6964
7169
  async function runUIMode(configFile, configCLIOverrides, options) {
6965
- const configLocation = import_common10.configLoader.resolveConfigLocation(configFile);
7170
+ const configLocation = import_common11.configLoader.resolveConfigLocation(configFile);
6966
7171
  return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server, cancelPromise) => {
6967
7172
  await import_coreBundle3.server.installRootRedirect(server, void 0, { ...options, webApp: "uiMode.html" });
6968
7173
  if (options.host !== void 0 || options.port !== void 0) {
@@ -6981,7 +7186,7 @@ async function runUIMode(configFile, configCLIOverrides, options) {
6981
7186
  });
6982
7187
  }
6983
7188
  async function installedChromiumChannelForUI(configLocation, configCLIOverrides) {
6984
- const config2 = await import_common10.configLoader.loadConfig(configLocation, configCLIOverrides).catch((e) => null);
7189
+ const config2 = await import_common11.configLoader.loadConfig(configLocation, configCLIOverrides).catch((e) => null);
6985
7190
  if (!config2)
6986
7191
  return void 0;
6987
7192
  if (config2.projects.some((p) => (!p.project.use.browserName || p.project.use.browserName === "chromium") && !p.project.use.channel))
@@ -6993,7 +7198,7 @@ async function installedChromiumChannelForUI(configLocation, configCLIOverrides)
6993
7198
  return void 0;
6994
7199
  }
6995
7200
  async function runTestServer(configFile, configCLIOverrides, options) {
6996
- const configLocation = import_common10.configLoader.resolveConfigLocation(configFile);
7201
+ const configLocation = import_common11.configLoader.resolveConfigLocation(configFile);
6997
7202
  return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server) => {
6998
7203
  console.log("Listening on " + server.urlPrefix("precise").replace("http:", "ws:") + "/" + server.wsGuid());
6999
7204
  });
@@ -7033,11 +7238,11 @@ __export(watchMode_exports, {
7033
7238
  });
7034
7239
  var import_path18 = __toESM(require("path"));
7035
7240
  var import_readline = __toESM(require("readline"));
7036
- var import_stream3 = require("stream");
7241
+ var import_events3 = require("events");
7037
7242
  var import_coreBundle4 = require("playwright-core/lib/coreBundle");
7038
7243
 
7039
7244
  // packages/playwright/src/isomorphic/testTree.ts
7040
- var statusEx = Symbol("statusEx");
7245
+ var statusEx = /* @__PURE__ */ Symbol("statusEx");
7041
7246
 
7042
7247
  // packages/playwright/src/isomorphic/teleSuiteUpdater.ts
7043
7248
  var TeleSuiteUpdater = class {
@@ -7380,7 +7585,7 @@ var { ManualPromise: ManualPromise8 } = require("playwright-core/lib/coreBundle"
7380
7585
  var { createGuid: createGuid3 } = require("playwright-core/lib/coreBundle").utils;
7381
7586
  var { getPackageManagerExecCommand: getPackageManagerExecCommand3 } = require("playwright-core/lib/coreBundle").utils;
7382
7587
  var { eventsHelper: eventsHelper2 } = require("playwright-core/lib/coreBundle").utils;
7383
- var InMemoryTransport = class extends import_stream3.EventEmitter {
7588
+ var InMemoryTransport = class extends import_events3.EventEmitter {
7384
7589
  constructor(send) {
7385
7590
  super();
7386
7591
  this._send = send;
@@ -7780,7 +7985,7 @@ var JsonStringInternalizer = class {
7780
7985
  };
7781
7986
 
7782
7987
  // packages/playwright/src/reporters/merge.ts
7783
- var import_util15 = require("../util");
7988
+ var import_util17 = require("../util");
7784
7989
  var { isPathInside } = require("playwright-core/lib/coreBundle").utils;
7785
7990
  var { ZipFile } = require("playwright-core/lib/coreBundle").utils;
7786
7991
  async function createMergedReport(config2, dir, reporterDescriptions, rootDirOverride) {
@@ -7845,6 +8050,7 @@ async function createMergedReport(config2, dir, reporterDescriptions, rootDirOve
7845
8050
  });
7846
8051
  }
7847
8052
  await dispatchEvents(eventData.epilogue);
8053
+ return multiplexer.hasReporterErrors() ? "failed" : "passed";
7848
8054
  }
7849
8055
  var commonEventNames = ["onBlobReportMetadata", "onConfigure", "onProject", "onBegin", "onEnd"];
7850
8056
  var commonEvents = new Set(commonEventNames);
@@ -7875,7 +8081,7 @@ async function extractAndParseReports(dir, shardFiles, internalizer, printStatus
7875
8081
  const reportNames = new UniqueFileNameGenerator();
7876
8082
  for (const file of shardFiles) {
7877
8083
  const absolutePath = import_path19.default.join(dir, file);
7878
- printStatus(`extracting: ${(0, import_util15.relativeFilePath)(absolutePath)}`);
8084
+ printStatus(`extracting: ${(0, import_util17.relativeFilePath)(absolutePath)}`);
7879
8085
  const zipFile = new ZipFile(absolutePath);
7880
8086
  const entryNames = await zipFile.entries();
7881
8087
  for (const entryName of entryNames.sort()) {