generated from nholtware/service-template-react
98 lines
3 KiB
TypeScript
98 lines
3 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { createMemoryRouter, RouterProvider } from "react-router";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { routes } from "./routes";
|
|
|
|
// Flags come from the Unleash SDK; tests control them directly.
|
|
const flagsOn = vi.hoisted(() => new Set<string>());
|
|
vi.mock("@unleash/proxy-client-react", () => ({
|
|
FlagProvider: ({ children }: { children: React.ReactNode }) => children,
|
|
useFlag: (name: string) => flagsOn.has(name),
|
|
useVariant: () => ({ name: "disabled", enabled: false }),
|
|
}));
|
|
|
|
function renderAt(path: string) {
|
|
const router = createMemoryRouter(routes, { initialEntries: [path] });
|
|
return render(<RouterProvider router={router} />);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
flagsOn.clear();
|
|
window.__APP_CONFIG__ = { API_BASE_URL: "/api", APP_NAME: "test-app" };
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
describe("app", () => {
|
|
it("library lists published stories and links to play", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(
|
|
async () =>
|
|
new Response(
|
|
JSON.stringify({
|
|
stories: [
|
|
{
|
|
id: "s1",
|
|
title: "Cave",
|
|
description: "Dark",
|
|
nodeCount: 3,
|
|
published: true,
|
|
},
|
|
],
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
renderAt("/");
|
|
expect(
|
|
await screen.findByRole("heading", { name: "Cave" }),
|
|
).toBeInTheDocument();
|
|
expect(
|
|
screen.getAllByRole("link", { name: "Play" }).at(-1)!,
|
|
).toHaveAttribute("href", "/play/s1");
|
|
});
|
|
|
|
it("library shows a builder prompt when empty", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () => new Response(JSON.stringify({ stories: [] }))),
|
|
);
|
|
renderAt("/");
|
|
expect(
|
|
await screen.findByText(/No published stories yet/),
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it("status fetches / and /readyz under API_BASE_URL and renders the JSON", async () => {
|
|
const fetchMock = vi.fn(async (url: string) => {
|
|
const body =
|
|
url === "/api/readyz" ? { status: "ready" } : { service: "svc" };
|
|
return new Response(JSON.stringify(body), { status: 200 });
|
|
});
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
|
|
renderAt("/status");
|
|
|
|
expect(await screen.findByText(/GET \/readyz/)).toBeInTheDocument();
|
|
expect(screen.getByText(/"status": "ready"/)).toBeInTheDocument();
|
|
expect(screen.getByText(/"service": "svc"/)).toBeInTheDocument();
|
|
// Layout also asks /auth/me who is signed in; that's not what's under test.
|
|
expect(
|
|
fetchMock.mock.calls.map((c) => c[0]).filter((u) => u !== "/api/auth/me"),
|
|
).toEqual(["/api/", "/api/readyz"]);
|
|
});
|
|
|
|
it("status shows the error page when the backend is unreachable", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () => {
|
|
throw new Error("network down");
|
|
}),
|
|
);
|
|
renderAt("/status");
|
|
expect(await screen.findByRole("alert")).toHaveTextContent("network down");
|
|
});
|
|
});
|