import type { ReviewCard } from "$lib/model"; import { cleanup, fireEvent, render, screen } from "@solidjs/testing-library"; import { afterEach, describe, expect, it, vi } from "vitest"; import { StudySession } from "../StudySession"; vi.mock( "$lib/api", () => ({ api: { submitReview: vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({}) }) } }), ); const mockCards: ReviewCard[] = [{ review_id: "review-1", card_id: "card-1", deck_id: "deck-1", deck_title: "Test Deck", front: "What is 2+2?", back: "4", media_url: undefined, hints: [], due_at: new Date().toISOString(), }, { review_id: "review-2", card_id: "card-2", deck_id: "deck-1", deck_title: "Test Deck", front: "What is the capital of France?", back: "Paris", media_url: undefined, hints: ["It's a famous city"], due_at: new Date().toISOString(), }]; describe("StudySession", () => { afterEach(cleanup); it("renders card front initially", () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); expect(screen.getByText("What is 2+2?")).toBeInTheDocument(); expect(screen.getByText("Press Space or click to reveal")).toBeInTheDocument(); }); it("shows progress indicator", () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); expect(screen.getByText(/Card 1 of 2/i)).toBeInTheDocument(); }); it("flips card on click", async () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); expect(screen.getByText("What is 2+2?")).toBeInTheDocument(); const cardElement = screen.getByText("What is 2+2?").closest("div[class*='cursor-pointer']"); if (cardElement) { fireEvent.click(cardElement); } expect(await screen.findByText("How well did you know this?")).toBeInTheDocument(); }); it("flips back to front on second click", async () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); const cardElement = screen.getByText("What is 2+2?").closest("div[class*='cursor-pointer']"); if (cardElement) fireEvent.click(cardElement); expect(await screen.findByText("How well did you know this?")).toBeInTheDocument(); if (cardElement) fireEvent.click(cardElement); expect(await screen.findByText("Press Space or click to reveal")).toBeInTheDocument(); expect(screen.queryByText("How well did you know this?")).not.toBeInTheDocument(); }); it("shows keyboard hints conditionally", async () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); expect(screen.getByText("Space: Flip")).toBeInTheDocument(); expect(screen.getByText("Esc: Exit")).toBeInTheDocument(); // Initially hidden expect(screen.queryByText("1-6: Grade")).not.toBeInTheDocument(); expect(screen.queryByText("E: Edit")).not.toBeInTheDocument(); // Flip card const cardElement = screen.getByText("What is 2+2?").closest("div[class*='cursor-pointer']"); if (cardElement) fireEvent.click(cardElement); // Now visible expect(await screen.findByText("1-6: Grade")).toBeInTheDocument(); expect(screen.getByText("E: Edit")).toBeInTheDocument(); }); it("calls onExit when exit button is clicked", () => { const onComplete = vi.fn(); const onExit = vi.fn(); render(() => ); const exitButton = screen.getByRole("button", { name: /✕ Exit/i }); fireEvent.click(exitButton); expect(onExit).toHaveBeenCalled(); }); });