Extract custom hooks for reusable logic
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { renderHook, act } from "@testing-library/react";
|
||||
import { vi, describe, test, expect, beforeEach, afterEach } from "vitest";
|
||||
import { useClickOutside } from "../../../app/hooks/useClickOutside";
|
||||
import { useRef } from "react";
|
||||
|
||||
describe("useClickOutside", () => {
|
||||
let handler: ReturnType<typeof vi.fn>;
|
||||
|
||||
beforeEach(() => {
|
||||
handler = vi.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("calls handler when clicking outside element", () => {
|
||||
const { result } = renderHook(() => {
|
||||
const ref = useRef(null);
|
||||
useClickOutside([ref], handler, true);
|
||||
return ref;
|
||||
});
|
||||
|
||||
const div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
result.current.current = div;
|
||||
|
||||
act(() => {
|
||||
document.body.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1);
|
||||
document.body.removeChild(div);
|
||||
});
|
||||
|
||||
test("does not call handler when clicking inside element", () => {
|
||||
const { result } = renderHook(() => {
|
||||
const ref = useRef(null);
|
||||
useClickOutside([ref], handler, true);
|
||||
return ref;
|
||||
});
|
||||
|
||||
const div = document.createElement("div");
|
||||
const innerDiv = document.createElement("div");
|
||||
div.appendChild(innerDiv);
|
||||
document.body.appendChild(div);
|
||||
result.current.current = div;
|
||||
|
||||
act(() => {
|
||||
innerDiv.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
document.body.removeChild(div);
|
||||
});
|
||||
|
||||
test("does not call handler when disabled", () => {
|
||||
const { result } = renderHook(() => {
|
||||
const ref = useRef(null);
|
||||
useClickOutside([ref], handler, false);
|
||||
return ref;
|
||||
});
|
||||
|
||||
act(() => {
|
||||
document.body.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("handles multiple refs", () => {
|
||||
const { result } = renderHook(() => {
|
||||
const ref1 = useRef(null);
|
||||
const ref2 = useRef(null);
|
||||
useClickOutside([ref1, ref2], handler, true);
|
||||
return { ref1, ref2 };
|
||||
});
|
||||
|
||||
const div1 = document.createElement("div");
|
||||
const div2 = document.createElement("div");
|
||||
document.body.appendChild(div1);
|
||||
document.body.appendChild(div2);
|
||||
result.current.ref1.current = div1;
|
||||
result.current.ref2.current = div2;
|
||||
|
||||
act(() => {
|
||||
document.body.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1);
|
||||
document.body.removeChild(div1);
|
||||
document.body.removeChild(div2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import { renderHook } from "@testing-library/react";
|
||||
import { describe, test, expect } from "vitest";
|
||||
import { useComponentId } from "../../../app/hooks/useComponentId";
|
||||
|
||||
describe("useComponentId", () => {
|
||||
test("generates unique IDs with prefix", () => {
|
||||
const { result } = renderHook(() => useComponentId("input"));
|
||||
expect(result.current.id).toMatch(/^input-/);
|
||||
expect(result.current.labelId).toMatch(/^input-.*-label$/);
|
||||
});
|
||||
|
||||
test("uses provided ID when given", () => {
|
||||
const { result } = renderHook(() => useComponentId("input", "custom-id"));
|
||||
expect(result.current.id).toBe("custom-id");
|
||||
expect(result.current.labelId).toBe("custom-id-label");
|
||||
});
|
||||
|
||||
test("generates different IDs for different prefixes", () => {
|
||||
const { result: result1 } = renderHook(() => useComponentId("input"));
|
||||
const { result: result2 } = renderHook(() => useComponentId("select"));
|
||||
|
||||
expect(result1.current.id).not.toBe(result2.current.id);
|
||||
expect(result1.current.id).toMatch(/^input-/);
|
||||
expect(result2.current.id).toMatch(/^select-/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
import { renderHook } from "@testing-library/react";
|
||||
import { describe, test, expect } from "vitest";
|
||||
import { useSchemaData } from "../../../app/hooks/useSchemaData";
|
||||
|
||||
describe("useSchemaData", () => {
|
||||
test("generates Organization schema", () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSchemaData({
|
||||
type: "Organization",
|
||||
name: "Test Org",
|
||||
url: "https://example.com",
|
||||
email: "test@example.com",
|
||||
sameAs: ["https://twitter.com/test"],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Test Org",
|
||||
url: "https://example.com",
|
||||
email: "test@example.com",
|
||||
sameAs: ["https://twitter.com/test"],
|
||||
});
|
||||
});
|
||||
|
||||
test("generates WebSite schema", () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSchemaData({
|
||||
type: "WebSite",
|
||||
name: "Test Site",
|
||||
url: "https://example.com",
|
||||
potentialAction: {
|
||||
target: "https://example.com/search?q={search_term_string}",
|
||||
"query-input": "required name=search_term_string",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
name: "Test Site",
|
||||
url: "https://example.com",
|
||||
potentialAction: {
|
||||
"@type": "SearchAction",
|
||||
target: "https://example.com/search?q={search_term_string}",
|
||||
"query-input": "required name=search_term_string",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("generates HowTo schema", () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSchemaData({
|
||||
type: "HowTo",
|
||||
name: "How to test",
|
||||
description: "Test description",
|
||||
steps: [
|
||||
{ name: "Step 1", text: "Do this" },
|
||||
{ name: "Step 2", text: "Do that" },
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "HowTo",
|
||||
name: "How to test",
|
||||
description: "Test description",
|
||||
step: [
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
position: 1,
|
||||
name: "Step 1",
|
||||
text: "Do this",
|
||||
},
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
position: 2,
|
||||
name: "Step 2",
|
||||
text: "Do that",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("generates BreadcrumbList schema", () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSchemaData({
|
||||
type: "BreadcrumbList",
|
||||
items: [
|
||||
{ name: "Home", url: "https://example.com" },
|
||||
{ name: "Page", url: "https://example.com/page" },
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
position: 1,
|
||||
name: "Home",
|
||||
item: "https://example.com",
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
position: 2,
|
||||
name: "Page",
|
||||
item: "https://example.com/page",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user