import { fireEvent, render, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { MedDetailModal } from "../../components/MedDetailModal"; import type { Coverage, Medication, RefillEntry, StockThresholds } from "../../types"; const defaultSettings: StockThresholds = { lowStockDays: 7, normalStockDays: 30, highStockDays: 90, }; const mockMedication: Medication = { id: 1, name: "Test Med", genericName: "Generic Name", packCount: 1, blistersPerPack: 1, pillsPerBlister: 30, looseTablets: 0, takenBy: ["John"], blisters: [{ usage: 1, every: 1, start: "2024-01-01T09:00:00" }], updatedAt: null, expiryDate: "2025-12-31", notes: "Test notes", }; const mockCoverage: Coverage = { name: "Test Med", medsLeft: 25, daysLeft: 25, depletionDate: "2024-04-01", depletionTime: Date.now() + 25 * 86400000, nextDose: null, }; const defaultProps = { selectedMed: mockMedication, coverage: { all: [mockCoverage] }, settings: defaultSettings, showImageLightbox: false, showRefillModal: false, showEditStockModal: false, onClose: vi.fn(), onOpenImageLightbox: vi.fn(), onCloseImageLightbox: vi.fn(), onOpenRefillModal: vi.fn(), onCloseRefillModal: vi.fn(), onOpenEditStockModal: vi.fn(), onCloseEditStockModal: vi.fn(), refillPacks: 0, onRefillPacksChange: vi.fn(), refillLoose: 0, onRefillLooseChange: vi.fn(), refillSaving: false, refillHistory: [] as RefillEntry[], refillHistoryExpanded: false, onRefillHistoryExpandedChange: vi.fn(), onSubmitRefill: vi.fn(), editStockFullBlisters: 0, onEditStockFullBlistersChange: vi.fn(), editStockPartialBlisterPills: 0, onEditStockPartialBlisterPillsChange: vi.fn(), editStockSaving: false, onSubmitStockCorrection: vi.fn(), }; describe("MedDetailModal", () => { beforeEach(() => { vi.clearAllMocks(); }); it("renders nothing when selectedMed is null", () => { render(); expect(screen.queryByText("Test Med")).not.toBeInTheDocument(); }); it("renders modal when medication is selected", () => { render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); it("displays medication name", () => { render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); it("displays generic name", () => { render(); expect(screen.getByText("Generic Name")).toBeInTheDocument(); }); it("renders close button", () => { render(); const closeBtn = screen.getByText("×"); expect(closeBtn).toBeInTheDocument(); }); it("calls onClose when close button clicked", () => { const onClose = vi.fn(); render(); const closeBtn = screen.getByText("×"); fireEvent.click(closeBtn); expect(onClose).toHaveBeenCalledTimes(1); }); it("calls onClose when overlay clicked", () => { const onClose = vi.fn(); render(); const overlay = document.querySelector(".modal-overlay"); if (overlay) { fireEvent.click(overlay); } expect(onClose).toHaveBeenCalledTimes(1); }); it("does not call onClose when modal content clicked", () => { const onClose = vi.fn(); render(); const content = document.querySelector(".modal-content"); if (content) { fireEvent.click(content); } expect(onClose).not.toHaveBeenCalled(); }); it("displays notes when available", () => { render(); expect(screen.getByText("Test notes")).toBeInTheDocument(); }); it("displays schedule information", () => { render(); // Should have schedule section const scheduleSection = document.querySelector(".med-detail-schedules"); expect(scheduleSection).toBeInTheDocument(); }); it("renders med detail header", () => { render(); const header = document.querySelector(".med-detail-header"); expect(header).toBeInTheDocument(); }); it("renders med detail body", () => { render(); const body = document.querySelector(".med-detail-body"); expect(body).toBeInTheDocument(); }); }); describe("MedDetailModal without coverage", () => { beforeEach(() => { vi.clearAllMocks(); }); it("works without coverage data", () => { render(); // Should still render the medication name expect(screen.getByText("Test Med")).toBeInTheDocument(); }); }); describe("MedDetailModal without optional fields", () => { beforeEach(() => { vi.clearAllMocks(); }); it("works without generic name", () => { const med = { ...mockMedication, genericName: null }; render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); it("works without notes", () => { const med = { ...mockMedication, notes: null }; render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); it("works without takenBy", () => { const med = { ...mockMedication, takenBy: [] }; render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); it("works without expiryDate", () => { const med = { ...mockMedication, expiryDate: null }; render(); expect(screen.getByText("Test Med")).toBeInTheDocument(); }); }); describe("MedDetailModal with refill modal", () => { beforeEach(() => { vi.clearAllMocks(); }); it("shows refill modal when open", () => { render(); // Modal should show refill section const modal = document.querySelector(".modal-overlay"); expect(modal).toBeInTheDocument(); }); it("calls onCloseRefillModal when refill modal closed", () => { const onCloseRefillModal = vi.fn(); render(); // Modal close button const closeButtons = document.querySelectorAll("button"); const cancelBtn = Array.from(closeButtons).find( (btn) => btn.textContent?.includes("cancel") || btn.textContent?.includes("Cancel") ); if (cancelBtn) { fireEvent.click(cancelBtn); } }); it("calls onSubmitRefill when refill submitted", () => { const onSubmitRefill = vi.fn(); render(); const submitBtns = document.querySelectorAll("button"); const submitBtn = Array.from(submitBtns).find( (btn) => btn.textContent?.includes("refill") || btn.textContent?.includes("submit") ); if (submitBtn) { fireEvent.click(submitBtn); } }); }); describe("MedDetailModal actions", () => { beforeEach(() => { vi.clearAllMocks(); }); it("renders action buttons", () => { render(); const buttons = document.querySelectorAll("button"); expect(buttons.length).toBeGreaterThan(0); }); it("calls onOpenRefillModal when refill clicked", () => { const onOpenRefillModal = vi.fn(); render(); const buttons = document.querySelectorAll("button"); const refillBtn = Array.from(buttons).find( (btn) => btn.textContent?.includes("refill") || btn.textContent?.includes("Refill") ); if (refillBtn) { fireEvent.click(refillBtn); expect(onOpenRefillModal).toHaveBeenCalled(); } }); }); describe("MedDetailModal with multiple blisters", () => { beforeEach(() => { vi.clearAllMocks(); }); it("renders multiple schedule entries", () => { const med = { ...mockMedication, blisters: [ { usage: 1, every: 1, start: "2024-01-01T09:00:00" }, { usage: 2, every: 7, start: "2024-01-01T20:00:00" }, ], }; render(); const _scheduleEntries = document.querySelectorAll(".schedule-entry"); // Should have multiple schedule entries }); }); describe("MedDetailModal with image", () => { beforeEach(() => { vi.clearAllMocks(); }); it("renders medication avatar", () => { render(); const avatar = document.querySelector(".med-avatar"); expect(avatar).toBeInTheDocument(); }); it("shows lightbox when image clicked", () => { const onOpenImageLightbox = vi.fn(); const med = { ...mockMedication, imageUrl: "test-image.jpg" }; render(); const avatar = document.querySelector(".med-avatar"); if (avatar) { fireEvent.click(avatar); } }); }); describe("MedDetailModal with low stock", () => { beforeEach(() => { vi.clearAllMocks(); }); it("shows stock status for low stock", () => { const lowCoverage: Coverage = { name: "Test Med", medsLeft: 3, daysLeft: 3, depletionDate: "2024-01-05", depletionTime: Date.now() + 3 * 86400000, nextDose: null, }; render(); // Should render status indicator const _statusElements = document.querySelectorAll(".danger, .warning, .success"); // Status should be visible }); }); describe("MedDetailModal with refill history", () => { beforeEach(() => { vi.clearAllMocks(); }); it("shows refill history when expanded", () => { const refillHistory: RefillEntry[] = [ { id: 1, medicationId: 1, timestamp: new Date().toISOString(), packsAdded: 1, looseAdded: 0 }, ]; render(); // Refill history should be visible const modal = document.querySelector(".modal-overlay"); expect(modal).toBeInTheDocument(); }); it("calls onRefillHistoryExpandedChange when toggle clicked", () => { const onRefillHistoryExpandedChange = vi.fn(); const refillHistory: RefillEntry[] = [ { id: 1, medicationId: 1, timestamp: new Date().toISOString(), packsAdded: 1, looseAdded: 0 }, ]; render( ); // Click expand toggle if exists const expandButton = document.querySelector('[class*="expand"], [class*="toggle"]'); if (expandButton) { fireEvent.click(expandButton); } }); });