@smoothdeploy/playwright 1.62.1 → 1.63.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.
@@ -53,9 +53,7 @@ __export(testRunner_exports, {
53
53
  runAllTestsWithConfig: () => runAllTestsWithConfig
54
54
  });
55
55
  var import_events2 = __toESM(require("events"));
56
- var import_fs13 = __toESM(require("fs"));
57
- var import_path17 = __toESM(require("path"));
58
- var import_coreBundle2 = require("playwright-core/lib/coreBundle");
56
+ var import_coreBundle3 = require("playwright-core/lib/coreBundle");
59
57
  var import_common10 = require("../common");
60
58
 
61
59
  // packages/playwright/src/runner/fsWatcher.ts
@@ -81,14 +79,21 @@ var FSWatcher = class {
81
79
  this._throttleTimer = void 0;
82
80
  if (!this._watchedPaths.length)
83
81
  return;
84
- const ignored = [...this._ignoredFolders, "**/node_modules/**"];
82
+ const ignoredPrefixes = this._ignoredFolders.map((folder) => folder.replace(/\\/g, "/") + "/");
83
+ const ignored = (file) => {
84
+ if (file.split("/").includes("node_modules"))
85
+ return true;
86
+ return ignoredPrefixes.some((prefix) => (file + "/").startsWith(prefix));
87
+ };
85
88
  this._fsWatcher = chokidar.watch(watchedPaths, { ignoreInitial: true, ignored }).on("all", async (event, file) => {
89
+ if (event !== "add" && event !== "addDir" && event !== "change" && event !== "unlink" && event !== "unlinkDir")
90
+ return;
86
91
  if (this._throttleTimer)
87
92
  clearTimeout(this._throttleTimer);
88
93
  this._collector.push({ event, file });
89
94
  this._throttleTimer = setTimeout(() => this._reportEventsIfAny(), 250);
90
95
  });
91
- await new Promise((resolve, reject) => this._fsWatcher.once("ready", resolve).once("error", reject));
96
+ await new Promise((resolve, reject) => this._fsWatcher.once("ready", () => resolve()).once("error", reject));
92
97
  }
93
98
  async close() {
94
99
  await this._fsWatcher?.close();
@@ -498,7 +503,9 @@ var TeleTestStep = class {
498
503
  this.steps = [];
499
504
  this._startTime = 0;
500
505
  this.title = payload.title;
506
+ this.subtitle = payload.subtitle;
501
507
  this.category = payload.category;
508
+ this.params = payload.params;
502
509
  this.location = location;
503
510
  this.parent = parentStep;
504
511
  this._startTime = payload.startTime;
@@ -597,7 +604,7 @@ function parseRegexPatterns(patterns) {
597
604
  }
598
605
  function computeTestCaseOutcome(test) {
599
606
  let skipped = 0;
600
- let didNotRun = 0;
607
+ let didNotRun2 = 0;
601
608
  let expected = 0;
602
609
  let interrupted = 0;
603
610
  let unexpected = 0;
@@ -607,7 +614,7 @@ function computeTestCaseOutcome(test) {
607
614
  } else if (result.status === "skipped" && test.expectedStatus === "skipped") {
608
615
  ++skipped;
609
616
  } else if (result.status === "skipped") {
610
- ++didNotRun;
617
+ ++didNotRun2;
611
618
  } else if (result.status === test.expectedStatus) {
612
619
  ++expected;
613
620
  } else {
@@ -759,7 +766,14 @@ async function gitCommitInfo(gitDir) {
759
766
  async function gitDiff(gitDir, ci) {
760
767
  const diffLimit = 1e5;
761
768
  if (ci?.prBaseHash) {
762
- await runGit(["fetch", "origin", ci.prBaseHash, "--depth=1", "--no-auto-maintenance", "--no-auto-gc", "--no-tags", "--no-recurse-submodules"], gitDir);
769
+ const hasBaseCommit = await runGit(["cat-file", "-e", `${ci.prBaseHash}^{commit}`], gitDir) !== void 0;
770
+ if (!hasBaseCommit) {
771
+ const isShallow = await runGit(["rev-parse", "--is-shallow-repository"], gitDir) === "true";
772
+ const fetchArgs = ["fetch", "origin", ci.prBaseHash, "--no-auto-maintenance", "--no-auto-gc", "--no-tags", "--no-recurse-submodules"];
773
+ if (isShallow)
774
+ fetchArgs.push("--depth=1");
775
+ await runGit(fetchArgs, gitDir);
776
+ }
763
777
  const diff3 = await runGit(["diff", ci.prBaseHash, "HEAD"], gitDir);
764
778
  if (diff3)
765
779
  return diff3.substring(0, diffLimit);
@@ -1180,7 +1194,7 @@ var TerminalReporter = class {
1180
1194
  const threshold = this.config.reportSlowTests.threshold;
1181
1195
  return fileDurations.filter(([, duration]) => duration > threshold).slice(0, count);
1182
1196
  }
1183
- generateSummaryMessage({ didNotRun, skipped, expected, interrupted, unexpected, flaky, fatalErrors }) {
1197
+ generateSummaryMessage({ didNotRun: didNotRun2, skipped, expected, interrupted, unexpected, flaky, fatalErrors }) {
1184
1198
  const tokens = [];
1185
1199
  if (unexpected.length) {
1186
1200
  tokens.push(this.screen.colors.red(` ${unexpected.length} failed`));
@@ -1199,8 +1213,8 @@ var TerminalReporter = class {
1199
1213
  }
1200
1214
  if (skipped)
1201
1215
  tokens.push(this.screen.colors.yellow(` ${skipped} skipped`));
1202
- if (didNotRun)
1203
- tokens.push(this.screen.colors.yellow(` ${didNotRun} did not run`));
1216
+ if (didNotRun2)
1217
+ tokens.push(this.screen.colors.yellow(` ${didNotRun2} did not run`));
1204
1218
  if (expected)
1205
1219
  tokens.push(this.screen.colors.green(` ${expected} passed`) + this.screen.colors.dim(` (${msToString(this.result.duration)})`));
1206
1220
  if (fatalErrors.length && expected + unexpected.length + interrupted.length + flaky.length > 0)
@@ -1208,7 +1222,7 @@ var TerminalReporter = class {
1208
1222
  return tokens.join("\n");
1209
1223
  }
1210
1224
  generateSummary() {
1211
- let didNotRun = 0;
1225
+ let didNotRun2 = 0;
1212
1226
  let skipped = 0;
1213
1227
  let expected = 0;
1214
1228
  const interrupted = [];
@@ -1223,7 +1237,7 @@ var TerminalReporter = class {
1223
1237
  interruptedToPrint.push(test);
1224
1238
  interrupted.push(test);
1225
1239
  } else if (!test.results.length || test.expectedStatus !== "skipped") {
1226
- ++didNotRun;
1240
+ ++didNotRun2;
1227
1241
  } else {
1228
1242
  ++skipped;
1229
1243
  }
@@ -1242,7 +1256,7 @@ var TerminalReporter = class {
1242
1256
  });
1243
1257
  const failuresToPrint = [...unexpected, ...flaky, ...interruptedToPrint];
1244
1258
  return {
1245
- didNotRun,
1259
+ didNotRun: didNotRun2,
1246
1260
  skipped,
1247
1261
  expected,
1248
1262
  interrupted,
@@ -1285,7 +1299,7 @@ var TerminalReporter = class {
1285
1299
  return formatTestTitle(this.screen, this.config, test, step, this._options);
1286
1300
  }
1287
1301
  formatTestHeader(test, options = {}) {
1288
- return formatTestHeader(this.screen, this.config, test, { ...options, includeTestId: this._options.includeTestId });
1302
+ return formatTestHeader(this.screen, this.config, test, { ...options, includeTestId: this._options.includeTestId, omitTags: this._options.omitTags });
1289
1303
  }
1290
1304
  formatFailure(test, index) {
1291
1305
  return formatFailure(this.screen, this.config, test, index, this._options);
@@ -1320,7 +1334,7 @@ function formatFailure(screen, config2, test, index, options) {
1320
1334
  if (!errors.length)
1321
1335
  continue;
1322
1336
  if (!printedHeader) {
1323
- const header = formatTestHeader(screen, config2, test, { indent: " ", index, mode: "error", includeTestId: options?.includeTestId });
1337
+ const header = formatTestHeader(screen, config2, test, { indent: " ", index, mode: "error", includeTestId: options?.includeTestId, omitTags: options?.omitTags });
1324
1338
  lines.push(screen.colors.red(header));
1325
1339
  printedHeader = true;
1326
1340
  }
@@ -1433,7 +1447,9 @@ function relativeTestPath(screen, config2, test) {
1433
1447
  return relativeFilePath(screen, config2, test.location.file);
1434
1448
  }
1435
1449
  function stepSuffix(step) {
1436
- const stepTitles = step ? step.titlePath() : [];
1450
+ const stepTitles = [];
1451
+ for (let current = step; current; current = current.parent)
1452
+ stepTitles.unshift(current.subtitle ? `${current.title} ${current.subtitle}` : current.title);
1437
1453
  return stepTitles.map((t2) => t2.split("\n")[0]).map((t2) => " \u203A " + t2).join("");
1438
1454
  }
1439
1455
  function formatTestTitle(screen, config2, test, step, options = {}) {
@@ -1443,7 +1459,7 @@ function formatTestTitle(screen, config2, test, step, options = {}) {
1443
1459
  const projectLabel = options.includeTestId ? `project=` : "";
1444
1460
  const projectTitle = projectName ? `[${projectLabel}${projectName}] \u203A ` : "";
1445
1461
  const testTitle = `${testId}${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`;
1446
- const extraTags = test.tags.filter((t2) => !testTitle.includes(t2) && !config2.tags.includes(t2));
1462
+ const extraTags = options.omitTags ? [] : test.tags.filter((t2) => !testTitle.includes(t2) && !config2.tags.includes(t2));
1447
1463
  return `${testTitle}${stepSuffix(step)}${extraTags.length ? " " + extraTags.join(" ") : ""}`;
1448
1464
  }
1449
1465
  function formatTestHeader(screen, config2, test, options = {}) {
@@ -1859,7 +1875,7 @@ function addLocationAndSnippetToError(config2, error, file) {
1859
1875
  }
1860
1876
 
1861
1877
  // packages/playwright/src/runner/testRunner.ts
1862
- var import_util15 = require("../util");
1878
+ var import_util16 = require("../util");
1863
1879
 
1864
1880
  // packages/playwright/src/runner/reporters.ts
1865
1881
  var reporters_exports = {};
@@ -1867,7 +1883,7 @@ __export(reporters_exports, {
1867
1883
  createErrorCollectingReporter: () => createErrorCollectingReporter,
1868
1884
  createReporters: () => createReporters
1869
1885
  });
1870
- var import_fs8 = __toESM(require("fs"));
1886
+ var import_fs9 = __toESM(require("fs"));
1871
1887
 
1872
1888
  // packages/playwright/src/runner/loadUtils.ts
1873
1889
  var import_path4 = __toESM(require("path"));
@@ -2007,11 +2023,23 @@ var ProcessHost = class extends import_events.EventEmitter {
2007
2023
  return;
2008
2024
  const exitPromise = new Promise((f) => this.once("exit", () => f()));
2009
2025
  const timeout = +(process.env.PWTEST_CHILD_PROCESS_TIMEOUT || 5 * 60 * 1e3);
2010
- const result = await raceAgainstDeadline2(() => exitPromise, monotonicTime4() + timeout);
2011
- if (result.timedOut) {
2012
- this.emit("processError", { message: `Error: ${this._processName} process did not exit within ${timeout}ms after stop, force-killed it` });
2013
- this._forceKill();
2014
- await exitPromise;
2026
+ let lastHeartbeat = monotonicTime4();
2027
+ const onHeartbeat = () => lastHeartbeat = monotonicTime4();
2028
+ this.on("__heartbeat__", onHeartbeat);
2029
+ try {
2030
+ while (true) {
2031
+ const result = await raceAgainstDeadline2(() => exitPromise, lastHeartbeat + timeout);
2032
+ if (!result.timedOut)
2033
+ return;
2034
+ if (monotonicTime4() < lastHeartbeat + timeout)
2035
+ continue;
2036
+ this.emit("processError", { message: `Error: ${this._processName} process did not exit within ${timeout}ms after stop, force-killed it` });
2037
+ this._forceKill();
2038
+ await exitPromise;
2039
+ return;
2040
+ }
2041
+ } finally {
2042
+ this.off("__heartbeat__", onHeartbeat);
2015
2043
  }
2016
2044
  }
2017
2045
  _forceKill() {
@@ -2361,7 +2389,8 @@ function createTestGroups(projectSuite, expectedParallelism) {
2361
2389
  requireFile: test._requireFile,
2362
2390
  repeatEachIndex: test.repeatEachIndex,
2363
2391
  projectId: test._projectId,
2364
- tests: []
2392
+ tests: [],
2393
+ locks: []
2365
2394
  };
2366
2395
  };
2367
2396
  for (const test of projectSuite.allTests()) {
@@ -2421,6 +2450,14 @@ function createTestGroups(projectSuite, expectedParallelism) {
2421
2450
  }
2422
2451
  }
2423
2452
  }
2453
+ for (const group of result) {
2454
+ const locks = /* @__PURE__ */ new Set();
2455
+ for (const test of group.tests) {
2456
+ for (const lock of test._locks)
2457
+ locks.add(lock);
2458
+ }
2459
+ group.locks = [...locks];
2460
+ }
2424
2461
  return result;
2425
2462
  }
2426
2463
  function filterForShard(shard, weights, testGroups) {
@@ -3003,7 +3040,9 @@ var TeleReporterEmitter = class {
3003
3040
  id: step[this._idSymbol],
3004
3041
  parentStepId: step.parent?.[this._idSymbol],
3005
3042
  title: step.title,
3043
+ subtitle: step.subtitle,
3006
3044
  category: step.category,
3045
+ params: step.params,
3007
3046
  startTime: +step.startTime,
3008
3047
  location: this._relativeLocation(step.location)
3009
3048
  };
@@ -3136,9 +3175,10 @@ var BlobReporter = class extends TeleReporterEmitter {
3136
3175
  };
3137
3176
 
3138
3177
  // packages/playwright/src/reporters/dot.ts
3178
+ var { getAsBooleanFromENV } = require("playwright-core/lib/coreBundle").utils;
3139
3179
  var DotReporter = class extends TerminalReporter {
3140
- constructor() {
3141
- super(...arguments);
3180
+ constructor(options) {
3181
+ super({ ...options, omitTags: getAsBooleanFromENV("PLAYWRIGHT_DOT_OMIT_TAGS", options?.omitTags) });
3142
3182
  this._counter = 0;
3143
3183
  }
3144
3184
  onBegin(suite) {
@@ -3228,6 +3268,7 @@ var import_path7 = __toESM(require("path"));
3228
3268
  var import_util7 = require("../util");
3229
3269
  var { noColors: noColors2 } = require("playwright-core/lib/coreBundle").iso;
3230
3270
  var { msToString: msToString2 } = require("playwright-core/lib/coreBundle").iso;
3271
+ var { getAsBooleanFromENV: getAsBooleanFromENV2 } = require("playwright-core/lib/coreBundle").utils;
3231
3272
  var GitHubLogger = class {
3232
3273
  newLine() {
3233
3274
  process.stdout.write("\n");
@@ -3253,7 +3294,7 @@ var GitHubLogger = class {
3253
3294
  };
3254
3295
  var GitHubReporter = class extends TerminalReporter {
3255
3296
  constructor(options = {}) {
3256
- super(options);
3297
+ super({ ...options, omitTags: getAsBooleanFromENV2("PLAYWRIGHT_GITHUB_OMIT_TAGS", options.omitTags) });
3257
3298
  this.githubLogger = new GitHubLogger();
3258
3299
  this._failedTestCount = 0;
3259
3300
  this.screen = { ...this.screen, colors: noColors2 };
@@ -3845,6 +3886,7 @@ var HtmlBuilder = class {
3845
3886
  title = `${title} (skipped${skipped.description ? ": " + skipped.description : ""})`;
3846
3887
  const testStep = {
3847
3888
  title,
3889
+ subtitle: step.subtitle,
3848
3890
  startTime: step.startTime.toISOString(),
3849
3891
  duration,
3850
3892
  steps: dedupeSteps(step.steps).map((s) => this._createTestStep(s, result)),
@@ -3930,7 +3972,7 @@ function dedupeSteps(steps) {
3930
3972
  for (const step of steps) {
3931
3973
  const canDedupe = !step.error && step.duration >= 0 && step.location?.file && !step.steps.length;
3932
3974
  const lastStep = lastResult?.step;
3933
- if (canDedupe && lastResult && lastStep && step.category === lastStep.category && step.title === lastStep.title && step.location?.file === lastStep.location?.file && step.location?.line === lastStep.location?.line && step.location?.column === lastStep.location?.column) {
3975
+ if (canDedupe && lastResult && lastStep && step.category === lastStep.category && step.title === lastStep.title && step.subtitle === lastStep.subtitle && step.location?.file === lastStep.location?.file && step.location?.line === lastStep.location?.line && step.location?.column === lastStep.location?.column) {
3934
3976
  ++lastResult.count;
3935
3977
  lastResult.duration += step.duration;
3936
3978
  continue;
@@ -4181,6 +4223,7 @@ var JSONReporter = class {
4181
4223
  const steps = step.steps.filter((s) => s.category === "test.step");
4182
4224
  return {
4183
4225
  title: step.title,
4226
+ subtitle: step.subtitle,
4184
4227
  duration: step.duration,
4185
4228
  error: step.error,
4186
4229
  steps: steps.length ? steps.map((s) => this._serializeTestStep(s)) : void 0
@@ -4215,7 +4258,7 @@ var json_default = JSONReporter;
4215
4258
  var import_fs7 = __toESM(require("fs"));
4216
4259
  var import_path10 = __toESM(require("path"));
4217
4260
  var import_util9 = require("../util");
4218
- var { getAsBooleanFromENV } = require("playwright-core/lib/coreBundle").utils;
4261
+ var { getAsBooleanFromENV: getAsBooleanFromENV3 } = require("playwright-core/lib/coreBundle").utils;
4219
4262
  var JUnitReporter = class {
4220
4263
  constructor(options) {
4221
4264
  this.totalTests = 0;
@@ -4225,9 +4268,11 @@ var JUnitReporter = class {
4225
4268
  this.stripANSIControlSequences = false;
4226
4269
  this.includeProjectInTestName = false;
4227
4270
  this.includeRetries = false;
4228
- this.stripANSIControlSequences = getAsBooleanFromENV("PLAYWRIGHT_JUNIT_STRIP_ANSI", !!options.stripANSIControlSequences);
4229
- this.includeProjectInTestName = getAsBooleanFromENV("PLAYWRIGHT_JUNIT_INCLUDE_PROJECT_IN_TEST_NAME", !!options.includeProjectInTestName);
4230
- this.includeRetries = getAsBooleanFromENV("PLAYWRIGHT_JUNIT_INCLUDE_RETRIES", !!options.includeRetries);
4271
+ this.omitTags = false;
4272
+ this.stripANSIControlSequences = getAsBooleanFromENV3("PLAYWRIGHT_JUNIT_STRIP_ANSI", !!options.stripANSIControlSequences);
4273
+ this.includeProjectInTestName = getAsBooleanFromENV3("PLAYWRIGHT_JUNIT_INCLUDE_PROJECT_IN_TEST_NAME", !!options.includeProjectInTestName);
4274
+ this.includeRetries = getAsBooleanFromENV3("PLAYWRIGHT_JUNIT_INCLUDE_RETRIES", !!options.includeRetries);
4275
+ this.omitTags = getAsBooleanFromENV3("PLAYWRIGHT_JUNIT_OMIT_TAGS", !!options.omitTags);
4231
4276
  this.configDir = options.configDir;
4232
4277
  this.resolvedOutputFile = resolveOutputFile("JUNIT", options)?.outputFile;
4233
4278
  }
@@ -4380,7 +4425,7 @@ var JUnitReporter = class {
4380
4425
  entry.children.push({
4381
4426
  name: errorInfo.elementName,
4382
4427
  attributes: { message: errorInfo.message, type: errorInfo.type },
4383
- text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4428
+ text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test, void 0, { omitTags: this.omitTags }))
4384
4429
  });
4385
4430
  return errorInfo.elementName;
4386
4431
  }
@@ -4390,7 +4435,7 @@ var JUnitReporter = class {
4390
4435
  message: `${import_path10.default.basename(test.location.file)}:${test.location.line}:${test.location.column} ${test.title}`,
4391
4436
  type: "FAILURE"
4392
4437
  },
4393
- text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test))
4438
+ text: (0, import_util9.stripAnsiEscapes)(formatFailure(nonTerminalScreen, this.config, test, void 0, { omitTags: this.omitTags }))
4394
4439
  });
4395
4440
  return "failure";
4396
4441
  }
@@ -4501,9 +4546,10 @@ function escape(text, stripANSIControlSequences, isCharacterData) {
4501
4546
  var junit_default = JUnitReporter;
4502
4547
 
4503
4548
  // packages/playwright/src/reporters/line.ts
4549
+ var { getAsBooleanFromENV: getAsBooleanFromENV4 } = require("playwright-core/lib/coreBundle").utils;
4504
4550
  var LineReporter = class extends TerminalReporter {
4505
- constructor() {
4506
- super(...arguments);
4551
+ constructor(options) {
4552
+ super({ ...options, omitTags: getAsBooleanFromENV4("PLAYWRIGHT_LINE_OMIT_TAGS", options?.omitTags) });
4507
4553
  this._current = 0;
4508
4554
  this._failures = 0;
4509
4555
  this._didBegin = false;
@@ -4612,13 +4658,13 @@ var line_default = LineReporter;
4612
4658
  // packages/playwright/src/reporters/list.ts
4613
4659
  var import_util10 = require("../util");
4614
4660
  var { msToString: msToString3 } = require("playwright-core/lib/coreBundle").iso;
4615
- var { getAsBooleanFromENV: getAsBooleanFromENV2 } = require("playwright-core/lib/coreBundle").utils;
4661
+ var { getAsBooleanFromENV: getAsBooleanFromENV5 } = require("playwright-core/lib/coreBundle").utils;
4616
4662
  var DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === "win32" && process.env.TERM_PROGRAM !== "vscode" && !process.env.WT_SESSION;
4617
4663
  var POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? "ok" : "\u2713";
4618
4664
  var NEGATIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? "x" : "\u2718";
4619
4665
  var ListReporter = class extends TerminalReporter {
4620
4666
  constructor(options) {
4621
- super(options);
4667
+ super({ ...options, omitTags: getAsBooleanFromENV5("PLAYWRIGHT_LIST_OMIT_TAGS", options?.omitTags) });
4622
4668
  this._lastRow = 0;
4623
4669
  this._lastColumn = 0;
4624
4670
  this._testRows = /* @__PURE__ */ new Map();
@@ -4628,8 +4674,8 @@ var ListReporter = class extends TerminalReporter {
4628
4674
  this._needNewLine = false;
4629
4675
  this._failureIndex = 0;
4630
4676
  this._paused = /* @__PURE__ */ new Set();
4631
- this._printSteps = getAsBooleanFromENV2("PLAYWRIGHT_LIST_PRINT_STEPS", options?.printSteps);
4632
- this._printFailuresInline = getAsBooleanFromENV2("PLAYWRIGHT_LIST_PRINT_FAILURES_INLINE", options?.printFailuresInline);
4677
+ this._printSteps = getAsBooleanFromENV5("PLAYWRIGHT_LIST_PRINT_STEPS", options?.printSteps);
4678
+ this._printFailuresInline = getAsBooleanFromENV5("PLAYWRIGHT_LIST_PRINT_FAILURES_INLINE", options?.printFailuresInline);
4633
4679
  }
4634
4680
  onBegin(suite) {
4635
4681
  super.onBegin(suite);
@@ -4888,29 +4934,383 @@ var ListModeReporter = class {
4888
4934
  };
4889
4935
  var listModeReporter_default = ListModeReporter;
4890
4936
 
4937
+ // packages/playwright/src/reporters/perfetto.ts
4938
+ var import_fs8 = __toESM(require("fs"));
4939
+ var import_path12 = __toESM(require("path"));
4940
+ var import_zlib = __toESM(require("zlib"));
4941
+ var import_coreBundle2 = require("playwright-core/lib/coreBundle");
4942
+ var import_util11 = require("../util");
4943
+ var { toPosixPath: toPosixPath4 } = require("playwright-core/lib/coreBundle").utils;
4944
+ var kStatusColors = {
4945
+ passed: "good",
4946
+ failed: "bad",
4947
+ timedOut: "terrible",
4948
+ interrupted: "yellow",
4949
+ skipped: "grey"
4950
+ };
4951
+ var kProcessId = 1;
4952
+ var kRunThreadId = 0;
4953
+ var PerfettoReporter = class {
4954
+ constructor(options) {
4955
+ this._events = [];
4956
+ this._laneEndTime = /* @__PURE__ */ new Map();
4957
+ this._globalErrors = [];
4958
+ this._resolvedOutputFile = resolveOutputFile("PERFETTO", {
4959
+ ...options,
4960
+ default: {
4961
+ fileName: "perfetto.json",
4962
+ outputDir: "test-results"
4963
+ }
4964
+ }).outputFile;
4965
+ }
4966
+ version() {
4967
+ return "v2";
4968
+ }
4969
+ printsToStdio() {
4970
+ return false;
4971
+ }
4972
+ onConfigure(config2) {
4973
+ this._config = config2;
4974
+ }
4975
+ onBegin(suite) {
4976
+ this._suite = suite;
4977
+ }
4978
+ onError(error) {
4979
+ this._globalErrors.push({ error, timestamp: Date.now() });
4980
+ }
4981
+ async onEnd(result) {
4982
+ const entries = [];
4983
+ for (const test of this._suite?.allTests() ?? []) {
4984
+ for (const testResult of test.results)
4985
+ entries.push({ test, result: testResult });
4986
+ }
4987
+ entries.sort((a, b) => a.result.startTime.getTime() - b.result.startTime.getTime());
4988
+ for (const entry of entries)
4989
+ this._appendTestResult(entry.test, entry.result);
4990
+ for (const { error, timestamp } of this._globalErrors) {
4991
+ this._events.push({
4992
+ name: "error",
4993
+ cat: "error",
4994
+ ph: "i",
4995
+ s: "g",
4996
+ ts: timestamp,
4997
+ pid: kProcessId,
4998
+ tid: kRunThreadId,
4999
+ cname: "bad",
5000
+ args: { error: this._formatError(error) }
5001
+ });
5002
+ }
5003
+ await this._writeReport(result);
5004
+ }
5005
+ _appendTestResult(test, result) {
5006
+ const startMs = result.startTime.getTime();
5007
+ let endMs = startMs + Math.max(0, result.duration);
5008
+ for (const step of result.steps)
5009
+ endMs = Math.max(endMs, stepEndTime(step));
5010
+ const lane = this._allocateLane(result.parallelIndex, startMs);
5011
+ this._laneEndTime.set(lane, endMs);
5012
+ const tid = lane + 1;
5013
+ this._events.push({
5014
+ name: test.title,
5015
+ cat: "test",
5016
+ ph: "X",
5017
+ ts: startMs,
5018
+ dur: endMs - startMs,
5019
+ pid: kProcessId,
5020
+ tid,
5021
+ cname: kStatusColors[result.status],
5022
+ args: this._testArgs(test, result)
5023
+ });
5024
+ for (const step of result.steps)
5025
+ this._appendStep(step, tid, startMs, endMs);
5026
+ }
5027
+ _allocateLane(preferredLane, startMs) {
5028
+ const preferred = Math.max(0, preferredLane);
5029
+ if (!(this._laneEndTime.get(preferred) > startMs))
5030
+ return preferred;
5031
+ for (let lane = 0; ; ++lane) {
5032
+ if (!(this._laneEndTime.get(lane) > startMs))
5033
+ return lane;
5034
+ }
5035
+ }
5036
+ _appendStep(step, tid, parentStart, parentEnd) {
5037
+ const stepStart = step.startTime.getTime();
5038
+ const startMs = clamp(stepStart, parentStart, parentEnd);
5039
+ const endMs = clamp(step.duration >= 0 ? stepStart + step.duration : parentEnd, startMs, parentEnd);
5040
+ this._events.push({
5041
+ name: step.subtitle ? `${step.title} ${step.subtitle}` : step.title,
5042
+ cat: step.category,
5043
+ ph: "X",
5044
+ ts: startMs,
5045
+ dur: endMs - startMs,
5046
+ pid: kProcessId,
5047
+ tid,
5048
+ cname: step.error ? "bad" : void 0,
5049
+ args: this._stepArgs(step)
5050
+ });
5051
+ for (const child of step.steps)
5052
+ this._appendStep(child, tid, startMs, endMs);
5053
+ }
5054
+ _testArgs(test, result) {
5055
+ const [, projectName, , ...titles] = test.titlePath();
5056
+ const args = {
5057
+ status: result.status,
5058
+ expectedStatus: test.expectedStatus,
5059
+ testId: test.id,
5060
+ workerIndex: result.workerIndex,
5061
+ parallelIndex: result.parallelIndex,
5062
+ timeout: test.timeout,
5063
+ location: this._formatLocation(test.location)
5064
+ };
5065
+ if (titles.length > 1)
5066
+ args.title = titles.join(" \u203A ");
5067
+ if (projectName)
5068
+ args.project = projectName;
5069
+ if (result.retry)
5070
+ args.retry = result.retry;
5071
+ if (test.tags.length)
5072
+ args.tags = test.tags.join(" ");
5073
+ if (result.annotations.length)
5074
+ args.annotations = result.annotations.map((annotation) => formatAnnotation(annotation));
5075
+ if (result.attachments.length)
5076
+ args.attachments = result.attachments.map((attachment) => this._formatAttachment(attachment));
5077
+ if (result.errors.length)
5078
+ args.errors = result.errors.map((error) => this._formatError(error));
5079
+ const stdout = concatChunks(result.stdout);
5080
+ if (stdout)
5081
+ args.stdout = stdout;
5082
+ const stderr = concatChunks(result.stderr);
5083
+ if (stderr)
5084
+ args.stderr = stderr;
5085
+ return args;
5086
+ }
5087
+ _stepArgs(step) {
5088
+ const args = {};
5089
+ if (step.params)
5090
+ args.params = step.params;
5091
+ if (step.location)
5092
+ args.location = this._formatLocation(step.location);
5093
+ if (step.annotations.length)
5094
+ args.annotations = step.annotations.map((annotation) => formatAnnotation(annotation));
5095
+ if (step.attachments.length)
5096
+ args.attachments = step.attachments.map((attachment) => this._formatAttachment(attachment));
5097
+ if (step.error)
5098
+ args.error = this._formatError(step.error);
5099
+ return Object.keys(args).length ? args : void 0;
5100
+ }
5101
+ _formatAttachment(attachment) {
5102
+ return attachment.path ? this._relativePath(attachment.path) : attachment.name;
5103
+ }
5104
+ _formatLocation(location) {
5105
+ if (!location)
5106
+ return void 0;
5107
+ return `${this._relativePath(location.file)}:${location.line}:${location.column}`;
5108
+ }
5109
+ _formatError(error) {
5110
+ return (0, import_util11.stripAnsiEscapes)(formatError(nonTerminalScreen, error).message);
5111
+ }
5112
+ _relativePath(file) {
5113
+ return toPosixPath4(import_path12.default.relative(this._config.rootDir, file));
5114
+ }
5115
+ async _writeReport(result) {
5116
+ let timeOrigin2 = result.startTime.getTime();
5117
+ for (const event of this._events)
5118
+ timeOrigin2 = Math.min(timeOrigin2, event.ts);
5119
+ const metadataEvents = [
5120
+ { name: "process_name", cat: "__metadata", ph: "M", ts: 0, pid: kProcessId, tid: kRunThreadId, args: { name: "Playwright Test" } },
5121
+ { name: "process_sort_index", cat: "__metadata", ph: "M", ts: 0, pid: kProcessId, tid: kRunThreadId, args: { sort_index: 0 } }
5122
+ ];
5123
+ for (const lane of [...this._laneEndTime.keys()].sort((a, b) => a - b)) {
5124
+ metadataEvents.push({ name: "thread_name", cat: "__metadata", ph: "M", ts: 0, pid: kProcessId, tid: lane + 1, args: { name: `Worker ${lane}` } });
5125
+ metadataEvents.push({ name: "thread_sort_index", cat: "__metadata", ph: "M", ts: 0, pid: kProcessId, tid: lane + 1, args: { sort_index: lane + 1 } });
5126
+ }
5127
+ this._events.sort((a, b) => a.ts - b.ts);
5128
+ for (const event of this._events) {
5129
+ event.ts = Math.round((event.ts - timeOrigin2) * 1e3);
5130
+ if (event.dur !== void 0)
5131
+ event.dur = Math.round(event.dur * 1e3);
5132
+ }
5133
+ const metadata = {
5134
+ "playwright-version": (0, import_coreBundle2.getPlaywrightVersion)(),
5135
+ "start-time": result.startTime.toISOString(),
5136
+ "duration": result.duration,
5137
+ "status": result.status
5138
+ };
5139
+ await import_fs8.default.promises.mkdir(import_path12.default.dirname(this._resolvedOutputFile), { recursive: true });
5140
+ const writer = new ChunkWriter(this._resolvedOutputFile);
5141
+ await writer.write('{"traceEvents":[');
5142
+ let separator2 = "";
5143
+ for (const events of [metadataEvents, this._events]) {
5144
+ for (const event of events) {
5145
+ await writer.write(separator2 + JSON.stringify(event));
5146
+ separator2 = ",";
5147
+ }
5148
+ }
5149
+ await writer.write(`],"displayTimeUnit":"ms","metadata":${JSON.stringify(metadata)}}`);
5150
+ await writer.close();
5151
+ }
5152
+ };
5153
+ var ChunkWriter = class {
5154
+ constructor(file) {
5155
+ const fileStream = import_fs8.default.createWriteStream(file);
5156
+ const gzip = file.endsWith(".gz") ? import_zlib.default.createGzip() : void 0;
5157
+ gzip?.pipe(fileStream);
5158
+ this._stream = gzip ?? fileStream;
5159
+ this._closed = new Promise((resolve) => fileStream.on("close", resolve));
5160
+ for (const stream of /* @__PURE__ */ new Set([this._stream, fileStream]))
5161
+ stream.on("error", (error) => this._error ??= error);
5162
+ }
5163
+ async write(chunk) {
5164
+ if (this._error)
5165
+ throw this._error;
5166
+ if (!this._stream.write(chunk))
5167
+ await new Promise((resolve) => this._stream.once("drain", () => resolve()));
5168
+ }
5169
+ async close() {
5170
+ this._stream.end();
5171
+ await this._closed;
5172
+ if (this._error)
5173
+ throw this._error;
5174
+ }
5175
+ };
5176
+ function stepEndTime(step) {
5177
+ let end = step.startTime.getTime() + Math.max(0, step.duration);
5178
+ for (const child of step.steps)
5179
+ end = Math.max(end, stepEndTime(child));
5180
+ return end;
5181
+ }
5182
+ function formatAnnotation(annotation) {
5183
+ return annotation.description ? `${annotation.type}: ${annotation.description}` : annotation.type;
5184
+ }
5185
+ function clamp(value, min, max) {
5186
+ return Math.min(Math.max(value, min), max);
5187
+ }
5188
+ function concatChunks(chunks) {
5189
+ return chunks.map((chunk) => typeof chunk === "string" ? chunk : chunk.toString("utf8")).join("");
5190
+ }
5191
+ var perfetto_default = PerfettoReporter;
5192
+
5193
+ // packages/playwright/src/reporters/smoothdeploy.ts
5194
+ var fs10 = __toESM(require("fs"));
5195
+ var path13 = __toESM(require("path"));
5196
+
5197
+ // packages/playwright/src/reporters/smoothdeployMatch.ts
5198
+ var ACTION_API = {
5199
+ navigate: ["Frame.goto"],
5200
+ click: ["Frame.click", "Frame.dblclick", "Frame.dispatchEvent"],
5201
+ fill: ["Frame.fill"],
5202
+ press: ["Frame.press"],
5203
+ hover: ["Frame.hover"],
5204
+ check: ["Frame.check"],
5205
+ uncheck: ["Frame.uncheck"],
5206
+ select: ["Frame.selectOption"],
5207
+ setInputFiles: ["Frame.setInputFiles", "ElementHandle.setInputFiles"],
5208
+ openPage: ["BrowserContext.newPage"],
5209
+ closePage: ["Page.close"],
5210
+ assertVisible: ["toBeVisible"],
5211
+ assertText: ["toContainText", "toHaveText"],
5212
+ assertValue: ["toHaveValue", "toBeEmpty"],
5213
+ assertChecked: ["toBeChecked", "not.toBeChecked"],
5214
+ assertSnapshot: ["toHaveScreenshot", "toMatchAriaSnapshot"]
5215
+ };
5216
+ var FILLER_API_NEVER_SKIPS_AHEAD = /* @__PURE__ */ new Set(["Frame.dispatchEvent"]);
5217
+ function stepApi(step) {
5218
+ if (step.category === "pw:api")
5219
+ return step.channelMethod ?? null;
5220
+ return normalizeApiName(step.apiName);
5221
+ }
5222
+ function shortApi(step) {
5223
+ const api = stepApi(step);
5224
+ if (!api)
5225
+ return null;
5226
+ const idx = api.lastIndexOf(".");
5227
+ return step.category === "pw:api" && idx >= 0 ? api.slice(idx + 1) : api;
5228
+ }
5229
+ function normalizeApiName(apiName) {
5230
+ if (!apiName)
5231
+ return null;
5232
+ if (apiName.startsWith("expect")) {
5233
+ if (apiName.includes(".poll") || apiName.includes(".soft"))
5234
+ return null;
5235
+ const matcher = apiName.slice("expect".length).replace(/^\./, "");
5236
+ return matcher || null;
5237
+ }
5238
+ const idx = apiName.lastIndexOf(".");
5239
+ return idx >= 0 ? apiName.slice(idx + 1) : apiName;
5240
+ }
5241
+ function apiMatches(step, expected) {
5242
+ const api = stepApi(step);
5243
+ if (!api)
5244
+ return false;
5245
+ const allowed = ACTION_API[expected.action];
5246
+ return !!allowed && allowed.includes(api);
5247
+ }
5248
+ function groupMatches(step, expected) {
5249
+ if (expected.title !== void 0)
5250
+ return step.title === expected.title;
5251
+ return expected.action === "group";
5252
+ }
5253
+ function stepMatches(step, expected) {
5254
+ if (step.category === "test.step")
5255
+ return groupMatches(step, expected);
5256
+ if (step.category === "pw:api" || step.category === "expect")
5257
+ return apiMatches(step, expected);
5258
+ return false;
5259
+ }
5260
+ function matchStep(step, siblings, cursor) {
5261
+ if (cursor < siblings.length && stepMatches(step, siblings[cursor]))
5262
+ return cursor;
5263
+ const api = stepApi(step);
5264
+ const canLookAhead = step.category === "test.step" ? siblings.some((s) => s.title !== void 0) : !!api && !FILLER_API_NEVER_SKIPS_AHEAD.has(api);
5265
+ if (!canLookAhead)
5266
+ return -1;
5267
+ for (let j = cursor + 1; j < siblings.length; j++) {
5268
+ if (stepMatches(step, siblings[j]))
5269
+ return j;
5270
+ }
5271
+ return -1;
5272
+ }
5273
+ var INTERNAL_STEP_TITLES = /* @__PURE__ */ new Set([
5274
+ "Before Hooks",
5275
+ "After Hooks",
5276
+ "Worker Cleanup",
5277
+ "Launch browser",
5278
+ "Launch persistent context",
5279
+ "Connect over CDP",
5280
+ "Close browser",
5281
+ "Create context",
5282
+ "Close context",
5283
+ "Create page",
5284
+ "Close page",
5285
+ "Create CDP session"
5286
+ ]);
5287
+ function isToPassWrapper(step) {
5288
+ return normalizeApiName(step.apiName) === "toPass";
5289
+ }
5290
+ function isUserStep(step) {
5291
+ if (step.category === "hook" || step.category === "fixture" || step.category === "test.attach")
5292
+ return false;
5293
+ if (step.title.startsWith('Fixture "'))
5294
+ return false;
5295
+ return !INTERNAL_STEP_TITLES.has(step.title);
5296
+ }
5297
+
4891
5298
  // packages/playwright/src/reporters/smoothdeploy.ts
4892
- var fs9 = __toESM(require("fs"));
4893
- var path12 = __toESM(require("path"));
5299
+ var NO_SCREENSHOT_PREFIXES = ["Navigate", "Go back", "Go forward", "Reload", "Screenshot", "Wait for", "Pause", "Evaluate"];
5300
+ var safeId = (id) => id.replace(/[^a-zA-Z0-9_-]/g, "-");
4894
5301
  var SmoothDeployReporter = class {
4895
5302
  constructor() {
4896
5303
  this._configDir = "";
4897
5304
  this._manifest = null;
4898
- // Resolved manifest test + paramIndex for each active pw test
4899
5305
  this._resolvedTests = /* @__PURE__ */ new Map();
4900
- // Map pw TestStep → matched manifest step
4901
- this._stepToManifest = /* @__PURE__ */ new WeakMap();
4902
- // Child counter per parent (TestStep for nested, test.id string for root-level)
4903
- this._childCounters = /* @__PURE__ */ new Map();
4904
- // Accumulate nested step data per test for output manifest
5306
+ this._matched = /* @__PURE__ */ new WeakMap();
5307
+ this._opaqueFiller = /* @__PURE__ */ new WeakSet();
5308
+ this._retries = /* @__PURE__ */ new WeakMap();
5309
+ this._rootCursors = /* @__PURE__ */ new Map();
4905
5310
  this._testSteps = /* @__PURE__ */ new Map();
4906
- // Track parent step → output StepData for nesting output
4907
- this._stepToOutput = /* @__PURE__ */ new WeakMap();
4908
- // ID remap: pw IDs → manifest IDs (sanitized). Built during execution, applied in onEnd.
4909
5311
  this._testIdMap = /* @__PURE__ */ new Map();
4910
- // safePwTestId → safeManifestTestId
4911
5312
  this._stepIdMap = /* @__PURE__ */ new Map();
4912
5313
  }
4913
- // safePwStepId → safeManifestStepId
4914
5314
  version() {
4915
5315
  return "v2";
4916
5316
  }
@@ -4918,55 +5318,46 @@ var SmoothDeployReporter = class {
4918
5318
  return false;
4919
5319
  }
4920
5320
  onConfigure(config2) {
4921
- this._configDir = config2.configFile ? path12.dirname(config2.configFile) : config2.rootDir;
4922
- this._loadManifest();
4923
- }
4924
- _loadManifest() {
4925
- const manifestPath = path12.join(this._configDir, ".smoothdeploy-manifest.json");
4926
- if (!fs9.existsSync(manifestPath))
4927
- throw new Error(`SmoothDeploy reporter requires .smoothdeploy-manifest.json in ${this._configDir}`);
4928
- const raw = fs9.readFileSync(manifestPath, "utf-8");
4929
- this._manifest = JSON.parse(raw);
4930
- }
4931
- _emit(event) {
4932
- process.stdout.write(`[SMOOTHDEPLOY_EVENT]${JSON.stringify(event)}
5321
+ this._configDir = config2.configFile ? path13.dirname(config2.configFile) : config2.rootDir;
5322
+ const manifestPath = path13.join(this._configDir, ".smoothdeploy-manifest.json");
5323
+ if (fs10.existsSync(manifestPath))
5324
+ this._manifest = JSON.parse(fs10.readFileSync(manifestPath, "utf-8"));
5325
+ }
5326
+ _emit(event, step) {
5327
+ const retry = step && this._nearestRetry(step);
5328
+ if (retry)
5329
+ retry.events.push(event);
5330
+ else
5331
+ process.stdout.write(`[SMOOTHDEPLOY_EVENT]${JSON.stringify(event)}
4933
5332
  `);
4934
5333
  }
4935
- _isUserStep(step) {
4936
- const title = step.title;
4937
- if (title === "Before Hooks" || title === "After Hooks" || title === "Worker Cleanup")
4938
- return false;
4939
- if (title.startsWith('Fixture "'))
4940
- return false;
4941
- const internalSteps = [
4942
- "Launch browser",
4943
- "Launch persistent context",
4944
- "Connect over CDP",
4945
- "Close browser",
4946
- "Create context",
4947
- "Close context",
4948
- "Create page",
4949
- "Close page",
4950
- "Create CDP session"
4951
- ];
4952
- if (internalSteps.includes(title))
4953
- return false;
4954
- return true;
5334
+ _nearestRetry(step) {
5335
+ for (let p = step.parent; p; p = p.parent) {
5336
+ const retry = this._retries.get(p);
5337
+ if (retry)
5338
+ return retry;
5339
+ }
5340
+ return void 0;
4955
5341
  }
4956
- // Resolve a pw TestCase to its manifest test entry + param index.
4957
- // For parameterized tests: manifest title "Foo" with params=3 matches pw titles "Foo0", "Foo1", "Foo2".
4958
- // For non-parameterized tests: exact match, paramIndex=0.
4959
5342
  _resolveManifestTest(test) {
5343
+ const manifestTest = this._findManifestTest(test);
5344
+ if (!manifestTest)
5345
+ return { manifestTest: { id: test.id, title: test.title, steps: [] }, paramIndex: 0, passthrough: true };
5346
+ const single = manifestTest.manifestTest.steps.length === 1 ? manifestTest.manifestTest.steps[0] : void 0;
5347
+ if (single && single.action === "script")
5348
+ return { ...manifestTest, passthrough: true, passthroughRootId: single.id };
5349
+ return { ...manifestTest, passthrough: false };
5350
+ }
5351
+ _findManifestTest(test) {
4960
5352
  if (!this._manifest)
4961
5353
  return null;
4962
5354
  const titlePath = test.titlePath();
4963
- const relFile = path12.relative(this._configDir, test.location.file);
5355
+ const relFile = path13.relative(this._configDir, test.location.file);
4964
5356
  const fileManifest = this._manifest.files[relFile];
4965
5357
  if (!fileManifest)
4966
5358
  return null;
4967
5359
  const fileIdx = titlePath.indexOf(relFile);
4968
5360
  const describeTitles = fileIdx >= 0 ? titlePath.slice(fileIdx + 1, -1) : [];
4969
- const testTitle = test.title;
4970
5361
  let currentSuites = fileManifest.suites;
4971
5362
  let currentTests = fileManifest.tests;
4972
5363
  for (const desc of describeTitles) {
@@ -4976,15 +5367,13 @@ var SmoothDeployReporter = class {
4976
5367
  currentSuites = suite.suites;
4977
5368
  currentTests = suite.tests;
4978
5369
  }
4979
- const exactMatch = currentTests.find((t2) => t2.title === testTitle);
5370
+ const exactMatch = currentTests.find((t2) => t2.title === test.title);
4980
5371
  if (exactMatch)
4981
5372
  return { manifestTest: exactMatch, paramIndex: 0 };
4982
5373
  for (const mt of currentTests) {
4983
- if (!mt.params || mt.params < 1)
4984
- continue;
4985
- if (!testTitle.startsWith(mt.title))
5374
+ if (!mt.params || mt.params < 1 || !test.title.startsWith(mt.title))
4986
5375
  continue;
4987
- const suffix = testTitle.slice(mt.title.length);
5376
+ const suffix = test.title.slice(mt.title.length);
4988
5377
  const idx = parseInt(suffix, 10);
4989
5378
  if (String(idx) === suffix && idx >= 0 && idx < mt.params)
4990
5379
  return { manifestTest: mt, paramIndex: idx };
@@ -4993,13 +5382,9 @@ var SmoothDeployReporter = class {
4993
5382
  }
4994
5383
  onTestBegin(test, result) {
4995
5384
  const resolved = this._resolveManifestTest(test);
4996
- if (!resolved)
4997
- return;
4998
5385
  this._resolvedTests.set(test.id, resolved);
4999
- const safePw = test.id.replace(/[^a-zA-Z0-9_-]/g, "-");
5000
- const safeManifest = resolved.manifestTest.id.replace(/[^a-zA-Z0-9_-]/g, "-");
5001
- this._testIdMap.set(safePw, safeManifest);
5002
- this._childCounters.set(test.id, 0);
5386
+ this._testIdMap.set(safeId(test.id), safeId(resolved.manifestTest.id));
5387
+ this._rootCursors.set(test.id, 0);
5003
5388
  this._testSteps.set(test.id, []);
5004
5389
  this._emit({
5005
5390
  event: "testBegin",
@@ -5008,11 +5393,36 @@ var SmoothDeployReporter = class {
5008
5393
  testTitle: test.title,
5009
5394
  timestamp: Date.now()
5010
5395
  });
5396
+ if (resolved.passthroughRootId) {
5397
+ this._emit({
5398
+ event: "stepBegin",
5399
+ testId: resolved.manifestTest.id,
5400
+ paramIndex: resolved.paramIndex,
5401
+ id: resolved.passthroughRootId,
5402
+ action: "script",
5403
+ title: test.title,
5404
+ category: "test.step",
5405
+ timestamp: Date.now()
5406
+ });
5407
+ }
5011
5408
  }
5012
5409
  onTestEnd(test, result) {
5013
5410
  const resolved = this._resolvedTests.get(test.id);
5014
5411
  if (!resolved)
5015
5412
  return;
5413
+ if (resolved.passthroughRootId) {
5414
+ this._emit({
5415
+ event: "stepEnd",
5416
+ testId: resolved.manifestTest.id,
5417
+ paramIndex: resolved.paramIndex,
5418
+ id: resolved.passthroughRootId,
5419
+ action: "script",
5420
+ title: test.title,
5421
+ duration: result.duration,
5422
+ error: result.error ? { message: result.error.message } : null,
5423
+ timestamp: Date.now()
5424
+ });
5425
+ }
5016
5426
  this._emit({
5017
5427
  event: "testEnd",
5018
5428
  testId: resolved.manifestTest.id,
@@ -5022,29 +5432,77 @@ var SmoothDeployReporter = class {
5022
5432
  duration: result.duration,
5023
5433
  timestamp: Date.now()
5024
5434
  });
5025
- this._childCounters.delete(test.id);
5435
+ this._rootCursors.delete(test.id);
5436
+ }
5437
+ _nearestMatchedAncestor(step) {
5438
+ for (let p = step.parent; p; p = p.parent) {
5439
+ const matched = this._matched.get(p);
5440
+ if (matched)
5441
+ return { matched, blocked: false };
5442
+ if (this._opaqueFiller.has(p))
5443
+ return { blocked: true };
5444
+ }
5445
+ return { blocked: false };
5446
+ }
5447
+ _resolveStep(test, resolved, step, parent) {
5448
+ const stepLike = { title: step.title, category: step.category, apiName: step._apiName, channelMethod: step._channelMethod };
5449
+ if (resolved.passthrough) {
5450
+ const index2 = parent ? parent.cursor : this._rootCursors.get(test.id) ?? 0;
5451
+ const prefix = parent ? `${parent.manifest.id}:` : resolved.passthroughRootId ? `${resolved.passthroughRootId}:` : "";
5452
+ if (parent)
5453
+ parent.cursor = index2 + 1;
5454
+ else
5455
+ this._rootCursors.set(test.id, index2 + 1);
5456
+ const action = step.category === "test.step" ? "group" : shortApi(stepLike) ?? step.category;
5457
+ return { id: `${prefix}${index2}`, action, title: step.title, children: [] };
5458
+ }
5459
+ if (parent && parent.manifest.children.length === 0)
5460
+ return null;
5461
+ const siblings = parent ? parent.manifest.children : resolved.manifestTest.steps;
5462
+ const cursor = parent ? parent.cursor : this._rootCursors.get(test.id) ?? 0;
5463
+ let index = matchStep(stepLike, siblings, cursor);
5464
+ const retry = this._nearestRetry(step);
5465
+ if (index < 0 && retry && retry.parent === parent && cursor > retry.startCursor) {
5466
+ index = matchStep(stepLike, siblings.slice(0, cursor), retry.startCursor);
5467
+ if (index >= 0)
5468
+ this._discardAttempt(test, retry);
5469
+ }
5470
+ if (index < 0)
5471
+ return null;
5472
+ if (parent)
5473
+ parent.cursor = index + 1;
5474
+ else
5475
+ this._rootCursors.set(test.id, index + 1);
5476
+ return siblings[index];
5477
+ }
5478
+ _discardAttempt(test, retry) {
5479
+ const list = retry.parent ? retry.parent.output.children : this._testSteps.get(test.id);
5480
+ for (const output of retry.outputs) {
5481
+ const i = list ? list.indexOf(output) : -1;
5482
+ if (i >= 0)
5483
+ list.splice(i, 1);
5484
+ }
5485
+ retry.outputs = [];
5486
+ retry.events = [];
5026
5487
  }
5027
5488
  onStepBegin(test, result, step) {
5028
- if (!this._isUserStep(step))
5489
+ if (!isUserStep(step))
5029
5490
  return;
5030
5491
  const resolved = this._resolvedTests.get(test.id);
5031
5492
  if (!resolved)
5032
5493
  return;
5033
- let parentStep = step.parent;
5034
- while (parentStep && !this._stepToOutput.has(parentStep))
5035
- parentStep = parentStep.parent;
5036
- const parentKey = parentStep ?? test.id;
5037
- const parentManifest = parentStep ? this._stepToManifest.get(parentStep) : void 0;
5038
- const parentSteps = parentManifest ? parentManifest.children : resolved.manifestTest.steps;
5039
- const idx = this._childCounters.get(parentKey) ?? 0;
5040
- this._childCounters.set(parentKey, idx + 1);
5041
- const manifestStep = parentSteps?.[idx] ?? null;
5042
- if (manifestStep)
5043
- this._stepToManifest.set(step, manifestStep);
5044
- this._childCounters.set(step, 0);
5045
- const outputStep = {
5046
- id: manifestStep?.id,
5047
- action: manifestStep?.action,
5494
+ const { matched: parent, blocked } = this._nearestMatchedAncestor(step);
5495
+ const manifestStep = blocked ? null : this._resolveStep(test, resolved, step, parent);
5496
+ if (!manifestStep) {
5497
+ if (blocked || !isToPassWrapper({ title: step.title, category: step.category, apiName: step._apiName }))
5498
+ this._opaqueFiller.add(step);
5499
+ else
5500
+ this._retries.set(step, { parent, startCursor: parent ? parent.cursor : this._rootCursors.get(test.id) ?? 0, events: [], outputs: [] });
5501
+ return;
5502
+ }
5503
+ const output = {
5504
+ id: manifestStep.id,
5505
+ action: manifestStep.action,
5048
5506
  title: step.title,
5049
5507
  category: step.category,
5050
5508
  duration: 0,
@@ -5052,97 +5510,106 @@ var SmoothDeployReporter = class {
5052
5510
  screenshots: null,
5053
5511
  children: []
5054
5512
  };
5055
- this._stepToOutput.set(step, outputStep);
5056
- const parentOutput = parentStep ? this._stepToOutput.get(parentStep) : void 0;
5057
- if (parentOutput)
5058
- parentOutput.children.push(outputStep);
5513
+ this._matched.set(step, { manifest: manifestStep, output, cursor: 0 });
5514
+ const retry = this._nearestRetry(step);
5515
+ if (retry && retry.parent === parent)
5516
+ retry.outputs.push(output);
5517
+ if (parent)
5518
+ parent.output.children.push(output);
5059
5519
  else
5060
- this._testSteps.get(test.id)?.push(outputStep);
5520
+ this._testSteps.get(test.id)?.push(output);
5061
5521
  this._emit({
5062
5522
  event: "stepBegin",
5063
5523
  testId: resolved.manifestTest.id,
5064
5524
  paramIndex: resolved.paramIndex,
5065
- id: manifestStep?.id,
5066
- action: manifestStep?.action,
5525
+ id: manifestStep.id,
5526
+ action: manifestStep.action,
5067
5527
  title: step.title,
5068
5528
  category: step.category,
5069
5529
  timestamp: Date.now()
5070
- });
5530
+ }, step);
5531
+ }
5532
+ _screenshotsFor(test, step) {
5533
+ const hasScreenshot = step.category === "pw:api" && !NO_SCREENSHOT_PREFIXES.some((prefix) => step.title.startsWith(prefix));
5534
+ if (!hasScreenshot)
5535
+ return null;
5536
+ const safeStepId = safeId(step._stepId ?? step.title);
5537
+ return {
5538
+ safeStepId,
5539
+ paths: {
5540
+ page: `.smoothdeploy-output/screenshots/${safeId(test.id)}/${safeStepId}-page.png`,
5541
+ element: `.smoothdeploy-output/screenshots/${safeId(test.id)}/${safeStepId}-element.png`
5542
+ }
5543
+ };
5071
5544
  }
5072
5545
  onStepEnd(test, result, step) {
5073
- if (!this._isUserStep(step))
5546
+ if (!isUserStep(step))
5074
5547
  return;
5075
5548
  const resolved = this._resolvedTests.get(test.id);
5076
5549
  if (!resolved)
5077
5550
  return;
5078
- const manifestStep = this._stepToManifest.get(step) ?? null;
5079
- const outputStep = this._stepToOutput.get(step);
5080
- const safeTestId = test.id.replace(/[^a-zA-Z0-9_-]/g, "-");
5081
- const noScreenshotPrefixes = [
5082
- "Navigate",
5083
- "Go back",
5084
- "Go forward",
5085
- "Reload",
5086
- "Screenshot",
5087
- "Wait for",
5088
- "Pause",
5089
- "Evaluate"
5090
- ];
5091
- const hasScreenshot = step.category === "pw:api" && !noScreenshotPrefixes.some((prefix) => step.title.startsWith(prefix));
5092
- const internalStepId = step._stepId ?? step.title;
5093
- const safeStepId = internalStepId.replace(/[^a-zA-Z0-9_-]/g, "-");
5094
- const screenshots = hasScreenshot ? {
5095
- page: `.smoothdeploy-output/screenshots/${safeTestId}/${safeStepId}-page.png`,
5096
- element: `.smoothdeploy-output/screenshots/${safeTestId}/${safeStepId}-element.png`
5097
- } : null;
5098
- if (manifestStep) {
5099
- const safeManifestStepId = manifestStep.id.replace(/[^a-zA-Z0-9_-]/g, "-");
5100
- this._stepIdMap.set(safeStepId, safeManifestStepId);
5101
- }
5102
- if (outputStep) {
5103
- outputStep.duration = step.duration;
5104
- const hasDescendantError = (steps) => steps.some((c) => c.error !== null || hasDescendantError(c.children));
5105
- outputStep.error = step.error && !hasDescendantError(outputStep.children) ? { message: step.error.message ?? "" } : null;
5106
- outputStep.screenshots = screenshots;
5107
- }
5108
- this._childCounters.delete(step);
5551
+ const retry = this._retries.get(step);
5552
+ if (retry) {
5553
+ this._retries.delete(step);
5554
+ for (const event of retry.events)
5555
+ this._emit(event, step);
5556
+ return;
5557
+ }
5558
+ const matched = this._matched.get(step);
5559
+ const screenshots = this._screenshotsFor(test, step);
5560
+ if (!matched) {
5561
+ const leaf = this._nearestMatchedAncestor(step).matched;
5562
+ if (screenshots && leaf && leaf.manifest.children.length === 0 && !leaf.output.screenshots) {
5563
+ this._stepIdMap.set(screenshots.safeStepId, safeId(leaf.manifest.id));
5564
+ leaf.output.screenshots = screenshots.paths;
5565
+ }
5566
+ return;
5567
+ }
5568
+ if (screenshots) {
5569
+ this._stepIdMap.set(screenshots.safeStepId, safeId(matched.manifest.id));
5570
+ matched.output.screenshots = screenshots.paths;
5571
+ }
5572
+ matched.output.duration = step.duration;
5573
+ const skipped = step.annotations.some((a) => a.type === "skip");
5574
+ if (skipped)
5575
+ matched.output.skipped = true;
5576
+ const hasDescendantError = (steps) => steps.some((c) => c.error !== null || hasDescendantError(c.children));
5577
+ matched.output.error = step.error && !hasDescendantError(matched.output.children) ? { message: step.error.message ?? "" } : null;
5109
5578
  this._emit({
5110
5579
  event: "stepEnd",
5111
5580
  testId: resolved.manifestTest.id,
5112
5581
  paramIndex: resolved.paramIndex,
5113
- id: manifestStep?.id,
5114
- action: manifestStep?.action,
5582
+ id: matched.manifest.id,
5583
+ action: matched.manifest.action,
5115
5584
  title: step.title,
5116
5585
  duration: step.duration,
5117
5586
  error: step.error ? { message: step.error.message } : null,
5587
+ skipped,
5118
5588
  timestamp: Date.now()
5119
- });
5589
+ }, step);
5120
5590
  }
5121
5591
  onEnd(result) {
5122
- const outputDir = path12.join(process.cwd(), ".smoothdeploy-output");
5123
- const screenshotsDir = path12.join(outputDir, "screenshots");
5124
- if (this._manifest) {
5125
- for (const [safePwTestId] of this._testIdMap) {
5126
- const testDir = path12.join(screenshotsDir, safePwTestId);
5127
- if (!fs9.existsSync(testDir))
5128
- continue;
5129
- for (const [safePwStepId, safeManifestStepId] of this._stepIdMap) {
5130
- for (const suffix of ["-page.png", "-element.png"]) {
5131
- const src = path12.join(testDir, `${safePwStepId}${suffix}`);
5132
- const dst = path12.join(testDir, `${safeManifestStepId}${suffix}`);
5133
- if (fs9.existsSync(src))
5134
- fs9.renameSync(src, dst);
5135
- }
5592
+ const outputDir = path13.join(process.cwd(), ".smoothdeploy-output");
5593
+ const screenshotsDir = path13.join(outputDir, "screenshots");
5594
+ for (const [safePwTestId] of this._testIdMap) {
5595
+ const testDir = path13.join(screenshotsDir, safePwTestId);
5596
+ if (!fs10.existsSync(testDir))
5597
+ continue;
5598
+ for (const [safePwStepId, safeManifestStepId] of this._stepIdMap) {
5599
+ for (const suffix of ["-page.png", "-element.png"]) {
5600
+ const src = path13.join(testDir, `${safePwStepId}${suffix}`);
5601
+ if (fs10.existsSync(src))
5602
+ fs10.renameSync(src, path13.join(testDir, `${safeManifestStepId}${suffix}`));
5136
5603
  }
5137
5604
  }
5138
- for (const [safePwTestId, safeManifestTestId] of this._testIdMap) {
5139
- const src = path12.join(screenshotsDir, safePwTestId);
5140
- const dst = path12.join(screenshotsDir, safeManifestTestId);
5141
- if (fs9.existsSync(src)) {
5142
- if (fs9.existsSync(dst))
5143
- fs9.rmSync(dst, { recursive: true });
5144
- fs9.renameSync(src, dst);
5145
- }
5605
+ }
5606
+ for (const [safePwTestId, safeManifestTestId] of this._testIdMap) {
5607
+ const src = path13.join(screenshotsDir, safePwTestId);
5608
+ const dst = path13.join(screenshotsDir, safeManifestTestId);
5609
+ if (src !== dst && fs10.existsSync(src)) {
5610
+ if (fs10.existsSync(dst))
5611
+ fs10.rmSync(dst, { recursive: true });
5612
+ fs10.renameSync(src, dst);
5146
5613
  }
5147
5614
  }
5148
5615
  const remapScreenshotPaths = (steps) => {
@@ -5160,24 +5627,17 @@ var SmoothDeployReporter = class {
5160
5627
  if (!resolved)
5161
5628
  continue;
5162
5629
  remapScreenshotPaths(steps);
5163
- const safeManifestTestId = resolved.manifestTest.id.replace(/[^a-zA-Z0-9_-]/g, "-");
5164
- const failurePath = path12.join(screenshotsDir, safeManifestTestId, "failure.png");
5165
- const failureScreenshot = fs9.existsSync(failurePath) ? `.smoothdeploy-output/screenshots/${safeManifestTestId}/failure.png` : null;
5630
+ const safeManifestTestId = safeId(resolved.manifestTest.id);
5631
+ const failurePath = path13.join(screenshotsDir, safeManifestTestId, "failure.png");
5632
+ const failureScreenshot = fs10.existsSync(failurePath) ? `.smoothdeploy-output/screenshots/${safeManifestTestId}/failure.png` : null;
5166
5633
  const key = resolved.manifestTest.id;
5167
5634
  if (!manifest[key])
5168
5635
  manifest[key] = [];
5169
5636
  manifest[key].push({ paramIndex: resolved.paramIndex, steps, failureScreenshot });
5170
5637
  }
5171
- fs9.mkdirSync(outputDir, { recursive: true });
5172
- fs9.writeFileSync(
5173
- path12.join(outputDir, "manifest.json"),
5174
- JSON.stringify(manifest, null, 2)
5175
- );
5176
- this._emit({
5177
- event: "runEnd",
5178
- status: result.status,
5179
- timestamp: Date.now()
5180
- });
5638
+ fs10.mkdirSync(outputDir, { recursive: true });
5639
+ fs10.writeFileSync(path13.join(outputDir, "manifest.json"), JSON.stringify(manifest, null, 2));
5640
+ this._emit({ event: "runEnd", status: result.status, timestamp: Date.now() });
5181
5641
  }
5182
5642
  _remapPath(screenshotPath) {
5183
5643
  let result = screenshotPath;
@@ -5194,21 +5654,20 @@ var smoothdeploy_default = SmoothDeployReporter;
5194
5654
  var { calculateSha1: calculateSha13 } = require("playwright-core/lib/coreBundle").utils;
5195
5655
  async function createReporters(config2, mode, descriptions, runOptions) {
5196
5656
  const defaultReporters = {
5197
- blob: BlobReporter,
5198
- dot: mode === "list" ? listModeReporter_default : dot_default,
5199
- line: mode === "list" ? listModeReporter_default : line_default,
5200
- list: mode === "list" ? listModeReporter_default : list_default,
5201
- github: github_default,
5202
- json: json_default,
5203
- junit: junit_default,
5204
- null: empty_default,
5205
- html: html_default,
5206
- smoothdeploy: smoothdeploy_default
5657
+ "blob": BlobReporter,
5658
+ "perfetto": perfetto_default,
5659
+ "dot": mode === "list" ? listModeReporter_default : dot_default,
5660
+ "line": mode === "list" ? listModeReporter_default : line_default,
5661
+ "list": mode === "list" ? listModeReporter_default : list_default,
5662
+ "github": github_default,
5663
+ "json": json_default,
5664
+ "junit": junit_default,
5665
+ "null": empty_default,
5666
+ "html": html_default,
5667
+ "smoothdeploy": smoothdeploy_default
5207
5668
  };
5208
5669
  const reporters = [];
5209
5670
  descriptions ??= config2.config.reporter;
5210
- if (runOptions?.additionalReporters)
5211
- descriptions = [...descriptions, ...runOptions.additionalReporters];
5212
5671
  const reportOptions = reporterCommandOptions(config2, mode, runOptions);
5213
5672
  for (const r of descriptions) {
5214
5673
  const [name, arg] = r;
@@ -5272,22 +5731,22 @@ function computeCommandHash(config2, runOptions) {
5272
5731
  if (config2.config.tags.length)
5273
5732
  command.tags = config2.config.tags.join(" ");
5274
5733
  if (runOptions?.testList)
5275
- command.testList = calculateSha13(import_fs8.default.readFileSync(runOptions.testList));
5734
+ command.testList = calculateSha13(import_fs9.default.readFileSync(runOptions.testList));
5276
5735
  if (runOptions?.testListInvert)
5277
- command.testListInvert = calculateSha13(import_fs8.default.readFileSync(runOptions.testListInvert));
5736
+ command.testListInvert = calculateSha13(import_fs9.default.readFileSync(runOptions.testListInvert));
5278
5737
  if (Object.keys(command).length)
5279
5738
  parts.push(calculateSha13(JSON.stringify(command)).substring(0, 7));
5280
5739
  return parts.join("-");
5281
5740
  }
5282
5741
 
5283
5742
  // packages/playwright/src/runner/tasks.ts
5284
- var import_fs11 = __toESM(require("fs"));
5285
- var import_path15 = __toESM(require("path"));
5286
- var import_util13 = require("util");
5743
+ var import_fs12 = __toESM(require("fs"));
5744
+ var import_path16 = __toESM(require("path"));
5745
+ var import_util14 = require("util");
5287
5746
 
5288
5747
  // packages/playwright/src/runner/rebase.ts
5289
- var import_fs9 = __toESM(require("fs"));
5290
- var import_path12 = __toESM(require("path"));
5748
+ var import_fs10 = __toESM(require("fs"));
5749
+ var import_path13 = __toESM(require("path"));
5291
5750
  var babel3 = __toESM(require("../transform/babelBundle"));
5292
5751
  var colors3 = require("playwright-core/lib/utilsBundle").colors;
5293
5752
  var diff = require("playwright-core/lib/utilsBundle").diff;
@@ -5311,9 +5770,9 @@ async function applySuggestedRebaselines(config2, reporter, filteredProjects) {
5311
5770
  const patches = [];
5312
5771
  const files = [];
5313
5772
  const gitCache = /* @__PURE__ */ new Map();
5314
- const patchFile = import_path12.default.join(project.project.outputDir, "rebaselines.patch");
5773
+ const patchFile = import_path13.default.join(project.project.outputDir, "rebaselines.patch");
5315
5774
  for (const fileName of [...suggestedRebaselines.keys()].sort()) {
5316
- const source = await import_fs9.default.promises.readFile(fileName, "utf8");
5775
+ const source = await import_fs10.default.promises.readFile(fileName, "utf8");
5317
5776
  const lines = source.split("\n");
5318
5777
  const replacements = suggestedRebaselines.get(fileName);
5319
5778
  const fileNode = babel3.babelParse(source, fileName, true);
@@ -5347,15 +5806,15 @@ async function applySuggestedRebaselines(config2, reporter, filteredProjects) {
5347
5806
  let result = source;
5348
5807
  for (const range of ranges)
5349
5808
  result = result.substring(0, range.start) + range.newText + result.substring(range.end);
5350
- const relativeName = import_path12.default.relative(process.cwd(), fileName);
5809
+ const relativeName = import_path13.default.relative(process.cwd(), fileName);
5351
5810
  files.push(relativeName);
5352
5811
  if (config2.config.updateSourceMethod === "overwrite") {
5353
- await import_fs9.default.promises.writeFile(fileName, result);
5812
+ await import_fs10.default.promises.writeFile(fileName, result);
5354
5813
  } else if (config2.config.updateSourceMethod === "3way") {
5355
- await import_fs9.default.promises.writeFile(fileName, applyPatchWithConflictMarkers(source, result));
5814
+ await import_fs10.default.promises.writeFile(fileName, applyPatchWithConflictMarkers(source, result));
5356
5815
  } else {
5357
- const gitFolder = findGitRoot(import_path12.default.dirname(fileName), gitCache);
5358
- const relativeToGit = import_path12.default.relative(gitFolder || process.cwd(), fileName);
5816
+ const gitFolder = findGitRoot(import_path13.default.dirname(fileName), gitCache);
5817
+ const relativeToGit = import_path13.default.relative(gitFolder || process.cwd(), fileName);
5359
5818
  patches.push(createPatch(relativeToGit, source, result));
5360
5819
  }
5361
5820
  }
@@ -5366,10 +5825,10 @@ New baselines created for:
5366
5825
  ${fileList}
5367
5826
  `);
5368
5827
  if (config2.config.updateSourceMethod === "patch") {
5369
- await import_fs9.default.promises.mkdir(import_path12.default.dirname(patchFile), { recursive: true });
5370
- await import_fs9.default.promises.writeFile(patchFile, patches.join("\n"));
5828
+ await import_fs10.default.promises.mkdir(import_path13.default.dirname(patchFile), { recursive: true });
5829
+ await import_fs10.default.promises.writeFile(patchFile, patches.join("\n"));
5371
5830
  reporter.onStdErr(`
5372
- ` + colors3.cyan("git apply " + import_path12.default.relative(process.cwd(), patchFile)) + "\n");
5831
+ ` + colors3.cyan("git apply " + import_path13.default.relative(process.cwd(), patchFile)) + "\n");
5373
5832
  }
5374
5833
  }
5375
5834
  function createPatch(fileName, before, after) {
@@ -5386,12 +5845,12 @@ function findGitRoot(dir, cache) {
5386
5845
  const result = cache.get(dir);
5387
5846
  if (result !== void 0)
5388
5847
  return result;
5389
- const gitPath = import_path12.default.join(dir, ".git");
5390
- if (import_fs9.default.existsSync(gitPath) && import_fs9.default.lstatSync(gitPath).isDirectory()) {
5848
+ const gitPath = import_path13.default.join(dir, ".git");
5849
+ if (import_fs10.default.existsSync(gitPath) && import_fs10.default.lstatSync(gitPath).isDirectory()) {
5391
5850
  cache.set(dir, dir);
5392
5851
  return dir;
5393
5852
  }
5394
- const parentDir = import_path12.default.dirname(dir);
5853
+ const parentDir = import_path13.default.dirname(dir);
5395
5854
  if (dir === parentDir) {
5396
5855
  cache.set(dir, null);
5397
5856
  return null;
@@ -5435,8 +5894,8 @@ function applyPatchWithConflictMarkers(oldText, newText) {
5435
5894
  }
5436
5895
 
5437
5896
  // packages/playwright/src/runner/workerHost.ts
5438
- var import_fs10 = __toESM(require("fs"));
5439
- var import_path13 = __toESM(require("path"));
5897
+ var import_fs11 = __toESM(require("fs"));
5898
+ var import_path14 = __toESM(require("path"));
5440
5899
  var import_common6 = require("../common");
5441
5900
 
5442
5901
  // packages/playwright/src/isomorphic/folders.ts
@@ -5465,13 +5924,13 @@ var WorkerHost = class extends ProcessHost {
5465
5924
  repeatEachIndex: testGroup.repeatEachIndex,
5466
5925
  projectId: testGroup.projectId,
5467
5926
  config: options.config,
5468
- artifactsDir: import_path13.default.join(options.outputDir, artifactsFolderName(workerIndex)),
5927
+ artifactsDir: import_path14.default.join(options.outputDir, artifactsFolderName(workerIndex)),
5469
5928
  pauseOnError: options.pauseOnError,
5470
5929
  pauseAtEnd: options.pauseAtEnd
5471
5930
  };
5472
5931
  }
5473
5932
  async start() {
5474
- await import_fs10.default.promises.mkdir(this._params.artifactsDir, { recursive: true });
5933
+ await import_fs11.default.promises.mkdir(this._params.artifactsDir, { recursive: true });
5475
5934
  return await this.startRunner(this._params, {
5476
5935
  onStdOut: (chunk) => this.emit("stdOut", import_common6.ipc.stdioChunkToParams(chunk)),
5477
5936
  onStdErr: (chunk) => this.emit("stdErr", import_common6.ipc.stdioChunkToParams(chunk))
@@ -5507,7 +5966,7 @@ var WorkerHost = class extends ProcessHost {
5507
5966
 
5508
5967
  // packages/playwright/src/runner/dispatcher.ts
5509
5968
  var import_common7 = require("../common");
5510
- var import_util11 = require("../util");
5969
+ var import_util12 = require("../util");
5511
5970
  var colors4 = require("playwright-core/lib/utilsBundle").colors;
5512
5971
  var { ManualPromise: ManualPromise3 } = require("playwright-core/lib/coreBundle").iso;
5513
5972
  var { eventsHelper } = require("playwright-core/lib/coreBundle").utils;
@@ -5530,11 +5989,22 @@ var Dispatcher = class {
5530
5989
  this._workerLimitPerProjectId.set(project.id, project.workers);
5531
5990
  }
5532
5991
  }
5992
+ _heldLocks() {
5993
+ const heldLocks = /* @__PURE__ */ new Set();
5994
+ for (const slot of this._workerSlots) {
5995
+ for (const lock of slot.jobDispatcher?.job.locks || [])
5996
+ heldLocks.add(lock);
5997
+ }
5998
+ return heldLocks;
5999
+ }
5533
6000
  _findFirstJobToRun() {
6001
+ const heldLocks = this._heldLocks();
5534
6002
  for (let index = 0; index < this._queue.length; index++) {
5535
6003
  const job = this._queue[index];
5536
6004
  if (this._isolatedJobs.has(job) && this._workerSlots.some((w) => !!w.jobDispatcher))
5537
6005
  continue;
6006
+ if (job.locks.some((lock) => heldLocks.has(lock)))
6007
+ continue;
5538
6008
  const projectIdWorkerLimit = this._workerLimitPerProjectId.get(job.projectId);
5539
6009
  if (!projectIdWorkerLimit)
5540
6010
  return index;
@@ -5544,18 +6014,22 @@ var Dispatcher = class {
5544
6014
  }
5545
6015
  return -1;
5546
6016
  }
6017
+ _scheduleJobs() {
6018
+ while (this._scheduleJob()) {
6019
+ }
6020
+ }
5547
6021
  _scheduleJob() {
5548
- if (this._isStopped)
5549
- return;
6022
+ if (this._isStopped || !this._workerSlots.some((w) => !w.jobDispatcher))
6023
+ return false;
5550
6024
  const jobIndex = this._findFirstJobToRun();
5551
6025
  if (jobIndex === -1)
5552
- return;
6026
+ return false;
5553
6027
  const job = this._queue[jobIndex];
5554
6028
  let workerIndex = this._workerSlots.findIndex((w) => !w.jobDispatcher && w.worker && w.worker.hash() === job.workerHash && !w.worker.didSendStop());
5555
6029
  if (workerIndex === -1)
5556
6030
  workerIndex = this._workerSlots.findIndex((w) => !w.jobDispatcher);
5557
6031
  if (workerIndex === -1) {
5558
- return;
6032
+ return false;
5559
6033
  }
5560
6034
  this._queue.splice(jobIndex, 1);
5561
6035
  const jobDispatcher = new JobDispatcher(job, this._testRun, this._ignoreMaxFailures ? void 0 : () => this.stop().catch(() => {
@@ -5564,8 +6038,9 @@ var Dispatcher = class {
5564
6038
  void this._runJobInWorker(workerIndex, jobDispatcher).then(() => {
5565
6039
  this._workerSlots[workerIndex].jobDispatcher = void 0;
5566
6040
  this._checkFinished();
5567
- this._scheduleJob();
6041
+ this._scheduleJobs();
5568
6042
  });
6043
+ return true;
5569
6044
  }
5570
6045
  async _runJobInWorker(index, jobDispatcher) {
5571
6046
  const job = jobDispatcher.job;
@@ -5643,8 +6118,7 @@ var Dispatcher = class {
5643
6118
  void this.stop();
5644
6119
  for (let i = 0; i < this._testRun.config.config.workers; i++)
5645
6120
  this._workerSlots.push({});
5646
- for (let i = 0; i < this._workerSlots.length; i++)
5647
- this._scheduleJob();
6121
+ this._scheduleJobs();
5648
6122
  this._checkFinished();
5649
6123
  await this._finished;
5650
6124
  }
@@ -5786,19 +6260,23 @@ var JobDispatcher = class {
5786
6260
  const parentStep = params.parentStepId ? steps.get(params.parentStepId) : void 0;
5787
6261
  const step = {
5788
6262
  title: params.title,
6263
+ subtitle: params.subtitle,
5789
6264
  titlePath: () => {
5790
6265
  const parentPath = parentStep?.titlePath() || [];
5791
6266
  return [...parentPath, params.title];
5792
6267
  },
5793
6268
  parent: parentStep,
5794
6269
  category: params.category,
6270
+ params: params.params,
5795
6271
  startTime: new Date(params.wallTime),
5796
6272
  duration: -1,
5797
6273
  steps: [],
5798
6274
  attachments: [],
5799
6275
  annotations: [],
5800
6276
  location: params.location,
5801
- _stepId: params.stepId
6277
+ _stepId: params.stepId,
6278
+ _apiName: params.apiName,
6279
+ _channelMethod: params.channelMethod
5802
6280
  };
5803
6281
  steps.set(params.stepId, step);
5804
6282
  (parentStep || result).steps.push(step);
@@ -5980,7 +6458,7 @@ var JobDispatcher = class {
5980
6458
  addLocationAndSnippetToError(this._testRun.config.config, response.error);
5981
6459
  return response;
5982
6460
  } catch (e) {
5983
- const error = (0, import_util11.serializeError)(e);
6461
+ const error = (0, import_util12.serializeError)(e);
5984
6462
  addLocationAndSnippetToError(this._testRun.config.config, error);
5985
6463
  return { response: void 0, error };
5986
6464
  }
@@ -6099,7 +6577,7 @@ var FixedNodeSIGINTHandler = class {
6099
6577
  };
6100
6578
 
6101
6579
  // packages/playwright/src/runner/taskRunner.ts
6102
- var import_util12 = require("../util");
6580
+ var import_util13 = require("../util");
6103
6581
  var colors5 = require("playwright-core/lib/utilsBundle").colors;
6104
6582
  var debug4 = require("playwright-core/lib/utilsBundle").debug;
6105
6583
  var { ManualPromise: ManualPromise4 } = require("playwright-core/lib/coreBundle").iso;
@@ -6140,7 +6618,7 @@ var TaskRunner = class _TaskRunner {
6140
6618
  await task.setup?.(context, errors, softErrors);
6141
6619
  } catch (e) {
6142
6620
  debug4("pw:test:task")(`error in "${task.title}": `, e);
6143
- errors.push((0, import_util12.serializeError)(e));
6621
+ errors.push((0, import_util13.serializeError)(e));
6144
6622
  } finally {
6145
6623
  for (const error of [...softErrors, ...errors])
6146
6624
  this._reporter.onError?.(error);
@@ -6202,7 +6680,7 @@ var TimeoutWatcher = class {
6202
6680
 
6203
6681
  // packages/playwright/src/runner/vcs.ts
6204
6682
  var import_child_process2 = __toESM(require("child_process"));
6205
- var import_path14 = __toESM(require("path"));
6683
+ var import_path15 = __toESM(require("path"));
6206
6684
  var import_common8 = require("../common");
6207
6685
  async function detectChangedTestFiles(baseCommit, configDir) {
6208
6686
  function gitFileList(args) {
@@ -6232,20 +6710,20 @@ async function detectChangedTestFiles(baseCommit, configDir) {
6232
6710
  ].join("\n"));
6233
6711
  }
6234
6712
  }
6235
- const untrackedFiles = gitFileList(["ls-files", "--others", "--exclude-standard"]).map((file) => import_path14.default.join(configDir, file));
6713
+ const untrackedFiles = gitFileList(["ls-files", "--others", "--exclude-standard"]).map((file) => import_path15.default.join(configDir, file));
6236
6714
  const [gitRoot] = gitFileList(["rev-parse", "--show-toplevel"]);
6237
- const trackedFilesWithChanges = gitFileList(["diff", baseCommit, "--name-only"]).map((file) => import_path14.default.join(gitRoot, file));
6715
+ const trackedFilesWithChanges = gitFileList(["diff", baseCommit, "--name-only"]).map((file) => import_path15.default.join(gitRoot, file));
6238
6716
  return new Set(import_common8.cc.affectedTestFiles([...untrackedFiles, ...trackedFilesWithChanges]));
6239
6717
  }
6240
6718
 
6241
6719
  // packages/playwright/src/runner/tasks.ts
6242
6720
  var import_common9 = require("../common");
6243
- var import_util14 = require("../util");
6721
+ var import_util15 = require("../util");
6244
6722
  var debug5 = require("playwright-core/lib/utilsBundle").debug;
6245
6723
  var { ManualPromise: ManualPromise5 } = require("playwright-core/lib/coreBundle").iso;
6246
6724
  var { monotonicTime: monotonicTime6 } = require("playwright-core/lib/coreBundle").iso;
6247
6725
  var { removeFolders: removeFolders4 } = require("playwright-core/lib/coreBundle").utils;
6248
- var readDirAsync2 = (0, import_util13.promisify)(import_fs11.default.readdir);
6726
+ var readDirAsync2 = (0, import_util14.promisify)(import_fs12.default.readdir);
6249
6727
  var TestRun = class {
6250
6728
  constructor(config2, reporter, options) {
6251
6729
  this.rootSuite = void 0;
@@ -6316,7 +6794,6 @@ function createRunTestsTasks(config2) {
6316
6794
  return [
6317
6795
  createPhasesTask(),
6318
6796
  createReportBeginTask(),
6319
- ...config2.plugins.map((plugin) => createPluginBeginTask(plugin)),
6320
6797
  createRunTestsTask()
6321
6798
  ];
6322
6799
  }
@@ -6324,9 +6801,7 @@ function createClearCacheTask(config2) {
6324
6801
  return {
6325
6802
  title: "clear cache",
6326
6803
  setup: async () => {
6327
- await (0, import_util14.removeDirAndLogToConsole)(import_common9.cc.cacheDir);
6328
- for (const plugin of config2.plugins)
6329
- await plugin.instance?.clearCache?.();
6804
+ await (0, import_util15.removeDirAndLogToConsole)(import_common9.cc.cacheDir);
6330
6805
  }
6331
6806
  };
6332
6807
  }
@@ -6355,17 +6830,6 @@ function createPluginSetupTasks(config2) {
6355
6830
  }
6356
6831
  }));
6357
6832
  }
6358
- function createPluginBeginTask(plugin) {
6359
- return {
6360
- title: "plugin begin",
6361
- setup: async (testRun) => {
6362
- await plugin.instance?.begin?.(testRun.rootSuite);
6363
- },
6364
- teardown: async () => {
6365
- await plugin.instance?.end?.();
6366
- }
6367
- };
6368
- }
6369
6833
  function createGlobalSetupTask(file, config2) {
6370
6834
  let title = "global setup";
6371
6835
  if (config2.globalSetups.length > 1)
@@ -6408,7 +6872,7 @@ function createRemoveOutputDirsTask() {
6408
6872
  return;
6409
6873
  if (error.code === "EBUSY") {
6410
6874
  const entries = await readDirAsync2(outputDir).catch((e) => []);
6411
- await Promise.all(entries.map((entry) => removeFolders4([import_path15.default.join(outputDir, entry)])));
6875
+ await Promise.all(entries.map((entry) => removeFolders4([import_path16.default.join(outputDir, entry)])));
6412
6876
  } else {
6413
6877
  throw error;
6414
6878
  }
@@ -6427,7 +6891,7 @@ function createListFilesTask() {
6427
6891
  projectSuite._fullProject = project;
6428
6892
  testRun.rootSuite._addSuite(projectSuite);
6429
6893
  const suites = files.map((file) => {
6430
- const title = import_path15.default.relative(testRun.config.config.rootDir, file);
6894
+ const title = import_path16.default.relative(testRun.config.config.rootDir, file);
6431
6895
  const suite = new import_common9.test.Suite(title, "file");
6432
6896
  suite.location = { file, line: 0, column: 0 };
6433
6897
  projectSuite._addSuite(suite);
@@ -6457,8 +6921,8 @@ function createLoadTask(mode, options) {
6457
6921
  testRun.preOnlyTestFilters.push((test) => !testFilter(test));
6458
6922
  }
6459
6923
  if (testRun.options.grep || testRun.options.grepInvert) {
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;
6924
+ const grepMatcher = testRun.options.grep ? (0, import_util15.createTitleMatcher)((0, import_util15.forceRegExp)(testRun.options.grep)) : () => true;
6925
+ const grepInvertMatcher = testRun.options.grepInvert ? (0, import_util15.createTitleMatcher)((0, import_util15.forceRegExp)(testRun.options.grepInvert)) : () => false;
6462
6926
  testRun.preOnlyTestFilters.push((test) => {
6463
6927
  const grepTitle = test._grepTitleWithTags();
6464
6928
  return !grepInvertMatcher(grepTitle) && grepMatcher(grepTitle);
@@ -6470,10 +6934,6 @@ function createLoadTask(mode, options) {
6470
6934
  }
6471
6935
  await collectProjectsAndTestFiles(testRun, !!options.doNotRunDepsOutsideProjectFilter);
6472
6936
  await loadFileSuites(testRun, mode, options.failOnLoadErrors ? errors : softErrors);
6473
- if (testRun.options.onlyChanged || options.populateDependencies) {
6474
- for (const plugin of testRun.config.plugins)
6475
- await plugin.instance?.populateDependencies?.();
6476
- }
6477
6937
  if (testRun.options.onlyChanged) {
6478
6938
  const changedFiles = await detectChangedTestFiles(testRun.options.onlyChanged, testRun.config.configDir);
6479
6939
  testRun.preOnlyTestFilters.push((test) => changedFiles.has(test.location.file));
@@ -6597,25 +7057,32 @@ function createRunTestsTask() {
6597
7057
  }
6598
7058
 
6599
7059
  // packages/playwright/src/runner/lastRun.ts
6600
- var import_fs12 = __toESM(require("fs"));
6601
- var import_path16 = __toESM(require("path"));
7060
+ var import_fs13 = __toESM(require("fs"));
7061
+ var import_path17 = __toESM(require("path"));
7062
+ function didNotRun(test) {
7063
+ if (test.outcome() !== "skipped")
7064
+ return false;
7065
+ if (test.results.some((result) => result.status === "interrupted"))
7066
+ return false;
7067
+ return !test.results.length || test.expectedStatus !== "skipped";
7068
+ }
6602
7069
  var LastRunReporter = class {
6603
7070
  constructor(filteredProjects, listMode, lastFailedFileOverride) {
6604
7071
  this._listMode = !!listMode;
6605
7072
  const override = lastFailedFileOverride ?? process.env.PLAYWRIGHT_LAST_RUN_OUTPUT_FILE;
6606
7073
  if (override) {
6607
- this._lastRunFile = import_path16.default.resolve(process.cwd(), override);
7074
+ this._lastRunFile = import_path17.default.resolve(process.cwd(), override);
6608
7075
  } else {
6609
7076
  const [project] = filteredProjects;
6610
7077
  if (project)
6611
- this._lastRunFile = import_path16.default.join(project.project.outputDir, ".last-run.json");
7078
+ this._lastRunFile = import_path17.default.join(project.project.outputDir, ".last-run.json");
6612
7079
  }
6613
7080
  }
6614
7081
  async filterLastFailed() {
6615
7082
  if (!this._lastRunFile)
6616
7083
  return void 0;
6617
7084
  try {
6618
- const lastRunInfo = JSON.parse(await import_fs12.default.promises.readFile(this._lastRunFile, "utf8"));
7085
+ const lastRunInfo = JSON.parse(await import_fs13.default.promises.readFile(this._lastRunFile, "utf8"));
6619
7086
  return lastRunInfo.failedTests;
6620
7087
  } catch {
6621
7088
  return void 0;
@@ -6635,10 +7102,10 @@ var LastRunReporter = class {
6635
7102
  return;
6636
7103
  const lastRunInfo = {
6637
7104
  status: result.status,
6638
- failedTests: this._suite?.allTests().filter((t2) => !t2.ok()).map((t2) => t2.id) || []
7105
+ failedTests: this._suite?.allTests().filter((t2) => !t2.ok() || didNotRun(t2)).map((t2) => t2.id) || []
6639
7106
  };
6640
- await import_fs12.default.promises.mkdir(import_path16.default.dirname(this._lastRunFile), { recursive: true });
6641
- await import_fs12.default.promises.writeFile(this._lastRunFile, JSON.stringify(lastRunInfo, void 0, 2));
7107
+ await import_fs13.default.promises.mkdir(import_path17.default.dirname(this._lastRunFile), { recursive: true });
7108
+ await import_fs13.default.promises.writeFile(this._lastRunFile, JSON.stringify(lastRunInfo, void 0, 2));
6642
7109
  }
6643
7110
  };
6644
7111
 
@@ -6658,7 +7125,6 @@ var TestRunner = class extends import_events2.default {
6658
7125
  this._watchedTestDependencies = /* @__PURE__ */ new Set();
6659
7126
  this._queue = Promise.resolve();
6660
7127
  this._watchTestDirs = false;
6661
- this._populateDependenciesOnList = false;
6662
7128
  this._startingEnv = {};
6663
7129
  this.configLocation = configLocation;
6664
7130
  this._configCLIOverrides = configCLIOverrides;
@@ -6671,7 +7137,6 @@ var TestRunner = class extends import_events2.default {
6671
7137
  async initialize(params) {
6672
7138
  setPlaywrightTestProcessEnv();
6673
7139
  this._watchTestDirs = !!params.watchTestDirs;
6674
- this._populateDependenciesOnList = !!params.populateDependenciesOnList;
6675
7140
  this._startingEnv = { ...process.env };
6676
7141
  }
6677
7142
  resizeTerminal(params) {
@@ -6683,7 +7148,7 @@ var TestRunner = class extends import_events2.default {
6683
7148
  hasSomeBrowsers() {
6684
7149
  for (const browserName of ["chromium", "webkit", "firefox"]) {
6685
7150
  try {
6686
- import_coreBundle2.registry.registry.findExecutable(browserName).executablePathOrDie("javascript");
7151
+ import_coreBundle3.registry.registry.findExecutable(browserName).executablePathOrDie("javascript");
6687
7152
  return true;
6688
7153
  } catch {
6689
7154
  }
@@ -6691,8 +7156,8 @@ var TestRunner = class extends import_events2.default {
6691
7156
  return false;
6692
7157
  }
6693
7158
  async installBrowsers() {
6694
- const executables = import_coreBundle2.registry.registry.defaultExecutables();
6695
- await import_coreBundle2.registry.registry.install(executables);
7159
+ const executables = import_coreBundle3.registry.registry.defaultExecutables();
7160
+ await import_coreBundle3.registry.registry.install(executables);
6696
7161
  }
6697
7162
  async loadConfig() {
6698
7163
  const { config: config2, error } = await this._loadConfig(this._configCLIOverrides);
@@ -6732,7 +7197,6 @@ var TestRunner = class extends import_events2.default {
6732
7197
  if (!config2)
6733
7198
  return { status: "failed" };
6734
7199
  const status = await runTasks(new TestRun(config2, reporter), [
6735
- ...createPluginSetupTasks(config2),
6736
7200
  createClearCacheTask(config2)
6737
7201
  ]);
6738
7202
  return { status };
@@ -6779,7 +7243,7 @@ var TestRunner = class extends import_events2.default {
6779
7243
  listMode: true
6780
7244
  };
6781
7245
  const status = await runTasks(new TestRun(config2, reporter, options), [
6782
- createLoadTask("out-of-process", { failOnLoadErrors: false, filterOnly: false, populateDependencies: this._populateDependenciesOnList }),
7246
+ createLoadTask("out-of-process", { failOnLoadErrors: false, filterOnly: false }),
6783
7247
  createReportBeginTask()
6784
7248
  ]);
6785
7249
  return { config: config2, status };
@@ -6791,11 +7255,6 @@ var TestRunner = class extends import_events2.default {
6791
7255
  this._watchedProjectDirs.add(p.project.testDir);
6792
7256
  this._ignoredProjectOutputs.add(p.project.outputDir);
6793
7257
  }
6794
- const result = await resolveCtDirs(config2);
6795
- if (result) {
6796
- this._watchedProjectDirs.add(result.templateDir);
6797
- this._ignoredProjectOutputs.add(result.outDir);
6798
- }
6799
7258
  if (this._watchTestDirs)
6800
7259
  await this._updateWatcher(false);
6801
7260
  }
@@ -6886,7 +7345,7 @@ var TestRunner = class extends import_events2.default {
6886
7345
  return { errors: errorReporter.errors(), testFiles: [] };
6887
7346
  const status = await runTasks(new TestRun(config2, reporter), [
6888
7347
  ...createPluginSetupTasks(config2),
6889
- createLoadTask("out-of-process", { failOnLoadErrors: true, filterOnly: false, populateDependencies: true })
7348
+ createLoadTask("out-of-process", { failOnLoadErrors: true, filterOnly: false })
6890
7349
  ]);
6891
7350
  if (status !== "passed")
6892
7351
  return { errors: errorReporter.errors(), testFiles: [] };
@@ -6915,7 +7374,7 @@ var TestRunner = class extends import_events2.default {
6915
7374
  this._lastLoadedConfig = config2;
6916
7375
  return { config: config2 };
6917
7376
  } catch (e) {
6918
- return { config: null, error: (0, import_util15.serializeError)(e) };
7377
+ return { config: null, error: (0, import_util16.serializeError)(e) };
6919
7378
  }
6920
7379
  }
6921
7380
  lastLoadedConfig() {
@@ -6935,18 +7394,6 @@ var TestRunner = class extends import_events2.default {
6935
7394
  function printInternalError(e) {
6936
7395
  console.error("Internal error:", e);
6937
7396
  }
6938
- async function resolveCtDirs(config2) {
6939
- const use = config2.config.projects[0].use;
6940
- const relativeTemplateDir = use.ctTemplateDir || "playwright";
6941
- const templateDir = await import_fs13.default.promises.realpath(import_path17.default.normalize(import_path17.default.join(config2.configDir, relativeTemplateDir))).catch(() => void 0);
6942
- if (!templateDir)
6943
- return null;
6944
- const outDir = use.ctCacheDir ? import_path17.default.resolve(config2.configDir, use.ctCacheDir) : import_path17.default.resolve(templateDir, ".cache");
6945
- return {
6946
- outDir,
6947
- templateDir
6948
- };
6949
- }
6950
7397
  async function runAllTestsWithConfig(config2, options) {
6951
7398
  setPlaywrightTestProcessEnv();
6952
7399
  addGitCommitInfoPlugin(config2);
@@ -6983,8 +7430,8 @@ __export(testServer_exports, {
6983
7430
  runTestServer: () => runTestServer,
6984
7431
  runUIMode: () => runUIMode
6985
7432
  });
6986
- var import_util16 = __toESM(require("util"));
6987
- var import_coreBundle3 = require("playwright-core/lib/coreBundle");
7433
+ var import_util17 = __toESM(require("util"));
7434
+ var import_coreBundle4 = require("playwright-core/lib/coreBundle");
6988
7435
  var import_common11 = require("../common");
6989
7436
 
6990
7437
  // packages/playwright/src/runner/uiModeReporter.ts
@@ -7013,7 +7460,7 @@ var TestServer = class {
7013
7460
  }
7014
7461
  async start(options) {
7015
7462
  this._dispatcher = new TestServerDispatcher(this._configLocation, this._configCLIOverrides);
7016
- return await import_coreBundle3.server.startTraceViewerServer({
7463
+ return await import_coreBundle4.server.startTraceViewerServer({
7017
7464
  host: options.host,
7018
7465
  port: options.port,
7019
7466
  allowedFileRoots: () => this._allowedFileRoots(),
@@ -7143,7 +7590,7 @@ var TestServerDispatcher = class {
7143
7590
  if (interceptStdio) {
7144
7591
  if (debug6.log === originalDebugLog) {
7145
7592
  debug6.log = (...args) => {
7146
- const string = import_util16.default.format(...args) + "\n";
7593
+ const string = import_util17.default.format(...args) + "\n";
7147
7594
  return originalStderrWrite.apply(process.stderr, [string]);
7148
7595
  };
7149
7596
  }
@@ -7169,12 +7616,12 @@ var TestServerDispatcher = class {
7169
7616
  async function runUIMode(configFile, configCLIOverrides, options) {
7170
7617
  const configLocation = import_common11.configLoader.resolveConfigLocation(configFile);
7171
7618
  return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server, cancelPromise) => {
7172
- await import_coreBundle3.server.installRootRedirect(server, void 0, { ...options, webApp: "uiMode.html" });
7619
+ await import_coreBundle4.server.installRootRedirect(server, void 0, { ...options, webApp: "uiMode.html" });
7173
7620
  if (options.host !== void 0 || options.port !== void 0) {
7174
- await import_coreBundle3.server.openTraceInBrowser(server.urlPrefix("human-readable"));
7621
+ await import_coreBundle4.server.openTraceInBrowser(server.urlPrefix("human-readable"));
7175
7622
  } else {
7176
7623
  const channel = await installedChromiumChannelForUI(configLocation, configCLIOverrides);
7177
- const page = await import_coreBundle3.server.openTraceViewerApp(server.urlPrefix("precise"), "chromium", {
7624
+ const page = await import_coreBundle4.server.openTraceViewerApp(server.urlPrefix("precise"), "chromium", {
7178
7625
  headless: isUnderTest() && process.env.PWTEST_HEADED_FOR_TEST !== "1",
7179
7626
  persistentContextOptions: {
7180
7627
  handleSIGINT: false,
@@ -7239,7 +7686,7 @@ __export(watchMode_exports, {
7239
7686
  var import_path18 = __toESM(require("path"));
7240
7687
  var import_readline = __toESM(require("readline"));
7241
7688
  var import_events3 = require("events");
7242
- var import_coreBundle4 = require("playwright-core/lib/coreBundle");
7689
+ var import_coreBundle5 = require("playwright-core/lib/coreBundle");
7243
7690
 
7244
7691
  // packages/playwright/src/isomorphic/testTree.ts
7245
7692
  var statusEx = /* @__PURE__ */ Symbol("statusEx");
@@ -7658,8 +8105,7 @@ async function runWatchModeLoop(configLocation, initialOptions) {
7658
8105
  testServerConnection.onReport((report2) => teleSuiteUpdater.processTestReportEvent(report2));
7659
8106
  await testServerConnection.initialize({
7660
8107
  interceptStdio: false,
7661
- watchTestDirs: true,
7662
- populateDependenciesOnList: true
8108
+ watchTestDirs: true
7663
8109
  });
7664
8110
  await testServerConnection.runGlobalSetup({});
7665
8111
  const { report } = await testServerConnection.listTests({});
@@ -7921,7 +8367,7 @@ ${colors6.dim("Waiting for file changes. Press")} ${colors6.bold("enter")} ${col
7921
8367
  }
7922
8368
  async function toggleShowBrowser() {
7923
8369
  if (!showBrowserServer) {
7924
- showBrowserServer = new import_coreBundle4.remote.PlaywrightServer({ mode: "extension", path: "/" + createGuid3(), maxConnections: 1 });
8370
+ showBrowserServer = new import_coreBundle5.remote.PlaywrightServer({ mode: "extension", path: "/" + createGuid3(), maxConnections: 1 });
7925
8371
  connectWsEndpoint = await showBrowserServer.listen();
7926
8372
  process.stdout.write(`${colors6.dim("Show & reuse browser:")} ${colors6.bold("on")}
7927
8373
  `);
@@ -7985,7 +8431,7 @@ var JsonStringInternalizer = class {
7985
8431
  };
7986
8432
 
7987
8433
  // packages/playwright/src/reporters/merge.ts
7988
- var import_util17 = require("../util");
8434
+ var import_util18 = require("../util");
7989
8435
  var { isPathInside } = require("playwright-core/lib/coreBundle").utils;
7990
8436
  var { ZipFile } = require("playwright-core/lib/coreBundle").utils;
7991
8437
  async function createMergedReport(config2, dir, reporterDescriptions, rootDirOverride) {
@@ -8081,7 +8527,7 @@ async function extractAndParseReports(dir, shardFiles, internalizer, printStatus
8081
8527
  const reportNames = new UniqueFileNameGenerator();
8082
8528
  for (const file of shardFiles) {
8083
8529
  const absolutePath = import_path19.default.join(dir, file);
8084
- printStatus(`extracting: ${(0, import_util17.relativeFilePath)(absolutePath)}`);
8530
+ printStatus(`extracting: ${(0, import_util18.relativeFilePath)(absolutePath)}`);
8085
8531
  const zipFile = new ZipFile(absolutePath);
8086
8532
  const entryNames = await zipFile.entries();
8087
8533
  for (const entryName of entryNames.sort()) {