browser_scroll_to_element
Scroll the browser viewport to make a specific web element visible using locator strategies like ID, CSS, or XPath for automated web testing and interaction.
Instructions
Scroll to an element
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| by | Yes | Locator strategy to find element | |
| timeout | No | Maximum time to wait for element in milliseconds | |
| value | Yes | Value for the locator strategy |
Implementation Reference
- src/tools/actionTools.ts:257-280 (registration)Registers the 'browser_scroll_to_element' MCP tool with input schema based on locatorSchema and an inline handler function that creates an ActionService instance and calls its scrollToElement method.server.tool( 'browser_scroll_to_element', 'Scroll to an element', { ...locatorSchema }, async ({ by, value, timeout = 15000 }) => { try { const driver = stateManager.getDriver(); const actionService = new ActionService(driver); await actionService.scrollToElement({ by, value, timeout }); return { content: [{ type: 'text', text: `Scrolled to element` }], }; } catch (e) { return { content: [ { type: 'text', text: `Error scrolling to element: ${(e as Error).message}`, }, ], }; } } );
- src/services/actionService.ts:69-73 (handler)Core handler logic for scrolling to an element: creates locator, waits for element, and executes JavaScript to scroll it into view using Selenium WebDriver.async scrollToElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); await this.driver.executeScript('arguments[0].scrollIntoView();', element); }
- src/types/index.ts:29-35 (schema)Zod schema definition for element locator parameters (by, value, timeout), spread into the tool's input schema.export const locatorSchema = { by: z .enum(['id', 'css', 'xpath', 'name', 'tag', 'class', 'link', 'partialLink']) .describe('Locator strategy to find element'), value: z.string().describe('Value for the locator strategy'), timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'), };
- src/types/index.ts:11-13 (helper)TypeScript interface defining the LocatorParams type used in the tool handler and service method.export interface LocatorParams { by: LocatorStrategy; value: string;
- src/services/actionService.ts:3-128 (helper)No, wait, better not. Actually, skipping LocatorFactory for now.import { LocatorFactory } from '../utils/locators.js'; import { LocatorParams } from '../types/index.js'; export class ActionService { constructor(private driver: WebDriver) {} async hoverOverElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); const actions = this.driver.actions({ bridge: true }); await actions.move({ origin: element }).perform(); } async waitForElement(params: LocatorParams): Promise<WebElement> { const locator = LocatorFactory.createLocator(params.by, params.value); return this.driver.wait(until.elementLocated(locator), params.timeout || 15000); } async dragAndDrop(sourceParams: LocatorParams, targetParams: LocatorParams): Promise<void> { const sourceLocator = LocatorFactory.createLocator(sourceParams.by, sourceParams.value); const targetLocator = LocatorFactory.createLocator(targetParams.by, targetParams.value); const sourceElement = await this.driver.wait(until.elementLocated(sourceLocator), sourceParams.timeout || 15000); const targetElement = await this.driver.wait(until.elementLocated(targetLocator), targetParams.timeout || 15000); const actions = this.driver.actions({ bridge: true }); await actions.dragAndDrop(sourceElement, targetElement).perform(); } async doubleClickElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); const actions = this.driver.actions({ bridge: true }); await actions.doubleClick(element).perform(); } async rightClickElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); const actions = this.driver.actions({ bridge: true }); await actions.contextClick(element).perform(); } async selectDropdownByText(params: LocatorParams & { text: string }): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const selectElement = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); const select = new Select(selectElement); await select.selectByVisibleText(params.text); } async selectDropdownByValue(params: LocatorParams & { value: string }): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const selectElement = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); const select = new Select(selectElement); await select.selectByValue(params.value); } async pressKey(key: string): Promise<void> { const actions = this.driver.actions({ bridge: true }); await actions.keyDown(key).keyUp(key).perform(); } async executeScript(script: string, args = []): Promise<any> { return this.driver.executeScript(script, ...args); } async scrollToElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); await this.driver.executeScript('arguments[0].scrollIntoView();', element); } async scrollToTop(): Promise<void> { await this.driver.executeScript('window.scrollTo(0, 0);'); } async scrollToBottom(): Promise<void> { await this.driver.executeScript('window.scrollTo(0, document.body.scrollHeight);'); } async scrollToCoordinates(x: number, y: number): Promise<void> { await this.driver.executeScript(`window.scrollTo(${x}, ${y});`); } async scrollByPixels(x: number, y: number): Promise<void> { await this.driver.executeScript(`window.scrollBy(${x}, ${y});`); } async submitForm(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const form = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); await form.submit(); } async focusElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); await this.driver.executeScript('arguments[0].focus();', element); } async blurElement(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const element = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); await this.driver.executeScript('arguments[0].blur();', element); } async selectCheckbox(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const checkbox = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); if (!(await checkbox.isSelected())) { await checkbox.click(); } } async unselectCheckbox(params: LocatorParams): Promise<void> { const locator = LocatorFactory.createLocator(params.by, params.value); const checkbox = await this.driver.wait(until.elementLocated(locator), params.timeout || 15000); if (await checkbox.isSelected()) { await checkbox.click(); } } async takeScreenshot(): Promise<string> { return this.driver.takeScreenshot(); } }