feat(dblclick): add double click (#654)

Fixes https://github.com/microsoft/playwright-mcp/issues/652
This commit is contained in:
Pavel Feldman 2025-07-11 16:45:39 -07:00 committed by GitHub
parent 1600ba6645
commit 59f1d67a4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 6 deletions

View File

@ -478,6 +478,7 @@ X Y coordinate space, based on the provided screenshot.
- Parameters: - Parameters:
- `element` (string): Human-readable element description used to obtain permission to interact with the element - `element` (string): Human-readable element description used to obtain permission to interact with the element
- `ref` (string): Exact target element reference from the page snapshot - `ref` (string): Exact target element reference from the page snapshot
- `doubleClick` (boolean, optional): Whether to perform a double click instead of a single click
- Read-only: **false** - Read-only: **false**
<!-- NOTE: This has been generated via update-readme.js --> <!-- NOTE: This has been generated via update-readme.js -->

View File

@ -46,13 +46,17 @@ const elementSchema = z.object({
ref: z.string().describe('Exact target element reference from the page snapshot'), ref: z.string().describe('Exact target element reference from the page snapshot'),
}); });
const clickSchema = elementSchema.extend({
doubleClick: z.boolean().optional().describe('Whether to perform a double click instead of a single click'),
});
const click = defineTool({ const click = defineTool({
capability: 'core', capability: 'core',
schema: { schema: {
name: 'browser_click', name: 'browser_click',
title: 'Click', title: 'Click',
description: 'Perform click on a web page', description: 'Perform click on a web page',
inputSchema: elementSchema, inputSchema: clickSchema,
type: 'destructive', type: 'destructive',
}, },
@ -60,14 +64,18 @@ const click = defineTool({
const tab = context.currentTabOrDie(); const tab = context.currentTabOrDie();
const locator = tab.snapshotOrDie().refLocator(params); const locator = tab.snapshotOrDie().refLocator(params);
const code = [ const code: string[] = [];
`// Click ${params.element}`, if (params.doubleClick) {
`await page.${await generateLocator(locator)}.click();` code.push(`// Double click ${params.element}`);
]; code.push(`await page.${await generateLocator(locator)}.dblclick();`);
} else {
code.push(`// Click ${params.element}`);
code.push(`await page.${await generateLocator(locator)}.click();`);
}
return { return {
code, code,
action: () => locator.click(), action: () => params.doubleClick ? locator.dblclick() : locator.click(),
captureSnapshot: true, captureSnapshot: true,
waitForNetwork: true, waitForNetwork: true,
}; };

View File

@ -70,6 +70,45 @@ await page.getByRole('button', { name: 'Submit' }).click();
`); `);
}); });
test('browser_click (double)', async ({ client, server }) => {
server.setContent('/', `
<title>Title</title>
<script>
function handle() {
document.querySelector('h1').textContent = 'Double clicked';
}
</script>
<h1 ondblclick="handle()">Click me</h1>
`, 'text/html');
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
});
expect(await client.callTool({
name: 'browser_click',
arguments: {
element: 'Click me',
ref: 'e2',
doubleClick: true,
},
})).toHaveTextContent(`
- Ran Playwright code:
\`\`\`js
// Double click Click me
await page.getByRole('heading', { name: 'Click me' }).dblclick();
\`\`\`
- Page URL: ${server.PREFIX}
- Page Title: Title
- Page Snapshot
\`\`\`yaml
- heading "Double clicked" [level=1] [ref=e3]
\`\`\`
`);
});
test('browser_select_option', async ({ client, server }) => { test('browser_select_option', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `
<title>Title</title> <title>Title</title>