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 = false;
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 = true;
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
- lines.push(`- Page Snapshot:`);
142
- lines.push("```yaml");
143
- lines.push(tabSnapshot.ariaSnapshot);
144
- lines.push("```");
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.userAction?.name === action.name) {
70
+ if (lastEntry?.userAction?.name === action.name) {
71
71
  lastEntry.userAction = action;
72
72
  lastEntry.code = code;
73
73
  return;
@@ -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) => this._requests.set(request, null));
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-22",
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-22"
67
+ "playwright-core": "1.56.0-alpha-2025-09-23"
68
68
  },
69
69
  "optionalDependencies": {
70
70
  "fsevents": "2.3.2"