Files
the-pet-loft/apps/storefront/src/lib/search/useClickOutside.test.tsx
ianshaloom 23efcab80c
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m11s
fix: resolve CI and workspace lint errors (admin + storefront)
- Allow require() in next.config.js (eslint-disable) for both apps
- Replace all catch (e: any) with catch (e: unknown) and proper error handling
- Remove no-explicit-any: add types (PreviewProduct, ProductImage, Id<addresses>,
  ProductDetailReview, error payloads) across admin and storefront
- Admin: use next/image in ImageUploadSection and ProductImageCarousel; remove
  unused layout fonts and sidebar imports; fix products page useMemo deps
- Storefront: use Link for /sign-in in header actions; fix useAddressMutations
  and product detail types; remove unused imports/vars and fix useMemo deps

Made-with: Cursor
2026-03-08 00:45:57 +03:00

146 lines
4.0 KiB
TypeScript

/**
* @vitest-environment happy-dom
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { useRef } from "react";
import { useClickOutside } from "./useClickOutside";
function fireMouseDown(target: EventTarget) {
target.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
}
describe("useClickOutside", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("does not call handler when enabled is false", () => {
const handler = vi.fn();
renderHook(() => {
const ref = useRef<HTMLDivElement>(document.createElement("div"));
useClickOutside([ref], handler, false);
return ref;
});
act(() => fireMouseDown(document.body));
expect(handler).not.toHaveBeenCalled();
});
it("calls handler when clicking outside all refs", () => {
const handler = vi.fn();
const el = document.createElement("div");
document.body.appendChild(el);
renderHook(() => {
const ref = useRef<HTMLDivElement>(el);
useClickOutside([ref], handler, true);
});
act(() => fireMouseDown(document.body));
expect(handler).toHaveBeenCalledTimes(1);
document.body.removeChild(el);
});
it("does not call handler when clicking inside the ref element", () => {
const handler = vi.fn();
const el = document.createElement("div");
document.body.appendChild(el);
renderHook(() => {
const ref = useRef<HTMLDivElement>(el);
useClickOutside([ref], handler, true);
});
act(() => fireMouseDown(el));
expect(handler).not.toHaveBeenCalled();
document.body.removeChild(el);
});
it("does not call handler when clicking inside a child of the ref element", () => {
const handler = vi.fn();
const parent = document.createElement("div");
const child = document.createElement("button");
parent.appendChild(child);
document.body.appendChild(parent);
renderHook(() => {
const ref = useRef<HTMLDivElement>(parent);
useClickOutside([ref], handler, true);
});
act(() => fireMouseDown(child));
expect(handler).not.toHaveBeenCalled();
document.body.removeChild(parent);
});
it("does not call handler when clicking inside any of multiple refs", () => {
const handler = vi.fn();
const el1 = document.createElement("div");
const el2 = document.createElement("div");
document.body.appendChild(el1);
document.body.appendChild(el2);
renderHook(() => {
const ref1 = useRef<HTMLDivElement>(el1);
const ref2 = useRef<HTMLDivElement>(el2);
useClickOutside([ref1, ref2], handler, true);
});
act(() => fireMouseDown(el1));
expect(handler).not.toHaveBeenCalled();
act(() => fireMouseDown(el2));
expect(handler).not.toHaveBeenCalled();
document.body.removeChild(el1);
document.body.removeChild(el2);
});
it("stops calling handler after enabled becomes false", () => {
const handler = vi.fn();
const el = document.createElement("div");
document.body.appendChild(el);
const { rerender } = renderHook(
({ enabled }: { enabled: boolean }) => {
const ref = useRef<HTMLDivElement>(el);
useClickOutside([ref], handler, enabled);
},
{ initialProps: { enabled: true } },
);
act(() => fireMouseDown(document.body));
expect(handler).toHaveBeenCalledTimes(1);
rerender({ enabled: false });
act(() => fireMouseDown(document.body));
expect(handler).toHaveBeenCalledTimes(1); // no additional calls
document.body.removeChild(el);
});
it("removes listener on unmount", () => {
const handler = vi.fn();
const el = document.createElement("div");
document.body.appendChild(el);
const { unmount } = renderHook(() => {
const ref = useRef<HTMLDivElement>(el);
useClickOutside([ref], handler, true);
});
unmount();
act(() => fireMouseDown(document.body));
expect(handler).not.toHaveBeenCalled();
document.body.removeChild(el);
});
});