patchright-bun 1.58.2 → 1.59.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.
Files changed (108) hide show
  1. package/ThirdPartyNotices.txt +10 -1133
  2. package/lib/agents/generateAgents.js +2 -4
  3. package/lib/common/config.js +4 -5
  4. package/lib/common/expectBundleImpl.js +221 -221
  5. package/lib/common/process.js +1 -0
  6. package/lib/common/test.js +10 -1
  7. package/lib/common/testType.js +3 -0
  8. package/lib/common/validators.js +38 -38
  9. package/lib/errorContext.js +121 -0
  10. package/lib/index.js +98 -60
  11. package/lib/isomorphic/teleReceiver.js +26 -9
  12. package/lib/isomorphic/testServerConnection.js +3 -5
  13. package/lib/matchers/matchers.js +2 -0
  14. package/lib/matchers/toMatchAriaSnapshot.js +5 -1
  15. package/lib/matchers/toMatchSnapshot.js +42 -35
  16. package/lib/mcp/test/browserBackend.js +45 -22
  17. package/lib/mcp/test/generatorTools.js +9 -9
  18. package/lib/mcp/test/plannerTools.js +17 -17
  19. package/lib/mcp/test/testBackend.js +27 -27
  20. package/lib/mcp/test/testContext.js +6 -8
  21. package/lib/mcp/test/testTools.js +9 -9
  22. package/lib/plugins/webServerPlugin.js +2 -1
  23. package/lib/program.js +34 -212
  24. package/lib/reportActions.js +80 -0
  25. package/lib/reporters/base.js +4 -5
  26. package/lib/reporters/blob.js +2 -2
  27. package/lib/reporters/github.js +1 -2
  28. package/lib/reporters/html.js +64 -31
  29. package/lib/reporters/junit.js +104 -15
  30. package/lib/reporters/line.js +1 -1
  31. package/lib/reporters/list.js +2 -3
  32. package/lib/reporters/merge.js +47 -26
  33. package/lib/reporters/multiplexer.js +6 -2
  34. package/lib/reporters/teleEmitter.js +2 -0
  35. package/lib/runner/dispatcher.js +6 -14
  36. package/lib/runner/loadUtils.js +11 -5
  37. package/lib/runner/projectUtils.js +1 -1
  38. package/lib/runner/reporters.js +5 -0
  39. package/lib/runner/tasks.js +11 -8
  40. package/lib/runner/testRunner.js +2 -2
  41. package/lib/runner/workerHost.js +0 -3
  42. package/lib/testActions.js +220 -0
  43. package/lib/transform/babelBundle.js +0 -3
  44. package/lib/transform/babelBundleImpl.js +134 -134
  45. package/lib/transform/compilationCache.js +0 -2
  46. package/lib/transform/esmLoader.js +8 -6
  47. package/lib/transform/transform.js +3 -10
  48. package/lib/utilsBundle.js +0 -7
  49. package/lib/utilsBundleImpl.js +48 -51
  50. package/lib/worker/fixtureRunner.js +2 -2
  51. package/lib/worker/testInfo.js +10 -14
  52. package/lib/worker/testTracing.js +12 -6
  53. package/lib/worker/timeoutManager.js +14 -3
  54. package/lib/worker/workerMain.js +24 -21
  55. package/package.json +2 -6
  56. package/types/test.d.ts +83 -12
  57. package/lib/mcp/browser/browserContextFactory.js +0 -329
  58. package/lib/mcp/browser/browserServerBackend.js +0 -84
  59. package/lib/mcp/browser/config.js +0 -421
  60. package/lib/mcp/browser/context.js +0 -244
  61. package/lib/mcp/browser/response.js +0 -278
  62. package/lib/mcp/browser/sessionLog.js +0 -75
  63. package/lib/mcp/browser/tab.js +0 -343
  64. package/lib/mcp/browser/tools/common.js +0 -65
  65. package/lib/mcp/browser/tools/console.js +0 -46
  66. package/lib/mcp/browser/tools/dialogs.js +0 -60
  67. package/lib/mcp/browser/tools/evaluate.js +0 -61
  68. package/lib/mcp/browser/tools/files.js +0 -58
  69. package/lib/mcp/browser/tools/form.js +0 -63
  70. package/lib/mcp/browser/tools/install.js +0 -72
  71. package/lib/mcp/browser/tools/keyboard.js +0 -107
  72. package/lib/mcp/browser/tools/mouse.js +0 -107
  73. package/lib/mcp/browser/tools/navigate.js +0 -71
  74. package/lib/mcp/browser/tools/network.js +0 -63
  75. package/lib/mcp/browser/tools/open.js +0 -57
  76. package/lib/mcp/browser/tools/pdf.js +0 -49
  77. package/lib/mcp/browser/tools/runCode.js +0 -78
  78. package/lib/mcp/browser/tools/screenshot.js +0 -93
  79. package/lib/mcp/browser/tools/snapshot.js +0 -173
  80. package/lib/mcp/browser/tools/tabs.js +0 -67
  81. package/lib/mcp/browser/tools/tool.js +0 -47
  82. package/lib/mcp/browser/tools/tracing.js +0 -74
  83. package/lib/mcp/browser/tools/utils.js +0 -94
  84. package/lib/mcp/browser/tools/verify.js +0 -143
  85. package/lib/mcp/browser/tools/wait.js +0 -63
  86. package/lib/mcp/browser/tools.js +0 -84
  87. package/lib/mcp/browser/watchdog.js +0 -44
  88. package/lib/mcp/config.d.js +0 -16
  89. package/lib/mcp/extension/cdpRelay.js +0 -351
  90. package/lib/mcp/extension/extensionContextFactory.js +0 -76
  91. package/lib/mcp/extension/protocol.js +0 -28
  92. package/lib/mcp/index.js +0 -61
  93. package/lib/mcp/log.js +0 -35
  94. package/lib/mcp/program.js +0 -111
  95. package/lib/mcp/sdk/exports.js +0 -28
  96. package/lib/mcp/sdk/http.js +0 -152
  97. package/lib/mcp/sdk/inProcessTransport.js +0 -71
  98. package/lib/mcp/sdk/server.js +0 -223
  99. package/lib/mcp/sdk/tool.js +0 -47
  100. package/lib/mcp/terminal/cli.js +0 -296
  101. package/lib/mcp/terminal/command.js +0 -56
  102. package/lib/mcp/terminal/commands.js +0 -333
  103. package/lib/mcp/terminal/daemon.js +0 -129
  104. package/lib/mcp/terminal/help.json +0 -32
  105. package/lib/mcp/terminal/helpGenerator.js +0 -88
  106. package/lib/mcp/terminal/socketConnection.js +0 -80
  107. package/lib/runner/storage.js +0 -91
  108. package/lib/transform/md.js +0 -221
@@ -222,14 +222,14 @@ class FixtureRunner {
222
222
  return null;
223
223
  params[name] = fixture.value;
224
224
  }
225
- return params;
225
+ return { result: params };
226
226
  }
227
227
  async resolveParametersAndRunFunction(fn, testInfo, autoFixtures, runnable) {
228
228
  const params = await this.resolveParametersForFunction(fn, testInfo, autoFixtures, runnable);
229
229
  if (params === null) {
230
230
  return null;
231
231
  }
232
- await testInfo._runWithTimeout(runnable, () => fn(params, testInfo));
232
+ await testInfo._runWithTimeout(runnable, () => fn(params.result, testInfo));
233
233
  }
234
234
  async _setupFixtureForRegistration(registration, testInfo, runnable) {
235
235
  if (registration.scope === "test")
@@ -50,9 +50,7 @@ const emtpyTestInfoCallbacks = {
50
50
  },
51
51
  onAttach: () => {
52
52
  },
53
- onTestPaused: () => Promise.reject(new Error("TestInfoImpl not initialized")),
54
- onCloneStorage: () => Promise.reject(new Error("TestInfoImpl not initialized")),
55
- onUpstreamStorage: () => Promise.resolve()
53
+ onTestPaused: () => Promise.reject(new Error("TestInfoImpl not initialized"))
56
54
  };
57
55
  class TestInfoImpl {
58
56
  constructor(configInternal, projectInternal, workerParams, test, retry, callbacks) {
@@ -62,6 +60,7 @@ class TestInfoImpl {
62
60
  this._lastStepId = 0;
63
61
  this._steps = [];
64
62
  this._stepMap = /* @__PURE__ */ new Map();
63
+ this._onDidFinishTestFunctionCallbacks = /* @__PURE__ */ new Set();
65
64
  this._hasNonRetriableError = false;
66
65
  this._hasUnhandledError = false;
67
66
  this._allowSkips = false;
@@ -71,6 +70,7 @@ class TestInfoImpl {
71
70
  this.status = "passed";
72
71
  this.snapshotSuffix = "";
73
72
  this.errors = [];
73
+ this._ignoreTimeoutsCounter = 0;
74
74
  this.testId = test?.id ?? "";
75
75
  this._callbacks = callbacks;
76
76
  this._startTime = (0, import_utils.monotonicTime)();
@@ -96,8 +96,8 @@ class TestInfoImpl {
96
96
  });
97
97
  this.expectedStatus = test?.expectedStatus ?? "skipped";
98
98
  this._timeoutManager = new import_timeoutManager.TimeoutManager(this.project.timeout);
99
- if (configInternal.configCLIOverrides.debug)
100
- this._setDebugMode();
99
+ if (configInternal.configCLIOverrides.debug === "inspector")
100
+ this._setIgnoreTimeouts(true);
101
101
  this.outputDir = (() => {
102
102
  const relativeTestFilePath = import_path.default.relative(this.project.testDir, this._requireFile.replace(/\.(spec|test)\.(js|ts|jsx|tsx|mjs|mts|cjs|cts)$/, ""));
103
103
  const sanitizedRelativePath = relativeTestFilePath.replace(process.platform === "win32" ? new RegExp("\\\\", "g") : new RegExp("/", "g"), "-");
@@ -341,8 +341,9 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
341
341
  const type = this._timeoutManager.currentSlotType();
342
342
  return ["beforeAll", "afterAll", "beforeEach", "afterEach"].includes(type) ? type : void 0;
343
343
  }
344
- _setDebugMode() {
345
- this._timeoutManager.setIgnoreTimeouts();
344
+ _setIgnoreTimeouts(ignoreTimeouts) {
345
+ this._ignoreTimeoutsCounter += ignoreTimeouts ? 1 : -1;
346
+ this._timeoutManager.setIgnoreTimeouts(this._ignoreTimeoutsCounter > 0);
346
347
  }
347
348
  async _didFinishTestFunction() {
348
349
  const shouldPause = this._workerParams.pauseAtEnd && !this._isFailure() || this._workerParams.pauseOnError && this._isFailure();
@@ -352,7 +353,8 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
352
353
  this._interruptedPromise
353
354
  ]);
354
355
  }
355
- await this._onDidFinishTestFunctionCallback?.();
356
+ for (const cb of this._onDidFinishTestFunctionCallbacks)
357
+ await cb();
356
358
  }
357
359
  // ------------ TestInfo methods ------------
358
360
  async attach(name, options = {}) {
@@ -472,12 +474,6 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
472
474
  setTimeout(timeout) {
473
475
  this._timeoutManager.setTimeout(timeout);
474
476
  }
475
- async _cloneStorage(storageFile) {
476
- return await this._callbacks.onCloneStorage({ storageFile });
477
- }
478
- async _upstreamStorage(storageFile, storageOutFile) {
479
- await this._callbacks.onUpstreamStorage({ storageFile, storageOutFile });
480
- }
481
477
  artifactsDir() {
482
478
  return this._workerParams.artifactsDir;
483
479
  }
@@ -35,7 +35,6 @@ module.exports = __toCommonJS(testTracing_exports);
35
35
  var import_fs = __toESM(require("fs"));
36
36
  var import_path = __toESM(require("path"));
37
37
  var import_utils = require("patchright-bun-core/lib/utils");
38
- var import_zipBundle = require("patchright-bun-core/lib/zipBundle");
39
38
  var import_util = require("../util");
40
39
  const testTraceEntryName = "test.trace";
41
40
  const version = 8;
@@ -73,10 +72,12 @@ class TestTracing {
73
72
  return true;
74
73
  if (this._options?.mode === "retain-on-first-failure" && this._testInfo.retry === 0)
75
74
  return true;
75
+ if (this._options?.mode === "retain-on-failure-and-retries")
76
+ return true;
76
77
  return false;
77
78
  }
78
79
  async startIfNeeded(value) {
79
- const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true, _live: false, mode: "off" };
80
+ const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true, live: false, mode: "off" };
80
81
  if (!value) {
81
82
  this._options = defaultTraceOptions;
82
83
  } else if (typeof value === "string") {
@@ -89,7 +90,7 @@ class TestTracing {
89
90
  this._options = void 0;
90
91
  return;
91
92
  }
92
- if (!this._liveTraceFile && this._options._live) {
93
+ if (!this._liveTraceFile && this._options.live) {
93
94
  this._liveTraceFile = { file: import_path.default.join(this._tracesDir, `${this._testInfo.testId}-test.trace`), fs: new import_utils.SerializedFS() };
94
95
  this._liveTraceFile.fs.mkdir(import_path.default.dirname(this._liveTraceFile.file));
95
96
  const data = this._traceEvents.map((e) => JSON.stringify(e)).join("\n") + "\n";
@@ -131,9 +132,12 @@ class TestTracing {
131
132
  if (!this._options)
132
133
  return true;
133
134
  const testFailed = this._testInfo.status !== this._testInfo.expectedStatus;
135
+ if (this._options.mode === "retain-on-failure-and-retries")
136
+ return !testFailed && this._testInfo.retry === 0;
134
137
  return !testFailed && (this._options.mode === "retain-on-failure" || this._options.mode === "retain-on-first-failure");
135
138
  }
136
139
  async stopIfNeeded() {
140
+ this._contextCreatedEvent.testTimeout = this._testInfo.timeout;
137
141
  if (!this._options)
138
142
  return;
139
143
  const error = await this._liveTraceFile?.fs.syncAndGetError();
@@ -145,7 +149,8 @@ class TestTracing {
145
149
  });
146
150
  return;
147
151
  }
148
- const zipFile = new import_zipBundle.yazl.ZipFile();
152
+ const { yazl } = await import("playwright-core/lib/zipBundle");
153
+ const zipFile = new yazl.ZipFile();
149
154
  if (!this._options?.attachments) {
150
155
  for (const event of this._traceEvents) {
151
156
  if (event.type === "after")
@@ -292,13 +297,14 @@ async function mergeTraceFiles(fileName, temporaryTraceFiles) {
292
297
  return;
293
298
  }
294
299
  const mergePromise = new import_utils.ManualPromise();
295
- const zipFile = new import_zipBundle.yazl.ZipFile();
300
+ const { yazl, yauzl } = await import("playwright-core/lib/zipBundle");
301
+ const zipFile = new yazl.ZipFile();
296
302
  const entryNames = /* @__PURE__ */ new Set();
297
303
  zipFile.on("error", (error) => mergePromise.reject(error));
298
304
  for (let i = temporaryTraceFiles.length - 1; i >= 0; --i) {
299
305
  const tempFile = temporaryTraceFiles[i];
300
306
  const promise = new import_utils.ManualPromise();
301
- import_zipBundle.yauzl.open(tempFile, (err, inZipFile) => {
307
+ yauzl.open(tempFile, (err, inZipFile) => {
302
308
  if (err) {
303
309
  promise.reject(err);
304
310
  return;
@@ -30,12 +30,20 @@ const kMaxDeadline = 2147483647;
30
30
  class TimeoutManager {
31
31
  constructor(timeout) {
32
32
  this._ignoreTimeouts = false;
33
+ this._slow = false;
33
34
  this._defaultSlot = { timeout, elapsed: 0 };
34
35
  }
35
- setIgnoreTimeouts() {
36
- this._ignoreTimeouts = true;
37
- if (this._running)
36
+ setIgnoreTimeouts(ignoreTimeouts) {
37
+ if (this._ignoreTimeouts === ignoreTimeouts)
38
+ return;
39
+ this._ignoreTimeouts = ignoreTimeouts;
40
+ if (this._running) {
41
+ if (ignoreTimeouts)
42
+ this._running.slot.elapsed += (0, import_utils.monotonicTime)() - this._running.start;
43
+ else
44
+ this._running.start = (0, import_utils.monotonicTime)();
38
45
  this._updateTimeout(this._running);
46
+ }
39
47
  }
40
48
  interrupt() {
41
49
  if (this._running)
@@ -97,6 +105,9 @@ class TimeoutManager {
97
105
  return this._defaultSlot;
98
106
  }
99
107
  slow() {
108
+ if (this._slow)
109
+ return;
110
+ this._slow = true;
100
111
  const slot = this._running ? this._running.slot : this._defaultSlot;
101
112
  slot.timeout = slot.timeout * 3;
102
113
  if (this._running)
@@ -181,24 +181,27 @@ class WorkerMain extends import_process.ProcessRunner {
181
181
  const suite = (0, import_suiteUtils.bindFileSuiteToProject)(this._project, fileSuite);
182
182
  if (this._params.repeatEachIndex)
183
183
  (0, import_suiteUtils.applyRepeatEachIndex)(this._project, suite, this._params.repeatEachIndex);
184
- const hasEntries = (0, import_suiteUtils.filterTestsRemoveEmptySuites)(suite, (test) => entries.has(test.id));
185
- if (hasEntries) {
186
- this._poolBuilder.buildPools(suite);
187
- this._activeSuites = /* @__PURE__ */ new Map();
188
- this._didRunFullCleanup = false;
189
- const tests = suite.allTests();
190
- for (let i = 0; i < tests.length; i++) {
191
- if (this._isStopped && this._didRunFullCleanup)
192
- break;
193
- const entry = entries.get(tests[i].id);
194
- entries.delete(tests[i].id);
195
- (0, import_util.debugTest)(`test started "${tests[i].title}"`);
196
- await this._runTest(tests[i], entry.retry, tests[i + 1]);
197
- (0, import_util.debugTest)(`test finished "${tests[i].title}"`);
198
- }
199
- } else {
200
- fatalUnknownTestIds = runPayload.entries.map((e) => e.testId);
184
+ (0, import_suiteUtils.filterTestsRemoveEmptySuites)(suite, (test) => entries.has(test.id));
185
+ const tests = suite.allTests();
186
+ const unknownTestIds = new Set(entries.keys());
187
+ for (const test of tests)
188
+ unknownTestIds.delete(test.id);
189
+ if (unknownTestIds.size) {
190
+ fatalUnknownTestIds = [...unknownTestIds];
201
191
  void this._stop();
192
+ return;
193
+ }
194
+ this._poolBuilder.buildPools(suite);
195
+ this._activeSuites = /* @__PURE__ */ new Map();
196
+ this._didRunFullCleanup = false;
197
+ for (let i = 0; i < tests.length; i++) {
198
+ if (this._isStopped && this._didRunFullCleanup)
199
+ break;
200
+ const entry = entries.get(tests[i].id);
201
+ entries.delete(tests[i].id);
202
+ (0, import_util.debugTest)(`test started "${tests[i].title}"`);
203
+ await this._runTest(tests[i], entry.retry, tests[i + 1]);
204
+ (0, import_util.debugTest)(`test finished "${tests[i].title}"`);
202
205
  }
203
206
  } catch (e) {
204
207
  this._fatalErrors.push((0, import_util2.testInfoError)(e));
@@ -242,9 +245,7 @@ class WorkerMain extends import_process.ProcessRunner {
242
245
  this._resumePromise = new import_utils.ManualPromise();
243
246
  this.dispatchEvent("testPaused", payload);
244
247
  return this._resumePromise;
245
- },
246
- onCloneStorage: async (payload) => this.sendRequest("cloneStorage", payload),
247
- onUpstreamStorage: (payload) => this.sendRequest("upstreamStorage", payload)
248
+ }
248
249
  });
249
250
  const processAnnotation = (annotation) => {
250
251
  testInfo.annotations.push(annotation);
@@ -313,7 +314,9 @@ class WorkerMain extends import_process.ProcessRunner {
313
314
  await this._runBeforeAllHooksForSuite(suite, testInfo);
314
315
  shouldRunAfterEachHooks = true;
315
316
  await this._runEachHooksForSuites(suites, "beforeEach", testInfo);
316
- testFunctionParams = await this._fixtureRunner.resolveParametersForFunction(test.fn, testInfo, "test", { type: "test" });
317
+ const params = await this._fixtureRunner.resolveParametersForFunction(test.fn, testInfo, "test", { type: "test" });
318
+ if (params !== null)
319
+ testFunctionParams = params.result;
317
320
  });
318
321
  if (testFunctionParams === null) {
319
322
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchright-bun",
3
- "version": "1.58.2",
3
+ "version": "1.59.0",
4
4
  "description": "Patchright with Bun WebSocket support",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,10 +22,6 @@
22
22
  "./lib/common/configLoader": "./lib/common/configLoader.js",
23
23
  "./lib/fsWatcher": "./lib/fsWatcher.js",
24
24
  "./lib/mcp/index": "./lib/mcp/index.js",
25
- "./lib/mcp/browser/tools": "./lib/mcp/browser/tools.js",
26
- "./lib/mcp/program": "./lib/mcp/program.js",
27
- "./lib/mcp/sdk/bundle": "./lib/mcp/sdk/bundle.js",
28
- "./lib/mcp/sdk/exports": "./lib/mcp/sdk/exports.js",
29
25
  "./lib/program": "./lib/program.js",
30
26
  "./lib/reporters/base": "./lib/reporters/base.js",
31
27
  "./lib/reporters/list": "./lib/reporters/list.js",
@@ -64,7 +60,7 @@
64
60
  },
65
61
  "license": "Apache-2.0",
66
62
  "dependencies": {
67
- "patchright-bun-core": "1.58.2"
63
+ "patchright-bun-core": "1.59.0"
68
64
  },
69
65
  "optionalDependencies": {
70
66
  "fsevents": "2.3.2"
package/types/test.d.ts CHANGED
@@ -20,7 +20,7 @@ export * from 'patchright-bun-core';
20
20
 
21
21
  export type BlobReporterOptions = { outputDir?: string, fileName?: string };
22
22
  export type ListReporterOptions = { printSteps?: boolean };
23
- export type JUnitReporterOptions = { outputFile?: string, stripANSIControlSequences?: boolean, includeProjectInTestName?: boolean };
23
+ export type JUnitReporterOptions = { outputFile?: string, stripANSIControlSequences?: boolean, includeProjectInTestName?: boolean, includeRetries?: boolean };
24
24
  export type JsonReporterOptions = { outputFile?: string };
25
25
  export type HtmlReporterOptions = {
26
26
  outputFolder?: string;
@@ -31,6 +31,7 @@ export type HtmlReporterOptions = {
31
31
  title?: string;
32
32
  noSnippets?: boolean;
33
33
  noCopyPrompt?: boolean;
34
+ doNotInlineAssets?: boolean;
34
35
  };
35
36
 
36
37
  export type ReporterDescription = Readonly<
@@ -250,6 +251,13 @@ interface TestProject<TestArgs = {}, WorkerArgs = {}> {
250
251
  * for details.
251
252
  */
252
253
  pathTemplate?: string;
254
+
255
+ /**
256
+ * Controls how children of the snapshot root are matched against the actual accessibility tree. This is equivalent to
257
+ * adding a `/children` property at the top of every aria snapshot template. Individual snapshots can override this by
258
+ * including an explicit `/children` property.
259
+ */
260
+ children?: "contain"|"equal"|"deep-equal";
253
261
  };
254
262
 
255
263
  /**
@@ -764,6 +772,11 @@ export interface FullProject<TestArgs = {}, WorkerArgs = {}> {
764
772
  */
765
773
  grepInvert: null|RegExp|Array<RegExp>;
766
774
 
775
+ /**
776
+ * See [testProject.ignoreSnapshots](https://playwright.dev/docs/api/class-testproject#test-project-ignore-snapshots).
777
+ */
778
+ ignoreSnapshots: boolean;
779
+
767
780
  /**
768
781
  * See [testProject.metadata](https://playwright.dev/docs/api/class-testproject#test-project-metadata).
769
782
  */
@@ -1176,6 +1189,13 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
1176
1189
  * for details.
1177
1190
  */
1178
1191
  pathTemplate?: string;
1192
+
1193
+ /**
1194
+ * Controls how children of the snapshot root are matched against the actual accessibility tree. This is equivalent to
1195
+ * adding a `/children` property at the top of every aria snapshot template. Individual snapshots can override this by
1196
+ * including an explicit `/children` property.
1197
+ */
1198
+ children?: "contain"|"equal"|"deep-equal";
1179
1199
  };
1180
1200
 
1181
1201
  /**
@@ -6882,6 +6902,7 @@ export interface PlaywrightWorkerOptions {
6882
6902
  * - `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
6883
6903
  * - `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retries. When test run
6884
6904
  * passes, remove the recorded trace.
6905
+ * - `'retain-on-failure-and-retries'`: Record trace for each test run. Retains all traces when an attempt fails.
6885
6906
  *
6886
6907
  * For more control, pass an object that specifies `mode` and trace features to enable.
6887
6908
  *
@@ -6913,6 +6934,10 @@ export interface PlaywrightWorkerOptions {
6913
6934
  * down to fit into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual
6914
6935
  * picture of each page will be scaled down if necessary to fit the specified size.
6915
6936
  *
6937
+ * To annotate actions in the video, pass `show` with `action` and/or `test` sub-options. The `action` option controls
6938
+ * visual highlights on interacted elements with an optional `delay` in milliseconds (defaults to `500`). The `test`
6939
+ * option controls which test information is displayed as a status overlay.
6940
+ *
6916
6941
  * **Usage**
6917
6942
  *
6918
6943
  * ```js
@@ -6928,13 +6953,12 @@ export interface PlaywrightWorkerOptions {
6928
6953
  *
6929
6954
  * Learn more about [recording video](https://playwright.dev/docs/test-use-options#recording-options).
6930
6955
  */
6931
- video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize };
6956
+ video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize, show?: { actions?: { duration?: number, position?: 'top-left' | 'top' | 'top-right' | 'bottom-left' | 'bottom' | 'bottom-right', fontSize?: number }, test?: { level?: 'file' | 'title' | 'step', position?: 'top-left' | 'top' | 'top-right' | 'bottom-left' | 'bottom' | 'bottom-right', fontSize?: number } } };
6932
6957
  }
6933
6958
 
6934
6959
  export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure';
6935
- export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure';
6960
+ export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure' | 'retain-on-failure-and-retries';
6936
6961
  export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
6937
-
6938
6962
  /**
6939
6963
  * Playwright Test provides many options to configure test environment,
6940
6964
  * [Browser](https://playwright.dev/docs/api/class-browser),
@@ -7693,6 +7717,9 @@ type CustomProperties<T> = ExcludeProps<T, PlaywrightTestOptions & PlaywrightWor
7693
7717
  export type PlaywrightTestProject<TestArgs = {}, WorkerArgs = {}> = Project<PlaywrightTestOptions & CustomProperties<TestArgs>, PlaywrightWorkerOptions & CustomProperties<WorkerArgs>>;
7694
7718
  export type PlaywrightTestConfig<TestArgs = {}, WorkerArgs = {}> = Config<PlaywrightTestOptions & CustomProperties<TestArgs>, PlaywrightWorkerOptions & CustomProperties<WorkerArgs>>;
7695
7719
 
7720
+ // Use the global URLPattern type if available (Node.js 22+, modern browsers),
7721
+ // otherwise fall back to `never` so it disappears from union types.
7722
+ type URLPattern = typeof globalThis extends { URLPattern: infer T } ? T : never;
7696
7723
  type AsymmetricMatcher = Record<string, any>;
7697
7724
 
7698
7725
  interface AsymmetricMatchers {
@@ -7880,7 +7907,11 @@ interface AsymmetricMatchers {
7880
7907
  */
7881
7908
  interface GenericAssertions<R> {
7882
7909
  /**
7883
- * Makes the assertion check for the opposite condition. For example, the following code passes:
7910
+ * Makes the assertion check for the opposite condition.
7911
+ *
7912
+ * **Usage**
7913
+ *
7914
+ * For example, the following code passes:
7884
7915
  *
7885
7916
  * ```js
7886
7917
  * const value = 1;
@@ -7889,6 +7920,34 @@ interface GenericAssertions<R> {
7889
7920
  *
7890
7921
  */
7891
7922
  not: GenericAssertions<R>;
7923
+ /**
7924
+ * Use `resolves` to unwrap the value of a fulfilled promise so any other matcher can be chained. If the promise is
7925
+ * rejected the assertion fails.
7926
+ *
7927
+ * For example, this code tests that the promise resolves and that the resulting value is `'lemon'`:
7928
+ *
7929
+ * ```js
7930
+ * test('resolves to lemon', async () => {
7931
+ * await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
7932
+ * });
7933
+ * ```
7934
+ *
7935
+ */
7936
+ resolves: GenericAssertions<R>;
7937
+ /**
7938
+ * Use `.rejects` to unwrap the reason of a rejected promise so any other matcher can be chained. If the promise is
7939
+ * fulfilled the assertion fails.
7940
+ *
7941
+ * For example, this code tests that the promise rejects with reason `'octopus'`:
7942
+ *
7943
+ * ```js
7944
+ * test('rejects to octopus', async () => {
7945
+ * await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
7946
+ * });
7947
+ * ```
7948
+ *
7949
+ */
7950
+ rejects: GenericAssertions<R>;
7892
7951
  /**
7893
7952
  * Compares value with
7894
7953
  * [`expected`](https://playwright.dev/docs/api/class-genericassertions#generic-assertions-to-be-option-expected) by
@@ -8542,8 +8601,11 @@ interface APIResponseAssertions {
8542
8601
  toBeOK(): Promise<void>;
8543
8602
 
8544
8603
  /**
8545
- * Makes the assertion check for the opposite condition. For example, this code tests that the response status is not
8546
- * successful:
8604
+ * Makes the assertion check for the opposite condition.
8605
+ *
8606
+ * **Usage**
8607
+ *
8608
+ * For example, this code tests that the response status is not successful:
8547
8609
  *
8548
8610
  * ```js
8549
8611
  * await expect(response).not.toBeOK();
@@ -9574,8 +9636,11 @@ interface LocatorAssertions {
9574
9636
  }): Promise<void>;
9575
9637
 
9576
9638
  /**
9577
- * Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain
9578
- * text `"error"`:
9639
+ * Makes the assertion check for the opposite condition.
9640
+ *
9641
+ * **Usage**
9642
+ *
9643
+ * For example, this code tests that the Locator doesn't contain text `"error"`:
9579
9644
  *
9580
9645
  * ```js
9581
9646
  * await expect(locator).not.toContainText('error');
@@ -9663,6 +9728,9 @@ interface PageAssertions {
9663
9728
  * // Check for the page URL to contain 'doc', followed by an optional 's', followed by '/'
9664
9729
  * await expect(page).toHaveURL(/docs?\//);
9665
9730
  *
9731
+ * // Check for the page URL to match the URL pattern
9732
+ * await expect(page).toHaveURL(new URLPattern({ pathname: '/docs/*' }));
9733
+ *
9666
9734
  * // Check for the predicate to be satisfied
9667
9735
  * // For example: verify query strings
9668
9736
  * await expect(page).toHaveURL(url => {
@@ -9678,7 +9746,7 @@ interface PageAssertions {
9678
9746
  * against the current browser URL.
9679
9747
  * @param options
9680
9748
  */
9681
- toHaveURL(url: string|RegExp|((url: URL) => boolean), options?: {
9749
+ toHaveURL(url: string|RegExp|URLPattern|((url: URL) => boolean), options?: {
9682
9750
  /**
9683
9751
  * Whether to perform case-insensitive match.
9684
9752
  * [`ignoreCase`](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-url-option-ignore-case)
@@ -9694,8 +9762,11 @@ interface PageAssertions {
9694
9762
  }): Promise<void>;
9695
9763
 
9696
9764
  /**
9697
- * Makes the assertion check for the opposite condition. For example, this code tests that the page URL doesn't
9698
- * contain `"error"`:
9765
+ * Makes the assertion check for the opposite condition.
9766
+ *
9767
+ * **Usage**
9768
+ *
9769
+ * For example, this code tests that the page URL doesn't contain `"error"`:
9699
9770
  *
9700
9771
  * ```js
9701
9772
  * await expect(page).not.toHaveURL('error');