disable some tests to see if we can narrow down the fuckery
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 2m51s
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 2m51s
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
// src/components/PriceHistoryChart.test.tsx
|
||||
import React from 'react';
|
||||
import { render, screen, waitFor, act } from '@testing-library/react';
|
||||
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
|
||||
import { PriceHistoryChart } from './PriceHistoryChart';
|
||||
import * as apiClient from '../../services/apiClient';
|
||||
import type { MasterGroceryItem } from '../../types';
|
||||
|
||||
// Mock the apiClient module. Since App.test.tsx provides a complete mock for the
|
||||
// entire test suite, we just need to ensure this file uses it.
|
||||
// The factory function `() => vi.importActual(...)` tells Vitest to
|
||||
// use the already-mocked version from the module registry. This was incorrect.
|
||||
// We should use `vi.importMock` to get the mocked version.
|
||||
vi.mock('../../services/apiClient', async () => {
|
||||
return vi.importMock<typeof apiClient>('../../services/apiClient');
|
||||
});
|
||||
|
||||
// Mock recharts library
|
||||
// This mock remains correct.
|
||||
vi.mock('recharts', async () => {
|
||||
const OriginalModule = await vi.importActual('recharts');
|
||||
return {
|
||||
...OriginalModule,
|
||||
ResponsiveContainer: ({ children }: { children: React.ReactNode }) => (
|
||||
<div data-testid="responsive-container">{children}</div>
|
||||
),
|
||||
// Wrap the mocked LineChart in vi.fn() so we can inspect its calls and props.
|
||||
// This is necessary for the test that verifies data processing.
|
||||
LineChart: vi.fn(({ children }: { children: React.ReactNode }) => <div data-testid="line-chart">{children}</div>),
|
||||
Line: ({ dataKey }: { dataKey: string }) => <div data-testid={`line-${dataKey}`}></div>,
|
||||
};
|
||||
});
|
||||
|
||||
const mockWatchedItems: MasterGroceryItem[] = [
|
||||
{ master_grocery_item_id: 1, name: 'Apples', category_id: 1, category_name: 'Produce', created_at: '' },
|
||||
{ master_grocery_item_id: 2, name: 'Milk', category_id: 2, category_name: 'Dairy', created_at: '' },
|
||||
{ master_grocery_item_id: 3, name: 'Bread', category_id: 3, category_name: 'Bakery', created_at: '' }, // Will be filtered out (1 data point)
|
||||
];
|
||||
|
||||
const mockRawData = [
|
||||
// Apples data
|
||||
{ master_item_id: 1, avg_price_in_cents: 120, summary_date: '2023-10-01' },
|
||||
{ master_item_id: 1, avg_price_in_cents: 110, summary_date: '2023-10-08' },
|
||||
{ master_item_id: 1, avg_price_in_cents: 130, summary_date: '2023-10-08' }, // Higher price, should be ignored
|
||||
// Milk data
|
||||
{ master_item_id: 2, avg_price_in_cents: 250, summary_date: '2023-10-01' },
|
||||
{ master_item_id: 2, avg_price_in_cents: 240, summary_date: '2023-10-15' },
|
||||
// Bread data (only one point)
|
||||
{ master_item_id: 3, avg_price_in_cents: 200, summary_date: '2023-10-01' },
|
||||
// Data with nulls to be ignored
|
||||
{ master_item_id: 4, avg_price_in_cents: null, summary_date: '2023-10-01' },
|
||||
];
|
||||
|
||||
describe('PriceHistoryChart', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it.todo('TODO: should render a loading spinner while fetching data', () => {
|
||||
// This test uses a manually-resolved promise pattern that is still causing test hangs and memory leaks.
|
||||
// Disabling to get the pipeline passing.
|
||||
});
|
||||
/*
|
||||
it('should render a loading spinner while fetching data', async () => {
|
||||
let resolvePromise: (value: Response) => void;
|
||||
const mockPromise = new Promise<Response>(resolve => {
|
||||
resolvePromise = resolve;
|
||||
});
|
||||
(apiClient.fetchHistoricalPriceData as Mock).mockReturnValue(mockPromise);
|
||||
render(<PriceHistoryChart watchedItems={mockWatchedItems} />);
|
||||
expect(screen.getByText(/loading price history/i)).toBeInTheDocument();
|
||||
expect(screen.getByRole('status')).toBeInTheDocument(); // LoadingSpinner
|
||||
await act(async () => {
|
||||
resolvePromise(new Response(JSON.stringify([])));
|
||||
await mockPromise;
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
it('should render an error message if fetching fails', async () => {
|
||||
(apiClient.fetchHistoricalPriceData as Mock).mockRejectedValue(new Error('API is down'));
|
||||
render(<PriceHistoryChart watchedItems={mockWatchedItems} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Error:')).toBeInTheDocument();
|
||||
expect(screen.getByText('API is down')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render a message if no watched items are provided', () => {
|
||||
render(<PriceHistoryChart watchedItems={[]} />);
|
||||
expect(screen.getByText(/add items to your watchlist/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render a message if not enough historical data is available', async () => {
|
||||
(apiClient.fetchHistoricalPriceData as Mock).mockResolvedValue(new Response(JSON.stringify([
|
||||
{ master_item_id: 1, avg_price_in_cents: 120, summary_date: '2023-10-01' }, // Only one data point
|
||||
])));
|
||||
render(<PriceHistoryChart watchedItems={mockWatchedItems} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/not enough historical data/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should process raw data and render the chart with correct lines', async () => {
|
||||
(apiClient.fetchHistoricalPriceData as Mock).mockResolvedValue(new Response(JSON.stringify(mockRawData)));
|
||||
render(<PriceHistoryChart watchedItems={mockWatchedItems} />);
|
||||
|
||||
await waitFor(() => {
|
||||
// Check that the chart components are rendered
|
||||
expect(screen.getByTestId('responsive-container')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('line-chart')).toBeInTheDocument();
|
||||
|
||||
// Check that lines are created for items with more than one data point
|
||||
expect(screen.getByTestId('line-Apples')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('line-Milk')).toBeInTheDocument();
|
||||
|
||||
// Check that 'Bread' is filtered out because it only has one data point
|
||||
expect(screen.queryByTestId('line-Bread')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly process data, keeping only the lowest price per day', async () => {
|
||||
// This test relies on the `chartData` calculation inside the component.
|
||||
// We can't directly inspect `chartData`, but we can verify the mock `LineChart`
|
||||
// receives the correctly processed data.
|
||||
(apiClient.fetchHistoricalPriceData as Mock).mockResolvedValue(new Response(JSON.stringify(mockRawData)));
|
||||
|
||||
// We need to spy on the props passed to the mocked LineChart
|
||||
const { LineChart } = await import('recharts');
|
||||
render(<PriceHistoryChart watchedItems={mockWatchedItems} />);
|
||||
|
||||
await waitFor(() => {
|
||||
const lineChartProps = vi.mocked(LineChart).mock.calls[0][0];
|
||||
const chartData = lineChartProps.data as { date: string; Apples?: number; Milk?: number }[];
|
||||
|
||||
// Find the entry for Oct 8
|
||||
const oct8Entry = chartData.find(d => d.date.includes('Oct') && d.date.includes('8'));
|
||||
// The price for Apples on Oct 8 should be 110, not 130.
|
||||
expect(oct8Entry?.Apples).toBe(110);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user