import { render, screen, fireEvent } from "@testing-library/react"; import SimpleProgram from "../../../src/pages/SimpleProgram/SimpleProgram"; import useProgramStore from "../../../src/utils/programStore"; /** * Helper to preload the program store before rendering. */ function loadProgram(phases: Record[]) { useProgramStore.getState().setProgramState({ phases }); } describe("SimpleProgram", () => { beforeEach(() => { loadProgram([]); }); test("shows empty state when no program is loaded", () => { render(); expect(screen.getByText("No program loaded.")).toBeInTheDocument(); }); test("renders first phase content", () => { loadProgram([ { id: "phase-1", norms: [{ id: "n1", norm: "Be polite" }], goals: [{ id: "g1", description: "Finish task", achieved: true }], triggers: [{ id: "t1", label: "Keyword trigger" }], }, ]); render(); expect(screen.getByText("Phase 1 / 1")).toBeInTheDocument(); expect(screen.getByText("Be polite")).toBeInTheDocument(); expect(screen.getByText("Finish task")).toBeInTheDocument(); expect(screen.getByText("Keyword trigger")).toBeInTheDocument(); }); test("renders empty messages when phase has no data", () => { loadProgram([ { id: "phase-1", norms: [], goals: [], triggers: [], }, ]); render(); expect(screen.getAllByText("No norms defined.").length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText("No goals defined.").length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText("No triggers defined.").length).toBeGreaterThanOrEqual(1); expect( screen.getByText("No conditional norms defined.") ).toBeInTheDocument(); }); test("allows navigating between phases", () => { loadProgram([ { id: "phase-1", norms: [], goals: [], triggers: [], }, { id: "phase-2", norms: [{ id: "n2", norm: "Be careful" }], goals: [], triggers: [], }, ]); render(); expect(screen.getByText("Phase 1 / 2")).toBeInTheDocument(); fireEvent.click(screen.getByText("Next ▶")); expect(screen.getByText("Phase 2 / 2")).toBeInTheDocument(); expect(screen.getByText("Be careful")).toBeInTheDocument(); }); test("prev button is disabled on first phase", () => { loadProgram([{ id: "phase-1", norms: [], goals: [], triggers: [] }]); render(); expect(screen.getByText("◀ Prev")).toBeDisabled(); }); test("next button is disabled on last phase", () => { loadProgram([{ id: "phase-1", norms: [], goals: [], triggers: [] }]); render(); expect(screen.getByText("Next ▶")).toBeDisabled(); }); test("prev and next buttons enable/disable correctly when navigating", () => { loadProgram([ { id: "p1", norms: [], goals: [], triggers: [] }, { id: "p2", norms: [], goals: [], triggers: [] }, ]); render(); const prev = screen.getByText("◀ Prev"); const next = screen.getByText("Next ▶"); expect(prev).toBeDisabled(); expect(next).not.toBeDisabled(); fireEvent.click(next); expect(prev).not.toBeDisabled(); expect(next).toBeDisabled(); }); test("renders achieved and unachieved goals with correct icons", () => { loadProgram([ { id: "phase-1", norms: [], goals: [ { id: "g1", description: "Done goal", achieved: true }, { id: "g2", description: "Failed goal", achieved: false }, ], triggers: [], }, ]); render(); expect(screen.getByText("✔")).toBeInTheDocument(); expect(screen.getByText("✖")).toBeInTheDocument(); expect(screen.getByText("Done goal")).toBeInTheDocument(); expect(screen.getByText("Failed goal")).toBeInTheDocument(); }); test("renders fallback labels when optional fields are missing", () => { loadProgram([ { id: "phase-1", norms: [{}], goals: [{}], triggers: [{}], }, ]); render(); expect(screen.getByText("Unnamed norm")).toBeInTheDocument(); expect(screen.getByText("Unnamed goal")).toBeInTheDocument(); expect(screen.getByText("Unnamed trigger")).toBeInTheDocument(); }); test("does not crash when navigating beyond boundaries", () => { loadProgram([ { id: "p1", norms: [], goals: [], triggers: [] }, { id: "p2", norms: [], goals: [], triggers: [] }, ]); render(); fireEvent.click(screen.getByText("Next ▶")); fireEvent.click(screen.getByText("Next ▶")); expect(screen.getByText("Phase 2 / 2")).toBeInTheDocument(); fireEvent.click(screen.getByText("◀ Prev")); fireEvent.click(screen.getByText("◀ Prev")); expect(screen.getByText("Phase 1 / 2")).toBeInTheDocument(); }); });