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

0
node_modules/playwright/lib/mcp/browser/tools/common.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/mcp/browser/tools/console.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/mcp/browser/tools/dialogs.js generated vendored Normal file → Executable file
View File

5
node_modules/playwright/lib/mcp/browser/tools/evaluate.js generated vendored Normal file → Executable file
View File

@@ -34,7 +34,6 @@ module.exports = __toCommonJS(evaluate_exports);
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var javascript = __toESM(require("../codegen"));
var import_utils = require("./utils");
const evaluateSchema = import_bundle.z.object({
function: import_bundle.z.string().describe("() => { /* code */ } or (element) => { /* code */ } when element is provided"),
element: import_bundle.z.string().optional().describe("Human-readable element description used to obtain permission to interact with the element"),
@@ -54,12 +53,12 @@ const evaluate = (0, import_tool.defineTabTool)({
let locator;
if (params.ref && params.element) {
locator = await tab.refLocator({ ref: params.ref, element: params.element });
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.evaluate(${javascript.quote(params.function)});`);
response.addCode(`await page.${locator.resolved}.evaluate(${javascript.quote(params.function)});`);
} else {
response.addCode(`await page.evaluate(${javascript.quote(params.function)});`);
}
await tab.waitForCompletion(async () => {
const receiver = locator ?? tab.page;
const receiver = locator?.locator ?? tab.page;
const result = await receiver._evaluateFunction(params.function);
response.addResult(JSON.stringify(result, null, 2) || "undefined");
});

0
node_modules/playwright/lib/mcp/browser/tools/files.js generated vendored Normal file → Executable file
View File

5
node_modules/playwright/lib/mcp/browser/tools/form.js generated vendored Normal file → Executable file
View File

@@ -33,7 +33,6 @@ __export(form_exports, {
module.exports = __toCommonJS(form_exports);
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var import_utils = require("./utils");
var codegen = __toESM(require("../codegen"));
const fillForm = (0, import_tool.defineTabTool)({
capability: "core",
@@ -53,8 +52,8 @@ const fillForm = (0, import_tool.defineTabTool)({
},
handle: async (tab, params, response) => {
for (const field of params.fields) {
const locator = await tab.refLocator({ element: field.name, ref: field.ref });
const locatorSource = `await page.${await (0, import_utils.generateLocator)(locator)}`;
const { locator, resolved } = await tab.refLocator({ element: field.name, ref: field.ref });
const locatorSource = `await page.${resolved}`;
if (field.type === "textbox" || field.type === "slider") {
const secret = tab.context.lookupSecret(field.value);
await locator.fill(secret.value);

0
node_modules/playwright/lib/mcp/browser/tools/install.js generated vendored Normal file → Executable file
View File

9
node_modules/playwright/lib/mcp/browser/tools/keyboard.js generated vendored Normal file → Executable file
View File

@@ -24,7 +24,6 @@ module.exports = __toCommonJS(keyboard_exports);
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var import_snapshot = require("./snapshot");
var import_utils = require("./utils");
const pressKey = (0, import_tool.defineTabTool)({
capability: "core",
schema: {
@@ -60,20 +59,20 @@ const type = (0, import_tool.defineTabTool)({
type: "input"
},
handle: async (tab, params, response) => {
const locator = await tab.refLocator(params);
const { locator, resolved } = await tab.refLocator(params);
const secret = tab.context.lookupSecret(params.text);
await tab.waitForCompletion(async () => {
if (params.slowly) {
response.setIncludeSnapshot();
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.pressSequentially(${secret.code});`);
response.addCode(`await page.${resolved}.pressSequentially(${secret.code});`);
await locator.pressSequentially(secret.value);
} else {
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.fill(${secret.code});`);
response.addCode(`await page.${resolved}.fill(${secret.code});`);
await locator.fill(secret.value);
}
if (params.submit) {
response.setIncludeSnapshot();
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.press('Enter');`);
response.addCode(`await page.${resolved}.press('Enter');`);
await locator.press("Enter");
}
});

0
node_modules/playwright/lib/mcp/browser/tools/mouse.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/mcp/browser/tools/navigate.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/mcp/browser/tools/network.js generated vendored Normal file → Executable file
View File

2
node_modules/playwright/lib/mcp/browser/tools/pdf.js generated vendored Normal file → Executable file
View File

@@ -36,7 +36,7 @@ var import_tool = require("./tool");
var javascript = __toESM(require("../codegen"));
var import_utils = require("./utils");
const pdfSchema = import_bundle.z.object({
filename: import_bundle.z.string().optional().describe("File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified.")
filename: import_bundle.z.string().optional().describe("File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified. Prefer relative file names to stay within the output directory.")
});
const pdf = (0, import_tool.defineTabTool)({
capability: "pdf",

75
node_modules/playwright/lib/mcp/browser/tools/runCode.js generated vendored Executable file
View File

@@ -0,0 +1,75 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var runCode_exports = {};
__export(runCode_exports, {
default: () => runCode_default
});
module.exports = __toCommonJS(runCode_exports);
var import_vm = __toESM(require("vm"));
var import_utils = require("playwright-core/lib/utils");
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
const codeSchema = import_bundle.z.object({
code: import_bundle.z.string().describe(`Playwright code snippet to run. The snippet should access the \`page\` object to interact with the page. Can make multiple statements. For example: \`await page.getByRole('button', { name: 'Submit' }).click();\``)
});
const runCode = (0, import_tool.defineTabTool)({
capability: "core",
schema: {
name: "browser_run_code",
title: "Run Playwright code",
description: "Run Playwright code snippet",
inputSchema: codeSchema,
type: "action"
},
handle: async (tab, params, response) => {
response.setIncludeSnapshot();
response.addCode(params.code);
const __end__ = new import_utils.ManualPromise();
const context = {
page: tab.page,
__end__
};
import_vm.default.createContext(context);
await tab.waitForCompletion(async () => {
const snippet = `(async () => {
try {
${params.code};
__end__.resolve();
} catch (e) {
__end__.reject(e);
}
})()`;
import_vm.default.runInContext(snippet, context);
await __end__;
});
}
});
var runCode_default = [
runCode
];

48
node_modules/playwright/lib/mcp/browser/tools/screenshot.js generated vendored Normal file → Executable file
View File

@@ -28,16 +28,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var screenshot_exports = {};
__export(screenshot_exports, {
default: () => screenshot_default
default: () => screenshot_default,
scaleImageToFitMessage: () => scaleImageToFitMessage
});
module.exports = __toCommonJS(screenshot_exports);
var import_fs = __toESM(require("fs"));
var import_utils = require("playwright-core/lib/utils");
var import_utilsBundle = require("playwright-core/lib/utilsBundle");
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var javascript = __toESM(require("../codegen"));
var import_utils = require("./utils");
var import_utils2 = require("./utils");
const screenshotSchema = import_bundle.z.object({
type: import_bundle.z.enum(["png", "jpeg"]).default("png").describe("Image format for the screenshot. Default is png."),
filename: import_bundle.z.string().optional().describe("File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified."),
filename: import_bundle.z.string().optional().describe("File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified. Prefer relative file names to stay within the output directory."),
element: import_bundle.z.string().optional().describe("Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too."),
ref: import_bundle.z.string().optional().describe("Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too."),
fullPage: import_bundle.z.boolean().optional().describe("When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots.")
@@ -57,32 +61,46 @@ const screenshot = (0, import_tool.defineTabTool)({
if (params.fullPage && params.ref)
throw new Error("fullPage cannot be used with element screenshots.");
const fileType = params.type || "png";
const fileName = await tab.context.outputFile(params.filename ?? (0, import_utils.dateAsFileName)(fileType), { origin: "llm", reason: "Saving screenshot" });
const fileName = await tab.context.outputFile(params.filename || (0, import_utils2.dateAsFileName)(fileType), { origin: "llm", reason: "Saving screenshot" });
const options = {
type: fileType,
quality: fileType === "png" ? void 0 : 90,
scale: "css",
path: fileName,
...params.fullPage !== void 0 && { fullPage: params.fullPage }
};
const isElementScreenshot = params.element && params.ref;
const screenshotTarget = isElementScreenshot ? params.element : params.fullPage ? "full page" : "viewport";
response.addCode(`// Screenshot ${screenshotTarget} and save it as ${fileName}`);
const locator = params.ref ? await tab.refLocator({ element: params.element || "", ref: params.ref }) : null;
if (locator)
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.screenshot(${javascript.formatObject(options)});`);
const ref = params.ref ? await tab.refLocator({ element: params.element || "", ref: params.ref }) : null;
if (ref)
response.addCode(`await page.${ref.resolved}.screenshot(${javascript.formatObject(options)});`);
else
response.addCode(`await page.screenshot(${javascript.formatObject(options)});`);
const buffer = locator ? await locator.screenshot(options) : await tab.page.screenshot(options);
const buffer = ref ? await ref.locator.screenshot(options) : await tab.page.screenshot(options);
await (0, import_utils.mkdirIfNeeded)(fileName);
await import_fs.default.promises.writeFile(fileName, buffer);
response.addResult(`Took the ${screenshotTarget} screenshot and saved it as ${fileName}`);
if (!params.fullPage) {
response.addImage({
contentType: fileType === "png" ? "image/png" : "image/jpeg",
data: buffer
});
}
response.addImage({
contentType: fileType === "png" ? "image/png" : "image/jpeg",
data: scaleImageToFitMessage(buffer, fileType)
});
}
});
function scaleImageToFitMessage(buffer, imageType) {
const image = imageType === "png" ? import_utilsBundle.PNG.sync.read(buffer) : import_utilsBundle.jpegjs.decode(buffer, { maxMemoryUsageInMB: 512 });
const pixels = image.width * image.height;
const shrink = Math.min(1568 / image.width, 1568 / image.height, Math.sqrt(1.15 * 1024 * 1024 / pixels));
if (shrink > 1)
return buffer;
const width = image.width * shrink | 0;
const height = image.height * shrink | 0;
const scaledImage = (0, import_utils.scaleImageToSize)(image, { width, height });
return imageType === "png" ? import_utilsBundle.PNG.sync.write(scaledImage) : import_utilsBundle.jpegjs.encode(scaledImage, 80).data;
}
var screenshot_default = [
screenshot
];
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
scaleImageToFitMessage
});

27
node_modules/playwright/lib/mcp/browser/tools/snapshot.js generated vendored Normal file → Executable file
View File

@@ -35,7 +35,6 @@ module.exports = __toCommonJS(snapshot_exports);
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var javascript = __toESM(require("../codegen"));
var import_utils = require("./utils");
const snapshot = (0, import_tool.defineTool)({
capability: "core",
schema: {
@@ -47,7 +46,7 @@ const snapshot = (0, import_tool.defineTool)({
},
handle: async (context, params, response) => {
await context.ensureTab();
response.setIncludeSnapshot();
response.setIncludeSnapshot("full");
}
});
const elementSchema = import_bundle.z.object({
@@ -70,7 +69,7 @@ const click = (0, import_tool.defineTabTool)({
},
handle: async (tab, params, response) => {
response.setIncludeSnapshot();
const locator = await tab.refLocator(params);
const { locator, resolved } = await tab.refLocator(params);
const options = {
button: params.button,
modifiers: params.modifiers
@@ -78,9 +77,9 @@ const click = (0, import_tool.defineTabTool)({
const formatted = javascript.formatObject(options, " ", "oneline");
const optionsAttr = formatted !== "{}" ? formatted : "";
if (params.doubleClick)
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.dblclick(${optionsAttr});`);
response.addCode(`await page.${resolved}.dblclick(${optionsAttr});`);
else
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.click(${optionsAttr});`);
response.addCode(`await page.${resolved}.click(${optionsAttr});`);
await tab.waitForCompletion(async () => {
if (params.doubleClick)
await locator.dblclick(options);
@@ -105,14 +104,14 @@ const drag = (0, import_tool.defineTabTool)({
},
handle: async (tab, params, response) => {
response.setIncludeSnapshot();
const [startLocator, endLocator] = await tab.refLocators([
const [start, end] = await tab.refLocators([
{ ref: params.startRef, element: params.startElement },
{ ref: params.endRef, element: params.endElement }
]);
await tab.waitForCompletion(async () => {
await startLocator.dragTo(endLocator);
await start.locator.dragTo(end.locator);
});
response.addCode(`await page.${await (0, import_utils.generateLocator)(startLocator)}.dragTo(page.${await (0, import_utils.generateLocator)(endLocator)});`);
response.addCode(`await page.${start.resolved}.dragTo(page.${end.resolved});`);
}
});
const hover = (0, import_tool.defineTabTool)({
@@ -126,8 +125,8 @@ const hover = (0, import_tool.defineTabTool)({
},
handle: async (tab, params, response) => {
response.setIncludeSnapshot();
const locator = await tab.refLocator(params);
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.hover();`);
const { locator, resolved } = await tab.refLocator(params);
response.addCode(`await page.${resolved}.hover();`);
await tab.waitForCompletion(async () => {
await locator.hover();
});
@@ -147,8 +146,8 @@ const selectOption = (0, import_tool.defineTabTool)({
},
handle: async (tab, params, response) => {
response.setIncludeSnapshot();
const locator = await tab.refLocator(params);
response.addCode(`await page.${await (0, import_utils.generateLocator)(locator)}.selectOption(${javascript.formatObject(params.values)});`);
const { locator, resolved } = await tab.refLocator(params);
response.addCode(`await page.${resolved}.selectOption(${javascript.formatObject(params.values)});`);
await tab.waitForCompletion(async () => {
await locator.selectOption(params.values);
});
@@ -164,8 +163,8 @@ const pickLocator = (0, import_tool.defineTabTool)({
type: "readOnly"
},
handle: async (tab, params, response) => {
const locator = await tab.refLocator(params);
response.addResult(await (0, import_utils.generateLocator)(locator));
const { resolved } = await tab.refLocator(params);
response.addResult(resolved);
}
});
var snapshot_default = [

4
node_modules/playwright/lib/mcp/browser/tools/tabs.js generated vendored Normal file → Executable file
View File

@@ -49,14 +49,14 @@ const browserTabs = (0, import_tool.defineTool)({
}
case "close": {
await context.closeTab(params.index);
response.setIncludeSnapshot();
response.setIncludeSnapshot("full");
return;
}
case "select": {
if (params.index === void 0)
throw new Error("Tab index is required");
await context.selectTab(params.index);
response.setIncludeSnapshot();
response.setIncludeSnapshot("full");
return;
}
}

0
node_modules/playwright/lib/mcp/browser/tools/tool.js generated vendored Normal file → Executable file
View File

0
node_modules/playwright/lib/mcp/browser/tools/tracing.js generated vendored Normal file → Executable file
View File

11
node_modules/playwright/lib/mcp/browser/tools/utils.js generated vendored Normal file → Executable file
View File

@@ -20,11 +20,9 @@ var utils_exports = {};
__export(utils_exports, {
callOnPageNoTrace: () => callOnPageNoTrace,
dateAsFileName: () => dateAsFileName,
generateLocator: () => generateLocator,
waitForCompletion: () => waitForCompletion
});
module.exports = __toCommonJS(utils_exports);
var import_utils = require("playwright-core/lib/utils");
async function waitForCompletion(tab, callback) {
const requests = /* @__PURE__ */ new Set();
let frameNavigated = false;
@@ -76,14 +74,6 @@ async function waitForCompletion(tab, callback) {
dispose();
}
}
async function generateLocator(locator) {
try {
const { resolvedSelector } = await locator._resolveSelector();
return (0, import_utils.asLocator)("javascript", resolvedSelector);
} catch (e) {
throw new Error("Ref not found, likely because element was removed. Use browser_snapshot to see what elements are currently on the page.");
}
}
async function callOnPageNoTrace(page, callback) {
return await page._wrapApiCall(() => callback(page), { internal: true });
}
@@ -95,6 +85,5 @@ function dateAsFileName(extension) {
0 && (module.exports = {
callOnPageNoTrace,
dateAsFileName,
generateLocator,
waitForCompletion
});

7
node_modules/playwright/lib/mcp/browser/tools/verify.js generated vendored Normal file → Executable file
View File

@@ -34,7 +34,6 @@ module.exports = __toCommonJS(verify_exports);
var import_bundle = require("../../sdk/bundle");
var import_tool = require("./tool");
var javascript = __toESM(require("../codegen"));
var import_utils = require("./utils");
const verifyElement = (0, import_tool.defineTabTool)({
capability: "testing",
schema: {
@@ -92,7 +91,7 @@ const verifyList = (0, import_tool.defineTabTool)({
type: "assertion"
},
handle: async (tab, params, response) => {
const locator = await tab.refLocator({ ref: params.ref, element: params.element });
const { locator } = await tab.refLocator({ ref: params.ref, element: params.element });
const itemTexts = [];
for (const item of params.items) {
const itemLocator = locator.getByText(item);
@@ -125,8 +124,8 @@ const verifyValue = (0, import_tool.defineTabTool)({
type: "assertion"
},
handle: async (tab, params, response) => {
const locator = await tab.refLocator({ ref: params.ref, element: params.element });
const locatorSource = `page.${await (0, import_utils.generateLocator)(locator)}`;
const { locator, resolved } = await tab.refLocator({ ref: params.ref, element: params.element });
const locatorSource = `page.${resolved}`;
if (params.type === "textbox" || params.type === "slider" || params.type === "combobox") {
const value = await locator.inputValue();
if (value !== params.value) {

0
node_modules/playwright/lib/mcp/browser/tools/wait.js generated vendored Normal file → Executable file
View File