Files
CIAgent/apps/web/tests/landing-page.test.tsx
T
sakshamandClaude Sonnet 5 086ca1f13f Add production deployment tooling: Nginx, Gitea, prod Dockerfiles
Sets up everything needed to deploy behind Cloudflare with a self-hosted
git server: multi-stage prod Dockerfiles (non-root), docker-compose.prod.yml
(Postgres/Redis with no host ports, Nginx reverse proxy, Gitea with
public-read/admin-write access control), scripts/bootstrap-env.sh to
auto-generate required secrets on first clone, and DEPLOYMENT.md covering
the full runbook. Provider API keys (Anthropic/Brave/NinjaPear/USPTO/
Turnstile) are deliberately kept out of .env in favor of the existing
DB-backed Settings UI, so the public repo stays safe to expose.

Also fixes two bugs only surfaced by live-testing the prod stack: Celery
beat couldn't write its schedule file as a non-root user, and Gitea's
embedded SSH server conflicted with the base image's own sshd on port 22.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-05 12:59:41 -04:00

86 lines
3.1 KiB
TypeScript

import { screen } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import LandingPage from "@/app/page";
import { renderWithQueryClient } from "./test-utils";
function mockFetchImplementation(isLocalhost: boolean) {
return vi.fn().mockImplementation((url: string) => {
const path = url.replace("http://localhost:8000", "");
if (path.startsWith("/api/v1/system/status")) {
return Promise.resolve({
ok: true,
status: 200,
json: async () => ({
app_env: "development",
auth_mode: "local",
llm_provider: "mock",
search_provider: "mock",
sms_enabled: false,
sms_provider: "twilio",
ninjapear_configured: false,
ninjapear_credit_balance: null,
ninjapear_estimated_credits_per_company: null,
is_localhost: isLocalhost,
components: [],
}),
});
}
return Promise.resolve({ ok: false, status: 404, json: async () => ({ detail: "not found" }) });
});
}
describe("LandingPage", () => {
beforeEach(() => {
vi.stubGlobal("fetch", mockFetchImplementation(true));
});
it("renders the value proposition and primary calls to action", async () => {
renderWithQueryClient(<LandingPage />);
expect(
screen.getByRole("heading", { name: /know what your competitors are doing/i }),
).toBeInTheDocument();
expect(
await screen.findByRole("link", { name: /open dashboard \(local mode\)/i }),
).toHaveAttribute("href", "/dashboard");
expect(screen.getByRole("link", { name: /sign in/i })).toHaveAttribute("href", "/login");
expect(screen.getByRole("link", { name: /create account/i })).toHaveAttribute(
"href",
"/register",
);
});
it("discloses the public-information-only collection policy", () => {
renderWithQueryClient(<LandingPage />);
expect(
screen.getByRole("heading", { name: /only publicly available information/i }),
).toBeInTheDocument();
});
it("drops the local-mode wording when the request isn't from localhost", async () => {
vi.stubGlobal("fetch", mockFetchImplementation(false));
renderWithQueryClient(<LandingPage />);
expect(await screen.findByRole("link", { name: /^open dashboard$/i })).toHaveAttribute(
"href",
"/dashboard",
);
expect(screen.queryByText(/local mode/i)).not.toBeInTheDocument();
});
it("hides the Git Repository link when no NEXT_PUBLIC_GIT_REPO_URL is configured", () => {
renderWithQueryClient(<LandingPage />);
expect(screen.queryByRole("link", { name: /git repository/i })).not.toBeInTheDocument();
});
it("shows a Git Repository link opening in a new tab when configured", () => {
vi.stubEnv("NEXT_PUBLIC_GIT_REPO_URL", "https://git.ciagent.org/admin/ci-agent");
renderWithQueryClient(<LandingPage />);
const link = screen.getByRole("link", { name: /git repository/i });
expect(link).toHaveAttribute("href", "https://git.ciagent.org/admin/ci-agent");
expect(link).toHaveAttribute("target", "_blank");
expect(link).toHaveAttribute("rel", "noopener noreferrer");
});
});