file re-org
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 53s

This commit is contained in:
2025-11-25 11:37:41 -08:00
parent 4b5fe4f8df
commit 8968813ee0
71 changed files with 1678 additions and 246 deletions

View File

@@ -0,0 +1,129 @@
// src/components/AdminBrandManager.test.tsx
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import toast from 'react-hot-toast';
import { AdminBrandManager } from './AdminBrandManager';
import * as apiClient from '../../../services/apiClient';
import type { Brand } from '../../../types';
// Mock the apiClient module
vi.mock('../services/apiClient');
// Mock react-hot-toast
vi.mock('react-hot-toast', () => ({
default: {
loading: vi.fn(),
success: vi.fn(),
error: vi.fn(),
},
}));
const mockBrands: Brand[] = [
{ brand_id: 1, name: 'No Frills', store_name: 'No Frills', logo_url: null },
{ brand_id: 2, name: 'Compliments', store_name: 'Sobeys', logo_url: 'http://example.com/compliments.png' },
];
describe('AdminBrandManager', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should render a loading state initially', () => {
(apiClient.fetchAllBrands as Mock).mockReturnValue(new Promise(() => {})); // Never resolves
render(<AdminBrandManager />);
expect(screen.getByText('Loading brands...')).toBeInTheDocument();
});
it('should render an error message if fetching brands fails', async () => {
(apiClient.fetchAllBrands as Mock).mockRejectedValue(new Error('Network Error'));
render(<AdminBrandManager />);
await waitFor(() => {
expect(screen.getByText('Failed to load brands: Network Error')).toBeInTheDocument();
});
});
it('should render the list of brands when data is fetched successfully', async () => {
(apiClient.fetchAllBrands as Mock).mockResolvedValue(mockBrands);
render(<AdminBrandManager />);
await waitFor(() => {
expect(screen.getByRole('heading', { name: /brand management/i })).toBeInTheDocument();
expect(screen.getByText('No Frills')).toBeInTheDocument();
expect(screen.getByText('(Sobeys)')).toBeInTheDocument();
expect(screen.getByAltText('Compliments logo')).toBeInTheDocument();
expect(screen.getByText('No Logo')).toBeInTheDocument();
});
});
it('should handle successful logo upload', async () => {
(apiClient.fetchAllBrands as Mock).mockResolvedValue(mockBrands);
(apiClient.uploadBrandLogo as Mock).mockResolvedValue({ logoUrl: 'http://example.com/new-logo.png' });
(toast.loading as Mock).mockReturnValue('toast-1');
render(<AdminBrandManager />);
await waitFor(() => expect(screen.getByText('No Frills')).toBeInTheDocument());
const file = new File(['logo'], 'logo.png', { type: 'image/png' });
const input = screen.getAllByRole('textbox', { hidden: true })[0]; // Find the first file input
fireEvent.change(input, { target: { files: [file] } });
await waitFor(() => {
expect(apiClient.uploadBrandLogo).toHaveBeenCalledWith(1, file);
expect(toast.loading).toHaveBeenCalledWith('Uploading logo...');
expect(toast.success).toHaveBeenCalledWith('Logo updated successfully!', { id: 'toast-1' });
// Check if the UI updates with the new logo
expect(screen.getByAltText('No Frills logo')).toHaveAttribute('src', 'http://example.com/new-logo.png');
});
});
it('should handle failed logo upload', async () => {
(apiClient.fetchAllBrands as Mock).mockResolvedValue(mockBrands);
(apiClient.uploadBrandLogo as Mock).mockRejectedValue(new Error('Upload failed'));
(toast.loading as Mock).mockReturnValue('toast-2');
render(<AdminBrandManager />);
await waitFor(() => expect(screen.getByText('No Frills')).toBeInTheDocument());
const file = new File(['logo'], 'logo.png', { type: 'image/png' });
const input = screen.getAllByRole('textbox', { hidden: true })[0];
fireEvent.change(input, { target: { files: [file] } });
await waitFor(() => {
expect(toast.error).toHaveBeenCalledWith('Upload failed: Upload failed', { id: 'toast-2' });
});
});
it('should show an error toast for invalid file type', async () => {
(apiClient.fetchAllBrands as Mock).mockResolvedValue(mockBrands);
render(<AdminBrandManager />);
await waitFor(() => expect(screen.getByText('No Frills')).toBeInTheDocument());
const file = new File(['text'], 'document.txt', { type: 'text/plain' });
const input = screen.getAllByRole('textbox', { hidden: true })[0];
fireEvent.change(input, { target: { files: [file] } });
await waitFor(() => {
expect(toast.error).toHaveBeenCalledWith('Invalid file type. Please upload a PNG, JPG, WEBP, or SVG.');
expect(apiClient.uploadBrandLogo).not.toHaveBeenCalled();
});
});
it('should show an error toast for oversized file', async () => {
(apiClient.fetchAllBrands as Mock).mockResolvedValue(mockBrands);
render(<AdminBrandManager />);
await waitFor(() => expect(screen.getByText('No Frills')).toBeInTheDocument());
const file = new File(['a'.repeat(3 * 1024 * 1024)], 'large.png', { type: 'image/png' });
const input = screen.getAllByRole('textbox', { hidden: true })[0];
fireEvent.change(input, { target: { files: [file] } });
await waitFor(() => {
expect(toast.error).toHaveBeenCalledWith('File is too large. Maximum size is 2MB.');
expect(apiClient.uploadBrandLogo).not.toHaveBeenCalled();
});
});
});