Files
flyer-crawler.projectium.com/src/components/TopDeals.test.tsx
Torben Sorensen 4b5fe4f8df
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 56s
unit testing for interface
2025-11-25 10:33:28 -08:00

90 lines
6.5 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';
describe('TopDeals', () => {
const mockFlyerItems: FlyerItem[] = [
...[
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
{ 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' } },
].map(item => ({
...item,
created_at: new Date().toISOString(),
view_count: 0,
click_count: 0,
updated_at: new Date().toISOString(),
}))
];
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[] = [
{ flyer_item_id: 1, item: 'Free Sample', price_display: 'FREE', price_in_cents: null, quantity: '1', category_name: 'Other', flyer_id: 1, master_item_id: undefined, unit_price: null, created_at: '', view_count: 0, click_count: 0, updated_at: '' },
{ flyer_item_id: 2, item: 'Info Brochure', price_display: '', price_in_cents: null, quantity: '', category_name: 'Other', flyer_id: 1, master_item_id: undefined, unit_price: null, created_at: '', view_count: 0, click_count: 0, updated_at: '' },
];
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
// 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), Tea (220), Milk (250)
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('Tea');
expect(listItems[8]).toHaveTextContent('$2.20');
expect(listItems[9]).toHaveTextContent('Milk');
expect(listItems[9]).toHaveTextContent('$2.50');
});
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();
});
});