// @vitest-environment happy-dom import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { vi, describe, it, expect, beforeEach } from 'vitest' const mockNavigate = vi.fn() vi.mock('@tanstack/react-router', () => ({ useNavigate: () => mockNavigate, Link: ({ to, children, className }: { to: string; children: React.ReactNode; className?: string }) => ( {children} ), })) // Mock formatRelativeTime to return a predictable string vi.mock('@/lib/utils', () => ({ cn: (...classes: string[]) => classes.filter(Boolean).join(' '), formatRelativeTime: () => '5 minutes ago', })) import { HQNeedsReviewSection } from './HQNeedsReviewSection' import { HQNeedsApprovalSection } from './HQNeedsApprovalSection' import { HQResolvingConflictsSection } from './HQResolvingConflictsSection' import { HQBlockedSection } from './HQBlockedSection' import { HQEmptyState } from './HQEmptyState' const since = new Date(Date.now() - 5 * 60 * 1000).toISOString() // ─── HQNeedsReviewSection ──────────────────────────────────────────────────── describe('HQNeedsReviewSection', () => { beforeEach(() => vi.clearAllMocks()) it('renders section heading "Needs Review"', () => { render() expect(screen.getByText('Needs Review')).toBeInTheDocument() }) it('2a: shows initiative name, "Content ready for review", "Review" CTA navigates correctly', () => { render( ) expect(screen.getByText('Init One')).toBeInTheDocument() expect(screen.getByText('Content ready for review')).toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: /^review$/i })) expect(mockNavigate).toHaveBeenCalledWith({ to: '/initiatives/$id', params: { id: 'init-1' }, search: { tab: 'review' }, }) }) it('2b: shows initiative › phase, "Phase execution complete — review diff", "Review Diff" navigates correctly', () => { render( ) expect(screen.getByText('Init One › Phase One')).toBeInTheDocument() expect(screen.getByText('Phase execution complete — review diff')).toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: /review diff/i })) expect(mockNavigate).toHaveBeenCalledWith({ to: '/initiatives/$id', params: { id: 'init-1' }, search: { tab: 'review' }, }) }) it('when only initiatives provided, only 2a cards render', () => { render( ) expect(screen.getByText('Content ready for review')).toBeInTheDocument() expect(screen.queryByText('Phase execution complete — review diff')).not.toBeInTheDocument() }) it('when only phases provided, only 2b cards render', () => { render( ) expect(screen.getByText('Phase execution complete — review diff')).toBeInTheDocument() expect(screen.queryByText('Content ready for review')).not.toBeInTheDocument() }) }) // ─── HQNeedsApprovalSection ────────────────────────────────────────────────── describe('HQNeedsApprovalSection', () => { beforeEach(() => vi.clearAllMocks()) it('renders "Needs Approval to Continue" heading', () => { render() expect(screen.getByText('Needs Approval to Continue')).toBeInTheDocument() }) it('shows singular phase count: "1 phase awaiting approval"', () => { render( ) expect(screen.getByText('Plan ready — 1 phase awaiting approval')).toBeInTheDocument() }) it('shows plural phase count: "3 phases awaiting approval"', () => { render( ) expect(screen.getByText('Plan ready — 3 phases awaiting approval')).toBeInTheDocument() }) it('"Review Plan" CTA navigates to /initiatives/$id?tab=plan', () => { render( ) fireEvent.click(screen.getByRole('button', { name: /review plan/i })) expect(mockNavigate).toHaveBeenCalledWith({ to: '/initiatives/$id', params: { id: 'init-1' }, search: { tab: 'plan' }, }) }) }) // ─── HQResolvingConflictsSection ────────────────────────────────────────────── describe('HQResolvingConflictsSection', () => { beforeEach(() => vi.clearAllMocks()) it('renders "Resolving Conflicts" heading', () => { render() expect(screen.getByText('Resolving Conflicts')).toBeInTheDocument() }) it('shows initiative name and "Running" badge for running agent', () => { render( ) expect(screen.getByText('My Initiative')).toBeInTheDocument() expect(screen.getByText('Running')).toBeInTheDocument() }) it('shows "Needs Input" badge for waiting_for_input agent', () => { render( ) expect(screen.getByText('Needs Input')).toBeInTheDocument() }) it('"View" CTA navigates to /initiatives/$id?tab=execution', () => { render( ) fireEvent.click(screen.getByRole('button', { name: /view/i })) expect(mockNavigate).toHaveBeenCalledWith({ to: '/initiatives/$id', params: { id: 'init-1' }, search: { tab: 'execution' }, }) }) }) // ─── HQBlockedSection ──────────────────────────────────────────────────────── describe('HQBlockedSection', () => { beforeEach(() => vi.clearAllMocks()) it('renders "Blocked" heading', () => { render() expect(screen.getByText('Blocked')).toBeInTheDocument() }) it('shows initiative › phase with "Blocked" badge', () => { render( ) expect(screen.getByText('Init One › Phase One')).toBeInTheDocument() // The "Blocked" badge - there will be one in the heading and one in the card const badges = screen.getAllByText('Blocked') expect(badges.length).toBeGreaterThanOrEqual(1) }) it('shows lastMessage when non-null', () => { render( ) expect(screen.getByText('Something went wrong.')).toBeInTheDocument() }) it('omits lastMessage when null', () => { render( ) expect(screen.queryByText('Something went wrong.')).not.toBeInTheDocument() }) it('"View" CTA navigates to /initiatives/$id?tab=execution', () => { render( ) fireEvent.click(screen.getByRole('button', { name: /view/i })) expect(mockNavigate).toHaveBeenCalledWith({ to: '/initiatives/$id', params: { id: 'init-1' }, search: { tab: 'execution' }, }) }) }) // ─── HQEmptyState ──────────────────────────────────────────────────────────── describe('HQEmptyState', () => { it('renders "All clear." text', () => { render() expect(screen.getByText('All clear.')).toBeInTheDocument() }) it('renders "Browse active work" link pointing to /initiatives', () => { render() const link = screen.getByRole('link', { name: /browse active work/i }) expect(link).toBeInTheDocument() expect(link).toHaveAttribute('href', '/initiatives') }) })