Files
Reactive-Resume/src/hooks/use-prompt.test.tsx
T
2026-04-02 00:14:54 +02:00

160 lines
4.3 KiB
TypeScript

import { act, fireEvent, render, renderHook, screen } from "@testing-library/react";
import React from "react";
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
vi.mock("@lingui/core/macro", () => ({
t: (strings: TemplateStringsArray) => strings[0],
}));
import { PromptDialogProvider, usePrompt } from "./use-prompt";
afterEach(() => {
document.body.innerHTML = "";
});
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function wrapper({ children }: { children: React.ReactNode }) {
return <PromptDialogProvider>{children}</PromptDialogProvider>;
}
function PromptTester() {
const prompt = usePrompt();
const [result, setResult] = React.useState<string | null | undefined>(undefined);
return (
<div>
<button
onClick={async () => {
const value = await prompt("Enter name", {
description: "Provide your full name",
defaultValue: "John",
confirmText: "Submit",
cancelText: "Skip",
});
setResult(value);
}}
>
Open Prompt
</button>
{result !== undefined && <span data-testid="result">{result === null ? "null" : result}</span>}
</div>
);
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe("usePrompt", () => {
it("throws when used outside provider", () => {
expect(() => {
renderHook(() => usePrompt());
}).toThrow("usePrompt must be used within a <PromptDialogProvider />");
});
it("returns a function when used inside provider", () => {
const { result } = renderHook(() => usePrompt(), { wrapper });
expect(typeof result.current).toBe("function");
});
it("prompt() returns a promise", () => {
const { result } = renderHook(() => usePrompt(), { wrapper });
let promise: Promise<string | null> | undefined;
act(() => {
promise = result.current("Enter value");
});
expect(promise).toBeInstanceOf(Promise);
});
it("opens dialog with title, description, and default value", async () => {
render(
<PromptDialogProvider>
<PromptTester />
</PromptDialogProvider>,
);
await act(async () => {
screen.getByText("Open Prompt").click();
});
expect(screen.getByText("Enter name")).toBeDefined();
expect(screen.getByText("Provide your full name")).toBeDefined();
expect(screen.getByText("Submit")).toBeDefined();
expect(screen.getByText("Skip")).toBeDefined();
// Check default value in input
const input = screen.getByDisplayValue("John");
expect(input).toBeDefined();
});
it("resolves with input value when confirm is clicked", async () => {
render(
<PromptDialogProvider>
<PromptTester />
</PromptDialogProvider>,
);
await act(async () => {
screen.getByText("Open Prompt").click();
});
// Change the input value
const input = screen.getByDisplayValue("John");
await act(async () => {
fireEvent.change(input, { target: { value: "Jane Doe" } });
});
await act(async () => {
screen.getByText("Submit").click();
});
expect(screen.getByTestId("result").textContent).toBe("Jane Doe");
});
it("resolves with null when cancel is clicked", async () => {
render(
<PromptDialogProvider>
<PromptTester />
</PromptDialogProvider>,
);
await act(async () => {
screen.getByText("Open Prompt").click();
});
await act(async () => {
screen.getByText("Skip").click();
});
expect(screen.getByTestId("result").textContent).toBe("null");
});
it("resolves with value when Enter key is pressed", async () => {
render(
<PromptDialogProvider>
<PromptTester />
</PromptDialogProvider>,
);
await act(async () => {
screen.getByText("Open Prompt").click();
});
const input = screen.getByDisplayValue("John");
await act(async () => {
fireEvent.change(input, { target: { value: "Enter User" } });
});
await act(async () => {
fireEvent.keyDown(input, { key: "Enter" });
});
expect(screen.getByTestId("result").textContent).toBe("Enter User");
});
});