Mouse API
The mouse API in Lupa enables precise simulation of raw pointer inputs, coordinate-based clicks, dragging gestures, and custom cursor paths page-wide.
The Mouse Singleton
To interact with the mouse, import the pre-instantiated mouse singleton:
import { mouse } from '@pawel-up/lupa/commands'Mouse Actions
All mouse actions are asynchronous and return a promise.
Cursor Movement
setPosition(point): Sets the mouse cursor to a specific coordinate(x, y)on the page immediately, without triggering intermediate mouse movement events.tsawait mouse.setPosition({ x: 100, y: 150 })move(point, options?): Moves the mouse cursor to a target coordinate(x, y). UnlikesetPosition,movesimulates a physical mouse path and fires intermediate mouse movement events.ts// Move to (300, 200) await mouse.move({ x: 300, y: 200 }) // Move in steps to control speed/granularity await mouse.move({ x: 300, y: 200 }, { steps: 5 })
Clicks and Gestures
click(point, options?): Performs a click at the specified(x, y)coordinate.tsawait mouse.click({ x: 150, y: 200 }) // Right-click or middle-click await mouse.click({ x: 150, y: 200 }, { button: 'right' })dblclick(point, options?): Performs a double-click at the specified coordinate.tsawait mouse.dblclick({ x: 150, y: 200 })
Pressing & Drag-and-Drop
down(options?)/up(options?): Simulates pressing down or releasing a mouse button.ts// Drag-and-drop workflow: await mouse.move({ x: 100, y: 100 }) await mouse.down({ button: 'left' }) await mouse.move({ x: 400, y: 400 }) await mouse.up({ button: 'left' })press(point, options?): Focuses a coordinate, holds the button, and simulates key modifiers during the mouse click event.ts// Click while holding Shift await mouse.press({ x: 200, y: 200 }, { button: 'left', key: 'Shift' })
Resetting Mouse State
reset(): Resets the cursor position to(0, 0)and releases any active mouse buttons (such as held-down left/right/middle buttons).tsawait mouse.reset()
State Preservation and Safety
CAUTION
Persistent State: The mouse retains its state (position and active button presses) across commands. If you call mouse.down({ button: 'left' }), the left button will remain pressed and affect subsequent mouse interactions.
Always call await mouse.reset() in your test teardown or in afterEach hooks if your tests simulate button presses.
import { test } from '@pawel-up/lupa'
import { mouse } from '@pawel-up/lupa/commands'
test.group('Drawing Canvas', (group) => {
group.teardown(async () => {
// Safely reset mouse status for the next test
await mouse.reset()
})
test('should draw on canvas', async ({ assert }) => {
await mouse.setPosition({ x: 50, y: 50 })
await mouse.down()
await mouse.move({ x: 200, y: 50 }, { steps: 10 })
await mouse.up()
// assert drawing result...
})
})Deprecation Notice
WARNING
The legacy sendMouse(payload) and resetMouse() helper functions are deprecated and will be removed:
// DEPRECATED
await sendMouse({ type: 'move', position: [100, 100] })
await resetMouse()Please transition your tests to the class-based mouse API:
// RECOMMENDED
await mouse.move({ x: 100, y: 100 })
await mouse.reset()Best Practices (Dos and Don'ts)
Dos
- Do use
locator.dragTo()or standard locator actions whenever possible. Raw coordinates can be fragile and break if the page layout changes. - Do call
mouse.reset()inside group/test teardown blocks to isolate mouse states between tests.
Don'ts
- Don't assume the mouse pointer starts at a specific element. Use
locator.getBoundingClientRect()orlocator.hover()to align the mouse position with a target element before triggering clicks.