test(web): add 57 UI component and hook tests with jsdom cleanup
Fix jsdom environment: add esbuild automatic JSX transform and afterEach cleanup to prevent DOM leakage between tests. Components: Badge (8), Button (13), FilterBar (5), EmptyState (8), ConfirmDialog (8), useSelection hook (15). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { renderHook, act } from "@testing-library/react";
|
||||
import { useSelection } from "./useSelection.js";
|
||||
|
||||
describe("useSelection", () => {
|
||||
it("starts with empty selection", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
expect(result.current.count).toBe(0);
|
||||
expect(result.current.selectedArray).toEqual([]);
|
||||
});
|
||||
|
||||
it("toggles an item on", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggle("a"));
|
||||
expect(result.current.selectedIds.has("a")).toBe(true);
|
||||
expect(result.current.count).toBe(1);
|
||||
});
|
||||
|
||||
it("toggles an item off", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggle("a"));
|
||||
act(() => result.current.toggle("a"));
|
||||
expect(result.current.selectedIds.has("a")).toBe(false);
|
||||
expect(result.current.count).toBe(0);
|
||||
});
|
||||
|
||||
it("toggleAll selects all items when none are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggleAll(["a", "b", "c"]));
|
||||
expect(result.current.count).toBe(3);
|
||||
expect(result.current.selectedIds.has("a")).toBe(true);
|
||||
expect(result.current.selectedIds.has("b")).toBe(true);
|
||||
expect(result.current.selectedIds.has("c")).toBe(true);
|
||||
});
|
||||
|
||||
it("toggleAll deselects all items when all are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggleAll(["a", "b"]));
|
||||
act(() => result.current.toggleAll(["a", "b"]));
|
||||
expect(result.current.count).toBe(0);
|
||||
});
|
||||
|
||||
it("toggleAll selects remaining items when some are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggle("a"));
|
||||
act(() => result.current.toggleAll(["a", "b", "c"]));
|
||||
expect(result.current.count).toBe(3);
|
||||
});
|
||||
|
||||
it("clear removes all selections", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => {
|
||||
result.current.toggle("a");
|
||||
result.current.toggle("b");
|
||||
});
|
||||
act(() => result.current.clear());
|
||||
expect(result.current.count).toBe(0);
|
||||
});
|
||||
|
||||
it("isAllSelected returns true when all given ids are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggleAll(["a", "b"]));
|
||||
expect(result.current.isAllSelected(["a", "b"])).toBe(true);
|
||||
});
|
||||
|
||||
it("isAllSelected returns false when some ids are not selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggle("a"));
|
||||
expect(result.current.isAllSelected(["a", "b"])).toBe(false);
|
||||
});
|
||||
|
||||
it("isAllSelected returns false for empty ids array", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
expect(result.current.isAllSelected([])).toBe(false);
|
||||
});
|
||||
|
||||
it("isIndeterminate returns true when some but not all are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggle("a"));
|
||||
expect(result.current.isIndeterminate(["a", "b"])).toBe(true);
|
||||
});
|
||||
|
||||
it("isIndeterminate returns false when all are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => result.current.toggleAll(["a", "b"]));
|
||||
expect(result.current.isIndeterminate(["a", "b"])).toBe(false);
|
||||
});
|
||||
|
||||
it("isIndeterminate returns false when none are selected", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
expect(result.current.isIndeterminate(["a", "b"])).toBe(false);
|
||||
});
|
||||
|
||||
it("selectedArray reflects the current selection", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => {
|
||||
result.current.toggle("x");
|
||||
result.current.toggle("y");
|
||||
});
|
||||
expect(result.current.selectedArray.sort()).toEqual(["x", "y"]);
|
||||
});
|
||||
|
||||
it("preserves other selections when toggling individual items", () => {
|
||||
const { result } = renderHook(() => useSelection());
|
||||
act(() => {
|
||||
result.current.toggle("a");
|
||||
result.current.toggle("b");
|
||||
});
|
||||
act(() => result.current.toggle("a"));
|
||||
expect(result.current.selectedIds.has("b")).toBe(true);
|
||||
expect(result.current.count).toBe(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user