mirror of
https://github.com/aphrody-labs/base-ui.git
synced 2026-10-14 21:29:38 +00:00
71 lines
2.9 KiB
TypeScript
71 lines
2.9 KiB
TypeScript
import { createEvent, fireEvent } from '@mui/internal-test-utils';
|
|
|
|
export function enterWithMouse(element: HTMLElement, init?: MouseEventInit) {
|
|
fireEvent.pointerEnter(element, { pointerType: 'mouse', ...init });
|
|
fireEvent.mouseEnter(element, init);
|
|
fireEvent.mouseMove(element, init);
|
|
}
|
|
|
|
export function moveMouse(from: HTMLElement, to: HTMLElement) {
|
|
fireEvent.pointerLeave(from, {
|
|
pointerType: 'mouse',
|
|
relatedTarget: to,
|
|
});
|
|
fireEvent.mouseLeave(from, { relatedTarget: to });
|
|
fireEvent.pointerEnter(to, {
|
|
pointerType: 'mouse',
|
|
relatedTarget: from,
|
|
});
|
|
fireEvent.mouseEnter(to, { relatedTarget: from });
|
|
fireEvent.mouseMove(to);
|
|
}
|
|
|
|
// `timeStamp` is required: omitting it would leave the event stamped off the runner's real clock,
|
|
// which is the exact dependency these helpers exist to remove, and would do so silently.
|
|
type PointerInit = PointerEventInit & { timeStamp: number };
|
|
|
|
function firePointerEvent(
|
|
type: 'pointerDown' | 'pointerMove' | 'pointerUp',
|
|
element: Element,
|
|
init: PointerInit,
|
|
) {
|
|
const { timeStamp, ...eventInit } = init;
|
|
|
|
if (!(timeStamp > 0)) {
|
|
// React's synthetic event reads `event.timeStamp || Date.now()`, so a falsy stamp reaches
|
|
// handlers as wall-clock time. `getValidTimeStamp` in `useSwipeDismiss` also rejects anything
|
|
// <= 0, so a zero stamp can never express "time zero" — it only reintroduces the real-clock
|
|
// dependency this helper exists to remove.
|
|
throw new Error(`firePointer: timeStamp must be greater than 0, received ${timeStamp}.`);
|
|
}
|
|
|
|
const event = createEvent[type](element, eventInit);
|
|
|
|
// `timeStamp` is read-only and not part of `PointerEventInit`, so passing it through `fireEvent`
|
|
// drops it silently: jsdom then stamps the event off the (faked) clock, while real browsers stamp
|
|
// it off the real monotonic clock. Velocity-sensitive logic would otherwise read whatever
|
|
// wall-clock gap the runner happened to leave between calls, which differs from run to run.
|
|
Object.defineProperty(event, 'timeStamp', { value: timeStamp });
|
|
|
|
return fireEvent(element, event);
|
|
}
|
|
|
|
/**
|
|
* Fires pointer events that honor the `timeStamp` given to them, so that tests asserting on
|
|
* gesture velocity describe a fixed timeline instead of inheriting the runner's real timing.
|
|
*/
|
|
export const firePointer = {
|
|
down: (element: Element, init: PointerInit) => firePointerEvent('pointerDown', element, init),
|
|
move: (element: Element, init: PointerInit) => firePointerEvent('pointerMove', element, init),
|
|
up: (element: Element, init: PointerInit) => firePointerEvent('pointerUp', element, init),
|
|
};
|
|
|
|
/**
|
|
* Presses an element the way a touch screen does before the click: a touch `pointerdown`
|
|
* followed by the compatibility `mousedown`.
|
|
*/
|
|
export function pressWithTouch(element: HTMLElement) {
|
|
fireEvent.pointerDown(element, { pointerType: 'touch' });
|
|
fireEvent.mouseDown(element);
|
|
}
|