( uid: string, value: string, context: McpContext, page: ContextPage, )
| 254 | } |
| 255 | |
| 256 | async function fillFormElement( |
| 257 | uid: string, |
| 258 | value: string, |
| 259 | context: McpContext, |
| 260 | page: ContextPage, |
| 261 | ) { |
| 262 | const handle = await page.getElementByUid(uid); |
| 263 | try { |
| 264 | const aXNode = context.getAXNodeByUid(uid); |
| 265 | // We assume that combobox needs to be handled as select if it has |
| 266 | // role='combobox' and option children. |
| 267 | if (aXNode && aXNode.role === 'combobox' && hasOptionChildren(aXNode)) { |
| 268 | await selectOption(handle, aXNode, value); |
| 269 | } else { |
| 270 | const isToggle = await handle.evaluate(el => { |
| 271 | if (el instanceof HTMLInputElement) { |
| 272 | return el.type === 'checkbox' || el.type === 'radio'; |
| 273 | } |
| 274 | const role = el.getAttribute('role'); |
| 275 | return role === 'checkbox' || role === 'radio' || role === 'switch'; |
| 276 | }); |
| 277 | |
| 278 | if (isToggle) { |
| 279 | if (['true', 'false'].includes(value)) { |
| 280 | await handle.asLocator().fill(value === 'true'); |
| 281 | } else { |
| 282 | throw new Error( |
| 283 | `Checkboxes, radio boxes and toggles require "true" or "false" value, but ${value} was used`, |
| 284 | ); |
| 285 | } |
| 286 | } else { |
| 287 | // Increase timeout for longer input values. |
| 288 | const timeoutPerChar = 10; // ms |
| 289 | const fillTimeout = |
| 290 | page.pptrPage.getDefaultTimeout() + value.length * timeoutPerChar; |
| 291 | await handle.asLocator().setTimeout(fillTimeout).fill(value); |
| 292 | } |
| 293 | } |
| 294 | } catch (error) { |
| 295 | handleActionError(error, uid); |
| 296 | } finally { |
| 297 | void handle.dispose(); |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | export const fill = definePageTool({ |
| 302 | name: 'fill', |
no test coverage detected
searching dependent graphs…