import { Optional } from '../dataTypes'; import { WaitForOption } from '../drivers/WaitForOption'; import { BoundingRect, Point } from '../geometry'; import { PartLocator } from '../locators'; import { WaitUntilOption } from '../utils/timingUtil'; import type { CssProperty } from './CssProperty'; import { EnterTextOption } from './EnterTextOption'; import { BlurOption, FocusOption } from './FocusOption'; import { ClickOption, HoverOption, MouseDownOption, MouseEnterOption, MouseLeaveOption, MouseMoveOption, MouseOutOption, MouseUpOption, } from './MouseOption'; import type { PressKeyOption } from './PressKeyOption'; /** * Pointer/mouse-driven, potentially DOM-mutating interactions: the pointer * gestures a real user performs with a mouse, plus the two dispatch-based * escape hatches ({@link PointerActions.contextMenu | contextMenu}, * {@link PointerActions.activate | activate}) for outcomes ordinary pointer * geometry cannot reach, and the drag primitives. * * Split out of {@link Interactor} as a capability facet (ADR-007) so a driver * can depend on just the pointer surface, and a partial-capability environment * can declare pointer support independently of the rest. `Interactor` * recomposes this facet unchanged. */ export interface PointerActions { /** * Click on the desired element * @param locator * @param option */ click(locator: PartLocator, option?: Partial): Promise; /** * Mouse move on the desired element * @param locator * @param option */ mouseMove(locator: PartLocator, option?: Partial): Promise; mouseDown(locator: PartLocator, option?: Partial): Promise; mouseUp(locator: PartLocator, option?: Partial): Promise; mouseOver(locator: PartLocator, option?: Partial): Promise; mouseOut(locator: PartLocator, option?: Partial): Promise; mouseEnter(locator: PartLocator, option?: Partial): Promise; mouseLeave(locator: PartLocator, option?: Partial): Promise; /** * Dispatch a right-click / `contextmenu` event on the desired element. * * A `contextmenu` event is the only way to open a context menu: such menus have * no `aria-expanded` toggle or controlled-open prop to flip, so the menu is * reachable only by the event a right-click produces. This is analogous to * {@link KeyboardActions.pressKey | pressKey} for keyboard-only behaviors — a * dedicated primitive for an outcome no ordinary {@link PointerActions.click | click} * can express. The element is focused first if focusable, mirroring `pressKey`, * so the event originates from the active element as in a real right-click. * * @param locator */ contextMenu(locator: PartLocator): Promise; /** * Activate the desired element without relying on pointer geometry — a * coordinate-free, dispatch-based click. * * This reaches elements an ordinary {@link PointerActions.click | click} cannot: * a visually-hidden or zero-size input covered by another element (e.g. MUI * Rating's hidden ``, where a positional click hit-tests to * the covering star label instead). Prefer {@link PointerActions.click | click} * for ordinary, visible targets. * * @param locator */ activate(locator: PartLocator): Promise; /** * Drag the source element and drop it onto the target element. * * Drives BOTH DnD models on the same gesture, so either kind of component * under test is driven: the pointer sequence * (`mousedown`/`mousemove`/`mouseup`, for pointer-based libraries such as * dnd-kit or react-beautiful-dnd) and native HTML5 drag-and-drop * (`dragstart`/`dragenter`/`dragover`/`drop`/`dragend`, sharing one * `dataTransfer`, for components built on `draggable` + * `ondragstart`/`ondragover`/`ondrop`) — see #922. The mechanism differs by * environment: Playwright drives a real, low-level pointer gesture that the * browser's own native drag recognition turns into genuine `drag*` events * with a real `DataTransfer` (no synthesis needed); jsdom has no browser * layer to recognize a gesture, so `DOMInteractor` explicitly synthesizes * both event families. * * jsdom has no layout engine, so the drag has no positional outcome there: * every event is synthesized at zeroed coordinates and only the event wiring * (and any handler the sequence triggers, including a `dataTransfer` * payload set in `dragstart` and read in `drop`) is exercised. Behavioral * assertions about the final position are therefore E2E-only; the jsdom path * only guarantees the events fire once both elements are found. * * @param source Locator of the element to drag * @param target Locator of the element to drop onto */ dragTo(source: PartLocator, target: PartLocator): Promise; /** * Drag the desired element by the given pixel delta from its center. * * Drives both DnD models, as {@link PointerActions.dragTo | dragTo} does — * see #922. There is no separate drop target for a single-element delta * drag, so the native HTML5 drag-and-drop sequence * (`dragstart`/`dragenter`/`dragover`/`drop`/`dragend`) runs on the element * itself, as its own drop target. * * jsdom has no layout engine, so the drag has no positional outcome there: the * pointer sequence is synthesized from the caller-supplied delta and only the * event wiring is exercised. Behavioral assertions about the resulting position * are therefore E2E-only; the jsdom path only guarantees the events fire once * the element is found. * * @param locator Locator of the element to drag * @param delta Pixel offset to drag by, where `x` is horizontal and `y` is vertical */ drag(locator: PartLocator, delta: Point): Promise; /** * Perform a mouse hover on the desired element * @param locator */ hover(locator: PartLocator, option?: HoverOption): Promise; } /** * Keyboard-driven interactions: dispatch of real key events, distinct from the * value-filling {@link FormActions} path. A capability facet of {@link Interactor} * (ADR-007). */ export interface KeyboardActions { /** * Dispatch a keyboard key press on the desired element. * * Unlike {@link FormActions.enterText | enterText}, which fills a value, this * dispatches an actual key event so components that key off `KeyboardEvent.key` * are exercised — e.g. Dialog dismissal on `Escape` or Chip deletion on * `Backspace`/`Delete`. The element is focused first so the event originates * from the active element, matching a real key press. On a focused * `contenteditable` host the press additionally carries `beforeinput`/`input` * fidelity, so editing keys such as `Backspace` reach components that commit * changes from input events (e.g. the MUI X picker section field, see #903); on * every other target — including text ``/`