feat: add slowly option for typing one character at a time (#121)

This commit is contained in:
Yury Semikhatsky 2025-04-02 14:36:30 -07:00 committed by GitHub
parent 89627fd23a
commit 2291011dc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 3 deletions

View File

@ -114,7 +114,7 @@ export const drag: Tool = {
const typeSchema = z.object({
text: z.string().describe('Text to type into the element'),
submit: z.boolean().describe('Whether to submit entered text (press Enter after)'),
submit: z.boolean().optional().describe('Whether to submit entered text (press Enter after)'),
});
export const type: Tool = {

View File

@ -101,7 +101,8 @@ export const hover: Tool = {
const typeSchema = elementSchema.extend({
text: z.string().describe('Text to type into the element'),
submit: z.boolean().describe('Whether to submit entered text (press Enter after)'),
submit: z.boolean().optional().describe('Whether to submit entered text (press Enter after)'),
slowly: z.boolean().optional().describe('Wether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.'),
});
export const type: Tool = {
@ -115,7 +116,10 @@ export const type: Tool = {
const validatedParams = typeSchema.parse(params);
return await context.runAndWaitWithSnapshot(async () => {
const locator = context.lastSnapshot().refLocator(validatedParams.ref);
await locator.fill(validatedParams.text);
if (validatedParams.slowly)
await locator.pressSequentially(validatedParams.text);
else
await locator.fill(validatedParams.text);
if (validatedParams.submit)
await locator.press('Enter');
}, {

View File

@ -368,3 +368,61 @@ test('executable path', async ({ startClient }) => {
});
expect(response).toContainTextContent(`executable doesn't exist`);
});
test('fill in text', async ({ client }) => {
await client.callTool({
name: 'browser_navigate',
arguments: {
url: `data:text/html,<input type='keypress' onkeypress="console.log('Key pressed:', event.key, ', Text:', event.target.value)"></input>`,
},
});
await client.callTool({
name: 'browser_type',
arguments: {
element: 'textbox',
ref: 's1e3',
text: 'Hi!',
submit: true,
},
});
const resource = await client.readResource({
uri: 'browser://console',
});
expect(resource.contents).toEqual([{
uri: 'browser://console',
mimeType: 'text/plain',
text: '[LOG] Key pressed: Enter , Text: Hi!',
}]);
});
test('type slowly', async ({ client }) => {
await client.callTool({
name: 'browser_navigate',
arguments: {
url: `data:text/html,<input type='text' onkeydown="console.log('Key pressed:', event.key, 'Text:', event.target.value)"></input>`,
},
});
await client.callTool({
name: 'browser_type',
arguments: {
element: 'textbox',
ref: 's1e3',
text: 'Hi!',
submit: true,
slowly: true,
},
});
const resource = await client.readResource({
uri: 'browser://console',
});
expect(resource.contents).toEqual([{
uri: 'browser://console',
mimeType: 'text/plain',
text: [
'[LOG] Key pressed: H Text: ',
'[LOG] Key pressed: i Text: H',
'[LOG] Key pressed: ! Text: Hi',
'[LOG] Key pressed: Enter Text: Hi!',
].join('\n'),
}]);
});