first round of review

This commit is contained in:
counterweight 2025-12-18 22:24:46 +01:00
parent 7ebfb7a2dd
commit da5a0d03eb
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
14 changed files with 362 additions and 244 deletions

View file

@ -12,14 +12,12 @@ vi.mock("next/navigation", () => ({
// Default mock values
let mockUser: { id: number; email: string } | null = { id: 1, email: "test@example.com" };
let mockToken: string | null = "valid-token";
let mockIsLoading = false;
const mockLogout = vi.fn();
vi.mock("./auth-context", () => ({
useAuth: () => ({
user: mockUser,
token: mockToken,
isLoading: mockIsLoading,
logout: mockLogout,
}),
@ -29,7 +27,6 @@ beforeEach(() => {
vi.clearAllMocks();
// Reset to authenticated state
mockUser = { id: 1, email: "test@example.com" };
mockToken = "valid-token";
mockIsLoading = false;
});
@ -64,14 +61,18 @@ describe("Home - Authenticated", () => {
expect(screen.getByText("Sign out")).toBeDefined();
});
test("clicking sign out calls logout", async () => {
test("clicking sign out calls logout and redirects", async () => {
vi.spyOn(global, "fetch").mockResolvedValue({
json: () => Promise.resolve({ value: 42 }),
} as Response);
render(<Home />);
fireEvent.click(screen.getByText("Sign out"));
expect(mockLogout).toHaveBeenCalled();
await waitFor(() => {
expect(mockLogout).toHaveBeenCalled();
expect(mockPush).toHaveBeenCalledWith("/login");
});
});
test("renders counter value after fetch", async () => {
@ -85,7 +86,7 @@ describe("Home - Authenticated", () => {
});
});
test("fetches counter with auth header", async () => {
test("fetches counter with credentials", async () => {
const fetchSpy = vi.spyOn(global, "fetch").mockResolvedValue({
json: () => Promise.resolve({ value: 0 }),
} as Response);
@ -96,7 +97,7 @@ describe("Home - Authenticated", () => {
expect(fetchSpy).toHaveBeenCalledWith(
"http://localhost:8000/api/counter",
expect.objectContaining({
headers: { Authorization: "Bearer valid-token" },
credentials: "include",
})
);
});
@ -111,7 +112,7 @@ describe("Home - Authenticated", () => {
expect(screen.getByText("Increment")).toBeDefined();
});
test("clicking increment button calls API with auth header", async () => {
test("clicking increment button calls API with credentials", async () => {
const fetchSpy = vi
.spyOn(global, "fetch")
.mockResolvedValueOnce({ json: () => Promise.resolve({ value: 0 }) } as Response)
@ -127,7 +128,7 @@ describe("Home - Authenticated", () => {
"http://localhost:8000/api/counter/increment",
expect.objectContaining({
method: "POST",
headers: { Authorization: "Bearer valid-token" },
credentials: "include",
})
);
});
@ -149,7 +150,6 @@ describe("Home - Authenticated", () => {
describe("Home - Unauthenticated", () => {
test("redirects to login when not authenticated", async () => {
mockUser = null;
mockToken = null;
render(<Home />);
@ -160,16 +160,14 @@ describe("Home - Unauthenticated", () => {
test("returns null when not authenticated", () => {
mockUser = null;
mockToken = null;
const { container } = render(<Home />);
// Should render nothing (just redirects)
expect(container.querySelector("main")).toBeNull();
});
test("does not fetch counter when no token", () => {
test("does not fetch counter when no user", () => {
mockUser = null;
mockToken = null;
const fetchSpy = vi.spyOn(global, "fetch");
render(<Home />);
@ -182,7 +180,6 @@ describe("Home - Loading State", () => {
test("does not redirect while loading", () => {
mockIsLoading = true;
mockUser = null;
mockToken = null;
render(<Home />);