import { act, render } from "@testing-library/react"
import { MemoryRouter, Route, Routes } from "react-router-dom"
import { afterEach, beforeEach, expect, test, vi } from "vitest"
// ProtectedRoute must NOT mount its children while AuthProvider is still
// running the initial getProfile() probe — except for the /dashboard/login
// path itself. Mounting the protected subtree during the probe would fire
// authenticated SWR fetches like /api/v1/setting before auth is confirmed.
// Without this contract, a regression in protect.tsx silently re-introduces
// pre-auth traffic and a flash of protected UI before redirect.
let mockProfile: { id: number; role: number } | undefined
let mockLoading = false
vi.mock("@/hooks/useAuth", () => ({
useAuth: () => ({ profile: mockProfile, loading: mockLoading }),
}))
beforeEach(() => {
mockProfile = undefined
mockLoading = true
})
afterEach(() => {
document.body.innerHTML = ""
})
function renderAtPath(path: string, child: React.ReactNode) {
return import("@/routes/protect").then(({ default: ProtectedRoute }) => {
return act(async () => {
render(
{child}
}
/>
{child}
}
/>
,
)
})
})
}
test("ProtectedRoute does not mount children for protected paths while auth is loading", async () => {
await renderAtPath(
"/dashboard",
protected
,
)
expect(document.querySelector("[data-testid='protected-child']")).toBeNull()
})
test("ProtectedRoute renders children on the login page even while auth is loading", async () => {
await renderAtPath(
"/dashboard/login",
login
,
)
expect(document.querySelector("[data-testid='login-child']")).not.toBeNull()
})
test("ProtectedRoute redirects unauthenticated users without mounting protected children", async () => {
mockLoading = false
mockProfile = undefined
const { default: ProtectedRoute } = await import("@/routes/protect")
await act(async () => {
render(
login
}
/>
protected
}
/>
,
)
})
expect(document.querySelector("[data-testid='protected-child']")).toBeNull()
expect(document.querySelector("[data-testid='login-child']")).not.toBeNull()
})
test("ProtectedRoute renders children once an authenticated profile resolves", async () => {
mockLoading = false
mockProfile = { id: 1, role: 0 }
await renderAtPath(
"/dashboard",
protected
,
)
expect(document.querySelector("[data-testid='protected-child']")).not.toBeNull()
})