mirror of
https://github.com/aphrody-labs/base-ui.git
synced 2026-10-14 13:19:31 +00:00
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
import { expect, describe, it } from 'vitest';
|
|
import * as React from 'react';
|
|
import { screen } from '@mui/internal-test-utils';
|
|
import { createRenderer, firePointer } from '#test-utils';
|
|
|
|
describe('firePointer', () => {
|
|
const { render } = createRenderer();
|
|
|
|
function Target(props: { onEvent: (event: React.PointerEvent) => void }) {
|
|
const { onEvent } = props;
|
|
return (
|
|
<div
|
|
data-testid="target"
|
|
onPointerDown={onEvent}
|
|
onPointerMove={onEvent}
|
|
onPointerUp={onEvent}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// `timeStamp` is read-only and not a valid `PointerEventInit` member, so `fireEvent` drops it and
|
|
// the event inherits the environment's clock instead — the fake one under jsdom, the real
|
|
// monotonic one in a browser. Every gesture test that asserts on velocity depends on this helper
|
|
// putting the requested value back, and would silently revert to real-clock timing if it stopped.
|
|
// React is what the components read, and its synthetic event substitutes `Date.now()` for a
|
|
// falsy stamp, so assert through a React handler rather than a native listener.
|
|
it('reports the requested timeStamp to React handlers', async () => {
|
|
const seen: number[] = [];
|
|
await render(<Target onEvent={(event) => seen.push(event.timeStamp)} />);
|
|
const target = screen.getByTestId('target');
|
|
|
|
firePointer.down(target, { pointerId: 1, timeStamp: 1000 });
|
|
firePointer.move(target, { pointerId: 1, timeStamp: 1050 });
|
|
firePointer.up(target, { pointerId: 1, timeStamp: 1100 });
|
|
|
|
expect(seen).toEqual([1000, 1050, 1100]);
|
|
});
|
|
|
|
// The rest of the init reaches the event through `createEvent`'s constructor rather than through
|
|
// explicit `defineProperty` calls, so it is only as good as the environment's `PointerEvent`.
|
|
// A stale `window.PointerEvent = window.MouseEvent` shim silently dropped `pointerId` and
|
|
// `pointerType` in both environments once, and nothing failed: every consumer keys on
|
|
// `'touch'`/`'pen'`, so `undefined` falls the same way as `'mouse'`.
|
|
it('delivers the rest of the init alongside the timeStamp', async () => {
|
|
const seen: Array<Record<string, unknown>> = [];
|
|
await render(
|
|
<Target
|
|
onEvent={(event) =>
|
|
seen.push({
|
|
pointerId: event.pointerId,
|
|
pointerType: event.pointerType,
|
|
clientX: event.clientX,
|
|
clientY: event.clientY,
|
|
buttons: event.buttons,
|
|
timeStamp: event.timeStamp,
|
|
})
|
|
}
|
|
/>,
|
|
);
|
|
|
|
firePointer.move(screen.getByTestId('target'), {
|
|
pointerId: 1,
|
|
pointerType: 'mouse',
|
|
clientX: 120,
|
|
clientY: 40,
|
|
buttons: 1,
|
|
timeStamp: 1050,
|
|
});
|
|
|
|
expect(seen).toEqual([
|
|
{
|
|
pointerId: 1,
|
|
pointerType: 'mouse',
|
|
clientX: 120,
|
|
clientY: 40,
|
|
buttons: 1,
|
|
timeStamp: 1050,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('rejects a non-positive timeStamp instead of falling back to the real clock', async () => {
|
|
const seen: number[] = [];
|
|
await render(<Target onEvent={(event) => seen.push(event.timeStamp)} />);
|
|
const target = screen.getByTestId('target');
|
|
|
|
expect(() => firePointer.down(target, { pointerId: 1, timeStamp: 0 })).toThrow(
|
|
/timeStamp must be greater than 0/,
|
|
);
|
|
expect(seen).toEqual([]);
|
|
});
|
|
});
|