playwright 1.56.0-alpha-1756505518000 → 1.56.0-alpha-2025-08-31

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.
package/lib/index.js CHANGED
@@ -222,7 +222,7 @@ const playwrightFixtures = {
222
222
  if ((0, import_utils.debugMode)() === "inspector")
223
223
  testInfo._setDebugMode();
224
224
  playwright._defaultContextOptions = _combinedContextOptions;
225
- playwright._defaultContextTimeout = process.env.PLAYWRIGHT_DEBUGGER_MCP ? 5e3 : actionTimeout || 0;
225
+ playwright._defaultContextTimeout = process.env.PLAYWRIGHT_DEBUGGER_ENABLED ? 5e3 : actionTimeout || 0;
226
226
  playwright._defaultContextNavigationTimeout = navigationTimeout || 0;
227
227
  await use();
228
228
  playwright._defaultContextOptions = void 0;
@@ -73,7 +73,7 @@ const doneToolSchema = (0, import_exports.defineToolSchema)({
73
73
  type: "destructive"
74
74
  });
75
75
  async function runBrowserBackendOnError(page, message) {
76
- if (!process.env.PLAYWRIGHT_DEBUGGER_MCP)
76
+ if (!process.env.PLAYWRIGHT_DEBUGGER_ENABLED)
77
77
  return;
78
78
  const snapshot2 = await page._snapshotForAI();
79
79
  const introMessage = `### Paused on error:
@@ -84,7 +84,7 @@ ${snapshot2}
84
84
 
85
85
  ### Task
86
86
  Try recovering from the error prior to continuing, use following tools to recover: ${tools.map((tool) => tool.schema.name).join(", ")}`;
87
- await (0, import_mdb.runOnPauseBackendLoop)(process.env.PLAYWRIGHT_DEBUGGER_MCP, new BrowserBackend(page), introMessage);
87
+ await (0, import_mdb.runOnPauseBackendLoop)(process.env.PLAYWRIGHT_MDB_URL, new BrowserBackend(page), introMessage);
88
88
  }
89
89
  // Annotate the CommonJS export names for ESM import in node:
90
90
  0 && (module.exports = {
@@ -144,7 +144,7 @@ async function runMainBackend(backendFactory, options) {
144
144
  create: () => mdbBackend
145
145
  };
146
146
  const url = await startAsHttp(factory, { port: options?.port || 0 });
147
- process.env.PLAYWRIGHT_DEBUGGER_MCP = url;
147
+ process.env.PLAYWRIGHT_MDB_URL = url;
148
148
  if (options?.port !== void 0)
149
149
  return url;
150
150
  await mcpServer.connect(factory, new mcpBundle.StdioServerTransport(), false);
@@ -33,22 +33,21 @@ __export(backend_exports, {
33
33
  module.exports = __toCommonJS(backend_exports);
34
34
  var mcp = __toESM(require("../sdk/exports.js"));
35
35
  var import_context = require("./context");
36
- var import_listTests = require("./listTests");
37
- var import_runTests = require("./runTests");
38
- var import_tools = require("../browser/tools");
36
+ var import_tools = require("./tools.js");
37
+ var import_tools2 = require("../browser/tools");
39
38
  class TestServerBackend {
40
39
  constructor(resolvedLocation, options) {
41
40
  this.name = "Playwright";
42
41
  this.version = "0.0.1";
43
- this._tools = [import_listTests.listTests, import_runTests.runTests];
42
+ this._tools = [import_tools.listTests, import_tools.runTests, import_tools.debugTest];
44
43
  this._context = new import_context.Context(resolvedLocation, options);
45
44
  }
46
45
  async listTools() {
47
46
  return [
48
47
  ...this._tools.map((tool) => mcp.toMcpTool(tool.schema)),
49
- mcp.toMcpTool(import_tools.snapshot.schema),
50
- mcp.toMcpTool(import_tools.pickLocator.schema),
51
- mcp.toMcpTool(import_tools.evaluate.schema)
48
+ mcp.toMcpTool(import_tools2.snapshot.schema),
49
+ mcp.toMcpTool(import_tools2.pickLocator.schema),
50
+ mcp.toMcpTool(import_tools2.evaluate.schema)
52
51
  ];
53
52
  }
54
53
  async callTool(name, args) {
@@ -26,27 +26,77 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var runTests_exports = {};
30
- __export(runTests_exports, {
29
+ var tools_exports = {};
30
+ __export(tools_exports, {
31
+ debugTest: () => debugTest,
32
+ listTests: () => listTests,
31
33
  runTests: () => runTests
32
34
  });
33
- module.exports = __toCommonJS(runTests_exports);
35
+ module.exports = __toCommonJS(tools_exports);
34
36
  var import_utils = require("playwright-core/lib/utils");
35
37
  var import_bundle = require("../sdk/bundle");
36
38
  var import_base = require("../../reporters/base");
37
39
  var import_list = __toESM(require("../../reporters/list"));
40
+ var import_listModeReporter = __toESM(require("../../reporters/listModeReporter"));
38
41
  var import_tool = require("./tool");
39
42
  var import_streams = require("./streams");
43
+ const listTests = (0, import_tool.defineTool)({
44
+ schema: {
45
+ name: "playwright_test_list_tests",
46
+ title: "List tests",
47
+ description: "List tests",
48
+ inputSchema: import_bundle.z.object({}),
49
+ type: "readOnly"
50
+ },
51
+ handle: async (context) => {
52
+ const { screen, stream } = createScreen();
53
+ const reporter = new import_listModeReporter.default({ screen, includeTestId: true });
54
+ const testRunner = await context.createTestRunner();
55
+ await testRunner.listTests(reporter, {});
56
+ return {
57
+ content: [{ type: "text", text: stream.content() }]
58
+ };
59
+ }
60
+ });
40
61
  const runTests = (0, import_tool.defineTool)({
41
62
  schema: {
42
63
  name: "playwright_test_run_tests",
43
64
  title: "Run tests",
44
65
  description: "Run tests",
45
66
  inputSchema: import_bundle.z.object({
46
- tests: import_bundle.z.array(import_bundle.z.object({
47
- id: import_bundle.z.string().describe("Test ID to run."),
48
- title: import_bundle.z.string().describe("Human readable test title for granting permission to run the test.")
49
- })).optional().describe("Tests to run. All tests are run if not provided.")
67
+ locations: import_bundle.z.array(import_bundle.z.string()).describe('Folder, file or location to run: "test/e2e" or "test/e2e/file.spec.ts" or "test/e2e/file.spec.ts:20"'),
68
+ projects: import_bundle.z.array(import_bundle.z.string()).optional().describe('Projects to run, projects from playwright.config.ts, by default runs all projects. Running with "chromium" is a good start')
69
+ }),
70
+ type: "readOnly"
71
+ },
72
+ handle: async (context, params) => {
73
+ const { screen, stream } = createScreen();
74
+ const configDir = context.configLocation.configDir;
75
+ const reporter = new import_list.default({ configDir, screen, includeTestId: true });
76
+ const testRunner = await context.createTestRunner();
77
+ const result = await testRunner.runTests(reporter, {
78
+ locations: params.locations,
79
+ projects: params.projects
80
+ });
81
+ const text = stream.content();
82
+ return {
83
+ content: [
84
+ { type: "text", text }
85
+ ],
86
+ isError: result.status !== "passed"
87
+ };
88
+ }
89
+ });
90
+ const debugTest = (0, import_tool.defineTool)({
91
+ schema: {
92
+ name: "playwright_test_debug_test",
93
+ title: "Debug single test",
94
+ description: "Debug single test",
95
+ inputSchema: import_bundle.z.object({
96
+ test: import_bundle.z.object({
97
+ id: import_bundle.z.string().describe("Test ID to debug."),
98
+ title: import_bundle.z.string().describe("Human readable test title for granting permission to debug the test.")
99
+ })
50
100
  }),
51
101
  type: "readOnly"
52
102
  },
@@ -62,11 +112,15 @@ const runTests = (0, import_tool.defineTool)({
62
112
  const configDir = context.configLocation.configDir;
63
113
  const reporter = new import_list.default({ configDir, screen });
64
114
  const testRunner = await context.createTestRunner();
115
+ process.env.PLAYWRIGHT_DEBUGGER_ENABLED = "1";
65
116
  const result = await testRunner.runTests(reporter, {
66
- testIds: params.tests?.map((test) => test.id),
117
+ headed: true,
118
+ testIds: [params.test.id],
67
119
  // For automatic recovery
68
120
  timeout: 0,
69
121
  workers: 1
122
+ }).finally(() => {
123
+ process.env.PLAYWRIGHT_DEBUGGER_ENABLED = void 0;
70
124
  });
71
125
  const text = stream.content();
72
126
  return {
@@ -77,7 +131,20 @@ const runTests = (0, import_tool.defineTool)({
77
131
  };
78
132
  }
79
133
  });
134
+ function createScreen() {
135
+ const stream = new import_streams.StringWriteStream();
136
+ const screen = {
137
+ ...import_base.terminalScreen,
138
+ isTTY: false,
139
+ colors: import_utils.noColors,
140
+ stdout: stream,
141
+ stderr: stream
142
+ };
143
+ return { screen, stream };
144
+ }
80
145
  // Annotate the CommonJS export names for ESM import in node:
81
146
  0 && (module.exports = {
147
+ debugTest,
148
+ listTests,
82
149
  runTests
83
150
  });
@@ -120,7 +120,7 @@ class TerminalReporter {
120
120
  this._fatalErrors = [];
121
121
  this._failureCount = 0;
122
122
  this.screen = options.screen ?? terminalScreen;
123
- this._omitFailures = options.omitFailures || false;
123
+ this._options = options;
124
124
  }
125
125
  version() {
126
126
  return "v2";
@@ -258,7 +258,7 @@ class TerminalReporter {
258
258
  epilogue(full) {
259
259
  const summary = this.generateSummary();
260
260
  const summaryMessage = this.generateSummaryMessage(summary);
261
- if (full && summary.failuresToPrint.length && !this._omitFailures)
261
+ if (full && summary.failuresToPrint.length && !this._options.omitFailures)
262
262
  this._printFailures(summary.failuresToPrint);
263
263
  this._printSlowTests();
264
264
  this._printSummary(summaryMessage);
@@ -284,14 +284,14 @@ class TerminalReporter {
284
284
  willRetry(test) {
285
285
  return test.outcome() === "unexpected" && test.results.length <= test.retries;
286
286
  }
287
- formatTestTitle(test, step, omitLocation = false) {
288
- return formatTestTitle(this.screen, this.config, test, step, omitLocation);
287
+ formatTestTitle(test, step) {
288
+ return formatTestTitle(this.screen, this.config, test, step, this._options);
289
289
  }
290
290
  formatTestHeader(test, options = {}) {
291
- return formatTestHeader(this.screen, this.config, test, options);
291
+ return formatTestHeader(this.screen, this.config, test, { ...options, includeTestId: this._options.includeTestId });
292
292
  }
293
293
  formatFailure(test, index) {
294
- return formatFailure(this.screen, this.config, test, index);
294
+ return formatFailure(this.screen, this.config, test, index, this._options);
295
295
  }
296
296
  formatError(error) {
297
297
  return formatError(this.screen, error);
@@ -300,9 +300,9 @@ class TerminalReporter {
300
300
  this.screen.stdout?.write(line ? line + "\n" : "\n");
301
301
  }
302
302
  }
303
- function formatFailure(screen, config, test, index) {
303
+ function formatFailure(screen, config, test, index, options) {
304
304
  const lines = [];
305
- const header = formatTestHeader(screen, config, test, { indent: " ", index, mode: "error" });
305
+ const header = formatTestHeader(screen, config, test, { indent: " ", index, mode: "error", includeTestId: options?.includeTestId });
306
306
  lines.push(screen.colors.red(header));
307
307
  for (const result of test.results) {
308
308
  const resultLines = [];
@@ -416,20 +416,18 @@ function stepSuffix(step) {
416
416
  const stepTitles = step ? step.titlePath() : [];
417
417
  return stepTitles.map((t) => t.split("\n")[0]).map((t) => " \u203A " + t).join("");
418
418
  }
419
- function formatTestTitle(screen, config, test, step, omitLocation = false) {
419
+ function formatTestTitle(screen, config, test, step, options = {}) {
420
420
  const [, projectName, , ...titles] = test.titlePath();
421
- let location;
422
- if (omitLocation)
423
- location = `${relativeTestPath(screen, config, test)}`;
424
- else
425
- location = `${relativeTestPath(screen, config, test)}:${test.location.line}:${test.location.column}`;
426
- const projectTitle = projectName ? `[${projectName}] \u203A ` : "";
427
- const testTitle = `${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`;
421
+ const location = `${relativeTestPath(screen, config, test)}:${test.location.line}:${test.location.column}`;
422
+ const testId = options.includeTestId ? `[id=${test.id}] ` : "";
423
+ const projectLabel = options.includeTestId ? `project=` : "";
424
+ const projectTitle = projectName ? `[${projectLabel}${projectName}] \u203A ` : "";
425
+ const testTitle = `${testId}${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`;
428
426
  const extraTags = test.tags.filter((t) => !testTitle.includes(t));
429
427
  return `${testTitle}${stepSuffix(step)}${extraTags.length ? " " + extraTags.join(" ") : ""}`;
430
428
  }
431
429
  function formatTestHeader(screen, config, test, options = {}) {
432
- const title = formatTestTitle(screen, config, test);
430
+ const title = formatTestTitle(screen, config, test, void 0, options);
433
431
  const header = `${options.indent || ""}${options.index ? options.index + ") " : ""}${title}`;
434
432
  let fullHeader = header;
435
433
  if (options.mode === "error") {
@@ -34,7 +34,8 @@ module.exports = __toCommonJS(listModeReporter_exports);
34
34
  var import_path = __toESM(require("path"));
35
35
  var import_base = require("./base");
36
36
  class ListModeReporter {
37
- constructor(options) {
37
+ constructor(options = {}) {
38
+ this._options = options;
38
39
  this.screen = options?.screen ?? import_base.terminalScreen;
39
40
  }
40
41
  version() {
@@ -50,8 +51,10 @@ class ListModeReporter {
50
51
  for (const test of tests) {
51
52
  const [, projectName, , ...titles] = test.titlePath();
52
53
  const location = `${import_path.default.relative(this.config.rootDir, test.location.file)}:${test.location.line}:${test.location.column}`;
53
- const projectTitle = projectName ? `[${projectName}] \u203A ` : "";
54
- this._writeLine(` ${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`);
54
+ const testId = this._options.includeTestId ? `[id=${test.id}] ` : "";
55
+ const projectLabel = this._options.includeTestId ? `project=` : "";
56
+ const projectTitle = projectName ? `[${projectLabel}${projectName}] \u203A ` : "";
57
+ this._writeLine(` ${testId}${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`);
55
58
  files.add(test.location.file);
56
59
  }
57
60
  this._writeLine(`Total: ${tests.length} ${tests.length === 1 ? "test" : "tests"} in ${files.size} ${files.size === 1 ? "file" : "files"}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.56.0-alpha-1756505518000",
3
+ "version": "1.56.0-alpha-2025-08-31",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "license": "Apache-2.0",
63
63
  "dependencies": {
64
- "playwright-core": "1.56.0-alpha-1756505518000"
64
+ "playwright-core": "1.56.0-alpha-2025-08-31"
65
65
  },
66
66
  "optionalDependencies": {
67
67
  "fsevents": "2.3.2"
@@ -1,88 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var listTests_exports = {};
30
- __export(listTests_exports, {
31
- listTests: () => listTests
32
- });
33
- module.exports = __toCommonJS(listTests_exports);
34
- var import_path = __toESM(require("path"));
35
- var import_bundle = require("../sdk/bundle");
36
- var import_tool = require("./tool.js");
37
- const listTests = (0, import_tool.defineTool)({
38
- schema: {
39
- name: "playwright_test_list_tests",
40
- title: "List tests",
41
- description: "List tests",
42
- inputSchema: import_bundle.z.object({}),
43
- type: "readOnly"
44
- },
45
- handle: async (context, params) => {
46
- const reporter = new ListModeReporter();
47
- const testRunner = await context.createTestRunner();
48
- await testRunner.listTests(reporter, {});
49
- if (reporter.hasErrors())
50
- throw new Error(reporter.content());
51
- return {
52
- content: [{ type: "text", text: reporter.content() }]
53
- };
54
- }
55
- });
56
- class ListModeReporter {
57
- constructor() {
58
- this._lines = [];
59
- this._hasErrors = false;
60
- }
61
- onBegin(config, suite) {
62
- this._lines.push(`Listing tests:`);
63
- const tests = suite.allTests();
64
- const files = /* @__PURE__ */ new Set();
65
- for (const test of tests) {
66
- const [, projectName, , ...titles] = test.titlePath();
67
- const location = `${import_path.default.relative(config.rootDir, test.location.file)}:${test.location.line}:${test.location.column}`;
68
- const projectTitle = projectName ? `[${projectName}] \u203A ` : "";
69
- this._lines.push(` [id=${test.id}] ${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`);
70
- files.add(test.location.file);
71
- }
72
- this._lines.push(`Total: ${tests.length} ${tests.length === 1 ? "test" : "tests"} in ${files.size} ${files.size === 1 ? "file" : "files"}`);
73
- }
74
- onError(error) {
75
- this._hasErrors = true;
76
- this._lines.push(error.stack || error.message || error.value || "");
77
- }
78
- hasErrors() {
79
- return this._hasErrors;
80
- }
81
- content() {
82
- return this._lines.join("\n");
83
- }
84
- }
85
- // Annotate the CommonJS export names for ESM import in node:
86
- 0 && (module.exports = {
87
- listTests
88
- });