79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
// @vitest-environment happy-dom
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { renderHook, act, waitFor } from "@testing-library/react";
|
|
|
|
vi.mock("./api", () => ({
|
|
authApi: {
|
|
me: vi.fn(),
|
|
login: vi.fn(),
|
|
logout: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
import { authApi } from "./api";
|
|
import { AuthProvider, useAuth } from "./AuthProvider";
|
|
|
|
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
<AuthProvider>{children}</AuthProvider>
|
|
);
|
|
|
|
describe("AuthProvider", () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
it("loads user on mount", async () => {
|
|
(authApi.me as unknown as ReturnType<typeof vi.fn>).mockResolvedValue({
|
|
id: 1,
|
|
username: "alice",
|
|
role: "user",
|
|
});
|
|
const { result } = renderHook(() => useAuth(), { wrapper });
|
|
await waitFor(() => expect(result.current.status).toBe("authenticated"));
|
|
expect(result.current.user?.username).toBe("alice");
|
|
});
|
|
|
|
it("status is unauthenticated when /me fails", async () => {
|
|
(authApi.me as unknown as ReturnType<typeof vi.fn>).mockRejectedValue(
|
|
new Error("401")
|
|
);
|
|
const { result } = renderHook(() => useAuth(), { wrapper });
|
|
await waitFor(() => expect(result.current.status).toBe("unauthenticated"));
|
|
expect(result.current.user).toBeNull();
|
|
});
|
|
|
|
it("login() updates state on success", async () => {
|
|
(authApi.me as unknown as ReturnType<typeof vi.fn>).mockRejectedValue(
|
|
new Error("401")
|
|
);
|
|
(
|
|
authApi.login as unknown as ReturnType<typeof vi.fn>
|
|
).mockResolvedValue({ id: 1, username: "alice", role: "admin" });
|
|
const { result } = renderHook(() => useAuth(), { wrapper });
|
|
await waitFor(() => expect(result.current.status).toBe("unauthenticated"));
|
|
await act(async () => {
|
|
await result.current.login("alice", "pw");
|
|
});
|
|
expect(result.current.user?.username).toBe("alice");
|
|
expect(result.current.status).toBe("authenticated");
|
|
});
|
|
|
|
it("logout() clears state", async () => {
|
|
(authApi.me as unknown as ReturnType<typeof vi.fn>).mockResolvedValue({
|
|
id: 1,
|
|
username: "alice",
|
|
role: "user",
|
|
});
|
|
(
|
|
authApi.logout as unknown as ReturnType<typeof vi.fn>
|
|
).mockResolvedValue(undefined);
|
|
const { result } = renderHook(() => useAuth(), { wrapper });
|
|
await waitFor(() => expect(result.current.status).toBe("authenticated"));
|
|
await act(async () => {
|
|
await result.current.logout();
|
|
});
|
|
expect(result.current.user).toBeNull();
|
|
expect(result.current.status).toBe("unauthenticated");
|
|
});
|
|
});
|