UNPKG

@web/test-runner-commands

Version:
189 lines (166 loc) 6.3 kB
import { TestRunnerPlugin } from '@web/test-runner-core'; import type { ChromeLauncher } from '@web/test-runner-chrome'; import type { PlaywrightLauncher } from '@web/test-runner-playwright'; import type { WebdriverLauncher } from '@web/test-runner-webdriver'; type MousePosition = [number, number]; type MouseButton = 'left' | 'middle' | 'right'; export type SendMousePayload = MovePayload | ClickPayload | DownPayload | UpPayload; export type MovePayload = { type: 'move'; position: MousePosition; }; export type ClickPayload = { type: 'click'; position: MousePosition; button?: MouseButton; }; export type DownPayload = { type: 'down'; button?: MouseButton; }; export type UpPayload = { type: 'up'; button?: MouseButton; }; function isObject(payload: unknown): payload is Record<string, unknown> { return payload != null && typeof payload === 'object'; } function isSendMousePayload(payload: unknown): payload is SendMousePayload { const validTypes = ['move', 'click', 'down', 'up']; const validButtons = ['left', 'middle', 'right']; if (!isObject(payload)) { throw new Error('You must provide a `SendMousePayload` object'); } if (typeof payload.type !== 'string' || !validTypes.includes(payload.type)) { throw new Error( `You must provide a type option with one of the following values: ${validTypes.join(', ')}.`, ); } if (['click', 'move'].includes(payload.type)) { if ( !Array.isArray(payload.position) || typeof payload.position[0] !== 'number' || typeof payload.position[1] !== 'number' || !Number.isInteger(payload.position[0]) || !Number.isInteger(payload.position[1]) ) { throw new Error( 'You must provide a position option as a [x, y] tuple where x and y are integers.', ); } } if (['click', 'up', 'down'].includes(payload.type)) { if (typeof payload.button === 'string' && !validButtons.includes(payload.button)) { throw new Error( `The button option must be one of the following values when provided: ${validButtons.join( ', ', )}.`, ); } } return true; } export function sendMousePlugin(): TestRunnerPlugin<SendMousePayload> { return { name: 'send-mouse-command', async executeCommand({ command, payload, session }): Promise<any> { if (command === 'send-mouse') { if (!payload || !isSendMousePayload(payload)) { throw new Error('You must provide a `SendMousePayload` object'); } // handle specific behavior for playwright if (session.browser.type === 'playwright') { const page = (session.browser as PlaywrightLauncher).getPage(session.id); switch (payload.type) { case 'move': await page.mouse.move(payload.position[0], payload.position[1]); return true; case 'click': await page.mouse.click(payload.position[0], payload.position[1], { button: payload.button, }); return true; case 'down': await page.mouse.down({ button: payload.button }); return true; case 'up': await page.mouse.up({ button: payload.button }); return true; } } // handle specific behavior for puppeteer if (session.browser.type === 'puppeteer') { const page = (session.browser as ChromeLauncher).getPage(session.id); switch (payload.type) { case 'move': await page.mouse.move(payload.position[0], payload.position[1]); return true; case 'click': await page.mouse.click(payload.position[0], payload.position[1], { button: payload.button, }); return true; case 'down': await page.mouse.down({ button: payload.button }); return true; case 'up': await page.mouse.up({ button: payload.button }); return true; } } // handle specific behavior for webdriver if (session.browser.type === 'webdriver') { const page = session.browser as WebdriverLauncher; switch (payload.type) { case 'move': await page.sendMouseMove(session.id, payload.position[0], payload.position[1]); return true; case 'click': await page.sendMouseClick( session.id, payload.position[0], payload.position[1], payload.button, ); return true; case 'down': await page.sendMouseDown(session.id, payload.button); return true; case 'up': await page.sendMouseUp(session.id, payload.button); return true; } } // you might not be able to support all browser launchers throw new Error(`Sending mouse is not supported for browser type ${session.browser.type}.`); } if (command === 'reset-mouse') { // handle specific behavior for playwright if (session.browser.type === 'playwright') { const page = (session.browser as PlaywrightLauncher).getPage(session.id); await page.mouse.up({ button: 'left' }); await page.mouse.up({ button: 'middle' }); await page.mouse.up({ button: 'right' }); await page.mouse.move(0, 0); return true; } // handle specific behavior for puppeteer if (session.browser.type === 'puppeteer') { const page = (session.browser as ChromeLauncher).getPage(session.id); await page.mouse.reset(); return true; } // handle specific behavior for webdriver if (session.browser.type === 'webdriver') { const page = session.browser as WebdriverLauncher; await page.resetMouse(session.id); return true; } // you might not be able to support all browser launchers throw new Error( `Resetting mouse is not supported for browser type ${session.browser.type}.`, ); } }, }; }