diff --git a/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx b/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
index 8e48bd5..20c3a65 100644
--- a/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
+++ b/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
@@ -1,7 +1,23 @@
-import { screen, fireEvent, waitFor } from '@testing-library/react';
import { vi } from 'vitest';
-import Login from '../Login';
-import { renderWithProviders, setupTestEnvironment } from '../../../test/test-utils';
+
+// Mock AuthContext to work with the test setup
+vi.mock('../../../contexts/AuthContext', () => ({
+ useAuth: vi.fn(() => ({
+ user: null,
+ loading: false,
+ login: vi.fn().mockResolvedValue({}),
+ register: vi.fn().mockResolvedValue({}),
+ logout: vi.fn(),
+ })),
+}));
+
+// Mock ThemeContext
+vi.mock('../../../contexts/ThemeContext', () => ({
+ useTheme: () => ({
+ darkMode: false,
+ toggleDarkMode: vi.fn()
+ }),
+}));
// Mock the API
vi.mock('../../../services/api', () => ({
@@ -25,6 +41,11 @@ vi.mock('react-router-dom', async () => {
};
});
+// Now import after all mocks are set up
+import { screen, fireEvent, waitFor } from '@testing-library/react';
+import { renderWithProviders, createMockUser } from '../../../test/test-utils';
+import Login from '../Login';
+
// Mock window.location
Object.defineProperty(window, 'location', {
value: {
@@ -36,7 +57,6 @@ Object.defineProperty(window, 'location', {
describe('Login - OIDC Features', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
});
const renderLogin = () => {
diff --git a/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx b/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
index f54375a..5761384 100644
--- a/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
+++ b/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
@@ -1,20 +1,46 @@
-import { screen, waitFor, fireEvent } from '@testing-library/react';
-import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { vi } from 'vitest';
-import OidcCallback from '../OidcCallback';
-import { renderWithProviders, setupTestEnvironment } from '../../../test/test-utils';
-import { api } from '../../../services/api';
+import React from 'react';
-// Mock the API
-vi.mock('../../../services/api', () => ({
- api: {
- get: vi.fn(),
- defaults: {
- headers: {
- common: {}
- }
+// Create stable mock functions
+const mockLogin = vi.fn().mockResolvedValue({});
+const mockRegister = vi.fn().mockResolvedValue({});
+const mockLogout = vi.fn();
+
+// Mock the auth context module completely
+vi.mock('../../../contexts/AuthContext', () => ({
+ useAuth: vi.fn(() => ({
+ user: null,
+ loading: false,
+ login: mockLogin,
+ register: mockRegister,
+ logout: mockLogout,
+ })),
+ AuthProvider: ({ children }: { children: React.ReactNode }) => React.createElement('div', null, children),
+}));
+
+// Mock axios comprehensively to prevent any real HTTP requests
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../../test/comprehensive-mocks';
+
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Create the mock API object
+const mockApi = {
+ get: vi.fn().mockResolvedValue({ data: { token: 'default-token' } }),
+ post: vi.fn().mockResolvedValue({ data: { success: true } }),
+ put: vi.fn().mockResolvedValue({ data: { success: true } }),
+ delete: vi.fn().mockResolvedValue({ data: { success: true } }),
+ patch: vi.fn().mockResolvedValue({ data: { success: true } }),
+ defaults: {
+ headers: {
+ common: {}
}
}
+};
+
+// Mock the services/api file
+vi.mock('../../../services/api', () => ({
+ api: mockApi,
+ default: mockApi,
}));
// Mock useNavigate
@@ -28,6 +54,11 @@ vi.mock('react-router-dom', async () => {
};
});
+// Now import after mocks
+import { screen, waitFor, fireEvent } from '@testing-library/react';
+import { renderWithProviders } from '../../../test/test-utils';
+import OidcCallback from '../OidcCallback';
+
// Mock window.location
Object.defineProperty(window, 'location', {
value: {
@@ -39,28 +70,29 @@ Object.defineProperty(window, 'location', {
describe('OidcCallback', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
+ vi.resetModules();
window.location.href = '';
// Clear API mocks
- (api.get as any).mockClear();
+ mockApi.get.mockClear();
// Reset API mocks to default implementation
- (api.get as any).mockResolvedValue({ data: { token: 'default-token' } });
+ mockApi.get.mockResolvedValue({ data: { token: 'default-token' } });
});
const renderOidcCallback = (search = '') => {
- return renderWithProviders(
-
-
- } />
- Login Page} />
-
-
- );
+ // Mock the URL search params for the component
+ const url = new URL(`http://localhost/auth/oidc/callback${search}`);
+ Object.defineProperty(window, 'location', {
+ value: { search: url.search },
+ writable: true
+ });
+
+ // Use renderWithProviders to get auth context
+ return renderWithProviders();
};
it('shows loading state initially', async () => {
// Mock the API call to delay so we can see the loading state
- (api.get as any).mockImplementation(() => new Promise(() => {})); // Never resolves
+ mockApi.get.mockImplementation(() => new Promise(() => {})); // Never resolves
renderOidcCallback('?code=test-code&state=test-state');
@@ -80,12 +112,12 @@ describe('OidcCallback', () => {
}
};
- (api.get as any).mockResolvedValueOnce(mockResponse);
+ mockApi.get.mockResolvedValueOnce(mockResponse);
renderOidcCallback('?code=test-code&state=test-state');
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/auth/oidc/callback?code=test-code&state=test-state');
+ expect(mockApi.get).toHaveBeenCalledWith('/auth/oidc/callback?code=test-code&state=test-state');
});
expect(localStorage.setItem).toHaveBeenCalledWith('token', 'test-jwt-token');
@@ -114,7 +146,7 @@ describe('OidcCallback', () => {
}
}
};
- (api.get as any).mockRejectedValueOnce(error);
+ mockApi.get.mockRejectedValueOnce(error);
renderOidcCallback('?code=test-code&state=test-state');
@@ -125,7 +157,7 @@ describe('OidcCallback', () => {
});
it('handles invalid response from server', async () => {
- (api.get as any).mockResolvedValueOnce({
+ mockApi.get.mockResolvedValueOnce({
data: {
// Missing token
user: { id: '123' }
@@ -141,7 +173,7 @@ describe('OidcCallback', () => {
});
it('provides return to login button on error', async () => {
- (api.get as any).mockRejectedValueOnce(new Error('Network error'));
+ mockApi.get.mockRejectedValueOnce(new Error('Network error'));
renderOidcCallback('?code=test-code&state=test-state');
diff --git a/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx b/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx
index 16d9e9e..8ffc886 100644
--- a/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx
+++ b/frontend/src/components/GlobalSearchBar/__tests__/GlobalSearchBar.test.tsx
@@ -1,14 +1,19 @@
-import React from 'react';
-import { screen, fireEvent, waitFor } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
import { vi } from 'vitest';
-import GlobalSearchBar from '../GlobalSearchBar';
-import { renderWithProviders, createMockApiServices, setupTestEnvironment, createMockLocalStorage } from '../../../test/test-utils';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../../test/comprehensive-mocks';
-// Use centralized API mocking
-const mockServices = createMockApiServices();
-const mockDocumentService = mockServices.documentService;
-const localStorageMock = createMockLocalStorage();
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Mock API services comprehensively
+vi.mock('../../../services/api', async () => {
+ const actual = await vi.importActual('../../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ ...apiMocks,
+ };
+});
// Mock useNavigate
const mockNavigate = vi.fn();
@@ -20,6 +25,18 @@ vi.mock('react-router-dom', async () => {
};
});
+// Import after mocking
+import React from 'react';
+import { screen, fireEvent, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import GlobalSearchBar from '../GlobalSearchBar';
+import { renderWithProviders, createMockApiServices, createMockLocalStorage } from '../../../test/test-utils';
+
+// Use centralized API mocking
+const mockServices = createMockApiServices();
+const mockDocumentService = mockServices.documentService;
+const localStorageMock = createMockLocalStorage();
+
// Mock data
const mockSearchResponse = {
data: {
@@ -45,7 +62,6 @@ const mockSearchResponse = {
describe('GlobalSearchBar', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
localStorageMock.getItem.mockReturnValue(null);
mockDocumentService.enhancedSearch.mockResolvedValue(mockSearchResponse);
});
diff --git a/frontend/src/components/Labels/__tests__/Label.test.tsx b/frontend/src/components/Labels/__tests__/Label.test.tsx
index ab82d83..48adfcc 100644
--- a/frontend/src/components/Labels/__tests__/Label.test.tsx
+++ b/frontend/src/components/Labels/__tests__/Label.test.tsx
@@ -4,8 +4,7 @@ import Label, { type LabelData } from '../Label';
import { renderWithProviders } from '../../../test/test-utils';
import {
createMockLabel,
- createMockSystemLabel,
- setupTestEnvironment
+ createMockSystemLabel
} from '../../../test/label-test-utils';
const mockLabel = createMockLabel({
@@ -31,7 +30,7 @@ const renderLabel = (props: Partial> = {}) =>
describe('Label Component', () => {
beforeEach(() => {
- setupTestEnvironment();
+ // Test setup is handled globally
});
describe('Basic Rendering', () => {
diff --git a/frontend/src/components/Labels/__tests__/LabelCreateDialog.test.tsx b/frontend/src/components/Labels/__tests__/LabelCreateDialog.test.tsx
index 6aebc27..9c9bd11 100644
--- a/frontend/src/components/Labels/__tests__/LabelCreateDialog.test.tsx
+++ b/frontend/src/components/Labels/__tests__/LabelCreateDialog.test.tsx
@@ -1,15 +1,17 @@
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
import LabelCreateDialog from '../LabelCreateDialog';
import { type LabelData } from '../Label';
import { renderWithProviders } from '../../../test/test-utils';
import {
createMockLabel,
- setupTestEnvironment,
labelValidationScenarios
} from '../../../test/label-test-utils';
+const theme = createTheme();
+
const mockEditingLabel = createMockLabel({
name: 'Existing Label',
description: 'An existing label',
@@ -33,7 +35,6 @@ describe('LabelCreateDialog Component', () => {
let user: ReturnType;
beforeEach(() => {
- setupTestEnvironment();
user = userEvent.setup();
});
diff --git a/frontend/src/components/Labels/__tests__/LabelSelector.test.tsx b/frontend/src/components/Labels/__tests__/LabelSelector.test.tsx
index d41c7f2..98b3245 100644
--- a/frontend/src/components/Labels/__tests__/LabelSelector.test.tsx
+++ b/frontend/src/components/Labels/__tests__/LabelSelector.test.tsx
@@ -5,7 +5,6 @@ import LabelSelector from '../LabelSelector';
import { type LabelData } from '../Label';
import { renderWithProviders } from '../../../test/test-utils';
import {
- setupTestEnvironment,
testDataBuilders
} from '../../../test/label-test-utils';
@@ -26,7 +25,6 @@ describe('LabelSelector Component', () => {
let user: ReturnType;
beforeEach(() => {
- setupTestEnvironment();
user = userEvent.setup();
});
@@ -81,7 +79,7 @@ describe('LabelSelector Component', () => {
await waitFor(() => {
expect(screen.getByText('Work')).toBeInTheDocument();
- expect(screen.getByText('Personal Project')).toBeInTheDocument();
+ expect(screen.getByText('Project Alpha')).toBeInTheDocument();
});
// Important should not appear in the dropdown options (but may appear in selected tags)
@@ -141,7 +139,7 @@ describe('LabelSelector Component', () => {
test('should remove label when delete button is clicked', async () => {
const onLabelsChange = vi.fn();
// Use only non-system labels since system labels don't have delete buttons
- const selectedLabels = [mockLabels[2]]; // Personal Project (non-system)
+ const selectedLabels = [mockLabels[3]]; // Project Alpha (non-system)
renderLabelSelector({
selectedLabels,
@@ -149,7 +147,7 @@ describe('LabelSelector Component', () => {
});
// Find the chip with the delete button
- const personalProjectChip = screen.getByText('Personal Project').closest('.MuiChip-root');
+ const personalProjectChip = screen.getByText('Project Alpha').closest('.MuiChip-root');
expect(personalProjectChip).toBeInTheDocument();
// Find the delete button within that specific chip
@@ -164,7 +162,7 @@ describe('LabelSelector Component', () => {
});
test('should not show delete buttons when disabled', () => {
- const selectedLabels = [mockLabels[2]]; // Non-system label
+ const selectedLabels = [mockLabels[3]]; // Non-system label
renderLabelSelector({
selectedLabels,
@@ -186,7 +184,7 @@ describe('LabelSelector Component', () => {
// Check that labels appear in the dropdown
expect(screen.getByText('Important')).toBeInTheDocument();
expect(screen.getByText('Work')).toBeInTheDocument();
- expect(screen.getByText('Personal Project')).toBeInTheDocument();
+ expect(screen.getByText('Project Alpha')).toBeInTheDocument();
});
});
@@ -200,7 +198,7 @@ describe('LabelSelector Component', () => {
await waitFor(() => {
expect(screen.getByText('Important')).toBeInTheDocument();
expect(screen.getByText('Work')).toBeInTheDocument();
- expect(screen.queryByText('Personal Project')).not.toBeInTheDocument();
+ expect(screen.queryByText('Project Alpha')).not.toBeInTheDocument();
});
});
});
@@ -215,7 +213,7 @@ describe('LabelSelector Component', () => {
await waitFor(() => {
expect(screen.getByText('Work')).toBeInTheDocument();
expect(screen.queryByText('Important')).not.toBeInTheDocument();
- expect(screen.queryByText('Personal Project')).not.toBeInTheDocument();
+ expect(screen.queryByText('Project Alpha')).not.toBeInTheDocument();
});
});
@@ -376,10 +374,10 @@ describe('LabelSelector Component', () => {
await user.click(input);
await waitFor(() => {
- expect(screen.getByText('Personal Project')).toBeInTheDocument();
+ expect(screen.getByText('Project Alpha')).toBeInTheDocument();
});
- await user.click(screen.getByText('Personal Project'));
+ await user.click(screen.getByText('Project Alpha'));
// Should not add the third label due to maxTags limit
expect(onLabelsChange).not.toHaveBeenCalled();
diff --git a/frontend/src/components/Notifications/__tests__/NotificationPanel.simple.test.tsx b/frontend/src/components/Notifications/__tests__/NotificationPanel.simple.test.tsx
index 081f7ab..b6aec47 100644
--- a/frontend/src/components/Notifications/__tests__/NotificationPanel.simple.test.tsx
+++ b/frontend/src/components/Notifications/__tests__/NotificationPanel.simple.test.tsx
@@ -1,8 +1,8 @@
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
+import { renderWithProviders } from '../../../test/test-utils';
import NotificationPanel from '../NotificationPanel';
import { NotificationProvider } from '../../../contexts/NotificationContext';
-import { renderWithProviders, setupTestEnvironment } from '../../../test/test-utils';
import React from 'react';
// Mock date-fns
@@ -28,7 +28,6 @@ const createMockAnchorEl = () => {
describe('NotificationPanel - Simple Tests', () => {
beforeEach(() => {
- setupTestEnvironment();
});
test('should not render when anchorEl is null', () => {
const { container } = renderWithProviders(
diff --git a/frontend/src/components/Upload/__tests__/UploadZone.test.tsx b/frontend/src/components/Upload/__tests__/UploadZone.test.tsx
index d861c34..a03c7f5 100644
--- a/frontend/src/components/Upload/__tests__/UploadZone.test.tsx
+++ b/frontend/src/components/Upload/__tests__/UploadZone.test.tsx
@@ -1,33 +1,30 @@
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../../test/comprehensive-mocks';
+
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Mock API services comprehensively
+vi.mock('../../../services/api', async () => {
+ const actual = await vi.importActual('../../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ ...apiMocks,
+ };
+});
+
+// Import after mocking
import { screen, fireEvent, act, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import UploadZone from '../UploadZone';
-import { renderWithProviders, setupTestEnvironment, createMockApiServices } from '../../../test/test-utils';
+import { renderWithProviders, createMockApiServices } from '../../../test/test-utils';
import { createMockLabel } from '../../../test/label-test-utils';
// Setup centralized API mocks for this component
const mockApiServices = createMockApiServices();
-// Mock axios directly with our mock labels
-vi.mock('axios', () => ({
- default: {
- create: vi.fn(() => ({
- get: vi.fn().mockResolvedValue({
- status: 200,
- data: [createMockLabel({
- name: 'Test Label',
- color: '#0969da',
- document_count: 0,
- source_count: 0,
- })]
- }),
- post: vi.fn().mockResolvedValue({ status: 201, data: {} }),
- put: vi.fn().mockResolvedValue({ status: 200, data: {} }),
- delete: vi.fn().mockResolvedValue({ status: 204 }),
- })),
- },
-}));
-
const mockProps = {
onUploadComplete: vi.fn(),
};
@@ -37,7 +34,6 @@ describe('UploadZone', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
// Suppress console.error for "Failed to fetch labels" during tests
originalConsoleError = console.error;
console.error = vi.fn().mockImplementation((message, ...args) => {
@@ -67,7 +63,7 @@ describe('UploadZone', () => {
});
test('shows accepted file types in UI', async () => {
- await renderWithProvider();
+ await renderWithProviders();
// Wait for component to load
await waitFor(() => {
@@ -79,7 +75,7 @@ describe('UploadZone', () => {
});
test('displays max file size limit', async () => {
- await renderWithProvider();
+ await renderWithProviders();
await waitFor(() => {
expect(screen.getByText(/maximum file size/i)).toBeInTheDocument();
@@ -89,7 +85,7 @@ describe('UploadZone', () => {
});
test('shows browse files button', async () => {
- await renderWithProvider();
+ await renderWithProviders();
await waitFor(() => {
const browseButton = screen.getByRole('button', { name: /choose files/i });
@@ -161,7 +157,7 @@ describe('UploadZone', () => {
test('handles click to browse files', async () => {
const user = userEvent.setup();
- await renderWithProvider();
+ await renderWithProviders();
await waitFor(() => {
const browseButton = screen.getByRole('button', { name: /choose files/i });
@@ -178,7 +174,7 @@ describe('UploadZone', () => {
});
test('renders upload zone structure correctly', async () => {
- await renderWithProvider();
+ await renderWithProviders();
// Wait for component to load
await waitFor(() => {
diff --git a/frontend/src/components/__tests__/FailedDocumentViewer.test.tsx b/frontend/src/components/__tests__/FailedDocumentViewer.test.tsx
index 28a5e3e..51d7aba 100644
--- a/frontend/src/components/__tests__/FailedDocumentViewer.test.tsx
+++ b/frontend/src/components/__tests__/FailedDocumentViewer.test.tsx
@@ -1,16 +1,48 @@
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
-import { screen, waitFor } from '@testing-library/react';
-import FailedDocumentViewer from '../FailedDocumentViewer';
-import { api } from '../../services/api';
-import { renderWithProviders, setupTestEnvironment } from '../../test/test-utils';
-// Mock the API
+// Create mock function before imports
+const mockApiGet = vi.fn();
+
+// Mock the api module before importing anything else
vi.mock('../../services/api', () => ({
api: {
- get: vi.fn(),
- },
+ get: mockApiGet,
+ post: vi.fn(),
+ put: vi.fn(),
+ delete: vi.fn(),
+ patch: vi.fn(),
+ defaults: { headers: { common: {} } },
+ create: vi.fn(),
+ interceptors: {
+ request: { use: vi.fn(), eject: vi.fn() },
+ response: { use: vi.fn(), eject: vi.fn() }
+ }
+ }
}));
+// Import after mocking
+import { screen, waitFor } from '@testing-library/react';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
+import FailedDocumentViewer from '../FailedDocumentViewer';
+import { renderWithProviders } from '../../test/test-utils';
+const theme = createTheme();
+
+// Mock URL constructor with static methods
+const mockCreateObjectURL = vi.fn(() => 'mock-object-url');
+const mockRevokeObjectURL = vi.fn();
+
+global.URL = class URL {
+ constructor(url) {
+ this.href = url;
+ this.protocol = 'http:';
+ this.hostname = 'localhost';
+ this.pathname = '/';
+ this.search = '';
+ }
+
+ static createObjectURL = mockCreateObjectURL;
+ static revokeObjectURL = mockRevokeObjectURL;
+} as any;
const defaultProps = {
failedDocumentId: 'test-failed-doc-id',
@@ -26,23 +58,19 @@ const renderFailedDocumentViewer = (props = {}) => {
);
};
-// Mock Blob and URL.createObjectURL
+// Mock Blob
const mockBlob = vi.fn(() => ({
text: () => Promise.resolve('mock text content'),
}));
global.Blob = mockBlob as any;
-const mockCreateObjectURL = vi.fn(() => 'mock-object-url');
-const mockRevokeObjectURL = vi.fn();
-global.URL = {
- createObjectURL: mockCreateObjectURL,
- revokeObjectURL: mockRevokeObjectURL,
-} as any;
-
describe('FailedDocumentViewer', () => {
beforeEach(() => {
- setupTestEnvironment();
vi.clearAllMocks();
+ // Set default mock response
+ mockApiGet.mockResolvedValue({
+ data: new Blob(['mock document content'], { type: 'application/pdf' })
+ });
});
afterEach(() => {
@@ -52,7 +80,7 @@ describe('FailedDocumentViewer', () => {
describe('Loading State', () => {
test('should show loading spinner initially', () => {
// Mock API to never resolve
- vi.mocked(api.get).mockImplementation(() => new Promise(() => {}));
+ mockApiGet.mockImplementation(() => new Promise(() => {}));
renderFailedDocumentViewer();
@@ -60,7 +88,7 @@ describe('FailedDocumentViewer', () => {
});
test('should show loading spinner with correct styling', () => {
- vi.mocked(api.get).mockImplementation(() => new Promise(() => {}));
+ mockApiGet.mockImplementation(() => new Promise(() => {}));
renderFailedDocumentViewer();
@@ -79,12 +107,12 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock pdf content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
+ expect(mockApiGet).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
responseType: 'blob'
});
});
@@ -102,7 +130,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock image content'], { type: 'image/jpeg' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
filename: 'test-image.jpg',
@@ -125,7 +153,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock text content'], { type: 'text/plain' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
filename: 'test-file.txt',
@@ -143,7 +171,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/unknown' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
filename: 'test-file.unknown',
@@ -163,7 +191,7 @@ describe('FailedDocumentViewer', () => {
const error = {
response: { status: 404 }
};
- vi.mocked(api.get).mockRejectedValueOnce(error);
+ mockApiGet.mockRejectedValueOnce(error);
renderFailedDocumentViewer();
@@ -175,7 +203,7 @@ describe('FailedDocumentViewer', () => {
test('should show generic error for other failures', async () => {
const error = new Error('Network error');
- vi.mocked(api.get).mockRejectedValueOnce(error);
+ mockApiGet.mockRejectedValueOnce(error);
renderFailedDocumentViewer();
@@ -189,7 +217,7 @@ describe('FailedDocumentViewer', () => {
const error = {
response: { status: 500 }
};
- vi.mocked(api.get).mockRejectedValueOnce(error);
+ mockApiGet.mockRejectedValueOnce(error);
renderFailedDocumentViewer();
@@ -204,7 +232,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
@@ -222,34 +250,29 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValue(mockResponse);
+ mockApiGet.mockResolvedValue(mockResponse);
const { rerender } = renderFailedDocumentViewer();
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
+ expect(mockApiGet).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
responseType: 'blob'
});
});
// Change the failedDocumentId
+ const newProps = { ...defaultProps, failedDocumentId: "new-doc-id" };
rerender(
-
-
-
+
);
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/documents/failed/new-doc-id/view', {
+ expect(mockApiGet).toHaveBeenCalledWith('/documents/failed/new-doc-id/view', {
responseType: 'blob'
});
});
- expect(api.get).toHaveBeenCalledTimes(2);
+ expect(mockApiGet).toHaveBeenCalledTimes(2);
});
});
@@ -258,7 +281,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock pdf content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
mimeType: 'application/pdf'
@@ -278,7 +301,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock image content'], { type: mimeType }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
const filename = `test.${mimeType.split('/')[1]}`;
renderFailedDocumentViewer({
@@ -304,7 +327,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock text content'], { type: mimeType }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
const filename = `test.${mimeType.split('/')[1]}`;
renderFailedDocumentViewer({
@@ -329,7 +352,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
@@ -343,7 +366,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock image content'], { type: 'image/jpeg' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
mimeType: 'image/jpeg'
@@ -363,12 +386,12 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
+ expect(mockApiGet).toHaveBeenCalledWith('/documents/failed/test-failed-doc-id/view', {
responseType: 'blob'
});
});
@@ -378,14 +401,14 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
failedDocumentId: 'different-doc-id'
});
await waitFor(() => {
- expect(api.get).toHaveBeenCalledWith('/documents/failed/different-doc-id/view', {
+ expect(mockApiGet).toHaveBeenCalledWith('/documents/failed/different-doc-id/view', {
responseType: 'blob'
});
});
@@ -397,7 +420,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob([], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
@@ -413,7 +436,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
filename: longFilename
@@ -429,7 +452,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
filename: specialFilename
@@ -444,7 +467,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: '' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
mimeType: undefined as any
@@ -462,7 +485,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock content'], { type: 'application/pdf' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer();
@@ -476,7 +499,7 @@ describe('FailedDocumentViewer', () => {
const mockResponse = {
data: new Blob(['mock image content'], { type: 'image/jpeg' }),
};
- vi.mocked(api.get).mockResolvedValueOnce(mockResponse);
+ mockApiGet.mockResolvedValueOnce(mockResponse);
renderFailedDocumentViewer({
mimeType: 'image/jpeg'
diff --git a/frontend/src/components/__tests__/RetryRecommendations.test.tsx b/frontend/src/components/__tests__/RetryRecommendations.test.tsx
index 2423a70..6a5f487 100644
--- a/frontend/src/components/__tests__/RetryRecommendations.test.tsx
+++ b/frontend/src/components/__tests__/RetryRecommendations.test.tsx
@@ -1,19 +1,33 @@
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
-import { render, screen, waitFor } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import { RetryRecommendations } from '../RetryRecommendations';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../test/comprehensive-mocks';
-// Create unique mock functions for this test file
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Create mock functions for this specific test
const mockGetRetryRecommendations = vi.fn();
const mockBulkRetryOcr = vi.fn();
-// Mock the API module with a unique namespace for this test
-vi.mock('../../services/api', () => ({
- documentService: {
- getRetryRecommendations: mockGetRetryRecommendations,
- bulkRetryOcr: mockBulkRetryOcr,
- },
-}));
+// Mock the API module with comprehensive mocking
+vi.mock('../../services/api', async () => {
+ const actual = await vi.importActual('../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ ...apiMocks,
+ documentService: {
+ ...apiMocks.documentService,
+ getRetryRecommendations: mockGetRetryRecommendations,
+ bulkRetryOcr: mockBulkRetryOcr,
+ },
+ };
+});
+
+// Import after mocking
+import { render, screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { RetryRecommendations } from '../RetryRecommendations';
describe('RetryRecommendations', () => {
const mockProps = {
diff --git a/frontend/src/components/__tests__/TestNotification.test.tsx b/frontend/src/components/__tests__/TestNotification.test.tsx
index da62250..279f916 100644
--- a/frontend/src/components/__tests__/TestNotification.test.tsx
+++ b/frontend/src/components/__tests__/TestNotification.test.tsx
@@ -1,8 +1,8 @@
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { screen, fireEvent } from '@testing-library/react';
+import { renderWithProviders } from '../../test/test-utils';
import TestNotification from '../TestNotification';
import { NotificationProvider } from '../../contexts/NotificationContext';
-import { renderWithProviders, setupTestEnvironment } from '../../test/test-utils';
import React from 'react';
const renderTestNotification = () => {
@@ -15,7 +15,6 @@ const renderTestNotification = () => {
describe('TestNotification', () => {
beforeEach(() => {
- setupTestEnvironment();
vi.clearAllMocks();
});
diff --git a/frontend/src/contexts/__tests__/NotificationContext.simple.test.tsx b/frontend/src/contexts/__tests__/NotificationContext.simple.test.tsx
index ef321b9..bead910 100644
--- a/frontend/src/contexts/__tests__/NotificationContext.simple.test.tsx
+++ b/frontend/src/contexts/__tests__/NotificationContext.simple.test.tsx
@@ -1,7 +1,7 @@
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
-import { screen, act } from '@testing-library/react';
+import { screen, act, render } from '@testing-library/react';
import { NotificationProvider, useNotifications } from '../NotificationContext';
-import { renderWithProviders, setupTestEnvironment } from '../../test/test-utils';
+import { renderWithProviders } from '../../test/test-utils';
import React from 'react';
// Simple test component
@@ -62,7 +62,6 @@ const renderWithProvider = () => {
describe('NotificationContext - Simple Tests', () => {
beforeEach(() => {
- setupTestEnvironment();
vi.useFakeTimers();
});
@@ -164,7 +163,7 @@ describe('NotificationContext - Simple Tests', () => {
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
expect(() => {
- renderWithProviders();
+ render();
}).toThrow('useNotifications must be used within NotificationProvider');
consoleSpy.mockRestore();
@@ -198,7 +197,6 @@ describe('NotificationContext - Types', () => {
};
beforeEach(() => {
- setupTestEnvironment();
vi.useFakeTimers();
});
diff --git a/frontend/src/pages/__tests__/DocumentManagementPage.runtime-errors.test.tsx b/frontend/src/pages/__tests__/DocumentManagementPage.runtime-errors.test.tsx
index 4203137..7fc33f3 100644
--- a/frontend/src/pages/__tests__/DocumentManagementPage.runtime-errors.test.tsx
+++ b/frontend/src/pages/__tests__/DocumentManagementPage.runtime-errors.test.tsx
@@ -1,40 +1,31 @@
import { describe, test, expect, vi, beforeEach } from 'vitest';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../test/comprehensive-mocks';
+
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Mock API services comprehensively
+vi.mock('../../services/api', async () => {
+ const actual = await vi.importActual('../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ ...apiMocks,
+ };
+});
+
+// Import components AFTER the mocks are set up
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { ThemeProvider, createTheme } from '@mui/material/styles';
-import DocumentManagementPage from '../DocumentManagementPage';
import userEvent from '@testing-library/user-event';
+import DocumentManagementPage from '../DocumentManagementPage';
-// Create mock objects first
-const mockDocumentService = {
- getFailedDocuments: vi.fn(),
- getFailedOcrDocuments: vi.fn(),
- getDuplicates: vi.fn(),
- retryOcr: vi.fn(),
- deleteLowConfidence: vi.fn(),
- deleteFailedOcr: vi.fn(),
- downloadFile: vi.fn(),
- getRetryRecommendations: vi.fn(),
- getRetryStats: vi.fn(),
- getDocumentRetryHistory: vi.fn(),
-};
-
-const mockQueueService = {
- requeueFailed: vi.fn(),
-};
-
-const mockApi = {
- get: vi.fn(),
- delete: vi.fn(),
- bulkRetryOcr: vi.fn(),
-};
-
-// Mock API with comprehensive responses
-vi.mock('../../services/api', () => ({
- api: mockApi,
- documentService: mockDocumentService,
- queueService: mockQueueService,
-}));
+// Get references to the mocked modules using dynamic import
+const { api, documentService } = await import('../../services/api');
+const mockApi = api;
+const mockDocumentService = documentService;
const theme = createTheme();
@@ -51,40 +42,11 @@ const DocumentManagementPageWrapper = ({ children }: { children: React.ReactNode
describe('DocumentManagementPage - Runtime Error Prevention', () => {
beforeEach(() => {
vi.clearAllMocks();
- mockDocumentService.getFailedDocuments.mockClear();
- mockDocumentService.getFailedOcrDocuments.mockClear();
- mockDocumentService.getDuplicates.mockClear();
- mockQueueService.requeueFailed.mockClear();
-
- // Setup default mock returns for retry functionality
- mockDocumentService.getRetryRecommendations.mockResolvedValue({
- data: { recommendations: [], total_recommendations: 0 }
- });
- mockDocumentService.getRetryStats.mockResolvedValue({
- data: { failure_reasons: [], file_types: [], total_failed: 0 }
- });
- mockDocumentService.getDocumentRetryHistory.mockResolvedValue({
- data: { document_id: 'test', retry_history: [], total_retries: 0 }
- });
- mockApi.bulkRetryOcr.mockResolvedValue({
- data: { success: true, queued_count: 0, matched_count: 0, documents: [] }
- });
});
describe('OCR Confidence Display - Null Safety', () => {
test('basic rendering test', async () => {
- // Very basic test first - wait for loading to complete
- mockDocumentService.getFailedDocuments.mockResolvedValue({
- data: {
- documents: [],
- pagination: { total: 0, limit: 25, offset: 0, total_pages: 0 },
- statistics: { total_failed: 0, by_reason: {}, by_stage: {} },
- },
- });
-
- mockApi.get.mockResolvedValue({
- data: { total_count: 0, total_size: 0 },
- });
+ // With axios mocked directly, all API calls should return empty data by default
render(
@@ -559,9 +521,8 @@ describe('DocumentManagementPage - Runtime Error Prevention', () => {
describe('Ignored Files Tab Functionality', () => {
test('should render ignored files tab without errors', async () => {
- // Mock ignored files API responses
- const { api } = await import('../../services/api');
- vi.mocked(api.get).mockImplementation((url) => {
+ // Setup mock responses using our already defined mocks
+ mockApi.get.mockImplementation((url) => {
if (url.includes('/ignored-files/stats')) {
return Promise.resolve({
data: {
@@ -582,8 +543,7 @@ describe('DocumentManagementPage - Runtime Error Prevention', () => {
return Promise.resolve({ data: {} });
});
- const { documentService } = await import('../../services/api');
- vi.mocked(documentService.getFailedDocuments).mockResolvedValueOnce({
+ mockDocumentService.getFailedDocuments.mockResolvedValueOnce({
data: {
documents: [],
pagination: { total: 0, limit: 25, offset: 0, total_pages: 1 },
diff --git a/frontend/src/pages/__tests__/LabelsPage.test.tsx b/frontend/src/pages/__tests__/LabelsPage.test.tsx
index 8fdc173..d81f159 100644
--- a/frontend/src/pages/__tests__/LabelsPage.test.tsx
+++ b/frontend/src/pages/__tests__/LabelsPage.test.tsx
@@ -3,7 +3,8 @@ import { screen, waitFor, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import LabelsPage from '../LabelsPage';
import * as useApiModule from '../../hooks/useApi';
-import { renderWithAuthenticatedUser, setupTestEnvironment } from '../../test/test-utils';\nimport { createMockLabel } from '../../test/label-test-utils';
+import { renderWithAuthenticatedUser } from '../../test/test-utils';
+import { createMockLabel } from '../../test/label-test-utils';
const mockLabels = [
createMockLabel({
@@ -66,7 +67,6 @@ describe('LabelsPage Component', () => {
};
beforeEach(() => {
- setupTestEnvironment();
user = userEvent.setup();
mockApi = {
diff --git a/frontend/src/pages/__tests__/SearchPage.test.tsx b/frontend/src/pages/__tests__/SearchPage.test.tsx
index 6411270..a6c514f 100644
--- a/frontend/src/pages/__tests__/SearchPage.test.tsx
+++ b/frontend/src/pages/__tests__/SearchPage.test.tsx
@@ -1,23 +1,26 @@
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
+import { renderWithAuthenticatedUser } from '../../test/test-utils';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../test/comprehensive-mocks';
import SearchPage from '../SearchPage';
-import { renderWithAuthenticatedUser, createMockUser, setupTestEnvironment } from '../../test/test-utils';
-// Mock API functions
-vi.mock('../../services/api', () => ({
- searchDocuments: vi.fn(() => Promise.resolve({
- results: [],
- total: 0,
- page: 1,
- page_size: 20
- })),
- getSettings: vi.fn(() => Promise.resolve({})),
-}));
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Mock API services comprehensively
+vi.mock('../../services/api', async () => {
+ const actual = await vi.importActual('../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ ...apiMocks,
+ };
+});
describe('SearchPage', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
});
test('renders search page structure', () => {
diff --git a/frontend/src/pages/__tests__/WebDAVTab.test.tsx b/frontend/src/pages/__tests__/WebDAVTab.test.tsx
index f0ae25c..eaeadf4 100644
--- a/frontend/src/pages/__tests__/WebDAVTab.test.tsx
+++ b/frontend/src/pages/__tests__/WebDAVTab.test.tsx
@@ -2,11 +2,26 @@ import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi, describe, it, expect, beforeEach } from 'vitest';
-import api from '../../services/api';
+import { createComprehensiveAxiosMock, createComprehensiveApiMocks } from '../../test/comprehensive-mocks';
-// Mock the API
-vi.mock('../../services/api');
-const mockedApi = vi.mocked(api);
+// Mock axios comprehensively to prevent any real HTTP requests
+vi.mock('axios', () => createComprehensiveAxiosMock());
+
+// Mock API services comprehensively
+vi.mock('../../services/api', async () => {
+ const actual = await vi.importActual('../../services/api');
+ const apiMocks = createComprehensiveApiMocks();
+
+ return {
+ ...actual,
+ default: apiMocks.api, // Since this file imports `api` as default
+ ...apiMocks,
+ };
+});
+
+// Get references to the mocked modules using dynamic import
+const { default: api } = await import('../../services/api');
+const mockedApi = api;
// Mock settings with WebDAV configuration
const mockSettings = {
diff --git a/frontend/src/services/__tests__/api.test.ts b/frontend/src/services/__tests__/api.test.ts
index ceef64a..b732ad6 100644
--- a/frontend/src/services/__tests__/api.test.ts
+++ b/frontend/src/services/__tests__/api.test.ts
@@ -1,6 +1,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { type OcrResponse, type Document } from '../api';
-import { createMockApiServices, setupTestEnvironment } from '../../test/test-utils';
+import { createMockApiServices } from '../../test/test-utils';
// Use centralized API mocking
const mockServices = createMockApiServices();
@@ -21,7 +21,6 @@ const { documentService } = await import('../api');
describe('documentService', () => {
beforeEach(() => {
vi.clearAllMocks();
- setupTestEnvironment();
});
describe('getOcrText', () => {
@@ -124,21 +123,21 @@ describe('documentService', () => {
});
it('should make correct API call', async () => {
- mockGetOcrText.mockResolvedValue({ data: mockOcrResponse });
+ mockDocumentService.getOcrText.mockResolvedValue({ data: mockOcrResponse });
await documentService.getOcrText('doc-123');
- expect(mockGetOcrText).toHaveBeenCalledWith('doc-123');
+ expect(mockDocumentService.getOcrText).toHaveBeenCalledWith('doc-123');
});
it('should handle network errors', async () => {
- mockGetOcrText.mockRejectedValue(new Error('Network Error'));
+ mockDocumentService.getOcrText.mockRejectedValue(new Error('Network Error'));
await expect(documentService.getOcrText('doc-123')).rejects.toThrow('Network Error');
});
it('should handle 404 errors for non-existent documents', async () => {
- mockGetOcrText.mockRejectedValue({
+ mockDocumentService.getOcrText.mockRejectedValue({
response: {
status: 404,
data: { error: 'Document not found' },
@@ -153,7 +152,7 @@ describe('documentService', () => {
});
it('should handle 401 unauthorized errors', async () => {
- mockGetOcrText.mockRejectedValue({
+ mockDocumentService.getOcrText.mockRejectedValue({
response: {
status: 401,
data: { error: 'Unauthorized' },
@@ -209,7 +208,7 @@ describe('documentService', () => {
config: {},
};
- mockList.mockResolvedValue(mockResponse);
+ mockDocumentService.list.mockResolvedValue(mockResponse);
const result = await documentService.list(50, 0);
@@ -236,24 +235,24 @@ describe('documentService', () => {
ocr_status: 'pending',
};
- mockUpload.mockResolvedValue({ data: mockUploadResponse });
+ mockDocumentService.upload.mockResolvedValue({ data: mockUploadResponse });
const result = await documentService.upload(mockFile);
expect(result.data).toEqual(mockUploadResponse);
- expect(mockUpload).toHaveBeenCalledWith(mockFile);
+ expect(mockDocumentService.upload).toHaveBeenCalledWith(mockFile);
});
});
describe('download', () => {
it('should download file as blob', async () => {
const mockBlob = new Blob(['file content'], { type: 'application/pdf' });
- mockDownload.mockResolvedValue({ data: mockBlob });
+ mockDocumentService.download.mockResolvedValue({ data: mockBlob });
const result = await documentService.download('doc-123');
expect(result.data).toEqual(mockBlob);
- expect(mockDownload).toHaveBeenCalledWith('doc-123');
+ expect(mockDocumentService.download).toHaveBeenCalledWith('doc-123');
});
});
});
@@ -325,11 +324,11 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockDeleteResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockDeleteResponse);
const result = await documentService.deleteLowConfidence(30.0, false);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(30.0, false);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(30.0, false);
expect(result.data.success).toBe(true);
expect(result.data.deleted_count).toBe(3);
expect(result.data.matched_count).toBe(3);
@@ -351,11 +350,11 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockPreviewResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockPreviewResponse);
const result = await documentService.deleteLowConfidence(50.0, true);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(50.0, true);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(50.0, true);
expect(result.data.success).toBe(true);
expect(result.data.preview).toBe(true);
expect(result.data.matched_count).toBe(5);
@@ -376,11 +375,11 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockEmptyResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockEmptyResponse);
const result = await documentService.deleteLowConfidence(10.0, false);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(10.0, false);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(10.0, false);
expect(result.data.success).toBe(true);
expect(result.data.deleted_count).toBe(0);
});
@@ -398,23 +397,23 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockErrorResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockErrorResponse);
const result = await documentService.deleteLowConfidence(-10.0, false);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(-10.0, false);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(-10.0, false);
expect(result.data.success).toBe(false);
expect(result.data.message).toContain('must be between 0.0 and 100.0');
});
it('should handle API errors gracefully', async () => {
const mockError = new Error('Network error');
- mockDeleteLowConfidence.mockRejectedValue(mockError);
+ mockDocumentService.deleteLowConfidence.mockRejectedValue(mockError);
await expect(documentService.deleteLowConfidence(30.0, false))
.rejects.toThrow('Network error');
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(30.0, false);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(30.0, false);
});
it('should use correct default values', async () => {
@@ -426,12 +425,12 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockResponse);
// Test with explicit false value (the default)
await documentService.deleteLowConfidence(40.0, false);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(40.0, false);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(40.0, false);
});
it('should handle partial deletion failures', async () => {
@@ -452,7 +451,7 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockPartialFailureResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockPartialFailureResponse);
const result = await documentService.deleteLowConfidence(25.0, false);
@@ -472,15 +471,15 @@ describe('documentService.deleteLowConfidence', () => {
config: {},
};
- mockDeleteLowConfidence.mockResolvedValue(mockResponse);
+ mockDocumentService.deleteLowConfidence.mockResolvedValue(mockResponse);
// Test various confidence values
const testValues = [0.0, 0.1, 30.5, 50.0, 99.9, 100.0];
for (const confidence of testValues) {
- mockDeleteLowConfidence.mockClear();
+ mockDocumentService.deleteLowConfidence.mockClear();
await documentService.deleteLowConfidence(confidence, true);
- expect(mockDeleteLowConfidence).toHaveBeenCalledWith(confidence, true);
+ expect(mockDocumentService.deleteLowConfidence).toHaveBeenCalledWith(confidence, true);
}
});
});
@@ -529,11 +528,11 @@ describe('documentService.getFailedOcrDocuments', () => {
config: {},
};
- mockGetFailedOcrDocuments.mockResolvedValue(mockResponse);
+ mockDocumentService.getFailedOcrDocuments.mockResolvedValue(mockResponse);
const result = await documentService.getFailedOcrDocuments(50, 0);
- expect(mockGetFailedOcrDocuments).toHaveBeenCalledWith(50, 0);
+ expect(mockDocumentService.getFailedOcrDocuments).toHaveBeenCalledWith(50, 0);
expect(result.data).toEqual(mockFailedOcrResponse);
expect(result.data.documents).toHaveLength(2);
expect(result.data.documents[0].failure_stage).toBe('ocr');
@@ -541,19 +540,19 @@ describe('documentService.getFailedOcrDocuments', () => {
});
it('should handle pagination parameters correctly', async () => {
- mockGetFailedOcrDocuments.mockResolvedValue({ data: mockFailedOcrResponse });
+ mockDocumentService.getFailedOcrDocuments.mockResolvedValue({ data: mockFailedOcrResponse });
await documentService.getFailedOcrDocuments(25, 10);
- expect(mockGetFailedOcrDocuments).toHaveBeenCalledWith(25, 10);
+ expect(mockDocumentService.getFailedOcrDocuments).toHaveBeenCalledWith(25, 10);
});
it('should use default pagination when not specified', async () => {
- mockGetFailedOcrDocuments.mockResolvedValue({ data: mockFailedOcrResponse });
+ mockDocumentService.getFailedOcrDocuments.mockResolvedValue({ data: mockFailedOcrResponse });
await documentService.getFailedOcrDocuments();
- expect(mockGetFailedOcrDocuments).toHaveBeenCalledWith();
+ expect(mockDocumentService.getFailedOcrDocuments).toHaveBeenCalledWith();
});
it('should handle empty results', async () => {
@@ -563,7 +562,7 @@ describe('documentService.getFailedOcrDocuments', () => {
statistics: { total_failed: 0, failure_categories: [] }
};
- mockGetFailedOcrDocuments.mockResolvedValue({ data: emptyResponse });
+ mockDocumentService.getFailedOcrDocuments.mockResolvedValue({ data: emptyResponse });
const result = await documentService.getFailedOcrDocuments();
@@ -574,7 +573,7 @@ describe('documentService.getFailedOcrDocuments', () => {
it('should handle API errors', async () => {
const mockError = new Error('Network error');
- mockGetFailedOcrDocuments.mockRejectedValue(mockError);
+ mockDocumentService.getFailedOcrDocuments.mockRejectedValue(mockError);
await expect(documentService.getFailedOcrDocuments()).rejects.toThrow('Network error');
});
@@ -625,11 +624,11 @@ describe('documentService.getFailedDocuments', () => {
};
it('should fetch failed documents with default parameters', async () => {
- mockGetFailedDocuments.mockResolvedValue({ data: mockFailedDocumentsResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: mockFailedDocumentsResponse });
const result = await documentService.getFailedDocuments();
- expect(mockGetFailedDocuments).toHaveBeenCalledWith();
+ expect(mockDocumentService.getFailedDocuments).toHaveBeenCalledWith();
expect(result.data).toEqual(mockFailedDocumentsResponse);
expect(result.data.documents).toHaveLength(3);
});
@@ -642,11 +641,11 @@ describe('documentService.getFailedDocuments', () => {
statistics: { total_failed: 1, failure_categories: [{ reason: 'low_ocr_confidence', display_name: 'Low OCR Confidence', count: 1 }] }
};
- mockGetFailedDocuments.mockResolvedValue({ data: ocrOnlyResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: ocrOnlyResponse });
const result = await documentService.getFailedDocuments(25, 0, 'ocr');
- expect(mockGetFailedDocuments).toHaveBeenCalledWith(25, 0, 'ocr');
+ expect(mockDocumentService.getFailedDocuments).toHaveBeenCalledWith(25, 0, 'ocr');
expect(result.data.documents).toHaveLength(1);
expect(result.data.documents[0].failure_stage).toBe('ocr');
});
@@ -659,11 +658,11 @@ describe('documentService.getFailedDocuments', () => {
statistics: { total_failed: 1, failure_categories: [{ reason: 'duplicate_content', display_name: 'Duplicate Content', count: 1 }] }
};
- mockGetFailedDocuments.mockResolvedValue({ data: duplicateOnlyResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: duplicateOnlyResponse });
const result = await documentService.getFailedDocuments(25, 0, undefined, 'duplicate_content');
- expect(mockGetFailedDocuments).toHaveBeenCalledWith(25, 0, undefined, 'duplicate_content');
+ expect(mockDocumentService.getFailedDocuments).toHaveBeenCalledWith(25, 0, undefined, 'duplicate_content');
expect(result.data.documents).toHaveLength(1);
expect(result.data.documents[0].failure_reason).toBe('duplicate_content');
});
@@ -676,22 +675,22 @@ describe('documentService.getFailedDocuments', () => {
statistics: { total_failed: 1, failure_categories: [{ reason: 'low_ocr_confidence', display_name: 'Low OCR Confidence', count: 1 }] }
};
- mockGetFailedDocuments.mockResolvedValue({ data: filteredResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: filteredResponse });
const result = await documentService.getFailedDocuments(25, 0, 'ocr', 'low_ocr_confidence');
- expect(mockGetFailedDocuments).toHaveBeenCalledWith(25, 0, 'ocr', 'low_ocr_confidence');
+ expect(mockDocumentService.getFailedDocuments).toHaveBeenCalledWith(25, 0, 'ocr', 'low_ocr_confidence');
expect(result.data.documents).toHaveLength(1);
expect(result.data.documents[0].failure_stage).toBe('ocr');
expect(result.data.documents[0].failure_reason).toBe('low_ocr_confidence');
});
it('should handle custom pagination', async () => {
- mockGetFailedDocuments.mockResolvedValue({ data: mockFailedDocumentsResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: mockFailedDocumentsResponse });
await documentService.getFailedDocuments(10, 20);
- expect(mockGetFailedDocuments).toHaveBeenCalledWith(10, 20);
+ expect(mockDocumentService.getFailedDocuments).toHaveBeenCalledWith(10, 20);
});
it('should handle empty results', async () => {
@@ -701,7 +700,7 @@ describe('documentService.getFailedDocuments', () => {
statistics: { total_failed: 0, failure_categories: [] }
};
- mockGetFailedDocuments.mockResolvedValue({ data: emptyResponse });
+ mockDocumentService.getFailedDocuments.mockResolvedValue({ data: emptyResponse });
const result = await documentService.getFailedDocuments();
@@ -724,11 +723,11 @@ describe('documentService.retryOcr', () => {
config: {},
};
- mockRetryOcr.mockResolvedValue(mockRetryResponse);
+ mockDocumentService.retryOcr.mockResolvedValue(mockRetryResponse);
const result = await documentService.retryOcr('doc-123');
- expect(mockRetryOcr).toHaveBeenCalledWith('doc-123');
+ expect(mockDocumentService.retryOcr).toHaveBeenCalledWith('doc-123');
expect(result.data.success).toBe(true);
expect(result.data.document_id).toBe('doc-123');
});
@@ -741,7 +740,7 @@ describe('documentService.retryOcr', () => {
}
};
- mockRetryOcr.mockRejectedValue(mockError);
+ mockDocumentService.retryOcr.mockRejectedValue(mockError);
await expect(documentService.retryOcr('non-existent-doc')).rejects.toMatchObject({
response: { status: 404 }
@@ -749,7 +748,7 @@ describe('documentService.retryOcr', () => {
});
it('should handle network errors', async () => {
- mockRetryOcr.mockRejectedValue(new Error('Network error'));
+ mockDocumentService.retryOcr.mockRejectedValue(new Error('Network error'));
await expect(documentService.retryOcr('doc-123')).rejects.toThrow('Network error');
});
diff --git a/frontend/src/test/comprehensive-mocks.ts b/frontend/src/test/comprehensive-mocks.ts
new file mode 100644
index 0000000..95d6feb
--- /dev/null
+++ b/frontend/src/test/comprehensive-mocks.ts
@@ -0,0 +1,129 @@
+// Comprehensive mocking utilities to prevent HTTP requests in tests
+import { vi } from 'vitest';
+
+/**
+ * Creates a comprehensive axios mock that prevents all HTTP requests
+ * This should be used in test files that have components making API calls
+ */
+export const createComprehensiveAxiosMock = () => {
+ const mockAxiosInstance = {
+ get: vi.fn().mockResolvedValue({ data: {} }),
+ post: vi.fn().mockResolvedValue({ data: { success: true } }),
+ put: vi.fn().mockResolvedValue({ data: { success: true } }),
+ delete: vi.fn().mockResolvedValue({ data: { success: true } }),
+ patch: vi.fn().mockResolvedValue({ data: { success: true } }),
+ request: vi.fn().mockResolvedValue({ data: { success: true } }),
+ head: vi.fn().mockResolvedValue({ data: {} }),
+ options: vi.fn().mockResolvedValue({ data: {} }),
+ defaults: {
+ headers: {
+ common: {},
+ get: {},
+ post: {},
+ put: {},
+ delete: {},
+ patch: {},
+ }
+ },
+ interceptors: {
+ request: { use: vi.fn(), eject: vi.fn() },
+ response: { use: vi.fn(), eject: vi.fn() },
+ },
+ };
+
+ return {
+ default: {
+ create: vi.fn(() => mockAxiosInstance),
+ ...mockAxiosInstance,
+ },
+ };
+};
+
+/**
+ * Creates comprehensive API service mocks
+ */
+export const createComprehensiveApiMocks = () => ({
+ api: {
+ get: vi.fn().mockResolvedValue({ data: {} }),
+ post: vi.fn().mockResolvedValue({ data: { success: true } }),
+ put: vi.fn().mockResolvedValue({ data: { success: true } }),
+ delete: vi.fn().mockResolvedValue({ data: { success: true } }),
+ patch: vi.fn().mockResolvedValue({ data: { success: true } }),
+ defaults: { headers: { common: {} } },
+ },
+ documentService: {
+ getRetryRecommendations: vi.fn().mockResolvedValue({
+ data: { recommendations: [], total_recommendations: 0 }
+ }),
+ bulkRetryOcr: vi.fn().mockResolvedValue({ data: { success: true } }),
+ getFailedDocuments: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ pagination: { total: 0, limit: 25, offset: 0, total_pages: 1 },
+ statistics: { total_failed: 0, by_reason: {}, by_stage: {} },
+ },
+ }),
+ getDuplicates: vi.fn().mockResolvedValue({
+ data: {
+ duplicates: [],
+ pagination: { total: 0, limit: 25, offset: 0, has_more: false },
+ statistics: { total_duplicate_groups: 0 },
+ },
+ }),
+ enhancedSearch: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ total: 0,
+ query_time_ms: 0,
+ suggestions: []
+ }
+ }),
+ search: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ total: 0,
+ query_time_ms: 0,
+ suggestions: []
+ }
+ }),
+ getOcrText: vi.fn().mockResolvedValue({ data: {} }),
+ upload: vi.fn().mockResolvedValue({ data: {} }),
+ list: vi.fn().mockResolvedValue({ data: [] }),
+ listWithPagination: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ pagination: { total: 0, limit: 20, offset: 0, has_more: false }
+ }
+ }),
+ delete: vi.fn().mockResolvedValue({}),
+ bulkDelete: vi.fn().mockResolvedValue({}),
+ retryOcr: vi.fn().mockResolvedValue({}),
+ getFacets: vi.fn().mockResolvedValue({ data: { mime_types: [], tags: [] } }),
+ download: vi.fn().mockResolvedValue({ data: new Blob() }),
+ deleteLowConfidence: vi.fn().mockResolvedValue({ data: {} }),
+ deleteFailedOcr: vi.fn().mockResolvedValue({ data: {} }),
+ view: vi.fn().mockResolvedValue({ data: new Blob() }),
+ getThumbnail: vi.fn().mockResolvedValue({ data: new Blob() }),
+ getProcessedImage: vi.fn().mockResolvedValue({ data: new Blob() }),
+ downloadFile: vi.fn().mockResolvedValue(undefined),
+ getRetryStats: vi.fn().mockResolvedValue({ data: {} }),
+ getDocumentRetryHistory: vi.fn().mockResolvedValue({ data: [] }),
+ },
+ queueService: {
+ getQueueStatus: vi.fn().mockResolvedValue({ data: { active: 0, waiting: 0 } }),
+ },
+});
+
+/**
+ * Standard pattern for mocking both axios and API services
+ * Use this at the top of test files that have components making API calls
+ */
+export const setupHttpMocks = () => {
+ // Mock axios comprehensively
+ vi.mock('axios', () => createComprehensiveAxiosMock());
+
+ // Mock API services
+ const apiMocks = createComprehensiveApiMocks();
+
+ return apiMocks;
+};
\ No newline at end of file
diff --git a/frontend/src/test/label-test-utils.ts b/frontend/src/test/label-test-utils.ts
index ffdd172..8c3ffcb 100644
--- a/frontend/src/test/label-test-utils.ts
+++ b/frontend/src/test/label-test-utils.ts
@@ -5,8 +5,11 @@ import { type LabelData } from '../components/Labels/Label';
* Test utilities for label-related tests
*/
+// Counter for generating unique IDs
+let labelIdCounter = 1;
+
export const createMockLabel = (overrides: Partial = {}): LabelData => ({
- id: 'test-label-1',
+ id: `test-label-${labelIdCounter++}`,
name: 'Test Label',
description: 'A test label',
color: '#0969da',
@@ -21,12 +24,15 @@ export const createMockLabel = (overrides: Partial = {}): LabelData =
});
export const createMockSystemLabel = (overrides: Partial = {}): LabelData => ({
- ...createMockLabel(),
- id: 'system-label-1',
+ id: `system-label-${labelIdCounter++}`,
name: 'Important',
+ description: 'A test label',
color: '#d73a49',
+ background_color: undefined,
icon: 'star',
is_system: true,
+ created_at: '2024-01-01T00:00:00Z',
+ updated_at: '2024-01-01T00:00:00Z',
document_count: 10,
source_count: 2,
...overrides,
@@ -213,12 +219,12 @@ export const testDataBuilders = {
* Creates a set of labels that represent typical usage patterns
*/
createTypicalLabelSet: (): LabelData[] => [
- createMockSystemLabel({ name: 'Important', color: '#d73a49', icon: 'star' }),
- createMockSystemLabel({ name: 'Work', color: '#0969da', icon: 'work' }),
- createMockSystemLabel({ name: 'Personal', color: '#28a745', icon: 'person' }),
- createMockLabel({ name: 'Project Alpha', color: '#8250df', icon: 'folder' }),
- createMockLabel({ name: 'Invoices', color: '#fb8500', icon: 'receipt' }),
- createMockLabel({ name: 'Archive', color: '#6e7781', icon: 'archive', document_count: 0 }),
+ createMockSystemLabel({ name: 'Important', description: 'High priority items', color: '#d73a49', icon: 'star' }),
+ createMockSystemLabel({ name: 'Work', description: 'Work-related documents', color: '#0969da', icon: 'work' }),
+ createMockSystemLabel({ name: 'Personal', description: 'Personal documents', color: '#28a745', icon: 'person' }),
+ createMockLabel({ name: 'Project Alpha', description: 'My personal project files', color: '#8250df', icon: 'folder' }),
+ createMockLabel({ name: 'Invoices', description: 'Financial documents', color: '#fb8500', icon: 'receipt' }),
+ createMockLabel({ name: 'Archive', description: 'Archived items', color: '#6e7781', icon: 'archive', document_count: 0 }),
],
/**
diff --git a/frontend/src/test/setup.ts b/frontend/src/test/setup.ts
index 6518e4f..6bd4095 100644
--- a/frontend/src/test/setup.ts
+++ b/frontend/src/test/setup.ts
@@ -3,7 +3,7 @@
import '@testing-library/jest-dom'
import { vi } from 'vitest'
-import { setupTestEnvironment } from './test-utils'
+import { setupTestEnvironment } from './test-utils.tsx'
// Setup global test environment
setupTestEnvironment()
diff --git a/frontend/src/test/test-utils.tsx b/frontend/src/test/test-utils.tsx
index bd854e5..643e21f 100644
--- a/frontend/src/test/test-utils.tsx
+++ b/frontend/src/test/test-utils.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { render, RenderOptions } from '@testing-library/react'
import { BrowserRouter } from 'react-router-dom'
import { vi } from 'vitest'
+import { NotificationProvider } from '../contexts/NotificationContext'
interface User {
id: string
@@ -38,12 +39,46 @@ export const createMockAdminUser = (overrides: Partial = {}): User => ({
// Centralized API mocking to eliminate per-file duplication
export const createMockApiServices = () => {
const mockDocumentService = {
- enhancedSearch: vi.fn().mockResolvedValue({ documents: [], total: 0 }),
+ enhancedSearch: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ total: 0,
+ query_time_ms: 0,
+ suggestions: []
+ }
+ }),
+ search: vi.fn().mockResolvedValue({
+ data: {
+ documents: [],
+ total: 0,
+ query_time_ms: 0,
+ suggestions: []
+ }
+ }),
bulkRetryOcr: vi.fn().mockResolvedValue({ success: true }),
getDocument: vi.fn().mockResolvedValue({}),
- uploadDocument: vi.fn().mockResolvedValue({}),
- deleteDocument: vi.fn().mockResolvedValue({}),
- updateDocument: vi.fn().mockResolvedValue({}),
+ getById: vi.fn().mockResolvedValue({ data: {} }),
+ upload: vi.fn().mockResolvedValue({ data: {} }),
+ list: vi.fn().mockResolvedValue({ data: [] }),
+ listWithPagination: vi.fn().mockResolvedValue({ data: { documents: [], pagination: { total: 0, limit: 20, offset: 0, has_more: false } } }),
+ delete: vi.fn().mockResolvedValue({}),
+ bulkDelete: vi.fn().mockResolvedValue({}),
+ retryOcr: vi.fn().mockResolvedValue({}),
+ getFacets: vi.fn().mockResolvedValue({ data: { mime_types: [], tags: [] } }),
+ getOcrText: vi.fn().mockResolvedValue({ data: {} }),
+ download: vi.fn().mockResolvedValue({ data: new Blob() }),
+ getFailedOcrDocuments: vi.fn().mockResolvedValue({ data: [] }),
+ getFailedDocuments: vi.fn().mockResolvedValue({ data: [] }),
+ deleteLowConfidence: vi.fn().mockResolvedValue({ data: {} }),
+ deleteFailedOcr: vi.fn().mockResolvedValue({ data: {} }),
+ view: vi.fn().mockResolvedValue({ data: new Blob() }),
+ getThumbnail: vi.fn().mockResolvedValue({ data: new Blob() }),
+ getProcessedImage: vi.fn().mockResolvedValue({ data: new Blob() }),
+ downloadFile: vi.fn().mockResolvedValue(undefined),
+ getDuplicates: vi.fn().mockResolvedValue({ data: [] }),
+ getRetryStats: vi.fn().mockResolvedValue({ data: {} }),
+ getRetryRecommendations: vi.fn().mockResolvedValue({ data: [] }),
+ getDocumentRetryHistory: vi.fn().mockResolvedValue({ data: [] }),
}
const mockAuthService = {
@@ -77,24 +112,11 @@ export const createMockApiServices = () => {
}
// Setup global API mocks (call this in setup files)
+// Note: Individual test files should handle their own vi.mock() calls
export const setupApiMocks = () => {
- const mockServices = createMockApiServices()
-
- vi.mock('../../services/api', () => ({
- documentService: mockServices.documentService,
- authService: mockServices.authService,
- sourceService: mockServices.sourceService,
- labelService: mockServices.labelService,
- api: {
- defaults: {
- headers: {
- common: {}
- }
- }
- }
- }))
-
- return mockServices
+ // Just return the mock services for use in tests
+ // The actual vi.mock() should be done in individual test files
+ return createMockApiServices()
}
// Create a mock AuthProvider for testing
@@ -136,9 +158,11 @@ const AllTheProviders = ({
}) => {
return (
-
- {children}
-
+
+
+ {children}
+
+
)
}