feat(tool): add locator.selectOption() action (#25)

Implemented `locator.selectOption`
This commit is contained in:
ryo kishida 2025-03-26 13:53:56 +09:00 committed by GitHub
parent 8f3214a06a
commit 9f93af3a81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 132 additions and 0 deletions

View File

@ -180,6 +180,13 @@ The Playwright MCP provides a set of tools for browser automation. Here are all
- `text` (string): Text to type into the element
- `submit` (boolean): Whether to submit entered text (press Enter after)
- **browser_select_option**
- Description: Select option in a dropdown
- Parameters:
- `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
- `values` (array): Array of values to select in the dropdown.
- **browser_press_key**
- Description: Press a key on the keyboard
- Parameters:

View File

@ -40,6 +40,7 @@ const snapshotTools: Tool[] = [
snapshot.click,
snapshot.hover,
snapshot.type,
snapshot.selectOption,
...commonTools,
];

View File

@ -112,6 +112,26 @@ export const type: Tool = {
},
};
const selectOptionSchema = elementSchema.extend({
values: z.array(z.string()).describe('Array of values to select in the dropdown. This can be a single value or multiple values.'),
});
export const selectOption: Tool = {
schema: {
name: 'browser_select_option',
description: 'Select an option in a dropdown',
inputSchema: zodToJsonSchema(selectOptionSchema),
},
handle: async (context, params) => {
const validatedParams = selectOptionSchema.parse(params);
return await runAndWait(context, `Selected option in "${validatedParams.element}"`, async page => {
const locator = refLocator(page, validatedParams.ref);
await locator.selectOption(validatedParams.values);
}, true);
},
};
function refLocator(page: playwright.Page, ref: string): playwright.Locator {
return page.locator(`aria-ref=${ref}`);
}

View File

@ -48,6 +48,9 @@ test('test tool list', async ({ server }) => {
expect.objectContaining({
name: 'browser_type',
}),
expect.objectContaining({
name: 'browser_select_option',
}),
expect.objectContaining({
name: 'browser_press_key',
}),
@ -227,3 +230,104 @@ test('test reopen browser', async ({ server }) => {
},
}));
});
test.describe('test browser_select_option', () => {
test('single option', async ({ server }) => {
await server.send({
jsonrpc: '2.0',
id: 2,
method: 'tools/call',
params: {
name: 'browser_navigate',
arguments: {
url: 'data:text/html,<html><title>Title</title><select><option value="foo">Foo</option><option value="bar">Bar</option></select></html>',
},
},
});
const response = await server.send({
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'browser_select_option',
arguments: {
element: 'Select',
ref: 's1e4',
values: ['bar'],
},
},
});
expect(response).toEqual(expect.objectContaining({
id: 3,
result: {
content: [{
type: 'text',
text: `Selected option in \"Select\"
- Page URL: data:text/html,<html><title>Title</title><select><option value="foo">Foo</option><option value="bar">Bar</option></select></html>
- Page Title: Title
- Page Snapshot
\`\`\`yaml
- document [ref=s2e2]:
- combobox [ref=s2e4]:
- option \"Foo\" [ref=s2e5]
- option \"Bar\" [selected] [ref=s2e6]
\`\`\`
`,
}],
},
}));
});
test('multiple option', async ({ server }) => {
await server.send({
jsonrpc: '2.0',
id: 2,
method: 'tools/call',
params: {
name: 'browser_navigate',
arguments: {
url: 'data:text/html,<html><title>Title</title><select multiple><option value="foo">Foo</option><option value="bar">Bar</option><option value="baz">Baz</option></select></html>',
},
},
});
const response = await server.send({
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'browser_select_option',
arguments: {
element: 'Select',
ref: 's1e4',
values: ['bar', 'baz'],
},
},
});
expect(response).toEqual(expect.objectContaining({
id: 3,
result: {
content: [{
type: 'text',
text: `Selected option in \"Select\"
- Page URL: data:text/html,<html><title>Title</title><select multiple><option value="foo">Foo</option><option value="bar">Bar</option><option value="baz">Baz</option></select></html>
- Page Title: Title
- Page Snapshot
\`\`\`yaml
- document [ref=s2e2]:
- listbox [ref=s2e4]:
- option \"Foo\" [ref=s2e5]
- option \"Bar\" [selected] [ref=s2e6]
- option \"Baz\" [selected] [ref=s2e7]
\`\`\`
`,
}],
},
}));
});
});