Manual timezone is the single source of local-time truth (task 7e173881) (#285)

Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com>
Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
This commit was merged in pull request #285.
This commit is contained in:
2026-09-30 10:02:05 -04:00
committed by approver_agent
parent 69db92b7b8
commit 0e726ac64f
46 changed files with 1556 additions and 429 deletions
+50 -7
View File
@@ -2,10 +2,29 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import App from "./App";
function jsonResponse(body: unknown, status = 200): Response {
return new Response(JSON.stringify(body), {
status,
headers: { "Content-Type": "application/json" },
});
}
let settingsResponse: () => Promise<Response>;
describe("NestQuest Admin shell", () => {
beforeEach(() => {
// The Today tab fetches the admin snapshot; keep the shell tests offline.
vi.stubGlobal("fetch", vi.fn(() => new Promise<Response>(() => {})));
settingsResponse = () =>
Promise.resolve(jsonResponse({ timezone: "", effective_timezone: "Europe/London" }));
// The shell loads the stored application timezone; every tab's own
// requests stay pending so the shell tests remain offline.
vi.stubGlobal(
"fetch",
vi.fn((url: string) =>
String(url).endsWith("/api/v1/admin/settings")
? settingsResponse()
: new Promise<Response>(() => {}),
),
);
});
afterEach(() => {
@@ -22,10 +41,10 @@ describe("NestQuest Admin shell", () => {
}
});
it("starts on the Today screen and switches on tab click", () => {
it("starts on the Today screen and switches on tab click", async () => {
render(<App />);
expect(screen.getByRole("heading", { name: "Today" })).toBeTruthy();
expect(await screen.findByRole("heading", { name: "Today" })).toBeTruthy();
fireEvent.click(screen.getByRole("tab", { name: "History" }));
@@ -36,12 +55,36 @@ describe("NestQuest Admin shell", () => {
);
});
it("the Tasks tab renders the definitions screen", () => {
it("the Tasks tab renders the definitions screen", async () => {
render(<App />);
fireEvent.click(screen.getByRole("tab", { name: "Tasks" }));
expect(screen.getByRole("heading", { name: "Tasks" })).toBeTruthy();
expect(await screen.findByRole("heading", { name: "Tasks" })).toBeTruthy();
expect(screen.getByRole("tabpanel").textContent).not.toContain("placeholder");
});
});
it("renders no screen until the stored application timezone is known", async () => {
settingsResponse = () => new Promise<Response>(() => {});
render(<App />);
expect(screen.getByTestId("timezone-loading")).toBeTruthy();
expect(screen.queryByRole("heading", { name: "Today" })).toBeNull();
});
it("a failed timezone load says so and retries", async () => {
settingsResponse = () => Promise.resolve(jsonResponse({ detail: "boom" }, 500));
render(<App />);
await screen.findByTestId("timezone-error");
expect(screen.queryByRole("heading", { name: "Today" })).toBeNull();
settingsResponse = () =>
Promise.resolve(
jsonResponse({ timezone: "Pacific/Auckland", effective_timezone: "Pacific/Auckland" }),
);
fireEvent.click(screen.getByRole("button", { name: "Try again" }));
expect(await screen.findByRole("heading", { name: "Today" })).toBeTruthy();
});
});