Adds a `useOverlayDismiss` hook that suppresses touch-synthesized mouse events on modal/dropdown overlays to prevent unintended close behavior on touch devices, with tests covering TaskCard dismissal and overlay interaction edge cases. Documentation updates in AGENTS.md and docs/architecture.md capt Fusion-Task-Id: FN-5482 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> Fusion-Task-Id: FN-5482
51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { describe, it, expect, vi } from "vitest";
|
|
import { render, fireEvent } from "@testing-library/react";
|
|
import { useOverlayDismiss } from "../useOverlayDismiss";
|
|
|
|
function OverlayHarness({ onClose }: { onClose: () => void }) {
|
|
const props = useOverlayDismiss(onClose);
|
|
return (
|
|
<div data-testid="overlay" {...props}>
|
|
<div data-testid="modal-content">content</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
describe("useOverlayDismiss", () => {
|
|
it("closes on real overlay mouse down/up", () => {
|
|
const onClose = vi.fn();
|
|
const { getByTestId } = render(<OverlayHarness onClose={onClose} />);
|
|
const overlay = getByTestId("overlay");
|
|
|
|
fireEvent.mouseDown(overlay);
|
|
fireEvent.mouseUp(overlay);
|
|
|
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("ignores compatibility mouse sequence immediately after touch", () => {
|
|
const onClose = vi.fn();
|
|
const { getByTestId } = render(<OverlayHarness onClose={onClose} />);
|
|
const overlay = getByTestId("overlay");
|
|
|
|
fireEvent.touchStart(overlay);
|
|
fireEvent.touchEnd(overlay);
|
|
fireEvent.mouseDown(overlay);
|
|
fireEvent.mouseUp(overlay);
|
|
|
|
expect(onClose).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it("does not close when mouse starts inside modal and ends on overlay", () => {
|
|
const onClose = vi.fn();
|
|
const { getByTestId } = render(<OverlayHarness onClose={onClose} />);
|
|
const overlay = getByTestId("overlay");
|
|
const modal = getByTestId("modal-content");
|
|
|
|
fireEvent.mouseDown(modal);
|
|
fireEvent.mouseUp(overlay);
|
|
|
|
expect(onClose).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|