playwright 1.56.0-alpha-2025-09-22 → 1.56.0-alpha-2025-09-23
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.
|
@@ -27,7 +27,7 @@ class Response {
|
|
|
27
27
|
this._result = [];
|
|
28
28
|
this._code = [];
|
|
29
29
|
this._images = [];
|
|
30
|
-
this._includeSnapshot =
|
|
30
|
+
this._includeSnapshot = "none";
|
|
31
31
|
this._includeTabs = false;
|
|
32
32
|
this._context = context;
|
|
33
33
|
this.toolName = toolName;
|
|
@@ -58,14 +58,14 @@ class Response {
|
|
|
58
58
|
images() {
|
|
59
59
|
return this._images;
|
|
60
60
|
}
|
|
61
|
-
setIncludeSnapshot() {
|
|
62
|
-
this._includeSnapshot =
|
|
61
|
+
setIncludeSnapshot(full) {
|
|
62
|
+
this._includeSnapshot = full ?? "partial";
|
|
63
63
|
}
|
|
64
64
|
setIncludeTabs() {
|
|
65
65
|
this._includeTabs = true;
|
|
66
66
|
}
|
|
67
67
|
async finish() {
|
|
68
|
-
if (this._includeSnapshot && this._context.currentTab())
|
|
68
|
+
if (this._includeSnapshot !== "none" && this._context.currentTab())
|
|
69
69
|
this._tabSnapshot = await this._context.currentTabOrDie().captureSnapshot();
|
|
70
70
|
for (const tab of this._context.tabs())
|
|
71
71
|
await tab.updateTitle();
|
|
@@ -87,13 +87,13 @@ ${this._code.join("\n")}
|
|
|
87
87
|
\`\`\``);
|
|
88
88
|
response.push("");
|
|
89
89
|
}
|
|
90
|
-
if (this._includeSnapshot || this._includeTabs)
|
|
90
|
+
if (this._includeSnapshot !== "none" || this._includeTabs)
|
|
91
91
|
response.push(...renderTabsMarkdown(this._context.tabs(), this._includeTabs));
|
|
92
92
|
if (this._tabSnapshot?.modalStates.length) {
|
|
93
93
|
response.push(...(0, import_tab.renderModalStates)(this._context, this._tabSnapshot.modalStates));
|
|
94
94
|
response.push("");
|
|
95
95
|
} else if (this._tabSnapshot) {
|
|
96
|
-
response.push(renderTabSnapshot(this._tabSnapshot));
|
|
96
|
+
response.push(renderTabSnapshot(this._tabSnapshot, this._includeSnapshot === "full"));
|
|
97
97
|
response.push("");
|
|
98
98
|
}
|
|
99
99
|
const content = [
|
|
@@ -117,7 +117,7 @@ ${this._code.join("\n")}
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
function renderTabSnapshot(tabSnapshot) {
|
|
120
|
+
function renderTabSnapshot(tabSnapshot, fullSnapshot) {
|
|
121
121
|
const lines = [];
|
|
122
122
|
if (tabSnapshot.consoleMessages.length) {
|
|
123
123
|
lines.push(`### New console messages`);
|
|
@@ -138,10 +138,15 @@ function renderTabSnapshot(tabSnapshot) {
|
|
|
138
138
|
lines.push(`### Page state`);
|
|
139
139
|
lines.push(`- Page URL: ${tabSnapshot.url}`);
|
|
140
140
|
lines.push(`- Page Title: ${tabSnapshot.title}`);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
if (!fullSnapshot && tabSnapshot.formattedAriaSnapshotDiff) {
|
|
142
|
+
lines.push(`- Page Snapshot Diff:`);
|
|
143
|
+
lines.push(tabSnapshot.formattedAriaSnapshotDiff);
|
|
144
|
+
} else {
|
|
145
|
+
lines.push(`- Page Snapshot:`);
|
|
146
|
+
lines.push("```yaml");
|
|
147
|
+
lines.push(tabSnapshot.ariaSnapshot);
|
|
148
|
+
lines.push("```");
|
|
149
|
+
}
|
|
145
150
|
return lines.join("\n");
|
|
146
151
|
}
|
|
147
152
|
function renderTabsMarkdown(tabs, force = false) {
|
|
@@ -67,7 +67,7 @@ class SessionLog {
|
|
|
67
67
|
code = code.trim();
|
|
68
68
|
if (isUpdate) {
|
|
69
69
|
const lastEntry = this._pendingEntries[this._pendingEntries.length - 1];
|
|
70
|
-
if (lastEntry
|
|
70
|
+
if (lastEntry?.userAction?.name === action.name) {
|
|
71
71
|
lastEntry.userAction = action;
|
|
72
72
|
lastEntry.code = code;
|
|
73
73
|
return;
|
package/lib/mcp/browser/tab.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(tab_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(tab_exports);
|
|
26
26
|
var import_events = require("events");
|
|
27
27
|
var import_utils = require("playwright-core/lib/utils");
|
|
28
|
+
var import_utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
28
29
|
var import_utils2 = require("./tools/utils");
|
|
29
30
|
var import_log = require("../log");
|
|
30
31
|
const TabEvents = {
|
|
@@ -44,7 +45,11 @@ class Tab extends import_events.EventEmitter {
|
|
|
44
45
|
this._onPageClose = onPageClose;
|
|
45
46
|
page.on("console", (event) => this._handleConsoleMessage(messageToConsoleMessage(event)));
|
|
46
47
|
page.on("pageerror", (error) => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
|
|
47
|
-
page.on("request", (request) =>
|
|
48
|
+
page.on("request", (request) => {
|
|
49
|
+
this._requests.set(request, null);
|
|
50
|
+
if (request.frame() === page.mainFrame() && request.isNavigationRequest())
|
|
51
|
+
this._willNavigateMainFrameToNewDocument();
|
|
52
|
+
});
|
|
48
53
|
page.on("response", (response) => this._requests.set(response.request(), response));
|
|
49
54
|
page.on("close", () => this._onClose());
|
|
50
55
|
page.on("filechooser", (chooser) => {
|
|
@@ -62,10 +67,27 @@ class Tab extends import_events.EventEmitter {
|
|
|
62
67
|
page.setDefaultNavigationTimeout(this.context.config.timeouts.navigation);
|
|
63
68
|
page.setDefaultTimeout(this.context.config.timeouts.action);
|
|
64
69
|
page[tabSymbol] = this;
|
|
70
|
+
void this._initialize();
|
|
65
71
|
}
|
|
66
72
|
static forPage(page) {
|
|
67
73
|
return page[tabSymbol];
|
|
68
74
|
}
|
|
75
|
+
async _initialize() {
|
|
76
|
+
const messages = await this.page.consoleMessages().catch(() => []);
|
|
77
|
+
for (const message of messages)
|
|
78
|
+
this._handleConsoleMessage(messageToConsoleMessage(message));
|
|
79
|
+
const errors = await this.page.pageErrors().catch(() => []);
|
|
80
|
+
for (const error of errors)
|
|
81
|
+
this._handleConsoleMessage(pageErrorToConsoleMessage(error));
|
|
82
|
+
const requests = await this.page.requests().catch(() => []);
|
|
83
|
+
for (const request of requests) {
|
|
84
|
+
this._requests.set(request, null);
|
|
85
|
+
void request.response().catch(() => null).then((response) => {
|
|
86
|
+
if (response)
|
|
87
|
+
this._requests.set(request, response);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
69
91
|
modalStates() {
|
|
70
92
|
return this._modalStates;
|
|
71
93
|
}
|
|
@@ -110,6 +132,9 @@ class Tab extends import_events.EventEmitter {
|
|
|
110
132
|
this._clearCollectedArtifacts();
|
|
111
133
|
this._onPageClose(this);
|
|
112
134
|
}
|
|
135
|
+
_willNavigateMainFrameToNewDocument() {
|
|
136
|
+
this._lastAriaSnapshot = void 0;
|
|
137
|
+
}
|
|
113
138
|
async updateTitle() {
|
|
114
139
|
await this._raceAgainstModalStates(async () => {
|
|
115
140
|
this._lastTitle = await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.title());
|
|
@@ -126,6 +151,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
126
151
|
}
|
|
127
152
|
async navigate(url) {
|
|
128
153
|
this._clearCollectedArtifacts();
|
|
154
|
+
this._willNavigateMainFrameToNewDocument();
|
|
129
155
|
const downloadEvent = (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.waitForEvent("download").catch(import_log.logUnhandledError));
|
|
130
156
|
try {
|
|
131
157
|
await this.page.goto(url, { waitUntil: "domcontentloaded" });
|
|
@@ -159,6 +185,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
159
185
|
url: this.page.url(),
|
|
160
186
|
title: await this.page.title(),
|
|
161
187
|
ariaSnapshot: snapshot,
|
|
188
|
+
formattedAriaSnapshotDiff: this._lastAriaSnapshot ? generateAriaSnapshotDiff(this._lastAriaSnapshot, snapshot) : void 0,
|
|
162
189
|
modalStates: [],
|
|
163
190
|
consoleMessages: [],
|
|
164
191
|
downloads: this._downloads
|
|
@@ -167,6 +194,7 @@ class Tab extends import_events.EventEmitter {
|
|
|
167
194
|
if (tabSnapshot) {
|
|
168
195
|
tabSnapshot.consoleMessages = this._recentConsoleMessages;
|
|
169
196
|
this._recentConsoleMessages = [];
|
|
197
|
+
this._lastAriaSnapshot = tabSnapshot.ariaSnapshot;
|
|
170
198
|
}
|
|
171
199
|
return tabSnapshot ?? {
|
|
172
200
|
url: this.page.url(),
|
|
@@ -248,6 +276,23 @@ function renderModalStates(context, modalStates) {
|
|
|
248
276
|
return result;
|
|
249
277
|
}
|
|
250
278
|
const tabSymbol = Symbol("tabSymbol");
|
|
279
|
+
function generateAriaSnapshotDiff(oldSnapshot, newSnapshot) {
|
|
280
|
+
const diffs = (0, import_utils.diffAriaSnapshots)(import_utilsBundle.yaml, oldSnapshot, newSnapshot);
|
|
281
|
+
if (diffs === "equal")
|
|
282
|
+
return "<no changes>";
|
|
283
|
+
if (diffs === "different")
|
|
284
|
+
return;
|
|
285
|
+
if (diffs.length > 3 || diffs.some((diff) => diff.newSource.split("\n").length > 100)) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const lines = [`The following refs have changed`];
|
|
289
|
+
for (const diff of diffs)
|
|
290
|
+
lines.push("", "```yaml", diff.newSource.trimEnd(), "```");
|
|
291
|
+
const combined = lines.join("\n");
|
|
292
|
+
if (combined.length >= newSnapshot.length)
|
|
293
|
+
return;
|
|
294
|
+
return combined;
|
|
295
|
+
}
|
|
251
296
|
// Annotate the CommonJS export names for ESM import in node:
|
|
252
297
|
0 && (module.exports = {
|
|
253
298
|
Tab,
|
|
@@ -47,7 +47,7 @@ const snapshot = (0, import_tool.defineTool)({
|
|
|
47
47
|
},
|
|
48
48
|
handle: async (context, params, response) => {
|
|
49
49
|
await context.ensureTab();
|
|
50
|
-
response.setIncludeSnapshot();
|
|
50
|
+
response.setIncludeSnapshot("full");
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
const elementSchema = import_bundle.z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright",
|
|
3
|
-
"version": "1.56.0-alpha-2025-09-
|
|
3
|
+
"version": "1.56.0-alpha-2025-09-23",
|
|
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-2025-09-
|
|
67
|
+
"playwright-core": "1.56.0-alpha-2025-09-23"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|