246 lines
7.3 KiB
TypeScript
246 lines
7.3 KiB
TypeScript
// src/components/TopDeals.test.tsx
|
|
import React from 'react';
|
|
import { render, screen } from '@testing-library/react';
|
|
import { describe, it, expect } from 'vitest';
|
|
import { TopDeals } from './TopDeals';
|
|
import type { FlyerItem } from '../../types';
|
|
import { createMockFlyerItem } from '../../tests/utils/mockFactories';
|
|
|
|
describe('TopDeals', () => {
|
|
const mockFlyerItems: FlyerItem[] = [
|
|
createMockFlyerItem({
|
|
flyer_item_id: 1,
|
|
item: 'Apples',
|
|
price_display: '$1.00',
|
|
price_in_cents: 100,
|
|
quantity: '1 lb',
|
|
category_name: 'Produce',
|
|
flyer_id: 1,
|
|
master_item_id: 1,
|
|
unit_price: { value: 100, unit: 'lb' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 2,
|
|
item: 'Milk',
|
|
price_display: '$2.50',
|
|
price_in_cents: 250,
|
|
quantity: '1L',
|
|
category_name: 'Dairy',
|
|
flyer_id: 1,
|
|
master_item_id: 2,
|
|
unit_price: { value: 250, unit: 'L' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 3,
|
|
item: 'Bread',
|
|
price_display: '$2.00',
|
|
price_in_cents: 200,
|
|
quantity: '1 loaf',
|
|
category_name: 'Bakery',
|
|
flyer_id: 1,
|
|
master_item_id: 3,
|
|
unit_price: { value: 200, unit: 'count' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 4,
|
|
item: 'Eggs',
|
|
price_display: '$3.00',
|
|
price_in_cents: 300,
|
|
quantity: '1 dozen',
|
|
category_name: 'Dairy',
|
|
flyer_id: 1,
|
|
master_item_id: 4,
|
|
unit_price: { value: 25, unit: 'count' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 5,
|
|
item: 'Cheese',
|
|
price_display: '$4.00',
|
|
price_in_cents: 400,
|
|
quantity: '200g',
|
|
category_name: 'Dairy',
|
|
flyer_id: 1,
|
|
master_item_id: 5,
|
|
unit_price: { value: 200, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 6,
|
|
item: 'Yogurt',
|
|
price_display: '$1.50',
|
|
price_in_cents: 150,
|
|
quantity: '500g',
|
|
category_name: 'Dairy',
|
|
flyer_id: 1,
|
|
master_item_id: 6,
|
|
unit_price: { value: 30, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 7,
|
|
item: 'Oranges',
|
|
price_display: '$1.20',
|
|
price_in_cents: 120,
|
|
quantity: '1 lb',
|
|
category_name: 'Produce',
|
|
flyer_id: 1,
|
|
master_item_id: 7,
|
|
unit_price: { value: 120, unit: 'lb' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 8,
|
|
item: 'Cereal',
|
|
price_display: '$3.50',
|
|
price_in_cents: 350,
|
|
quantity: '300g',
|
|
category_name: 'Breakfast',
|
|
flyer_id: 1,
|
|
master_item_id: 8,
|
|
unit_price: { value: 117, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 9,
|
|
item: 'Coffee',
|
|
price_display: '$5.00',
|
|
price_in_cents: 500,
|
|
quantity: '250g',
|
|
category_name: 'Beverages',
|
|
flyer_id: 1,
|
|
master_item_id: 9,
|
|
unit_price: { value: 200, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 10,
|
|
item: 'Tea',
|
|
price_display: '$2.20',
|
|
price_in_cents: 220,
|
|
quantity: '20 bags',
|
|
category_name: 'Beverages',
|
|
flyer_id: 1,
|
|
master_item_id: 10,
|
|
unit_price: { value: 11, unit: 'count' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 11,
|
|
item: 'Pasta',
|
|
price_display: '$1.80',
|
|
price_in_cents: 180,
|
|
quantity: '500g',
|
|
category_name: 'Pantry',
|
|
flyer_id: 1,
|
|
master_item_id: 11,
|
|
unit_price: { value: 36, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 12,
|
|
item: 'Water',
|
|
price_display: '$0.99',
|
|
price_in_cents: 99,
|
|
quantity: '1L',
|
|
category_name: 'Beverages',
|
|
flyer_id: 1,
|
|
master_item_id: 12,
|
|
unit_price: { value: 99, unit: 'L' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 13,
|
|
item: 'Soda',
|
|
price_display: '$0.75',
|
|
price_in_cents: 75,
|
|
quantity: '355ml',
|
|
category_name: 'Beverages',
|
|
flyer_id: 1,
|
|
master_item_id: 13,
|
|
unit_price: { value: 21, unit: '100ml' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 14,
|
|
item: 'Chips',
|
|
price_display: '$2.10',
|
|
price_in_cents: 210,
|
|
quantity: '150g',
|
|
category_name: 'Snacks',
|
|
flyer_id: 1,
|
|
master_item_id: 14,
|
|
unit_price: { value: 140, unit: '100g' },
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 15,
|
|
item: 'Candy',
|
|
price_display: '$0.50',
|
|
price_in_cents: 50,
|
|
quantity: '50g',
|
|
category_name: 'Snacks',
|
|
flyer_id: 1,
|
|
master_item_id: 15,
|
|
unit_price: { value: 100, unit: '100g' },
|
|
}),
|
|
];
|
|
|
|
it('should not render if the items array is empty', () => {
|
|
const { container } = render(<TopDeals items={[]} />);
|
|
expect(container.firstChild).toBeNull();
|
|
});
|
|
|
|
it('should not render if no items have price_in_cents', () => {
|
|
const itemsWithoutPrices: FlyerItem[] = [
|
|
createMockFlyerItem({
|
|
flyer_item_id: 1,
|
|
item: 'Free Sample',
|
|
price_display: 'FREE',
|
|
price_in_cents: null,
|
|
}),
|
|
createMockFlyerItem({
|
|
flyer_item_id: 2,
|
|
item: 'Info Brochure',
|
|
price_display: '',
|
|
price_in_cents: null,
|
|
}),
|
|
];
|
|
const { container } = render(<TopDeals items={itemsWithoutPrices} />);
|
|
expect(container.firstChild).toBeNull();
|
|
});
|
|
|
|
it('should render the correct heading', () => {
|
|
render(<TopDeals items={mockFlyerItems.slice(0, 5)} />);
|
|
expect(
|
|
screen.getByRole('heading', { name: /top 10 deals across all flyers/i }),
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display up to 10 items, sorted by price_in_cents ascending', () => {
|
|
render(<TopDeals items={mockFlyerItems} />);
|
|
|
|
const listItems = screen.getAllByRole('listitem');
|
|
expect(listItems).toHaveLength(10); // Should only show top 10
|
|
|
|
// Corrected expected order of items based on price_in_cents:
|
|
// Candy (50), Soda (75), Water (99), Apples (100), Oranges (120), Yogurt (150), Pasta (180), Bread (200), Chips (210), Tea (220)
|
|
expect(listItems[0]).toHaveTextContent('Candy');
|
|
expect(listItems[0]).toHaveTextContent('$0.50');
|
|
expect(listItems[1]).toHaveTextContent('Soda');
|
|
expect(listItems[1]).toHaveTextContent('$0.75');
|
|
expect(listItems[2]).toHaveTextContent('Water');
|
|
expect(listItems[2]).toHaveTextContent('$0.99');
|
|
expect(listItems[3]).toHaveTextContent('Apples');
|
|
expect(listItems[3]).toHaveTextContent('$1.00');
|
|
expect(listItems[4]).toHaveTextContent('Oranges');
|
|
expect(listItems[4]).toHaveTextContent('$1.20');
|
|
expect(listItems[5]).toHaveTextContent('Yogurt');
|
|
expect(listItems[5]).toHaveTextContent('$1.50');
|
|
expect(listItems[6]).toHaveTextContent('Pasta');
|
|
expect(listItems[6]).toHaveTextContent('$1.80');
|
|
expect(listItems[7]).toHaveTextContent('Bread');
|
|
expect(listItems[7]).toHaveTextContent('$2.00');
|
|
expect(listItems[8]).toHaveTextContent('Chips');
|
|
expect(listItems[8]).toHaveTextContent('$2.10');
|
|
expect(listItems[9]).toHaveTextContent('Tea');
|
|
expect(listItems[9]).toHaveTextContent('$2.20');
|
|
});
|
|
|
|
it('should display item name, price_display, and quantity for each deal', () => {
|
|
render(<TopDeals items={mockFlyerItems.slice(0, 1)} />); // Render just one item for simplicity
|
|
expect(screen.getByText('Apples')).toBeInTheDocument();
|
|
expect(screen.getByText('$1.00')).toBeInTheDocument();
|
|
expect(screen.getByText('(Qty: 1 lb)')).toBeInTheDocument();
|
|
});
|
|
});
|