// @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')
})
})