/** * Tests for AgentInfoPanel merge_conflict status handling * Verifies that merge_conflict status is treated like backlog for: * - shouldFetchData (no polling for merge_conflict features) * - Rendering path (shows model/preset info like backlog) */ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { AgentInfoPanel } from '../../../src/components/views/board-view/components/kanban-card/agent-info-panel'; import { useAppStore } from '@automaker/ui/store/app-store'; import { useFeature, useAgentOutput } from '@automaker/ui/hooks/queries'; import { getElectronAPI } from '@automaker/ui/lib/electron'; import type { ReactNode } from 'react'; // Mock dependencies vi.mock('@automaker/ui/store/app-store'); vi.mock('@automaker/ui/hooks/queries'); vi.mock('@automaker/ui/lib/electron'); const mockUseAppStore = vi.mocked(useAppStore); const mockUseFeature = vi.mocked(useFeature); const mockUseAgentOutput = vi.mocked(useAgentOutput); const mockGetElectronAPI = vi.mocked(getElectronAPI); function createWrapper() { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); return function Wrapper({ children }: { children: ReactNode }) { return {children}; }; } describe('AgentInfoPanel - merge_conflict status', () => { const createMockFeature = (overrides = {}) => ({ id: 'feature-merge-test', title: 'Test Feature', description: 'Test feature', status: 'merge_conflict', model: 'claude-sonnet-4-5', providerId: undefined, ...overrides, }); beforeEach(() => { vi.clearAllMocks(); mockUseAppStore.mockImplementation((selector) => { const state = { claudeCompatibleProviders: [], }; return selector(state); }); mockUseFeature.mockReturnValue({ data: null, isLoading: false, } as ReturnType); mockUseAgentOutput.mockReturnValue({ data: null, isLoading: false, } as ReturnType); mockGetElectronAPI.mockReturnValue(null); }); it('should render model info for merge_conflict features (like backlog)', () => { const feature = createMockFeature({ status: 'merge_conflict' }); render(, { wrapper: createWrapper(), }); // merge_conflict features should show model name like backlog expect(screen.getByText('Sonnet 4.5')).toBeInTheDocument(); }); it('should render model info for backlog features (baseline comparison)', () => { const feature = createMockFeature({ status: 'backlog' }); render(, { wrapper: createWrapper(), }); expect(screen.getByText('Sonnet 4.5')).toBeInTheDocument(); }); it('should show provider-aware model name for merge_conflict features', () => { mockUseAppStore.mockImplementation((selector) => { const state = { claudeCompatibleProviders: [ { id: 'moonshot-ai', name: 'Moonshot AI', models: [{ id: 'claude-sonnet-4-5', displayName: 'Moonshot v1.8' }], }, ], }; return selector(state); }); const feature = createMockFeature({ status: 'merge_conflict', model: 'claude-sonnet-4-5', providerId: 'moonshot-ai', }); render(, { wrapper: createWrapper(), }); expect(screen.getByText('Moonshot v1.8')).toBeInTheDocument(); }); it('should not pass isActivelyRunning polling for merge_conflict features', () => { const feature = createMockFeature({ status: 'merge_conflict' }); // Render without isActivelyRunning (merge_conflict features should not be polled) render(, { wrapper: createWrapper(), }); // useFeature and useAgentOutput should have been called but with shouldFetchData=false behavior // The key indicator is that the component renders the backlog-like model info view expect(screen.getByText('Sonnet 4.5')).toBeInTheDocument(); }); it('should show thinking level for merge_conflict Claude features', () => { const feature = createMockFeature({ status: 'merge_conflict', model: 'claude-sonnet-4-5', thinkingLevel: 'high', }); render(, { wrapper: createWrapper(), }); expect(screen.getByText('Sonnet 4.5')).toBeInTheDocument(); // ThinkingLevel indicator should be visible expect(screen.getByText('High')).toBeInTheDocument(); }); });