diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts
index 03e75f9..46001ec 100644
--- a/src/tools/screenshot.ts
+++ b/src/tools/screenshot.ts
@@ -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 = {
diff --git a/src/tools/snapshot.ts b/src/tools/snapshot.ts
index b0b9e12..4646dce 100644
--- a/src/tools/snapshot.ts
+++ b/src/tools/snapshot.ts
@@ -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');
}, {
diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts
index 663a583..b138ed1 100644
--- a/tests/basic.spec.ts
+++ b/tests/basic.spec.ts
@@ -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,`,
+ },
+ });
+ 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,`,
+ },
+ });
+ 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'),
+ }]);
+});