FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import { screen, waitFor } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import ForgotPasswordPage from "@/app/forgot-password/page";
|
|
import ResetPasswordPage from "@/app/reset-password/page";
|
|
import UnbanRequestPage from "@/app/unban-request/page";
|
|
import VerifyEmailPage from "@/app/verify-email/page";
|
|
import { renderWithQueryClient } from "./test-utils";
|
|
|
|
let searchParams = new URLSearchParams();
|
|
|
|
vi.mock("next/navigation", () => ({
|
|
useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
|
|
useSearchParams: () => searchParams,
|
|
}));
|
|
|
|
beforeEach(() => {
|
|
searchParams = new URLSearchParams();
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn().mockResolvedValue({
|
|
ok: false,
|
|
status: 401,
|
|
json: async () => ({ detail: "Not authenticated" }),
|
|
}),
|
|
);
|
|
});
|
|
|
|
describe("VerifyEmailPage", () => {
|
|
it("shows a validation error for an empty code", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<VerifyEmailPage />);
|
|
await user.click(await screen.findByRole("button", { name: /verify email/i }));
|
|
expect(await screen.findByText(/^enter the 6-digit code$/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows the email address pulled from the query string", async () => {
|
|
searchParams = new URLSearchParams({ email: "[email protected]" });
|
|
renderWithQueryClient(<VerifyEmailPage />);
|
|
expect(await screen.findByText(/ada@example\.com/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("ForgotPasswordPage", () => {
|
|
it("rejects an invalid email", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<ForgotPasswordPage />);
|
|
await user.type(screen.getByLabelText(/email/i), "not-an-email");
|
|
await user.click(screen.getByRole("button", { name: /send reset code/i }));
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/enter a valid email address/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it("links back to sign in", async () => {
|
|
renderWithQueryClient(<ForgotPasswordPage />);
|
|
expect(await screen.findByRole("link", { name: /back to sign in/i })).toHaveAttribute(
|
|
"href",
|
|
"/login",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("ResetPasswordPage", () => {
|
|
it("prefills email from the query string", async () => {
|
|
searchParams = new URLSearchParams({ email: "[email protected]" });
|
|
renderWithQueryClient(<ResetPasswordPage />);
|
|
expect(await screen.findByDisplayValue("[email protected]")).toBeInTheDocument();
|
|
});
|
|
|
|
it("rejects a weak new password", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<ResetPasswordPage />);
|
|
await user.type(screen.getByLabelText(/^email$/i), "[email protected]");
|
|
await user.type(screen.getByLabelText(/reset code/i), "123456");
|
|
await user.type(screen.getByLabelText(/new password/i), "allletters");
|
|
await user.click(screen.getByRole("button", { name: /reset password/i }));
|
|
await waitFor(() => {
|
|
expect(
|
|
screen.getByText(/must contain at least one letter and one digit/i),
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("UnbanRequestPage", () => {
|
|
it("submits and shows a confirmation", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn().mockResolvedValue({
|
|
ok: true,
|
|
status: 204,
|
|
json: async () => ({}),
|
|
}),
|
|
);
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<UnbanRequestPage />);
|
|
|
|
await user.type(screen.getByLabelText(/message/i), "This looks like a mistake.");
|
|
await user.click(screen.getByRole("button", { name: /send request/i }));
|
|
|
|
expect(await screen.findByText(/request received/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it("links back to sign in", async () => {
|
|
renderWithQueryClient(<UnbanRequestPage />);
|
|
expect(await screen.findByRole("link", { name: /back to sign in/i })).toHaveAttribute(
|
|
"href",
|
|
"/login",
|
|
);
|
|
});
|
|
});
|