test: add dashboard redesign tests (refs #201)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 3m22s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 51s
Deploy to Staging / Verify Staging (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 3m22s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 51s
Deploy to Staging / Verify Staging (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { ActionBar } from '../ActionBar';
|
||||
|
||||
describe('ActionBar', () => {
|
||||
it('renders both buttons with correct text', () => {
|
||||
const onAddVehicle = jest.fn();
|
||||
const onLogFuel = jest.fn();
|
||||
|
||||
render(<ActionBar onAddVehicle={onAddVehicle} onLogFuel={onLogFuel} />);
|
||||
|
||||
expect(screen.getByText('Add Vehicle')).toBeInTheDocument();
|
||||
expect(screen.getByText('Log Fuel')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onAddVehicle when Add Vehicle button clicked', () => {
|
||||
const onAddVehicle = jest.fn();
|
||||
const onLogFuel = jest.fn();
|
||||
|
||||
render(<ActionBar onAddVehicle={onAddVehicle} onLogFuel={onLogFuel} />);
|
||||
|
||||
const addVehicleButton = screen.getByText('Add Vehicle');
|
||||
fireEvent.click(addVehicleButton);
|
||||
|
||||
expect(onAddVehicle).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls onLogFuel when Log Fuel button clicked', () => {
|
||||
const onAddVehicle = jest.fn();
|
||||
const onLogFuel = jest.fn();
|
||||
|
||||
render(<ActionBar onAddVehicle={onAddVehicle} onLogFuel={onLogFuel} />);
|
||||
|
||||
const logFuelButton = screen.getByText('Log Fuel');
|
||||
fireEvent.click(logFuelButton);
|
||||
|
||||
expect(onLogFuel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,125 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ThemeProvider, createTheme } from '@mui/material';
|
||||
import { DashboardScreen } from '../DashboardScreen';
|
||||
import { Vehicle } from '../../../vehicles/types/vehicles.types';
|
||||
import { VehicleRosterData } from '../../types';
|
||||
import { useVehicleRoster } from '../../hooks/useDashboardData';
|
||||
|
||||
jest.mock('@auth0/auth0-react');
|
||||
jest.mock('../../../../core/api/client');
|
||||
jest.mock('../../../vehicles/api/vehicles.api');
|
||||
jest.mock('../../../maintenance/api/maintenance.api');
|
||||
jest.mock('../../../documents/api/documents.api');
|
||||
jest.mock('../../../vehicles/components/VehicleImage', () => ({
|
||||
VehicleImage: () => <div data-testid="vehicle-image" />,
|
||||
}));
|
||||
jest.mock('../../../email-ingestion/components/PendingAssociationBanner', () => ({
|
||||
PendingAssociationBanner: () => null,
|
||||
}));
|
||||
jest.mock('../../../email-ingestion/components/PendingAssociationList', () => ({
|
||||
PendingAssociationList: () => null,
|
||||
}));
|
||||
jest.mock('../../hooks/useDashboardData');
|
||||
|
||||
const mockUseVehicleRoster = useVehicleRoster as jest.MockedFunction<typeof useVehicleRoster>;
|
||||
|
||||
const makeVehicle = (overrides: Partial<Vehicle> = {}): Vehicle => ({
|
||||
id: 'vehicle-1',
|
||||
userId: 'user-1',
|
||||
vin: '1HGBH41JXMN109186',
|
||||
year: 2019,
|
||||
make: 'Ford',
|
||||
model: 'F-150',
|
||||
odometerReading: 87412,
|
||||
isActive: true,
|
||||
createdAt: '2025-01-01T00:00:00Z',
|
||||
updatedAt: '2025-01-01T00:00:00Z',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
const makeRosterData = (vehicle?: Vehicle): VehicleRosterData => ({
|
||||
vehicle: vehicle ?? makeVehicle(),
|
||||
health: 'green' as const,
|
||||
attentionItems: [],
|
||||
});
|
||||
|
||||
const theme = createTheme();
|
||||
|
||||
const renderWithProviders = (ui: React.ReactElement) => {
|
||||
return render(
|
||||
<ThemeProvider theme={theme}>
|
||||
{ui}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('DashboardScreen', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders vehicle roster cards', () => {
|
||||
const vehicle1 = makeVehicle({ id: 'v1', make: 'Ford', model: 'F-150', year: 2019 });
|
||||
const vehicle2 = makeVehicle({ id: 'v2', make: 'Honda', model: 'Civic', year: 2020 });
|
||||
const roster = [makeRosterData(vehicle1), makeRosterData(vehicle2)];
|
||||
|
||||
mockUseVehicleRoster.mockReturnValue({
|
||||
data: roster,
|
||||
vehicles: [vehicle1, vehicle2],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refetch: jest.fn(),
|
||||
});
|
||||
|
||||
renderWithProviders(<DashboardScreen />);
|
||||
|
||||
expect(screen.getByText('2019 Ford F-150')).toBeInTheDocument();
|
||||
expect(screen.getByText('2020 Honda Civic')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders empty state when 0 vehicles', () => {
|
||||
mockUseVehicleRoster.mockReturnValue({
|
||||
data: [],
|
||||
vehicles: [],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refetch: jest.fn(),
|
||||
});
|
||||
|
||||
renderWithProviders(<DashboardScreen />);
|
||||
|
||||
expect(screen.getByText('Welcome to MotoVaultPro')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders loading skeletons when loading', () => {
|
||||
mockUseVehicleRoster.mockReturnValue({
|
||||
data: undefined,
|
||||
vehicles: undefined,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
refetch: jest.fn(),
|
||||
});
|
||||
|
||||
renderWithProviders(<DashboardScreen />);
|
||||
|
||||
expect(screen.getByText('Your Fleet')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders "Your Fleet" heading', () => {
|
||||
const vehicle = makeVehicle();
|
||||
const roster = [makeRosterData(vehicle)];
|
||||
|
||||
mockUseVehicleRoster.mockReturnValue({
|
||||
data: roster,
|
||||
vehicles: [vehicle],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refetch: jest.fn(),
|
||||
});
|
||||
|
||||
renderWithProviders(<DashboardScreen />);
|
||||
|
||||
expect(screen.getByText('Your Fleet')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { VehicleRosterCard } from '../VehicleRosterCard';
|
||||
import { Vehicle } from '../../../vehicles/types/vehicles.types';
|
||||
import { VehicleRosterData, AttentionItem } from '../../types';
|
||||
|
||||
jest.mock('@auth0/auth0-react');
|
||||
jest.mock('../../../vehicles/components/VehicleImage', () => ({
|
||||
VehicleImage: () => <div data-testid="vehicle-image" />,
|
||||
}));
|
||||
|
||||
const makeVehicle = (overrides: Partial<Vehicle> = {}): Vehicle => ({
|
||||
id: 'vehicle-1',
|
||||
userId: 'user-1',
|
||||
vin: '1HGBH41JXMN109186',
|
||||
year: 2019,
|
||||
make: 'Ford',
|
||||
model: 'F-150',
|
||||
odometerReading: 87412,
|
||||
isActive: true,
|
||||
createdAt: '2025-01-01T00:00:00Z',
|
||||
updatedAt: '2025-01-01T00:00:00Z',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
const makeRosterData = (overrides: Partial<VehicleRosterData> = {}): VehicleRosterData => ({
|
||||
vehicle: makeVehicle(),
|
||||
health: 'green',
|
||||
attentionItems: [],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe('VehicleRosterCard', () => {
|
||||
it('renders vehicle label with year make model', () => {
|
||||
const data = makeRosterData();
|
||||
const onClick = jest.fn();
|
||||
|
||||
render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
expect(screen.getByText('2019 Ford F-150')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders health badge with correct color class for green health', () => {
|
||||
const data = makeRosterData({ health: 'green' });
|
||||
const onClick = jest.fn();
|
||||
|
||||
const { container } = render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
const badge = container.querySelector('.bg-emerald-500');
|
||||
expect(badge).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders health badge with correct color class for yellow health', () => {
|
||||
const data = makeRosterData({ health: 'yellow' });
|
||||
const onClick = jest.fn();
|
||||
|
||||
const { container } = render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
const badge = container.querySelector('.bg-amber-500');
|
||||
expect(badge).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders health badge with correct color class for red health', () => {
|
||||
const data = makeRosterData({ health: 'red' });
|
||||
const onClick = jest.fn();
|
||||
|
||||
const { container } = render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
const badge = container.querySelector('.bg-red-500');
|
||||
expect(badge).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders attention items text', () => {
|
||||
const attentionItems: AttentionItem[] = [
|
||||
{
|
||||
label: 'Oil Change',
|
||||
urgency: 'overdue',
|
||||
daysUntilDue: -5,
|
||||
source: 'maintenance',
|
||||
},
|
||||
];
|
||||
const data = makeRosterData({ attentionItems });
|
||||
const onClick = jest.fn();
|
||||
|
||||
render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
expect(screen.getByText('Oil Change - OVERDUE')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders odometer with formatting', () => {
|
||||
const data = makeRosterData();
|
||||
const onClick = jest.fn();
|
||||
|
||||
render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
expect(screen.getByText('87,412 mi')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onClick with vehicle ID when clicked', () => {
|
||||
const data = makeRosterData();
|
||||
const onClick = jest.fn();
|
||||
|
||||
render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
fireEvent.click(screen.getByText('2019 Ford F-150'));
|
||||
|
||||
expect(onClick).toHaveBeenCalledWith('vehicle-1');
|
||||
});
|
||||
|
||||
it('renders All clear when no attention items', () => {
|
||||
const data = makeRosterData({ attentionItems: [] });
|
||||
const onClick = jest.fn();
|
||||
|
||||
render(<VehicleRosterCard data={data} onClick={onClick} />);
|
||||
|
||||
expect(screen.getByText('All clear')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user