Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m11s
- 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
146 lines
4.0 KiB
TypeScript
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);
|
|
});
|
|
});
|