Initial commit: CI Agent competitive-intelligence monitoring app

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).
This commit is contained in:
2026-08-05 10:48:20 -04:00
commit 1a4c80958f
365 changed files with 43541 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
import { screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it, vi } from "vitest";
import LoginPage from "@/app/login/page";
import RegisterPage from "@/app/register/page";
import { renderWithQueryClient } from "./test-utils";
vi.mock("next/navigation", () => ({
useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
useSearchParams: () => new URLSearchParams(),
}));
beforeEach(() => {
vi.stubGlobal(
"fetch",
vi.fn().mockResolvedValue({
ok: false,
status: 401,
json: async () => ({ detail: "Not authenticated" }),
}),
);
});
describe("LoginPage", () => {
it("shows validation errors for an empty submission", async () => {
const user = userEvent.setup();
renderWithQueryClient(<LoginPage />);
await user.click(await screen.findByRole("button", { name: /sign in/i }));
expect(await screen.findByText(/enter a valid email address/i)).toBeInTheDocument();
expect(await screen.findByText(/enter your password/i)).toBeInTheDocument();
});
it("links to the register page", async () => {
renderWithQueryClient(<LoginPage />);
expect(await screen.findByRole("link", { name: /create one/i })).toHaveAttribute(
"href",
"/register",
);
});
});
describe("RegisterPage", () => {
it("rejects a weak password before submitting", async () => {
const user = userEvent.setup();
renderWithQueryClient(<RegisterPage />);
await user.type(screen.getByLabelText(/full name/i), "Ada Lovelace");
await user.type(screen.getByLabelText(/^email$/i), "[email protected]");
await user.type(screen.getByLabelText(/^password$/i), "allletters");
await user.click(screen.getByRole("button", { name: /create account/i }));
await waitFor(() => {
expect(
screen.getByText(/must contain at least one letter and one digit/i),
).toBeInTheDocument();
});
});
it("links to the login page", async () => {
renderWithQueryClient(<RegisterPage />);
expect(await screen.findByRole("link", { name: /sign in/i })).toHaveAttribute("href", "/login");
});
});