b229a0dac7
13 new test files for untested components (color-palette, player-management, stat-block, settings-modal, export/import dialogs, bulk-import-prompt, source-fetch-prompt, player-character-section) and hooks (use-long-press, use-swipe-to-dismiss, use-bulk-import, use-initiative-rolls). Expand combatant-row tests with inline editing, HP popover, and condition picker. Component coverage: 59% → 80% lines, 55% → 71% branches Hook coverage: 72% → 83% lines, 55% → 66% branches Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
117 lines
3.8 KiB
TypeScript
117 lines
3.8 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { act, renderHook } from "@testing-library/react";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { useSwipeToDismiss } from "../use-swipe-to-dismiss.js";
|
|
|
|
const PANEL_WIDTH = 300;
|
|
|
|
function makeTouchEvent(clientX: number, clientY = 0): React.TouchEvent {
|
|
return {
|
|
touches: [{ clientX, clientY }],
|
|
currentTarget: {
|
|
getBoundingClientRect: () => ({ width: PANEL_WIDTH }),
|
|
},
|
|
} as unknown as React.TouchEvent;
|
|
}
|
|
|
|
describe("useSwipeToDismiss", () => {
|
|
beforeEach(() => {
|
|
vi.spyOn(Date, "now").mockReturnValue(0);
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("starts with offsetX 0 and isSwiping false", () => {
|
|
const { result } = renderHook(() => useSwipeToDismiss(vi.fn()));
|
|
expect(result.current.offsetX).toBe(0);
|
|
expect(result.current.isSwiping).toBe(false);
|
|
});
|
|
|
|
it("horizontal drag updates offsetX and sets isSwiping", () => {
|
|
const { result } = renderHook(() => useSwipeToDismiss(vi.fn()));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0)));
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(50)));
|
|
|
|
expect(result.current.offsetX).toBe(50);
|
|
expect(result.current.isSwiping).toBe(true);
|
|
});
|
|
|
|
it("vertical drag is ignored after direction lock", () => {
|
|
const { result } = renderHook(() => useSwipeToDismiss(vi.fn()));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0, 0)));
|
|
// Move vertically > 10px to lock vertical
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(0, 20)));
|
|
|
|
expect(result.current.offsetX).toBe(0);
|
|
});
|
|
|
|
it("small movement does not lock direction", () => {
|
|
const { result } = renderHook(() => useSwipeToDismiss(vi.fn()));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0)));
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(5)));
|
|
|
|
// No direction locked yet, no update
|
|
expect(result.current.offsetX).toBe(0);
|
|
expect(result.current.isSwiping).toBe(false);
|
|
});
|
|
|
|
it("leftward drag is clamped to 0", () => {
|
|
const { result } = renderHook(() => useSwipeToDismiss(vi.fn()));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(100)));
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(50)));
|
|
|
|
expect(result.current.offsetX).toBe(0);
|
|
});
|
|
|
|
it("calls onDismiss when ratio exceeds threshold", () => {
|
|
const onDismiss = vi.fn();
|
|
const { result } = renderHook(() => useSwipeToDismiss(onDismiss));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0)));
|
|
// Move > 35% of panel width (300 * 0.35 = 105)
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(120)));
|
|
|
|
vi.spyOn(Date, "now").mockReturnValue(5000); // slow swipe
|
|
act(() => result.current.handlers.onTouchEnd());
|
|
|
|
expect(onDismiss).toHaveBeenCalled();
|
|
});
|
|
|
|
it("calls onDismiss with fast velocity", () => {
|
|
const onDismiss = vi.fn();
|
|
const { result } = renderHook(() => useSwipeToDismiss(onDismiss));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0)));
|
|
// Small distance but fast
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(30)));
|
|
|
|
// Very fast: 30px in 0.1s = 300px/s, velocity = 300/300 = 1.0 > 0.5
|
|
vi.spyOn(Date, "now").mockReturnValue(100);
|
|
act(() => result.current.handlers.onTouchEnd());
|
|
|
|
expect(onDismiss).toHaveBeenCalled();
|
|
});
|
|
|
|
it("does not dismiss when below thresholds", () => {
|
|
const onDismiss = vi.fn();
|
|
const { result } = renderHook(() => useSwipeToDismiss(onDismiss));
|
|
|
|
act(() => result.current.handlers.onTouchStart(makeTouchEvent(0)));
|
|
// Small distance, slow speed
|
|
act(() => result.current.handlers.onTouchMove(makeTouchEvent(20)));
|
|
|
|
vi.spyOn(Date, "now").mockReturnValue(5000);
|
|
act(() => result.current.handlers.onTouchEnd());
|
|
|
|
expect(onDismiss).not.toHaveBeenCalled();
|
|
expect(result.current.offsetX).toBe(0);
|
|
expect(result.current.isSwiping).toBe(false);
|
|
});
|
|
});
|