mirror of
https://github.com/microsoft/playwright-mcp.git
synced 2025-07-26 08:32:26 +08:00
feat: add fullPage mode to browser_take_screenshot (#704)
This commit is contained in:
parent
29ac29e6bb
commit
1eee30fd45
@ -534,6 +534,7 @@ http.createServer(async (req, res) => {
|
|||||||
- `filename` (string, optional): File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.
|
- `filename` (string, optional): File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.
|
||||||
- `element` (string, optional): 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.
|
- `element` (string, optional): 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` (string, optional): 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.
|
- `ref` (string, optional): 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` (boolean, optional): When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots.
|
||||||
- Read-only: **true**
|
- Read-only: **true**
|
||||||
|
|
||||||
<!-- NOTE: This has been generated via update-readme.js -->
|
<!-- NOTE: This has been generated via update-readme.js -->
|
||||||
|
@ -28,11 +28,17 @@ const screenshotSchema = z.object({
|
|||||||
filename: z.string().optional().describe('File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.'),
|
filename: z.string().optional().describe('File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.'),
|
||||||
element: 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.'),
|
element: 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: 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.'),
|
ref: 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: 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.'),
|
||||||
}).refine(data => {
|
}).refine(data => {
|
||||||
return !!data.element === !!data.ref;
|
return !!data.element === !!data.ref;
|
||||||
}, {
|
}, {
|
||||||
message: 'Both element and ref must be provided or neither.',
|
message: 'Both element and ref must be provided or neither.',
|
||||||
path: ['ref', 'element']
|
path: ['ref', 'element']
|
||||||
|
}).refine(data => {
|
||||||
|
return !(data.fullPage && (data.element || data.ref));
|
||||||
|
}, {
|
||||||
|
message: 'fullPage cannot be used with element screenshots.',
|
||||||
|
path: ['fullPage']
|
||||||
});
|
});
|
||||||
|
|
||||||
const screenshot = defineTool({
|
const screenshot = defineTool({
|
||||||
@ -50,11 +56,18 @@ const screenshot = defineTool({
|
|||||||
const snapshot = tab.snapshotOrDie();
|
const snapshot = tab.snapshotOrDie();
|
||||||
const fileType = params.raw ? 'png' : 'jpeg';
|
const fileType = params.raw ? 'png' : 'jpeg';
|
||||||
const fileName = await outputFile(context.config, params.filename ?? `page-${new Date().toISOString()}.${fileType}`);
|
const fileName = await outputFile(context.config, params.filename ?? `page-${new Date().toISOString()}.${fileType}`);
|
||||||
const options: playwright.PageScreenshotOptions = { type: fileType, quality: fileType === 'png' ? undefined : 50, scale: 'css', path: fileName };
|
const options: playwright.PageScreenshotOptions = {
|
||||||
|
type: fileType,
|
||||||
|
quality: fileType === 'png' ? undefined : 50,
|
||||||
|
scale: 'css',
|
||||||
|
path: fileName,
|
||||||
|
...(params.fullPage !== undefined && { fullPage: params.fullPage })
|
||||||
|
};
|
||||||
const isElementScreenshot = params.element && params.ref;
|
const isElementScreenshot = params.element && params.ref;
|
||||||
|
|
||||||
|
const screenshotTarget = isElementScreenshot ? params.element : (params.fullPage ? 'full page' : 'viewport');
|
||||||
const code = [
|
const code = [
|
||||||
`// Screenshot ${isElementScreenshot ? params.element : 'viewport'} and save it as ${fileName}`,
|
`// Screenshot ${screenshotTarget} and save it as ${fileName}`,
|
||||||
];
|
];
|
||||||
|
|
||||||
const locator = params.ref ? snapshot.refLocator({ element: params.element || '', ref: params.ref }) : null;
|
const locator = params.ref ? snapshot.refLocator({ element: params.element || '', ref: params.ref }) : null;
|
||||||
|
@ -201,3 +201,52 @@ test('browser_take_screenshot (imageResponses=omit)', async ({ startClient, serv
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('browser_take_screenshot (fullPage: true)', async ({ startClient, server }, testInfo) => {
|
||||||
|
const { client } = await startClient({
|
||||||
|
config: { outputDir: testInfo.outputPath('output') },
|
||||||
|
});
|
||||||
|
expect(await client.callTool({
|
||||||
|
name: 'browser_navigate',
|
||||||
|
arguments: { url: server.HELLO_WORLD },
|
||||||
|
})).toContainTextContent(`Navigate to http://localhost`);
|
||||||
|
|
||||||
|
expect(await client.callTool({
|
||||||
|
name: 'browser_take_screenshot',
|
||||||
|
arguments: { fullPage: true },
|
||||||
|
})).toEqual({
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
data: expect.any(String),
|
||||||
|
mimeType: 'image/jpeg',
|
||||||
|
type: 'image',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: expect.stringContaining(`Screenshot full page and save it as`),
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('browser_take_screenshot (fullPage with element should error)', async ({ startClient, server }, testInfo) => {
|
||||||
|
const { client } = await startClient({
|
||||||
|
config: { outputDir: testInfo.outputPath('output') },
|
||||||
|
});
|
||||||
|
expect(await client.callTool({
|
||||||
|
name: 'browser_navigate',
|
||||||
|
arguments: { url: server.HELLO_WORLD },
|
||||||
|
})).toContainTextContent(`[ref=e1]`);
|
||||||
|
|
||||||
|
const result = await client.callTool({
|
||||||
|
name: 'browser_take_screenshot',
|
||||||
|
arguments: {
|
||||||
|
fullPage: true,
|
||||||
|
element: 'hello button',
|
||||||
|
ref: 'e1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.isError).toBe(true);
|
||||||
|
expect(result.content?.[0]?.text).toContain('fullPage cannot be used with element screenshots');
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user