Skip to content

Commit e784581

Browse files
committed
use option text as value
1 parent 772dc62 commit e784581

File tree

4 files changed

+55
-30
lines changed

4 files changed

+55
-30
lines changed

src/McpContext.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,15 @@ export class McpContext implements Context {
323323
children: [],
324324
};
325325

326-
// The AXNode for an option doesn't contain its value, so add it from the element.
326+
// The AXNode for an option doesn't contain its `value`.
327+
// Therefore, set text content of the option as value.
327328
if (node.role === 'option') {
328329
const handle = await node.elementHandle();
329330
if (handle) {
330-
const valueHandle = await handle.getProperty('value');
331-
const optionValue = await valueHandle.jsonValue();
332-
if (optionValue) {
333-
nodeWithId.value = optionValue.toString();
331+
const textContentHandle = await handle.getProperty('textContent');
332+
const optionText = await textContentHandle.jsonValue();
333+
if (optionText) {
334+
nodeWithId.value = optionText.toString();
334335
}
335336
}
336337
}

src/tools/input.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,26 @@ export const fill = defineTool({
9797
const handle = await context.getElementByUid(request.params.uid);
9898
try {
9999
await context.waitForEventsAfterAction(async () => {
100-
await handle.asLocator().fill(request.params.value);
100+
// The AXNode for an option doesn't contain its `value`. We set text content of the option as value.
101+
// To fill the form, get the correct option by its text value.
102+
const isSelectElement = await handle.evaluate(
103+
el => el.tagName === 'SELECT',
104+
);
105+
if (isSelectElement) {
106+
const value = await handle.evaluate((el, text) => {
107+
const option = Array.from((el as HTMLSelectElement).options).find(
108+
option => option.text === text,
109+
);
110+
if (option) {
111+
return option.value;
112+
}
113+
return request.params.value;
114+
}, request.params.value);
115+
116+
await handle.asLocator().fill(value);
117+
} else {
118+
await handle.asLocator().fill(request.params.value);
119+
}
101120
});
102121
response.appendResponseLine(`Successfully filled out the element`);
103122
response.setIncludeSnapshot(true);

tests/McpContext.test.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,6 @@ describe('McpContext', () => {
3333
});
3434
});
3535

36-
it('should include the value of an option in the text snapshot', async () => {
37-
await withBrowser(async (_response, context) => {
38-
const page = context.getSelectedPage();
39-
await page.setContent(`
40-
<!DOCTYPE html>
41-
<select>
42-
<option value="1">One</option>
43-
<option value="2">Two</option>
44-
</select>
45-
`);
46-
await context.createTextSnapshot();
47-
const snapshot = context.getTextSnapshot();
48-
assert.ok(snapshot);
49-
50-
const option1 = snapshot.root.children[0]?.children[0];
51-
assert.strictEqual(option1?.role, 'option');
52-
assert.strictEqual(option1?.value, '1');
53-
54-
const option2 = snapshot.root.children[0]?.children[1];
55-
assert.strictEqual(option2?.role, 'option');
56-
assert.strictEqual(option2?.value, '2');
57-
});
58-
});
59-
6036
it('can store and retrieve performance traces', async () => {
6137
await withBrowser(async (_response, context) => {
6238
const fakeTrace1 = {} as unknown as TraceResult;

tests/tools/input.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,35 @@ describe('input', () => {
202202
assert.ok(await page.$('text/test'));
203203
});
204204
});
205+
206+
it('fills out a select by text', async () => {
207+
await withBrowser(async (response, context) => {
208+
const page = context.getSelectedPage();
209+
await page.setContent(
210+
`<!DOCTYPE html><select><option value="v1">one</option><option value="v2">two</option></select>`,
211+
);
212+
await context.createTextSnapshot();
213+
await fill.handler(
214+
{
215+
params: {
216+
uid: '1_1',
217+
value: 'two',
218+
},
219+
},
220+
response,
221+
context,
222+
);
223+
assert.strictEqual(
224+
response.responseLines[0],
225+
'Successfully filled out the element',
226+
);
227+
assert.ok(response.includeSnapshot);
228+
const selectedValue = await page.evaluate(
229+
() => document.querySelector('select')!.value,
230+
);
231+
assert.strictEqual(selectedValue, 'v2');
232+
});
233+
});
205234
});
206235

207236
describe('drags', () => {

0 commit comments

Comments
 (0)