Add SPA session validation and buglist, update migration docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-03 21:28:08 +00:00
parent 9be3dfc14e
commit cff287e870
24169 changed files with 10223 additions and 7120 deletions

35
node_modules/playwright/lib/mcp/browser/tab.js generated vendored Normal file → Executable file
View File

@@ -29,6 +29,7 @@ var import_utils2 = require("./tools/utils");
var import_log = require("../log");
var import_dialogs = require("./tools/dialogs");
var import_files = require("./tools/files");
var import_transform = require("../../transform/transform");
const TabEvents = {
modalState: "modalState"
};
@@ -41,6 +42,7 @@ class Tab extends import_events.EventEmitter {
this._requests = /* @__PURE__ */ new Set();
this._modalStates = [];
this._downloads = [];
this._needsFullSnapshot = false;
this.context = context;
this.page = page;
this._onPageClose = onPageClose;
@@ -63,7 +65,7 @@ class Tab extends import_events.EventEmitter {
page.setDefaultNavigationTimeout(this.context.config.timeouts.navigation);
page.setDefaultTimeout(this.context.config.timeouts.action);
page[tabSymbol] = this;
this._initializedPromise = this._initialize();
this.initializedPromise = this._initialize();
}
static forPage(page) {
return page[tabSymbol];
@@ -84,6 +86,14 @@ class Tab extends import_events.EventEmitter {
const requests = await this.page.requests().catch(() => []);
for (const request of requests)
this._requests.add(request);
for (const initPage of this.context.config.browser.initPage || []) {
try {
const { default: func } = await (0, import_transform.requireOrImport)(initPage);
await func({ page: this.page });
} catch (e) {
(0, import_log.logUnhandledError)(e);
}
}
}
modalStates() {
return this._modalStates;
@@ -165,21 +175,22 @@ class Tab extends import_events.EventEmitter {
await this.waitForLoadState("load", { timeout: 5e3 });
}
async consoleMessages(type) {
await this._initializedPromise;
await this.initializedPromise;
return this._consoleMessages.filter((message) => type ? message.type === type : true);
}
async requests() {
await this._initializedPromise;
await this.initializedPromise;
return this._requests;
}
async captureSnapshot() {
let tabSnapshot;
const modalStates = await this._raceAgainstModalStates(async () => {
const snapshot = await this.page._snapshotForAI();
const snapshot = await this.page._snapshotForAI({ track: "response" });
tabSnapshot = {
url: this.page.url(),
title: await this.page.title(),
ariaSnapshot: snapshot,
ariaSnapshot: snapshot.full,
ariaSnapshotDiff: this._needsFullSnapshot ? void 0 : snapshot.incremental,
modalStates: [],
consoleMessages: [],
downloads: this._downloads
@@ -189,6 +200,7 @@ class Tab extends import_events.EventEmitter {
tabSnapshot.consoleMessages = this._recentConsoleMessages;
this._recentConsoleMessages = [];
}
this._needsFullSnapshot = !tabSnapshot;
return tabSnapshot ?? {
url: this.page.url(),
title: "",
@@ -222,12 +234,15 @@ class Tab extends import_events.EventEmitter {
return (await this.refLocators([params]))[0];
}
async refLocators(params) {
const snapshot = await this.page._snapshotForAI();
return params.map((param) => {
if (!snapshot.includes(`[ref=${param.ref}]`))
return Promise.all(params.map(async (param) => {
try {
const locator = this.page.locator(`aria-ref=${param.ref}`).describe(param.element);
const { resolvedSelector } = await locator._resolveSelector();
return { locator, resolved: (0, import_utils.asLocator)("javascript", resolvedSelector) };
} catch (e) {
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
return this.page.locator(`aria-ref=${param.ref}`).describe(param.element);
});
}
}));
}
async waitForTimeout(time) {
if (this._javaScriptBlocked()) {