61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
import { MemoryRouter } from "react-router-dom";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { adminApi } from "../lib/api";
|
|
import AppRoutes from "../routes";
|
|
|
|
vi.mock("../lib/api", () => ({
|
|
adminApi: {
|
|
get: vi.fn(),
|
|
post: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
describe("PrivilegedGate", () => {
|
|
beforeEach(() => {
|
|
localStorage.clear();
|
|
vi.clearAllMocks();
|
|
vi.mocked(adminApi.get).mockResolvedValue({
|
|
data: {
|
|
alerts: [],
|
|
metrics: [],
|
|
shortcuts: [],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("exchanges a privileged token and enters the admin shell", async () => {
|
|
vi.mocked(adminApi.post).mockResolvedValue({
|
|
data: {
|
|
expiresAt: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
|
operatorEmail: "ops@xtablo.com",
|
|
operatorId: "operator-1",
|
|
role: "operator",
|
|
sessionToken: "admin-session-token",
|
|
},
|
|
});
|
|
|
|
render(
|
|
<MemoryRouter initialEntries={["/"]}>
|
|
<AppRoutes />
|
|
</MemoryRouter>
|
|
);
|
|
|
|
fireEvent.change(screen.getByLabelText(/access token/i), {
|
|
target: { value: "valid-access-token" },
|
|
});
|
|
fireEvent.click(screen.getByRole("button", { name: /unlock admin/i }));
|
|
|
|
await waitFor(() => {
|
|
expect(adminApi.post).toHaveBeenCalledWith("/admin/auth/exchange", {
|
|
accessToken: "valid-access-token",
|
|
});
|
|
});
|
|
|
|
expect(
|
|
await screen.findByRole("heading", {
|
|
name: /production command deck for privileged supabase operations/i,
|
|
})
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|