playwright 1.54.0-alpha-2025-07-08 → 1.54.0-beta-1752075907000

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.

Potentially problematic release.


This version of playwright might be problematic. Click here for more details.

package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🎭 Playwright
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-139.0.7258.5-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-140.0.2-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-18.5-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord)
3
+ [![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-139.0.7258.5-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-140.0.2-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-26.0-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord)
4
4
 
5
5
  ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
6
6
 
@@ -9,7 +9,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
9
9
  | | Linux | macOS | Windows |
10
10
  | :--- | :---: | :---: | :---: |
11
11
  | Chromium <!-- GEN:chromium-version -->139.0.7258.5<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
12
- | WebKit <!-- GEN:webkit-version -->18.5<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
12
+ | WebKit <!-- GEN:webkit-version -->26.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
13
13
  | Firefox <!-- GEN:firefox-version -->140.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
14
14
 
15
15
  Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
@@ -237,7 +237,11 @@ class TestCase extends Base {
237
237
  return status === "expected" || status === "flaky" || status === "skipped";
238
238
  }
239
239
  get tags() {
240
- return this._grepTitle().match(/@[\S]+/g) || [];
240
+ const titleTags = this._grepBaseTitlePath().join(" ").match(/@[\S]+/g) || [];
241
+ return [
242
+ ...titleTags,
243
+ ...this._tags
244
+ ];
241
245
  }
242
246
  _serialize() {
243
247
  return {
@@ -298,10 +302,14 @@ class TestCase extends Base {
298
302
  this.results.push(result);
299
303
  return result;
300
304
  }
301
- _grepTitle() {
305
+ _grepBaseTitlePath() {
302
306
  const path = [];
303
307
  this.parent._collectGrepTitlePath(path);
304
308
  path.push(this.title);
309
+ return path;
310
+ }
311
+ _grepTitleWithTags() {
312
+ const path = this._grepBaseTitlePath();
305
313
  path.push(...this._tags);
306
314
  return path.join(" ");
307
315
  }
@@ -60,6 +60,7 @@ class SnapshotHelper {
60
60
  this.options = options;
61
61
  name = nameFromOptions;
62
62
  }
63
+ this.name = Array.isArray(name) ? name.join(import_path.default.sep) : name || "";
63
64
  const resolvedPaths = testInfo._resolveSnapshotPaths(matcherName === "toHaveScreenshot" ? "screenshot" : "snapshot", name, "updateSnapshotIndex", anonymousSnapshotExtension);
64
65
  this.expectedPath = resolvedPaths.absoluteSnapshotPath;
65
66
  this.attachmentBaseName = resolvedPaths.relativeOutputPath;
@@ -140,26 +141,25 @@ class SnapshotHelper {
140
141
  }
141
142
  handleDifferent(actual, expected, previous, diff, header, diffError, log, step) {
142
143
  const output = [`${header}${indent(diffError, " ")}`];
144
+ if (this.name) {
145
+ output.push("");
146
+ output.push(` Snapshot: ${this.name}`);
147
+ }
143
148
  if (expected !== void 0) {
144
149
  writeFileSync(this.legacyExpectedPath, expected);
145
150
  step?._attachToStep({ name: (0, import_util.addSuffixToFilePath)(this.attachmentBaseName, "-expected"), contentType: this.mimeType, path: this.expectedPath });
146
- output.push(`
147
- Expected: ${import_utils2.colors.yellow(this.expectedPath)}`);
148
151
  }
149
152
  if (previous !== void 0) {
150
153
  writeFileSync(this.previousPath, previous);
151
154
  step?._attachToStep({ name: (0, import_util.addSuffixToFilePath)(this.attachmentBaseName, "-previous"), contentType: this.mimeType, path: this.previousPath });
152
- output.push(`Previous: ${import_utils2.colors.yellow(this.previousPath)}`);
153
155
  }
154
156
  if (actual !== void 0) {
155
157
  writeFileSync(this.actualPath, actual);
156
158
  step?._attachToStep({ name: (0, import_util.addSuffixToFilePath)(this.attachmentBaseName, "-actual"), contentType: this.mimeType, path: this.actualPath });
157
- output.push(`Received: ${import_utils2.colors.yellow(this.actualPath)}`);
158
159
  }
159
160
  if (diff !== void 0) {
160
161
  writeFileSync(this.diffPath, diff);
161
162
  step?._attachToStep({ name: (0, import_util.addSuffixToFilePath)(this.attachmentBaseName, "-diff"), contentType: this.mimeType, path: this.diffPath });
162
- output.push(` Diff: ${import_utils2.colors.yellow(this.diffPath)}`);
163
163
  }
164
164
  if (log?.length)
165
165
  output.push((0, import_util.callLogText)(log));
@@ -307,8 +307,9 @@ function formatFailure(screen, config, test, index) {
307
307
  resultLines.push(screen.colors.gray(separator(screen, ` Retry #${result.retry}`)));
308
308
  }
309
309
  resultLines.push(...errors.map((error) => "\n" + error.message));
310
- for (let i = 0; i < result.attachments.length; ++i) {
311
- const attachment = result.attachments[i];
310
+ const attachmentGroups = groupAttachments(result.attachments);
311
+ for (let i = 0; i < attachmentGroups.length; ++i) {
312
+ const attachment = attachmentGroups[i];
312
313
  if (attachment.name === "error-context" && attachment.path) {
313
314
  resultLines.push("");
314
315
  resultLines.push(screen.colors.dim(` Error Context: ${relativeFilePath(screen, config, attachment.path)}`));
@@ -320,15 +321,30 @@ function formatFailure(screen, config, test, index) {
320
321
  if (!attachment.path && !hasPrintableContent)
321
322
  continue;
322
323
  resultLines.push("");
323
- resultLines.push(screen.colors.cyan(separator(screen, ` attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`)));
324
- if (attachment.path) {
325
- const relativePath = import_path.default.relative(process.cwd(), attachment.path);
326
- resultLines.push(screen.colors.cyan(` ${relativePath}`));
324
+ resultLines.push(screen.colors.dim(separator(screen, ` attachment #${i + 1}: ${screen.colors.bold(attachment.name)} (${attachment.contentType})`)));
325
+ if (attachment.actual?.path) {
326
+ if (attachment.expected?.path) {
327
+ const expectedPath = relativeFilePath(screen, config, attachment.expected.path);
328
+ resultLines.push(screen.colors.dim(` Expected: ${expectedPath}`));
329
+ }
330
+ const actualPath = relativeFilePath(screen, config, attachment.actual.path);
331
+ resultLines.push(screen.colors.dim(` Received: ${actualPath}`));
332
+ if (attachment.previous?.path) {
333
+ const previousPath = relativeFilePath(screen, config, attachment.previous.path);
334
+ resultLines.push(screen.colors.dim(` Previous: ${previousPath}`));
335
+ }
336
+ if (attachment.diff?.path) {
337
+ const diffPath = relativeFilePath(screen, config, attachment.diff.path);
338
+ resultLines.push(screen.colors.dim(` Diff: ${diffPath}`));
339
+ }
340
+ } else if (attachment.path) {
341
+ const relativePath = relativeFilePath(screen, config, attachment.path);
342
+ resultLines.push(screen.colors.dim(` ${relativePath}`));
327
343
  if (attachment.name === "trace") {
328
344
  const packageManagerCommand = (0, import_utils.getPackageManagerExecCommand)();
329
- resultLines.push(screen.colors.cyan(` Usage:`));
345
+ resultLines.push(screen.colors.dim(` Usage:`));
330
346
  resultLines.push("");
331
- resultLines.push(screen.colors.cyan(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`));
347
+ resultLines.push(screen.colors.dim(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`));
332
348
  resultLines.push("");
333
349
  }
334
350
  } else {
@@ -337,10 +353,10 @@ function formatFailure(screen, config, test, index) {
337
353
  if (text.length > 300)
338
354
  text = text.slice(0, 300) + "...";
339
355
  for (const line of text.split("\n"))
340
- resultLines.push(screen.colors.cyan(` ${line}`));
356
+ resultLines.push(screen.colors.dim(` ${line}`));
341
357
  }
342
358
  }
343
- resultLines.push(screen.colors.cyan(separator(screen, " ")));
359
+ resultLines.push(screen.colors.dim(separator(screen, " ")));
344
360
  }
345
361
  lines.push(...resultLines);
346
362
  }
@@ -460,7 +476,7 @@ function separator(screen, text = "") {
460
476
  if (text)
461
477
  text += " ";
462
478
  const columns = Math.min(100, screen.ttyWidth || 100);
463
- return text + screen.colors.dim("\u2500".repeat(Math.max(0, columns - text.length)));
479
+ return text + screen.colors.dim("\u2500".repeat(Math.max(0, columns - (0, import_util.stripAnsiEscapes)(text).length)));
464
480
  }
465
481
  function indent(lines, tab) {
466
482
  return lines.replace(/^(?=.+$)/gm, tab);
@@ -537,6 +553,37 @@ function resolveOutputFile(reporterName, options) {
537
553
  outputFile = import_path.default.resolve(outputDir, reportName);
538
554
  return { outputFile, outputDir };
539
555
  }
556
+ function groupAttachments(attachments) {
557
+ const result = [];
558
+ const attachmentsByPrefix = /* @__PURE__ */ new Map();
559
+ for (const attachment of attachments) {
560
+ if (!attachment.path) {
561
+ result.push(attachment);
562
+ continue;
563
+ }
564
+ const match = attachment.name.match(/^(.*)-(expected|actual|diff|previous)(\.[^.]+)?$/);
565
+ if (!match) {
566
+ result.push(attachment);
567
+ continue;
568
+ }
569
+ const [, name, category] = match;
570
+ let group = attachmentsByPrefix.get(name);
571
+ if (!group) {
572
+ group = { ...attachment, name };
573
+ attachmentsByPrefix.set(name, group);
574
+ result.push(group);
575
+ }
576
+ if (category === "expected")
577
+ group.expected = attachment;
578
+ else if (category === "actual")
579
+ group.actual = attachment;
580
+ else if (category === "diff")
581
+ group.diff = attachment;
582
+ else if (category === "previous")
583
+ group.previous = attachment;
584
+ }
585
+ return result;
586
+ }
540
587
  // Annotate the CommonJS export names for ESM import in node:
541
588
  0 && (module.exports = {
542
589
  TerminalReporter,
@@ -184,7 +184,7 @@ function createProjectSuite(project, fileSuites) {
184
184
  const grepMatcher = (0, import_util.createTitleMatcher)(project.project.grep);
185
185
  const grepInvertMatcher = project.project.grepInvert ? (0, import_util.createTitleMatcher)(project.project.grepInvert) : null;
186
186
  (0, import_suiteUtils.filterTestsRemoveEmptySuites)(projectSuite, (test) => {
187
- const grepTitle = test._grepTitle();
187
+ const grepTitle = test._grepTitleWithTags();
188
188
  if (grepInvertMatcher?.(grepTitle))
189
189
  return false;
190
190
  return grepMatcher(grepTitle);
@@ -200,7 +200,7 @@ function filterProjectSuite(projectSuite, options) {
200
200
  if (options.testIdMatcher)
201
201
  (0, import_suiteUtils.filterByTestIds)(result, options.testIdMatcher);
202
202
  (0, import_suiteUtils.filterTestsRemoveEmptySuites)(result, (test) => {
203
- if (options.cliTitleMatcher && !options.cliTitleMatcher(test._grepTitle()))
203
+ if (options.cliTitleMatcher && !options.cliTitleMatcher(test._grepTitleWithTags()))
204
204
  return false;
205
205
  if (options.additionalFileMatcher && !options.additionalFileMatcher(test.location.file))
206
206
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.54.0-alpha-2025-07-08",
3
+ "version": "1.54.0-beta-1752075907000",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "license": "Apache-2.0",
58
58
  "dependencies": {
59
- "playwright-core": "1.54.0-alpha-2025-07-08"
59
+ "playwright-core": "1.54.0-beta-1752075907000"
60
60
  },
61
61
  "optionalDependencies": {
62
62
  "fsevents": "2.3.2"