playwright 1.56.0-alpha-1758839353000 → 1.56.0-alpha-2025-09-27
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/README.md +2 -2
- package/lib/agents/generateAgents.js +1 -0
- package/lib/agents/healer.md +2 -0
- package/lib/mcp/browser/context.js +1 -1
- package/lib/mcp/browser/tab.js +9 -13
- package/lib/mcp/browser/tools/console.js +2 -1
- package/lib/mcp/browser/tools/network.js +10 -5
- package/lib/mcp/test/testTools.js +2 -2
- package/lib/reporters/html.js +3 -22
- package/package.json +2 -2
- package/types/test.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🎭 Playwright
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop --> [](https://aka.ms/playwright/discord)
|
|
4
4
|
|
|
5
5
|
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
|
|
|
8
8
|
|
|
9
9
|
| | Linux | macOS | Windows |
|
|
10
10
|
| :--- | :---: | :---: | :---: |
|
|
11
|
-
| Chromium <!-- GEN:chromium-version -->141.0.7390.
|
|
11
|
+
| Chromium <!-- GEN:chromium-version -->141.0.7390.37<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
|
12
12
|
| WebKit <!-- GEN:webkit-version -->26.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
|
13
13
|
| Firefox <!-- GEN:firefox-version -->142.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
|
14
14
|
|
|
@@ -241,6 +241,7 @@ async function initVSCodeRepo() {
|
|
|
241
241
|
type: "stdio",
|
|
242
242
|
command: commonMcpServers.playwrightTest.command,
|
|
243
243
|
args: commonMcpServers.playwrightTest.args,
|
|
244
|
+
cwd: "${workspaceFolder}",
|
|
244
245
|
env: { "PLAYWRIGHT_MCP_TOOL_PREFIX": vscodeToolPrefix }
|
|
245
246
|
};
|
|
246
247
|
await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2));
|
package/lib/agents/healer.md
CHANGED
|
@@ -9,8 +9,10 @@ tools:
|
|
|
9
9
|
- read
|
|
10
10
|
- write
|
|
11
11
|
- edit
|
|
12
|
+
- playwright-test/browser_console_messages
|
|
12
13
|
- playwright-test/browser_evaluate
|
|
13
14
|
- playwright-test/browser_generate_locator
|
|
15
|
+
- playwright-test/browser_network_requests
|
|
14
16
|
- playwright-test/browser_snapshot
|
|
15
17
|
- playwright-test/test_debug
|
|
16
18
|
- playwright-test/test_list
|
|
@@ -138,7 +138,7 @@ class Context {
|
|
|
138
138
|
await promise.then(async ({ browserContext, close }) => {
|
|
139
139
|
if (this.config.saveTrace)
|
|
140
140
|
await browserContext.tracing.stop();
|
|
141
|
-
const videos = browserContext.pages().map((page) => page.video()).filter((video) => !!video);
|
|
141
|
+
const videos = this.config.saveVideo ? browserContext.pages().map((page) => page.video()).filter((video) => !!video) : [];
|
|
142
142
|
await close(async () => {
|
|
143
143
|
for (const video of videos) {
|
|
144
144
|
const name = await this.outputFile((0, import_utils.dateAsFileName)("webm"), { origin: "code", reason: "Saving video" });
|
package/lib/mcp/browser/tab.js
CHANGED
|
@@ -38,7 +38,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
38
38
|
this._lastTitle = "about:blank";
|
|
39
39
|
this._consoleMessages = [];
|
|
40
40
|
this._recentConsoleMessages = [];
|
|
41
|
-
this._requests = /* @__PURE__ */ new
|
|
41
|
+
this._requests = /* @__PURE__ */ new Set();
|
|
42
42
|
this._modalStates = [];
|
|
43
43
|
this._downloads = [];
|
|
44
44
|
this.context = context;
|
|
@@ -46,8 +46,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
46
46
|
this._onPageClose = onPageClose;
|
|
47
47
|
page.on("console", (event) => this._handleConsoleMessage(messageToConsoleMessage(event)));
|
|
48
48
|
page.on("pageerror", (error) => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
|
|
49
|
-
page.on("request", (request) => this._requests.
|
|
50
|
-
page.on("response", (response) => this._requests.set(response.request(), response));
|
|
49
|
+
page.on("request", (request) => this._requests.add(request));
|
|
51
50
|
page.on("close", () => this._onClose());
|
|
52
51
|
page.on("filechooser", (chooser) => {
|
|
53
52
|
this.setModalState({
|
|
@@ -64,7 +63,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
64
63
|
page.setDefaultNavigationTimeout(this.context.config.timeouts.navigation);
|
|
65
64
|
page.setDefaultTimeout(this.context.config.timeouts.action);
|
|
66
65
|
page[tabSymbol] = this;
|
|
67
|
-
|
|
66
|
+
this._initializedPromise = this._initialize();
|
|
68
67
|
}
|
|
69
68
|
static forPage(page) {
|
|
70
69
|
return page[tabSymbol];
|
|
@@ -77,13 +76,8 @@ class Tab extends import_events.EventEmitter {
|
|
|
77
76
|
for (const error of errors)
|
|
78
77
|
this._handleConsoleMessage(pageErrorToConsoleMessage(error));
|
|
79
78
|
const requests = await this.page.requests().catch(() => []);
|
|
80
|
-
for (const request of requests)
|
|
81
|
-
this._requests.
|
|
82
|
-
void request.response().catch(() => null).then((response) => {
|
|
83
|
-
if (response)
|
|
84
|
-
this._requests.set(request, response);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
79
|
+
for (const request of requests)
|
|
80
|
+
this._requests.add(request);
|
|
87
81
|
}
|
|
88
82
|
modalStates() {
|
|
89
83
|
return this._modalStates;
|
|
@@ -164,10 +158,12 @@ class Tab extends import_events.EventEmitter {
|
|
|
164
158
|
}
|
|
165
159
|
await this.waitForLoadState("load", { timeout: 5e3 });
|
|
166
160
|
}
|
|
167
|
-
consoleMessages() {
|
|
161
|
+
async consoleMessages() {
|
|
162
|
+
await this._initializedPromise;
|
|
168
163
|
return this._consoleMessages;
|
|
169
164
|
}
|
|
170
|
-
requests() {
|
|
165
|
+
async requests() {
|
|
166
|
+
await this._initializedPromise;
|
|
171
167
|
return this._requests;
|
|
172
168
|
}
|
|
173
169
|
async captureSnapshot() {
|
|
@@ -33,7 +33,8 @@ const console = (0, import_tool.defineTabTool)({
|
|
|
33
33
|
type: "readOnly"
|
|
34
34
|
},
|
|
35
35
|
handle: async (tab, params, response) => {
|
|
36
|
-
tab.consoleMessages()
|
|
36
|
+
const messages = await tab.consoleMessages();
|
|
37
|
+
messages.map((message) => response.addResult(message.toString()));
|
|
37
38
|
}
|
|
38
39
|
});
|
|
39
40
|
var console_default = [
|
|
@@ -33,15 +33,20 @@ const requests = (0, import_tool.defineTabTool)({
|
|
|
33
33
|
type: "readOnly"
|
|
34
34
|
},
|
|
35
35
|
handle: async (tab, params, response) => {
|
|
36
|
-
const requests2 = tab.requests();
|
|
37
|
-
|
|
36
|
+
const requests2 = await tab.requests();
|
|
37
|
+
for (const request of requests2)
|
|
38
|
+
response.addResult(await renderRequest(request));
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
|
-
function renderRequest(request
|
|
41
|
+
async function renderRequest(request) {
|
|
41
42
|
const result = [];
|
|
42
43
|
result.push(`[${request.method().toUpperCase()}] ${request.url()}`);
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const hasResponse = request._hasResponse;
|
|
45
|
+
if (hasResponse) {
|
|
46
|
+
const response = await request.response();
|
|
47
|
+
if (response)
|
|
48
|
+
result.push(`=> [${response.status()}] ${response.statusText()}`);
|
|
49
|
+
}
|
|
45
50
|
return result.join(" ");
|
|
46
51
|
}
|
|
47
52
|
var network_default = [
|
|
@@ -150,7 +150,7 @@ test.describe('Test group', () => {
|
|
|
150
150
|
const candidateFiles = [];
|
|
151
151
|
candidateFiles.push(import_path.default.resolve(testDir, params.seedFile));
|
|
152
152
|
candidateFiles.push(import_path.default.resolve(configDir, params.seedFile));
|
|
153
|
-
candidateFiles.push(import_path.default.resolve(
|
|
153
|
+
candidateFiles.push(import_path.default.resolve(context.rootPath, params.seedFile));
|
|
154
154
|
for (const candidateFile of candidateFiles) {
|
|
155
155
|
if (await (0, import_util.fileExistsAsync)(candidateFile)) {
|
|
156
156
|
seedFile = candidateFile;
|
|
@@ -169,7 +169,7 @@ ${seedFileContent}
|
|
|
169
169
|
` });
|
|
170
170
|
const result = await testRunner.runTests(reporter, {
|
|
171
171
|
headed: !context.options?.headless,
|
|
172
|
-
locations: [seedFile],
|
|
172
|
+
locations: ["/" + (0, import_utils.escapeRegExp)(seedFile) + "/"],
|
|
173
173
|
projects: params.project ? [params.project] : void 0,
|
|
174
174
|
timeout: 0,
|
|
175
175
|
workers: 1,
|
package/lib/reporters/html.js
CHANGED
|
@@ -119,17 +119,10 @@ class HtmlReporter {
|
|
|
119
119
|
else if (process.env.PLAYWRIGHT_HTML_NO_COPY_PROMPT)
|
|
120
120
|
noCopyPrompt = true;
|
|
121
121
|
noCopyPrompt = noCopyPrompt || this._options.noCopyPrompt;
|
|
122
|
-
let noFiles;
|
|
123
|
-
if (process.env.PLAYWRIGHT_HTML_NO_FILES === "false" || process.env.PLAYWRIGHT_HTML_NO_FILES === "0")
|
|
124
|
-
noFiles = false;
|
|
125
|
-
else if (process.env.PLAYWRIGHT_HTML_NO_FILES)
|
|
126
|
-
noFiles = true;
|
|
127
|
-
noFiles = noFiles || this._options.noFiles;
|
|
128
122
|
const builder = new HtmlBuilder(this.config, this._outputFolder, this._attachmentsBaseURL, {
|
|
129
123
|
title: process.env.PLAYWRIGHT_HTML_TITLE || this._options.title,
|
|
130
124
|
noSnippets,
|
|
131
|
-
noCopyPrompt
|
|
132
|
-
noFiles
|
|
125
|
+
noCopyPrompt
|
|
133
126
|
});
|
|
134
127
|
this._buildResult = await builder.build(this.config.metadata, projectSuites, result, this._topLevelErrors);
|
|
135
128
|
}
|
|
@@ -229,20 +222,8 @@ class HtmlBuilder {
|
|
|
229
222
|
for (const projectSuite of projectSuites) {
|
|
230
223
|
const projectName = projectSuite.project().name;
|
|
231
224
|
for (const fileSuite of projectSuite.suites) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const groupName = describeSuite.title;
|
|
235
|
-
this._createEntryForSuite(data, projectName, describeSuite, groupName, true);
|
|
236
|
-
}
|
|
237
|
-
const hasTestsOutsideGroups = fileSuite.tests.length > 0;
|
|
238
|
-
if (hasTestsOutsideGroups) {
|
|
239
|
-
const fileName = "<anonymous>";
|
|
240
|
-
this._createEntryForSuite(data, projectName, fileSuite, fileName, false);
|
|
241
|
-
}
|
|
242
|
-
} else {
|
|
243
|
-
const fileName = this._relativeLocation(fileSuite.location).file;
|
|
244
|
-
this._createEntryForSuite(data, projectName, fileSuite, fileName, true);
|
|
245
|
-
}
|
|
225
|
+
const fileName = this._relativeLocation(fileSuite.location).file;
|
|
226
|
+
this._createEntryForSuite(data, projectName, fileSuite, fileName, true);
|
|
246
227
|
}
|
|
247
228
|
}
|
|
248
229
|
if (!this._options.noSnippets)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright",
|
|
3
|
-
"version": "1.56.0-alpha-
|
|
3
|
+
"version": "1.56.0-alpha-2025-09-27",
|
|
4
4
|
"description": "A high-level API to automate web browsers",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"license": "Apache-2.0",
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"playwright-core": "1.56.0-alpha-
|
|
67
|
+
"playwright-core": "1.56.0-alpha-2025-09-27"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|