feat: story library, player and builder UI
All checks were successful
/ checks (push) Successful in 41s
/ deploy (push) Successful in 4s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nholtware 2026-11-05 12:45:06 -06:00
parent 52778622a4
commit 364a911794
14 changed files with 1149 additions and 41 deletions

View file

@ -26,26 +26,44 @@ afterEach(() => {
});
describe("app", () => {
it("home shows the app name from runtime config and the build sha", async () => {
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: "test-app" }),
await screen.findByRole("heading", { name: "Cave" }),
).toBeInTheDocument();
expect(screen.getByTestId("build-sha")).toHaveTextContent("dev");
expect(
screen.getAllByRole("link", { name: "Play" }).at(-1)!,
).toHaveAttribute("href", "/play/s1");
});
it("home hides the banner while hello-banner is off", async () => {
renderAt("/");
await screen.findByRole("heading", { name: "test-app" });
expect(screen.queryByTestId("banner")).not.toBeInTheDocument();
});
it("home shows the banner while hello-banner is on", async () => {
flagsOn.add("hello-banner");
renderAt("/");
expect(await screen.findByTestId("banner")).toHaveTextContent(
"hello-banner flag is on",
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 () => {