feat: move waiting_for_input badge from Inbox to HQ nav, remove Inbox entry
Badge showing agents in waiting_for_input status now appears on HQ nav item. Inbox link removed from the nav. Adds regression test for navItems structure.
This commit is contained in:
66
apps/web/src/layouts/AppLayout.test.tsx
Normal file
66
apps/web/src/layouts/AppLayout.test.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
import { render, screen, within } from '@testing-library/react'
|
||||||
|
import '@testing-library/jest-dom/vitest'
|
||||||
|
import { vi } from 'vitest'
|
||||||
|
import { AppLayout } from './AppLayout'
|
||||||
|
|
||||||
|
// Mock dependencies
|
||||||
|
vi.mock('@tanstack/react-router', () => ({
|
||||||
|
Link: ({ children, to }: any) => {
|
||||||
|
const content = typeof children === 'function' ? children({ isActive: false }) : children
|
||||||
|
return <a href={to}>{content}</a>
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
vi.mock('@/components/ThemeToggle', () => ({ ThemeToggle: () => null }))
|
||||||
|
vi.mock('@/components/HealthDot', () => ({ HealthDot: () => null }))
|
||||||
|
vi.mock('@/components/NavBadge', () => ({
|
||||||
|
NavBadge: ({ count }: { count: number }) => (
|
||||||
|
count > 0 ? <span data-testid="nav-badge">{count}</span> : null
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const mockUseQuery = vi.hoisted(() => vi.fn())
|
||||||
|
vi.mock('@/lib/trpc', () => ({
|
||||||
|
trpc: {
|
||||||
|
listAgents: { useQuery: mockUseQuery },
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
mockUseQuery.mockReturnValue({ data: [] })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('AppLayout navItems', () => {
|
||||||
|
it('renders HQ nav link', () => {
|
||||||
|
render(<AppLayout connectionState="connected">{null}</AppLayout>)
|
||||||
|
expect(screen.getByRole('link', { name: /hq/i })).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not render Inbox nav link', () => {
|
||||||
|
render(<AppLayout connectionState="connected">{null}</AppLayout>)
|
||||||
|
expect(screen.queryByRole('link', { name: /inbox/i })).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows badge on HQ when agents are waiting_for_input', () => {
|
||||||
|
mockUseQuery.mockReturnValue({
|
||||||
|
data: [
|
||||||
|
{ id: '1', status: 'waiting_for_input' },
|
||||||
|
{ id: '2', status: 'running' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
render(<AppLayout connectionState="connected">{null}</AppLayout>)
|
||||||
|
// NavBadge rendered next to HQ link (count=1)
|
||||||
|
const hqLink = screen.getByRole('link', { name: /hq/i })
|
||||||
|
const badge = within(hqLink).getByTestId('nav-badge')
|
||||||
|
expect(badge).toHaveTextContent('1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not show questions badge on any Inbox link (Inbox removed)', () => {
|
||||||
|
mockUseQuery.mockReturnValue({
|
||||||
|
data: [{ id: '1', status: 'waiting_for_input' }],
|
||||||
|
})
|
||||||
|
render(<AppLayout connectionState="connected">{null}</AppLayout>)
|
||||||
|
expect(screen.queryByRole('link', { name: /inbox/i })).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -7,11 +7,10 @@ import { trpc } from '@/lib/trpc'
|
|||||||
import type { ConnectionState } from '@/hooks/useConnectionStatus'
|
import type { ConnectionState } from '@/hooks/useConnectionStatus'
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ label: 'HQ', to: '/hq', badgeKey: null },
|
{ label: 'HQ', to: '/hq', badgeKey: 'questions' as const },
|
||||||
{ label: 'Initiatives', to: '/initiatives', badgeKey: null },
|
{ label: 'Initiatives', to: '/initiatives', badgeKey: null },
|
||||||
{ label: 'Agents', to: '/agents', badgeKey: 'running' as const },
|
{ label: 'Agents', to: '/agents', badgeKey: 'running' as const },
|
||||||
{ label: 'Radar', to: '/radar', badgeKey: null },
|
{ label: 'Radar', to: '/radar', badgeKey: null },
|
||||||
{ label: 'Inbox', to: '/inbox', badgeKey: 'questions' as const },
|
|
||||||
{ label: 'Settings', to: '/settings', badgeKey: null },
|
{ label: 'Settings', to: '/settings', badgeKey: null },
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user