playwright 1.56.0-alpha-1756475278000 → 1.56.0-alpha-2025-08-30
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/common/config.js +1 -1
- package/lib/index.js +1 -1
- package/lib/mcp/browser/backend.js +2 -2
- package/lib/mcp/sdk/bundle.js +3 -0
- package/lib/mcp/sdk/mdb.js +1 -1
- package/lib/mcp/test/backend.js +7 -12
- package/lib/mcp/test/context.js +1 -18
- package/lib/mcp/test/{runTests.js → tools.js} +75 -8
- package/lib/mcpBundleImpl.js +10 -10
- package/lib/reporters/base.js +15 -17
- package/lib/reporters/listModeReporter.js +6 -3
- package/lib/runner/testRunner.js +3 -46
- package/lib/runner/testServer.js +33 -4
- package/package.json +3 -2
- package/lib/mcp/test/listTests.js +0 -88
package/lib/common/config.js
CHANGED
|
@@ -112,7 +112,7 @@ class FullConfigInternal {
|
|
|
112
112
|
} else {
|
|
113
113
|
this.webServers = [];
|
|
114
114
|
}
|
|
115
|
-
const projectConfigs = configCLIOverrides.projects || userConfig.projects || [userConfig];
|
|
115
|
+
const projectConfigs = configCLIOverrides.projects || userConfig.projects || [{ ...userConfig, workers: void 0 }];
|
|
116
116
|
this.projects = projectConfigs.map((p) => new FullProjectInternal(configDir, userConfig, this, p, this.configCLIOverrides, packageJsonDir));
|
|
117
117
|
resolveProjectDependencies(this.projects);
|
|
118
118
|
this._assignUniqueProjectIds(this.projects);
|
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.
|
|
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.
|
|
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.
|
|
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 = {
|
package/lib/mcp/sdk/bundle.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(bundle_exports, {
|
|
|
25
25
|
PingRequestSchema: () => PingRequestSchema,
|
|
26
26
|
SSEServerTransport: () => SSEServerTransport,
|
|
27
27
|
Server: () => Server,
|
|
28
|
+
StdioClientTransport: () => StdioClientTransport,
|
|
28
29
|
StdioServerTransport: () => StdioServerTransport,
|
|
29
30
|
StreamableHTTPClientTransport: () => StreamableHTTPClientTransport,
|
|
30
31
|
StreamableHTTPServerTransport: () => StreamableHTTPServerTransport,
|
|
@@ -37,6 +38,7 @@ const zodToJsonSchema = bundle.zodToJsonSchema;
|
|
|
37
38
|
const Client = bundle.Client;
|
|
38
39
|
const Server = bundle.Server;
|
|
39
40
|
const SSEServerTransport = bundle.SSEServerTransport;
|
|
41
|
+
const StdioClientTransport = bundle.StdioClientTransport;
|
|
40
42
|
const StdioServerTransport = bundle.StdioServerTransport;
|
|
41
43
|
const StreamableHTTPServerTransport = bundle.StreamableHTTPServerTransport;
|
|
42
44
|
const StreamableHTTPClientTransport = bundle.StreamableHTTPClientTransport;
|
|
@@ -54,6 +56,7 @@ const z = bundle.z;
|
|
|
54
56
|
PingRequestSchema,
|
|
55
57
|
SSEServerTransport,
|
|
56
58
|
Server,
|
|
59
|
+
StdioClientTransport,
|
|
57
60
|
StdioServerTransport,
|
|
58
61
|
StreamableHTTPClientTransport,
|
|
59
62
|
StreamableHTTPServerTransport,
|
package/lib/mcp/sdk/mdb.js
CHANGED
|
@@ -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.
|
|
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);
|
package/lib/mcp/test/backend.js
CHANGED
|
@@ -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
|
|
37
|
-
var
|
|
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 = [
|
|
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(
|
|
50
|
-
mcp.toMcpTool(
|
|
51
|
-
mcp.toMcpTool(
|
|
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) {
|
|
@@ -56,11 +55,7 @@ class TestServerBackend {
|
|
|
56
55
|
if (!tool)
|
|
57
56
|
throw new Error(`Tool not found: ${name}. Available tools: ${this._tools.map((tool2) => tool2.schema.name).join(", ")}`);
|
|
58
57
|
const parsedArguments = tool.schema.inputSchema.parse(args || {});
|
|
59
|
-
|
|
60
|
-
const stdio = this._context.takeStdio();
|
|
61
|
-
if (stdio.trim())
|
|
62
|
-
result.content.push({ type: "text", text: stdio });
|
|
63
|
-
return result;
|
|
58
|
+
return await tool.handle(this._context, parsedArguments);
|
|
64
59
|
}
|
|
65
60
|
serverClosed() {
|
|
66
61
|
void this._context.close();
|
package/lib/mcp/test/context.js
CHANGED
|
@@ -24,7 +24,6 @@ module.exports = __toCommonJS(context_exports);
|
|
|
24
24
|
var import_testRunner = require("../../runner/testRunner");
|
|
25
25
|
class Context {
|
|
26
26
|
constructor(configLocation, options) {
|
|
27
|
-
this._stdio = [];
|
|
28
27
|
this.configLocation = configLocation;
|
|
29
28
|
this.options = options;
|
|
30
29
|
}
|
|
@@ -32,13 +31,7 @@ class Context {
|
|
|
32
31
|
if (this._testRunner)
|
|
33
32
|
await this._testRunner.stopTests();
|
|
34
33
|
const testRunner = new import_testRunner.TestRunner(this.configLocation, {});
|
|
35
|
-
await testRunner.initialize({
|
|
36
|
-
sendStdioEvents: true,
|
|
37
|
-
muteConsole: this.options?.muteConsole
|
|
38
|
-
});
|
|
39
|
-
testRunner.on(import_testRunner.TestRunnerEvent.StdioChunk, (chunk, stdio) => {
|
|
40
|
-
this._stdio.push({ chunk, stdio });
|
|
41
|
-
});
|
|
34
|
+
await testRunner.initialize({});
|
|
42
35
|
this._testRunner = testRunner;
|
|
43
36
|
testRunner.on(import_testRunner.TestRunnerEvent.TestFilesChanged, (testFiles) => {
|
|
44
37
|
this._testRunner?.emit(import_testRunner.TestRunnerEvent.TestFilesChanged, testFiles);
|
|
@@ -46,19 +39,9 @@ class Context {
|
|
|
46
39
|
this._testRunner = testRunner;
|
|
47
40
|
return testRunner;
|
|
48
41
|
}
|
|
49
|
-
takeStdio() {
|
|
50
|
-
const text = this._stdio.map((entry) => chunkToPayload(entry.stdio, entry.chunk)).join("\n");
|
|
51
|
-
this._stdio = [];
|
|
52
|
-
return text;
|
|
53
|
-
}
|
|
54
42
|
async close() {
|
|
55
43
|
}
|
|
56
44
|
}
|
|
57
|
-
function chunkToPayload(type, chunk) {
|
|
58
|
-
if (chunk instanceof Uint8Array)
|
|
59
|
-
return "<binary>";
|
|
60
|
-
return `[${type}] ${chunk}`;
|
|
61
|
-
}
|
|
62
45
|
// Annotate the CommonJS export names for ESM import in node:
|
|
63
46
|
0 && (module.exports = {
|
|
64
47
|
Context
|
|
@@ -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
|
|
30
|
-
__export(
|
|
29
|
+
var tools_exports = {};
|
|
30
|
+
__export(tools_exports, {
|
|
31
|
+
debugTest: () => debugTest,
|
|
32
|
+
listTests: () => listTests,
|
|
31
33
|
runTests: () => runTests
|
|
32
34
|
});
|
|
33
|
-
module.exports = __toCommonJS(
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
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
|
});
|