Add component tests for P3.11 (82 tests across 5 files)
- DecisionCard tests: 11 tests covering rendering, status icons, styling - DataPanel tests: 18 tests covering biometrics display, null handling, styling - NutritionPanel tests: 12 tests covering seeds, carbs, keto guidance display - OverrideToggles tests: 18 tests covering toggle states, callbacks, styling - DayCell tests: 23 tests covering phase coloring, today highlighting, click handling Total tests now: 707 passing across 40 test files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
166
src/components/dashboard/decision-card.test.tsx
Normal file
166
src/components/dashboard/decision-card.test.tsx
Normal file
@@ -0,0 +1,166 @@
|
||||
// ABOUTME: Unit tests for DecisionCard component.
|
||||
// ABOUTME: Tests rendering of decision status, icon, and reason.
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { Decision } from "@/types";
|
||||
import { DecisionCard } from "./decision-card";
|
||||
|
||||
describe("DecisionCard", () => {
|
||||
describe("rendering", () => {
|
||||
it("renders the decision icon", () => {
|
||||
const decision: Decision = {
|
||||
status: "REST",
|
||||
reason: "Your body needs recovery today",
|
||||
icon: "🛌",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("🛌")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the decision status", () => {
|
||||
const decision: Decision = {
|
||||
status: "TRAIN",
|
||||
reason: "Good to go",
|
||||
icon: "🏃",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("TRAIN")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the decision reason", () => {
|
||||
const decision: Decision = {
|
||||
status: "GENTLE",
|
||||
reason: "Take it easy today",
|
||||
icon: "🧘",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("Take it easy today")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("different status types", () => {
|
||||
it("renders REST status correctly", () => {
|
||||
const decision: Decision = {
|
||||
status: "REST",
|
||||
reason: "HRV unbalanced - recovery day",
|
||||
icon: "🛌",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("REST")).toBeInTheDocument();
|
||||
expect(screen.getByText("🛌")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("HRV unbalanced - recovery day"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders GENTLE status correctly", () => {
|
||||
const decision: Decision = {
|
||||
status: "GENTLE",
|
||||
reason: "Light movement recommended",
|
||||
icon: "🧘",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("GENTLE")).toBeInTheDocument();
|
||||
expect(screen.getByText("🧘")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("Light movement recommended"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders LIGHT status correctly", () => {
|
||||
const decision: Decision = {
|
||||
status: "LIGHT",
|
||||
reason: "Keep intensity moderate",
|
||||
icon: "🚶",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("LIGHT")).toBeInTheDocument();
|
||||
expect(screen.getByText("🚶")).toBeInTheDocument();
|
||||
expect(screen.getByText("Keep intensity moderate")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders REDUCED status correctly", () => {
|
||||
const decision: Decision = {
|
||||
status: "REDUCED",
|
||||
reason: "Lower intensity today",
|
||||
icon: "⬇️",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("REDUCED")).toBeInTheDocument();
|
||||
expect(screen.getByText("⬇️")).toBeInTheDocument();
|
||||
expect(screen.getByText("Lower intensity today")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders TRAIN status correctly", () => {
|
||||
const decision: Decision = {
|
||||
status: "TRAIN",
|
||||
reason: "Full intensity training approved",
|
||||
icon: "🏃",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
expect(screen.getByText("TRAIN")).toBeInTheDocument();
|
||||
expect(screen.getByText("🏃")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("Full intensity training approved"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("styling", () => {
|
||||
it("renders within a bordered container", () => {
|
||||
const decision: Decision = {
|
||||
status: "REST",
|
||||
reason: "Test reason",
|
||||
icon: "🛌",
|
||||
};
|
||||
|
||||
const { container } = render(<DecisionCard decision={decision} />);
|
||||
|
||||
const card = container.firstChild as HTMLElement;
|
||||
expect(card).toHaveClass("rounded-lg", "border", "p-6");
|
||||
});
|
||||
|
||||
it("renders status as bold heading", () => {
|
||||
const decision: Decision = {
|
||||
status: "TRAIN",
|
||||
reason: "Test",
|
||||
icon: "🏃",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
const heading = screen.getByRole("heading", { level: 2 });
|
||||
expect(heading).toHaveTextContent("TRAIN");
|
||||
expect(heading).toHaveClass("font-bold");
|
||||
});
|
||||
|
||||
it("renders reason with muted color", () => {
|
||||
const decision: Decision = {
|
||||
status: "REST",
|
||||
reason: "Muted reason text",
|
||||
icon: "🛌",
|
||||
};
|
||||
|
||||
render(<DecisionCard decision={decision} />);
|
||||
|
||||
const reason = screen.getByText("Muted reason text");
|
||||
expect(reason).toHaveClass("text-gray-600");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user