import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { FocusCard } from "@/components/FocusCard"; import type { FocusItem } from "@/lib/types"; import { makeFocusItem as makeItem } from "../helpers/fixtures"; /** FocusCard tests use a richer default with context quote and requestedBy set. */ function makeFocusItem(overrides: Partial = {}): FocusItem { return makeItem({ contextQuote: "Can you take a look? I need this for the release tomorrow", requestedBy: "sarah", ...overrides, }); } describe("FocusCard", () => { const onStart = vi.fn(); const onDefer1h = vi.fn(); const onDeferTomorrow = vi.fn(); const onSkip = vi.fn(); beforeEach(() => { vi.clearAllMocks(); }); function renderCard(item: FocusItem = makeFocusItem()) { return render( ); } describe("rendering", () => { it("displays the item title", () => { renderCard(); expect( screen.getByText("Fix authentication token refresh logic") ).toBeInTheDocument(); }); it("displays the type badge", () => { renderCard(); expect(screen.getByText(/MR REVIEW/i)).toBeInTheDocument(); }); it("displays the project path and IID", () => { renderCard(); expect(screen.getByText(/!847/)).toBeInTheDocument(); expect(screen.getByText(/platform\/core/)).toBeInTheDocument(); }); it("displays the context quote when present", () => { renderCard(); expect( screen.getByText(/Can you take a look/) ).toBeInTheDocument(); }); it("displays who requested attention", () => { renderCard(); expect(screen.getByText(/@sarah/)).toBeInTheDocument(); }); it("hides context section when no quote", () => { renderCard(makeFocusItem({ contextQuote: null, requestedBy: null })); expect(screen.queryByText(/@/)).not.toBeInTheDocument(); }); it("shows issue type badge for issues", () => { renderCard(makeFocusItem({ type: "issue", iid: 42 })); expect(screen.getByText(/ISSUE/i)).toBeInTheDocument(); expect(screen.getByText(/#42/)).toBeInTheDocument(); }); it("shows authored MR badge", () => { renderCard(makeFocusItem({ type: "mr_authored" })); expect(screen.getByText(/MR AUTHORED/i)).toBeInTheDocument(); }); }); describe("action buttons", () => { it("calls onStart when Start button is clicked", async () => { const user = userEvent.setup(); renderCard(); await user.click(screen.getByRole("button", { name: /start/i })); expect(onStart).toHaveBeenCalledOnce(); }); it("calls onDefer1h when 1 hour button is clicked", async () => { const user = userEvent.setup(); renderCard(); await user.click(screen.getByRole("button", { name: /1 hour/i })); expect(onDefer1h).toHaveBeenCalledOnce(); }); it("calls onDeferTomorrow when Tomorrow button is clicked", async () => { const user = userEvent.setup(); renderCard(); await user.click(screen.getByRole("button", { name: /tomorrow/i })); expect(onDeferTomorrow).toHaveBeenCalledOnce(); }); it("calls onSkip when Skip button is clicked", async () => { const user = userEvent.setup(); renderCard(); await user.click(screen.getByRole("button", { name: /skip/i })); expect(onSkip).toHaveBeenCalledOnce(); }); }); describe("keyboard shortcuts", () => { it("triggers Start on Enter key", async () => { const user = userEvent.setup(); renderCard(); await user.keyboard("{Enter}"); expect(onStart).toHaveBeenCalledOnce(); }); it("triggers Skip on Cmd+S", async () => { const user = userEvent.setup(); renderCard(); await user.keyboard("{Meta>}s{/Meta}"); expect(onSkip).toHaveBeenCalledOnce(); }); }); }); describe("FocusCard empty state", () => { it("shows empty state message when no item", () => { render( ); expect(screen.getByText(/all clear/i)).toBeInTheDocument(); }); });