All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 57m50s
143 lines
6.5 KiB
TypeScript
143 lines
6.5 KiB
TypeScript
// src/features/flyer/FlyerDisplay.test.tsx
|
|
import React from 'react';
|
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { FlyerDisplay } from './FlyerDisplay';
|
|
import { createMockStore } from '../../tests/utils/mockFactories';
|
|
|
|
const mockStore = createMockStore({ store_id: 1, name: 'SuperMart', logo_url: 'http://example.com/logo.png' });
|
|
|
|
const mockOnOpenCorrectionTool = vi.fn();
|
|
|
|
const defaultProps = {
|
|
imageUrl: 'http://example.com/flyer.jpg',
|
|
store: mockStore,
|
|
validFrom: '2023-10-26',
|
|
validTo: '2023-11-01',
|
|
storeAddress: '123 Main St, Anytown',
|
|
onOpenCorrectionTool: mockOnOpenCorrectionTool,
|
|
};
|
|
|
|
describe('FlyerDisplay', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('should render all elements when all props are provided', () => {
|
|
render(<FlyerDisplay {...defaultProps} />);
|
|
|
|
// Check for store info
|
|
expect(screen.getByRole('heading', { name: 'SuperMart' })).toBeInTheDocument();
|
|
expect(screen.getByAltText('SuperMart Logo')).toHaveAttribute('src', mockStore.logo_url);
|
|
expect(screen.getByText('123 Main St, Anytown')).toBeInTheDocument();
|
|
|
|
// Check for date range
|
|
expect(screen.getByText('Deals valid from October 26, 2023 to November 1, 2023')).toBeInTheDocument();
|
|
|
|
// Check for flyer image
|
|
expect(screen.getByAltText('Grocery Flyer')).toHaveAttribute('src', defaultProps.imageUrl);
|
|
});
|
|
|
|
it('should render a placeholder when imageUrl is null', () => {
|
|
render(<FlyerDisplay {...defaultProps} imageUrl={null} />);
|
|
expect(screen.getByText('Flyer image will be displayed here')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should not render the header if store and date info are missing', () => {
|
|
render(<FlyerDisplay imageUrl={defaultProps.imageUrl} onOpenCorrectionTool={mockOnOpenCorrectionTool} />);
|
|
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should render without a logo if store.logo_url is not provided', () => {
|
|
render(<FlyerDisplay {...defaultProps} store={{ ...mockStore, logo_url: null }} />);
|
|
expect(screen.getByRole('heading', { name: 'SuperMart' })).toBeInTheDocument();
|
|
expect(screen.queryByAltText('SuperMart Logo')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should format a single day validity correctly', () => {
|
|
render(<FlyerDisplay {...defaultProps} validFrom="2023-10-26" validTo="2023-10-26" />);
|
|
expect(screen.getByText('Valid on October 26, 2023')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should format correctly with only a start date', () => {
|
|
render(<FlyerDisplay {...defaultProps} validTo={null} />);
|
|
expect(screen.getByText('Deals start October 26, 2023')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should format correctly with only an end date', () => {
|
|
render(<FlyerDisplay {...defaultProps} validFrom={null} />);
|
|
expect(screen.getByText('Deals end November 1, 2023')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply dark mode image styles', () => {
|
|
render(<FlyerDisplay {...defaultProps} />);
|
|
const image = screen.getByAltText('Grocery Flyer');
|
|
expect(image).toHaveClass('dark:invert');
|
|
expect(image).toHaveClass('dark:hue-rotate-180');
|
|
});
|
|
|
|
describe('"Correct Data" Button', () => {
|
|
it('should be visible when the header is rendered', () => {
|
|
render(<FlyerDisplay {...defaultProps} />);
|
|
expect(screen.getByRole('button', { name: /correct data/i })).toBeInTheDocument();
|
|
});
|
|
|
|
it('should not be visible when the header is not rendered', () => {
|
|
render(<FlyerDisplay imageUrl={defaultProps.imageUrl} onOpenCorrectionTool={mockOnOpenCorrectionTool} />);
|
|
expect(screen.queryByRole('button', { name: /correct data/i })).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should call onOpenCorrectionTool when clicked', () => {
|
|
render(<FlyerDisplay {...defaultProps} />);
|
|
fireEvent.click(screen.getByRole('button', { name: /correct data/i }));
|
|
expect(mockOnOpenCorrectionTool).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('Image Source Logic', () => {
|
|
it('should use the imageUrl directly if it is a full URL', () => {
|
|
render(<FlyerDisplay {...defaultProps} imageUrl="https://cdn.example.com/flyer.png" />);
|
|
const image = screen.getByAltText('Grocery Flyer');
|
|
expect(image).toHaveAttribute('src', 'https://cdn.example.com/flyer.png');
|
|
});
|
|
|
|
it('should use the imageUrl directly if it is an absolute path', () => {
|
|
render(<FlyerDisplay {...defaultProps} imageUrl="/assets/flyers/flyer.png" />);
|
|
const image = screen.getByAltText('Grocery Flyer');
|
|
expect(image).toHaveAttribute('src', '/assets/flyers/flyer.png');
|
|
});
|
|
|
|
it('should prepend the path for a relative imageUrl from the database', () => {
|
|
render(<FlyerDisplay {...defaultProps} imageUrl="flyer-from-db.jpg" />);
|
|
const image = screen.getByAltText('Grocery Flyer');
|
|
expect(image).toHaveAttribute('src', '/flyer-images/flyer-from-db.jpg');
|
|
});
|
|
});
|
|
|
|
describe('Date Formatting Robustness', () => {
|
|
it('should handle invalid date strings gracefully by not displaying them', () => {
|
|
render(<FlyerDisplay {...defaultProps} validFrom="invalid-date" validTo="another-bad-date" />);
|
|
expect(screen.queryByText(/deals valid from/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/valid on/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/deals start/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/deals end/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/invalid date/i)).not.toBeInTheDocument(); // Ensure no "Invalid Date" text
|
|
});
|
|
|
|
it('should handle a mix of valid and invalid date strings gracefully (start date valid)', () => {
|
|
render(<FlyerDisplay {...defaultProps} validFrom="2023-10-26" validTo="invalid-date" />);
|
|
expect(screen.getByText('Deals start October 26, 2023')).toBeInTheDocument();
|
|
expect(screen.queryByText(/deals valid from/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/deals end/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/invalid date/i)).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should handle a mix of valid and invalid date strings gracefully (end date valid)', () => {
|
|
render(<FlyerDisplay {...defaultProps} validFrom="another-bad-date" validTo="2023-11-01" />);
|
|
expect(screen.getByText('Deals end November 1, 2023')).toBeInTheDocument();
|
|
expect(screen.queryByText(/deals valid from/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/deals start/i)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/invalid date/i)).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
}); |