diff --git a/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx b/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx index 31062b5..c987e8d 100644 --- a/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx +++ b/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx @@ -7,10 +7,12 @@ import GlobalSearchBar from '../GlobalSearchBar'; import { documentService } from '../../../services/api'; // Mock the API service +const mockDocumentService = { + enhancedSearch: vi.fn(), +}; + vi.mock('../../../services/api', () => ({ - documentService: { - enhancedSearch: vi.fn(), - } + documentService: mockDocumentService, })); // Mock useNavigate @@ -76,7 +78,7 @@ describe('GlobalSearchBar', () => { beforeEach(() => { vi.clearAllMocks(); localStorageMock.getItem.mockReturnValue(null); - (documentService.enhancedSearch as any).mockResolvedValue(mockSearchResponse); + mockDocumentService.enhancedSearch.mockResolvedValue(mockSearchResponse); }); test('renders search input with placeholder', () => { @@ -265,7 +267,7 @@ describe('GlobalSearchBar', () => { test('shows "View all results" link when there are many results', async () => { // Mock response with 5 or more results to trigger the link - (documentService.enhancedSearch as any).mockResolvedValue({ + mockDocumentService.enhancedSearch.mockResolvedValue({ data: { documents: Array.from({ length: 5 }, (_, i) => ({ id: `${i + 1}`, diff --git a/frontend/src/components/MimeTypeFacetFilter/MimeTypeFacetFilter.tsx b/frontend/src/components/MimeTypeFacetFilter/MimeTypeFacetFilter.tsx index c0c7f10..a4ca2b7 100644 --- a/frontend/src/components/MimeTypeFacetFilter/MimeTypeFacetFilter.tsx +++ b/frontend/src/components/MimeTypeFacetFilter/MimeTypeFacetFilter.tsx @@ -104,9 +104,10 @@ const MimeTypeFacetFilter: React.FC = ({ try { setLoading(true); const response = await documentService.getFacets(); - setFacets(response.data.mime_types); + setFacets(response.data.mime_types || []); } catch (error) { console.error('Failed to load facets:', error); + setFacets([]); } finally { setLoading(false); } @@ -170,7 +171,7 @@ const MimeTypeFacetFilter: React.FC = ({ } }; - const filteredFacets = facets.filter(facet => + const filteredFacets = (facets || []).filter(facet => searchTerm === '' || facet.value.toLowerCase().includes(searchTerm.toLowerCase()) || getMimeTypeLabel(facet.value).toLowerCase().includes(searchTerm.toLowerCase()) diff --git a/frontend/src/pages/__tests__/SearchPage.integration.test.tsx b/frontend/src/pages/__tests__/SearchPage.integration.test.tsx index 24b19c5..009057d 100644 --- a/frontend/src/pages/__tests__/SearchPage.integration.test.tsx +++ b/frontend/src/pages/__tests__/SearchPage.integration.test.tsx @@ -6,13 +6,15 @@ import SearchPage from '../SearchPage'; import { documentService } from '../../services/api'; // Mock the document service +const mockDocumentService = { + search: vi.fn(), + enhancedSearch: vi.fn(), + getFacets: vi.fn(), + download: vi.fn(), +}; + vi.mock('../../services/api', () => ({ - documentService: { - search: vi.fn(), - enhancedSearch: vi.fn(), - getFacets: vi.fn(), - download: vi.fn(), - }, + documentService: mockDocumentService, })); const mockSearchResponse = { @@ -87,9 +89,9 @@ const renderSearchPage = () => { describe('SearchPage Integration Tests', () => { beforeEach(() => { vi.clearAllMocks(); - (documentService.enhancedSearch as any).mockResolvedValue(mockSearchResponse); - (documentService.search as any).mockResolvedValue(mockSearchResponse); - (documentService.getFacets as any).mockResolvedValue(mockFacetsResponse); + mockDocumentService.enhancedSearch.mockResolvedValue(mockSearchResponse); + mockDocumentService.search.mockResolvedValue(mockSearchResponse); + mockDocumentService.getFacets.mockResolvedValue(mockFacetsResponse); }); test('performs complete search workflow', async () => { @@ -102,7 +104,7 @@ describe('SearchPage Integration Tests', () => { }); // Enter search query - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Wait for search results @@ -137,7 +139,7 @@ describe('SearchPage Integration Tests', () => { }); // Enter search query first - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Wait for initial results @@ -187,7 +189,7 @@ describe('SearchPage Integration Tests', () => { await user.click(screen.getByText('Long (400 chars)')); // Perform search - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Verify advanced settings are applied @@ -207,7 +209,7 @@ describe('SearchPage Integration Tests', () => { renderSearchPage(); // Perform search - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Wait for results with snippets @@ -245,7 +247,7 @@ describe('SearchPage Integration Tests', () => { await user.click(exampleButtons[0]); // Verify search input is populated - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); expect(searchInput).toHaveValue('invoice'); // Verify search is triggered @@ -264,7 +266,7 @@ describe('SearchPage Integration Tests', () => { renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Should show error message @@ -278,7 +280,7 @@ describe('SearchPage Integration Tests', () => { renderSearchPage(); // Perform search first - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Wait for results @@ -299,7 +301,7 @@ describe('SearchPage Integration Tests', () => { const user = userEvent.setup(); renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Wait for suggestions to appear @@ -327,7 +329,7 @@ describe('SearchPage Integration Tests', () => { }); // Enter search query - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Apply PDF filter @@ -388,10 +390,10 @@ describe('SearchPage Integration Tests', () => { }, }; - (documentService.enhancedSearch as any).mockResolvedValue(emptyResponse); + mockDocumentService.enhancedSearch.mockResolvedValue(emptyResponse); renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'nonexistent'); await waitFor(() => { @@ -403,7 +405,7 @@ describe('SearchPage Integration Tests', () => { const user = userEvent.setup(); renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Verify URL is updated (this would require checking window.location or using a memory router) @@ -416,15 +418,15 @@ describe('SearchPage Integration Tests', () => { describe('SearchPage Performance Tests', () => { beforeEach(() => { vi.clearAllMocks(); - (documentService.enhancedSearch as any).mockResolvedValue(mockSearchResponse); - (documentService.getFacets as any).mockResolvedValue(mockFacetsResponse); + mockDocumentService.enhancedSearch.mockResolvedValue(mockSearchResponse); + mockDocumentService.getFacets.mockResolvedValue(mockFacetsResponse); }); test('debounces search input to avoid excessive API calls', async () => { const user = userEvent.setup(); renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); // Type quickly await user.type(searchInput, 'invoice', { delay: 50 }); @@ -452,7 +454,7 @@ describe('SearchPage Performance Tests', () => { renderSearchPage(); - const searchInput = screen.getByPlaceholderText(/search your documents/i); + const searchInput = screen.getByPlaceholderText(/search documents/i); await user.type(searchInput, 'invoice'); // Should show loading indicator diff --git a/frontend/src/pages/__tests__/SearchPage.test.tsx b/frontend/src/pages/__tests__/SearchPage.test.tsx index 212b31a..008224a 100644 --- a/frontend/src/pages/__tests__/SearchPage.test.tsx +++ b/frontend/src/pages/__tests__/SearchPage.test.tsx @@ -6,12 +6,14 @@ import SearchPage from '../SearchPage'; import { documentService } from '../../services/api'; // Mock the API service +const mockDocumentService = { + enhancedSearch: vi.fn(), + search: vi.fn(), + download: vi.fn(), +}; + vi.mock('../../services/api', () => ({ - documentService: { - enhancedSearch: vi.fn(), - search: vi.fn(), - download: vi.fn(), - } + documentService: mockDocumentService, })); // Mock SearchGuidance component @@ -79,8 +81,8 @@ const renderWithRouter = (component) => { describe('SearchPage', () => { beforeEach(() => { vi.clearAllMocks(); - (documentService.enhancedSearch as any).mockResolvedValue(mockSearchResponse); - (documentService.search as any).mockResolvedValue(mockSearchResponse); + mockDocumentService.enhancedSearch.mockResolvedValue(mockSearchResponse); + mockDocumentService.search.mockResolvedValue(mockSearchResponse); }); test('renders search page with prominent search bar', () => { @@ -387,7 +389,7 @@ describe('SearchPage', () => { test('handles document download', async () => { const user = userEvent.setup(); const mockBlob = new Blob(['test content'], { type: 'application/pdf' }); - (documentService.download as any).mockResolvedValue({ data: mockBlob }); + mockDocumentService.download.mockResolvedValue({ data: mockBlob }); // Mock URL.createObjectURL global.URL.createObjectURL = vi.fn(() => 'mock-url'); @@ -516,7 +518,7 @@ describe('Enhanced Search Features', () => { const user = userEvent.setup(); // Mock empty response - (documentService.enhancedSearch as any).mockResolvedValue({ + mockDocumentService.enhancedSearch.mockResolvedValue({ data: { documents: [], total: 0,