feat: added tests
ref: N25B-399
This commit is contained in:
@@ -2,8 +2,9 @@ import React from "react";
|
||||
import styles from "./SimpleProgram.module.css";
|
||||
import useProgramStore from "../../utils/programStore.ts";
|
||||
|
||||
/* ---------- Reusable UI ---------- */
|
||||
|
||||
/**
|
||||
* Generic container box with a header and content area.
|
||||
*/
|
||||
type BoxProps = {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
@@ -16,8 +17,10 @@ const Box: React.FC<BoxProps> = ({ title, children }) => (
|
||||
</div>
|
||||
);
|
||||
|
||||
/* ---------- Lists ---------- */
|
||||
|
||||
/**
|
||||
* Renders a list of goals for a phase.
|
||||
* Expects goal-like objects from the program store.
|
||||
*/
|
||||
const GoalList: React.FC<{ goals: unknown[] }> = ({ goals }) => {
|
||||
if (!goals.length) {
|
||||
return <p className={styles.empty}>No goals defined.</p>;
|
||||
@@ -49,6 +52,9 @@ const GoalList: React.FC<{ goals: unknown[] }> = ({ goals }) => {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a list of triggers for a phase.
|
||||
*/
|
||||
const TriggerList: React.FC<{ triggers: unknown[] }> = ({ triggers }) => {
|
||||
if (!triggers.length) {
|
||||
return <p className={styles.empty}>No triggers defined.</p>;
|
||||
@@ -73,6 +79,9 @@ const TriggerList: React.FC<{ triggers: unknown[] }> = ({ triggers }) => {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a list of norms for a phase.
|
||||
*/
|
||||
const NormList: React.FC<{ norms: unknown[] }> = ({ norms }) => {
|
||||
if (!norms.length) {
|
||||
return <p className={styles.empty}>No norms defined.</p>;
|
||||
@@ -92,8 +101,9 @@ const NormList: React.FC<{ norms: unknown[] }> = ({ norms }) => {
|
||||
);
|
||||
};
|
||||
|
||||
/* ---------- Phase Grid ---------- */
|
||||
|
||||
/**
|
||||
* Displays all phase-related information in a grid layout.
|
||||
*/
|
||||
type PhaseGridProps = {
|
||||
norms: unknown[];
|
||||
goals: unknown[];
|
||||
@@ -104,31 +114,31 @@ const PhaseGrid: React.FC<PhaseGridProps> = ({
|
||||
norms,
|
||||
goals,
|
||||
triggers,
|
||||
}) => {
|
||||
return (
|
||||
<div className={styles.phaseGrid}>
|
||||
<Box title="Norms">
|
||||
<NormList norms={norms} />
|
||||
</Box>
|
||||
}) => (
|
||||
<div className={styles.phaseGrid}>
|
||||
<Box title="Norms">
|
||||
<NormList norms={norms} />
|
||||
</Box>
|
||||
|
||||
<Box title="Triggers">
|
||||
<TriggerList triggers={triggers} />
|
||||
</Box>
|
||||
<Box title="Triggers">
|
||||
<TriggerList triggers={triggers} />
|
||||
</Box>
|
||||
|
||||
<Box title="Goals">
|
||||
<GoalList goals={goals} />
|
||||
</Box>
|
||||
<Box title="Goals">
|
||||
<GoalList goals={goals} />
|
||||
</Box>
|
||||
|
||||
<Box title="Conditional Norms">
|
||||
<p className={styles.empty}>No conditional norms defined.</p>
|
||||
</Box>
|
||||
{/* Let er dus op dat deze erbij moeten */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/* ---------- Main Component ---------- */
|
||||
<Box title="Conditional Norms">
|
||||
<p className={styles.empty}>No conditional norms defined.</p>
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* Main program viewer.
|
||||
* Reads all data from the program store and allows
|
||||
* navigating between phases.
|
||||
*/
|
||||
const SimpleProgram: React.FC = () => {
|
||||
const getPhaseIds = useProgramStore((s) => s.getPhaseIds);
|
||||
const getNormsInPhase = useProgramStore((s) => s.getNormsInPhase);
|
||||
|
||||
83
test/pages/simpleProgram/SimpleProgram.tsx
Normal file
83
test/pages/simpleProgram/SimpleProgram.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
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<string, unknown>[]) {
|
||||
useProgramStore.getState().setProgramState({ phases });
|
||||
}
|
||||
|
||||
describe("SimpleProgram", () => {
|
||||
beforeEach(() => {
|
||||
loadProgram([]);
|
||||
});
|
||||
|
||||
test("shows empty state when no program is loaded", () => {
|
||||
render(<SimpleProgram />);
|
||||
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(<SimpleProgram />);
|
||||
|
||||
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("allows navigating between phases", () => {
|
||||
loadProgram([
|
||||
{
|
||||
id: "phase-1",
|
||||
norms: [],
|
||||
goals: [],
|
||||
triggers: [],
|
||||
},
|
||||
{
|
||||
id: "phase-2",
|
||||
norms: [{ id: "n2", norm: "Be careful" }],
|
||||
goals: [],
|
||||
triggers: [],
|
||||
},
|
||||
]);
|
||||
|
||||
render(<SimpleProgram />);
|
||||
|
||||
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(<SimpleProgram />);
|
||||
expect(screen.getByText("◀ Prev")).toBeDisabled();
|
||||
});
|
||||
|
||||
test("next button is disabled on last phase", () => {
|
||||
loadProgram([
|
||||
{ id: "phase-1", norms: [], goals: [], triggers: [] },
|
||||
]);
|
||||
|
||||
render(<SimpleProgram />);
|
||||
expect(screen.getByText("Next ▶")).toBeDisabled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user