complete project using prettier!

This commit is contained in:
2025-12-22 09:45:14 -08:00
parent 621d30b84f
commit a10f84aa48
339 changed files with 18041 additions and 8969 deletions

View File

@@ -6,7 +6,10 @@ import { PriceHistoryChart } from './PriceHistoryChart';
import { useUserData } from '../../hooks/useUserData';
import * as apiClient from '../../services/apiClient';
import type { MasterGroceryItem, HistoricalPriceDataPoint } from '../../types';
import { createMockMasterGroceryItem, createMockHistoricalPriceDataPoint } from '../../tests/utils/mockFactories';
import {
createMockMasterGroceryItem,
createMockHistoricalPriceDataPoint,
} from '../../tests/utils/mockFactories';
// Mock the apiClient
vi.mock('../../services/apiClient');
@@ -24,19 +27,24 @@ vi.mock('../../services/logger', () => ({
// Mock the recharts library to prevent rendering complex SVGs in jsdom
vi.mock('recharts', () => ({
ResponsiveContainer: ({ children }: { children: React.ReactNode }) => <div data-testid="responsive-container">{children}</div>,
ResponsiveContainer: ({ children }: { children: React.ReactNode }) => (
<div data-testid="responsive-container">{children}</div>
),
// Expose the data prop for testing data transformations
LineChart: ({ children, data }: { children: React.ReactNode; data: any[] }) => (
<div data-testid="line-chart" data-chartdata={JSON.stringify(data)}>
{children}
</div>),
</div>
),
CartesianGrid: () => <div data-testid="cartesian-grid" />,
XAxis: () => <div data-testid="x-axis" />,
YAxis: () => <div data-testid="y-axis" />,
Tooltip: () => <div data-testid="tooltip" />,
Legend: () => <div data-testid="legend" />,
// Fix: Use dataKey if name is not explicitly provided, as the component relies on dataKey
Line: ({ name, dataKey }: { name?: string; dataKey?: string }) => <div data-testid={`line-${name || dataKey}`} />,
Line: ({ name, dataKey }: { name?: string; dataKey?: string }) => (
<div data-testid={`line-${name || dataKey}`} />
),
}));
const mockWatchedItems: MasterGroceryItem[] = [
@@ -45,10 +53,26 @@ const mockWatchedItems: MasterGroceryItem[] = [
];
const mockPriceHistory: HistoricalPriceDataPoint[] = [
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 110 }),
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-08', avg_price_in_cents: 99 }),
createMockHistoricalPriceDataPoint({ master_item_id: 2, summary_date: '2024-10-01', avg_price_in_cents: 350 }),
createMockHistoricalPriceDataPoint({ master_item_id: 2, summary_date: '2024-10-08', avg_price_in_cents: 349 }),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-01',
avg_price_in_cents: 110,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-08',
avg_price_in_cents: 99,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 2,
summary_date: '2024-10-01',
avg_price_in_cents: 350,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 2,
summary_date: '2024-10-08',
avg_price_in_cents: 349,
}),
];
describe('PriceHistoryChart', () => {
@@ -75,7 +99,9 @@ describe('PriceHistoryChart', () => {
error: null,
});
render(<PriceHistoryChart />);
expect(screen.getByText('Add items to your watchlist to see their price trends over time.')).toBeInTheDocument();
expect(
screen.getByText('Add items to your watchlist to see their price trends over time.'),
).toBeInTheDocument();
});
it('should display a loading state while fetching data', () => {
@@ -95,16 +121,24 @@ describe('PriceHistoryChart', () => {
});
it('should display a message if no historical data is returned', async () => {
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify([])));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify([])),
);
render(<PriceHistoryChart />);
await waitFor(() => {
expect(screen.getByText('Not enough historical data for your watched items. Process more flyers to build a trend.')).toBeInTheDocument();
expect(
screen.getByText(
'Not enough historical data for your watched items. Process more flyers to build a trend.',
),
).toBeInTheDocument();
});
});
it('should render the chart with data on successful fetch', async () => {
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(mockPriceHistory)));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify(mockPriceHistory)),
);
render(<PriceHistoryChart />);
await waitFor(() => {
@@ -139,7 +173,9 @@ describe('PriceHistoryChart', () => {
});
it('should clear the chart when the watchlist becomes empty', async () => {
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(mockPriceHistory)));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify(mockPriceHistory)),
);
const { rerender } = render(<PriceHistoryChart />);
// Initial render with items
@@ -160,18 +196,34 @@ describe('PriceHistoryChart', () => {
// Chart should be gone, placeholder should appear
await waitFor(() => {
expect(screen.getByText('Add items to your watchlist to see their price trends over time.')).toBeInTheDocument();
expect(
screen.getByText('Add items to your watchlist to see their price trends over time.'),
).toBeInTheDocument();
expect(screen.queryByTestId('line-chart')).not.toBeInTheDocument();
});
});
it('should filter out items with only one data point', async () => {
const dataWithSinglePoint: HistoricalPriceDataPoint[] = [
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 110 }),
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-08', avg_price_in_cents: 99 }),
createMockHistoricalPriceDataPoint({ master_item_id: 2, summary_date: '2024-10-01', avg_price_in_cents: 350 }), // Almond Milk only has one point
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-01',
avg_price_in_cents: 110,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-08',
avg_price_in_cents: 99,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 2,
summary_date: '2024-10-01',
avg_price_in_cents: 350,
}), // Almond Milk only has one point
];
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(dataWithSinglePoint)));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify(dataWithSinglePoint)),
);
render(<PriceHistoryChart />);
await waitFor(() => {
@@ -182,37 +234,65 @@ describe('PriceHistoryChart', () => {
it('should process data to only keep the lowest price for a given day', async () => {
const dataWithDuplicateDate: HistoricalPriceDataPoint[] = [
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 110 }),
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 105 }), // Lower price
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-08', avg_price_in_cents: 99 }),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-01',
avg_price_in_cents: 110,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-01',
avg_price_in_cents: 105,
}), // Lower price
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-08',
avg_price_in_cents: 99,
}),
];
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(dataWithDuplicateDate)));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify(dataWithDuplicateDate)),
);
render(<PriceHistoryChart />);
await waitFor(() => {
const chart = screen.getByTestId('line-chart');
const chartData = JSON.parse(chart.getAttribute('data-chartdata')!);
// The date gets formatted to 'Oct 1'
const dataPointForOct1 = chartData.find((d: any) => d.date === 'Oct 1');
expect(dataPointForOct1['Organic Bananas']).toBe(105);
});
});
it('should filter out data points with a price of zero', async () => {
const dataWithZeroPrice: HistoricalPriceDataPoint[] = [
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-01', avg_price_in_cents: 110 }),
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-08', avg_price_in_cents: 0 }), // Zero price should be filtered
createMockHistoricalPriceDataPoint({ master_item_id: 1, summary_date: '2024-10-15', avg_price_in_cents: 105 }),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-01',
avg_price_in_cents: 110,
}),
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-08',
avg_price_in_cents: 0,
}), // Zero price should be filtered
createMockHistoricalPriceDataPoint({
master_item_id: 1,
summary_date: '2024-10-15',
avg_price_in_cents: 105,
}),
];
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(new Response(JSON.stringify(dataWithZeroPrice)));
vi.mocked(apiClient.fetchHistoricalPriceData).mockResolvedValue(
new Response(JSON.stringify(dataWithZeroPrice)),
);
render(<PriceHistoryChart />);
await waitFor(() => {
const chart = screen.getByTestId('line-chart');
const chartData = JSON.parse(chart.getAttribute('data-chartdata')!);
// The date 'Oct 8' should not be in the chart data at all
const dataPointForOct8 = chartData.find((d: any) => d.date === 'Oct 8');
expect(dataPointForOct8).toBeUndefined();
@@ -221,4 +301,4 @@ describe('PriceHistoryChart', () => {
expect(chartData).toHaveLength(2);
});
});
});
});