Files
flyer-crawler.projectium.com/src/pages/MyDealsPage.test.tsx
Torben Sorensen 9bee0a013b
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 17m8s
unit test auto-provider refactor
2026-01-02 11:58:03 -08:00

133 lines
4.5 KiB
TypeScript

// src/pages/MyDealsPage.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mocked } from 'vitest';
import MyDealsPage from './MyDealsPage';
import * as apiClient from '../services/apiClient';
import type { WatchedItemDeal } from '../types';
import { logger } from '../services/logger.client';
import { createMockWatchedItemDeal } from '../tests/utils/mockFactories';
// The apiClient is mocked globally in `src/tests/setup/globalApiMock.ts`.
const mockedApiClient = vi.mocked(apiClient);
// Mock lucide-react icons to prevent rendering errors in the test environment
vi.mock('lucide-react', () => ({
AlertCircle: () => <div data-testid="alert-circle-icon" />,
Tag: () => <div data-testid="tag-icon" />,
Store: () => <div data-testid="store-icon" />,
Calendar: () => <div data-testid="calendar-icon" />,
}));
describe('MyDealsPage', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should display a loading message initially', () => {
// Mock a pending promise
mockedApiClient.fetchBestSalePrices.mockReturnValue(new Promise(() => {}));
render(<MyDealsPage />);
expect(screen.getByText('Loading your deals...')).toBeInTheDocument();
});
it('should display an error message if the API call fails', async () => {
mockedApiClient.fetchBestSalePrices.mockResolvedValue(
new Response(null, { status: 500, statusText: 'Server Error' }),
);
render(<MyDealsPage />);
await waitFor(() => {
expect(screen.getByText('Error')).toBeInTheDocument();
expect(
screen.getByText('Failed to fetch deals. Please try again later.'),
).toBeInTheDocument();
});
expect(logger.error).toHaveBeenCalledWith(
'Error fetching watched item deals:',
'Failed to fetch deals. Please try again later.',
);
});
it('should handle network errors and log them', async () => {
const networkError = new Error('Network connection failed');
mockedApiClient.fetchBestSalePrices.mockRejectedValue(networkError);
render(<MyDealsPage />);
await waitFor(() => {
expect(screen.getByText('Error')).toBeInTheDocument();
expect(screen.getByText('Network connection failed')).toBeInTheDocument();
});
expect(logger.error).toHaveBeenCalledWith(
'Error fetching watched item deals:',
'Network connection failed',
);
});
it('should handle unknown errors and log them', async () => {
// Mock a rejection with a non-Error object (e.g., a string) to trigger the fallback error message
mockedApiClient.fetchBestSalePrices.mockRejectedValue('Unknown failure');
render(<MyDealsPage />);
await waitFor(() => {
expect(screen.getByText('Error')).toBeInTheDocument();
expect(screen.getByText('An unknown error occurred.')).toBeInTheDocument();
});
expect(logger.error).toHaveBeenCalledWith(
'Error fetching watched item deals:',
'An unknown error occurred.',
);
});
it('should display a message when no deals are found', async () => {
mockedApiClient.fetchBestSalePrices.mockResolvedValue(
new Response(JSON.stringify([]), {
headers: { 'Content-Type': 'application/json' },
}),
);
render(<MyDealsPage />);
await waitFor(() => {
expect(
screen.getByText('No deals found for your watched items right now.'),
).toBeInTheDocument();
});
});
it('should render the list of deals on successful fetch', async () => {
const mockDeals: WatchedItemDeal[] = [
createMockWatchedItemDeal({
master_item_id: 1,
item_name: 'Organic Bananas',
best_price_in_cents: 99,
store_name: 'Green Grocer',
flyer_id: 101,
valid_to: '2024-10-20',
}),
createMockWatchedItemDeal({
master_item_id: 2,
item_name: 'Almond Milk',
best_price_in_cents: 349,
store_name: 'SuperMart',
flyer_id: 102,
valid_to: '2024-10-22',
}),
];
mockedApiClient.fetchBestSalePrices.mockResolvedValue(
new Response(JSON.stringify(mockDeals), {
headers: { 'Content-Type': 'application/json' },
}),
);
render(<MyDealsPage />);
await waitFor(() => {
expect(screen.getByText('Organic Bananas')).toBeInTheDocument();
expect(screen.getByText('$0.99')).toBeInTheDocument();
expect(screen.getByText('Almond Milk')).toBeInTheDocument();
expect(screen.getByText('$3.49')).toBeInTheDocument();
expect(screen.getByText('Green Grocer')).toBeInTheDocument();
});
});
});