import React from 'react';
import { render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi, describe, test, beforeEach, expect } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import { FilterProvider } from '../../contexts/FilterContext';
import { AdminProvider } from '../../contexts/AdminContext';
import HeaderNav from '../../components/HeaderNav';
import FilterBar from '../../components/FilterBar';
import ExportModal from '../../components/ExportModal';
import HelpPage from '../../pages/HelpPage';
// Mock react-router-dom
const mockNavigate = vi.fn();
const mockUseLocation = vi.fn();
vi.mock('react-router-dom', () => ({
BrowserRouter: ({ children }: { children: React.ReactNode }) => <>{children}>,
useNavigate: () => mockNavigate,
useLocation: () => mockUseLocation(),
}));
// Mock the useFilterContext hook
const mockUseFilterContext = {
search: '',
srcFilter: '',
catFilter: '',
regionFilter: '',
countryFilter: '',
imageTypeFilter: '',
showReferenceExamples: false,
setSearch: vi.fn(),
setSrcFilter: vi.fn(),
setCatFilter: vi.fn(),
setRegionFilter: vi.fn(),
setCountryFilter: vi.fn(),
setImageTypeFilter: vi.fn(),
setShowReferenceExamples: vi.fn(),
clearAllFilters: vi.fn(),
};
// Mock the useAdminContext hook
const mockUseAdminContext = {
isAdmin: true,
login: vi.fn(),
logout: vi.fn(),
};
vi.mock('../../hooks/useFilterContext', () => ({
useFilterContext: () => mockUseFilterContext,
}));
vi.mock('../../hooks/useAdminContext', () => ({
useAdminContext: () => mockUseAdminContext,
}));
// Mock JSZip
vi.mock('jszip', () => ({
__esModule: true,
default: vi.fn().mockImplementation(() => ({
file: vi.fn(),
generateAsync: vi.fn().mockResolvedValue('mock-zip-data'),
})),
}));
describe('App Workflow Integration', () => {
const mockProps = {
sources: [{ s_code: 'WFP', label: 'World Food Programme' }, { s_code: 'IFRC', label: 'IFRC' }],
types: [{ t_code: 'EARTHQUAKE', label: 'Earthquake' }, { t_code: 'FLOOD', label: 'Flood' }],
regions: [{ r_code: 'ASIA', label: 'Asia' }, { r_code: 'AFRICA', label: 'Africa' }],
countries: [{ c_code: 'BD', label: 'Bangladesh', r_code: 'ASIA' }, { c_code: 'IN', label: 'India', r_code: 'ASIA' }],
imageTypes: [{ image_type: 'SATELLITE', label: 'Satellite' }, { image_type: 'AERIAL', label: 'Aerial' }],
};
beforeEach(() => {
vi.clearAllMocks();
mockUseLocation.mockReturnValue({ pathname: '/' });
});
test('Complete user workflow: navigate, filter, and export', async () => {
const user = userEvent.setup();
const mockOnClose = vi.fn();
const mockOnExport = vi.fn();
render(
);
// Step 1: Navigate to help page
const helpButton = screen.getByRole('button', { name: /help/i });
await user.click(helpButton);
expect(mockNavigate).toHaveBeenCalledWith('/help');
// Step 2: Apply filters
const sourceInput = screen.getByPlaceholderText('All Sources');
const categoryInput = screen.getByPlaceholderText('All Categories');
await user.click(sourceInput);
const wfpOption = screen.getByText('World Food Programme');
await user.click(wfpOption);
expect(mockUseFilterContext.setSrcFilter).toHaveBeenCalledWith('WFP');
await user.click(categoryInput);
const earthquakeOption = screen.getByText('Earthquake');
await user.click(earthquakeOption);
expect(mockUseFilterContext.setCatFilter).toHaveBeenCalledWith('EARTHQUAKE');
// Step 3: Check export modal
expect(screen.getByText(/Crisis Maps/i)).toBeInTheDocument();
expect(screen.getByText(/Drone Images/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /export selected/i })).toBeInTheDocument();
});
test('Admin workflow: access admin features and manage data', async () => {
// Mock admin state
mockUseAdminContext.isAdmin = true;
render(
);
// Step 1: Check admin navigation
const adminButton = screen.getByRole('button', { name: /dev/i });
expect(adminButton).toBeInTheDocument();
// Step 2: Check admin export features
expect(screen.getByText(/Export Dataset/i)).toBeInTheDocument();
expect(screen.getByText(/Crisis Maps/i)).toBeInTheDocument();
expect(screen.getByText(/Drone Images/i)).toBeInTheDocument();
});
test('Filter workflow: apply and clear filters', async () => {
const user = userEvent.setup();
render(
);
// Step 1: Apply multiple filters
const sourceInput = screen.getByPlaceholderText('All Sources');
const categoryInput = screen.getByPlaceholderText('All Categories');
await user.click(sourceInput);
const ifrcOption = screen.getByText('IFRC');
await user.click(ifrcOption);
await user.click(categoryInput);
const floodOption = screen.getByText('Flood');
await user.click(floodOption);
// Step 2: Verify filters are set
expect(mockUseFilterContext.setSrcFilter).toHaveBeenCalledWith('IFRC');
expect(mockUseFilterContext.setCatFilter).toHaveBeenCalledWith('FLOOD');
// Step 3: Clear all filters
const clearButton = screen.getByRole('button', { name: /clear/i });
await user.click(clearButton);
expect(mockUseFilterContext.clearAllFilters).toHaveBeenCalled();
});
test('Navigation workflow: move between different pages', async () => {
const user = userEvent.setup();
render(
);
// Step 1: Navigate to help page
const helpButton = screen.getByRole('button', { name: /help/i });
await user.click(helpButton);
expect(mockNavigate).toHaveBeenCalledWith('/help');
// Step 2: Check that help page is rendered
expect(screen.getByRole('heading', { name: /Introduction/i })).toBeInTheDocument();
});
test('Context integration: filters and admin state work together', () => {
// Mock admin state
mockUseAdminContext.isAdmin = true;
render(
);
// Check that admin features are available
expect(screen.getByRole('button', { name: /dev/i })).toBeInTheDocument();
expect(screen.getByText(/Export Dataset/i)).toBeInTheDocument();
// Check that filter functionality is available
expect(screen.getByPlaceholderText('All Sources')).toBeInTheDocument();
expect(screen.getByPlaceholderText('All Categories')).toBeInTheDocument();
});
test('Error handling workflow: handle missing data gracefully', () => {
render(
);
// Check that empty state is handled gracefully
expect(screen.getByText(/Crisis Maps \(0 images\)/i)).toBeInTheDocument();
expect(screen.getByText(/Drone Images \(0 images\)/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /export selected/i })).toBeInTheDocument();
});
});