lootsa tests fixes
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 4m26s
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 4m26s
This commit is contained in:
@@ -3,13 +3,15 @@ import React from 'react';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { FlyerList } from './FlyerList';
|
||||
import type { Flyer } from '../../types';
|
||||
import type { Flyer, UserProfile } from '../../types';
|
||||
import { createMockUserProfile } from '../../tests/utils/mockFactories';
|
||||
|
||||
const mockFlyers: Flyer[] = [
|
||||
{
|
||||
flyer_id: 1,
|
||||
created_at: '2023-10-01T10:00:00Z',
|
||||
file_name: 'metro_flyer_oct_1.pdf',
|
||||
item_count: 50,
|
||||
image_url: 'http://example.com/flyer1.jpg',
|
||||
store: {
|
||||
store_id: 101,
|
||||
@@ -23,6 +25,7 @@ const mockFlyers: Flyer[] = [
|
||||
flyer_id: 2,
|
||||
created_at: '2023-10-02T11:00:00Z',
|
||||
file_name: 'walmart_flyer.pdf',
|
||||
item_count: 75,
|
||||
image_url: 'http://example.com/flyer2.jpg',
|
||||
store: {
|
||||
store_id: 102,
|
||||
@@ -36,33 +39,33 @@ const mockFlyers: Flyer[] = [
|
||||
|
||||
describe('FlyerList', () => {
|
||||
const mockOnFlyerSelect = vi.fn();
|
||||
const mockProfile: UserProfile = createMockUserProfile({ user_id: '1', role: 'user' });
|
||||
|
||||
it('should render the heading', () => {
|
||||
render(<FlyerList flyers={[]} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} />);
|
||||
render(<FlyerList flyers={[]} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} profile={null} />);
|
||||
expect(screen.getByRole('heading', { name: /processed flyers/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display a message when there are no flyers', () => {
|
||||
render(<FlyerList flyers={[]} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} />);
|
||||
render(<FlyerList flyers={[]} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} profile={null} />);
|
||||
expect(screen.getByText(/no flyers have been processed yet/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render a list of flyers with correct details', () => {
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} />);
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} profile={mockProfile} />);
|
||||
|
||||
// Check first flyer
|
||||
expect(screen.getByText('Metro')).toBeInTheDocument();
|
||||
expect(screen.getByText('metro_flyer_oct_1.pdf')).toBeInTheDocument();
|
||||
expect(screen.getByText(/processed: 10\/1\/2023/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/valid: Oct 5 - Oct 11/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/50 items/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Valid: Oct 5 - Oct 11/i)).toBeInTheDocument();
|
||||
|
||||
// Check second flyer
|
||||
expect(screen.getByText('Walmart')).toBeInTheDocument();
|
||||
expect(screen.getByText(/valid: Oct 6/i)).toBeInTheDocument(); // Single day validity
|
||||
expect(screen.getByText(/Valid: Oct 6/i)).toBeInTheDocument(); // Single day validity
|
||||
});
|
||||
|
||||
it('should call onFlyerSelect with the correct flyer when an item is clicked', () => {
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} />);
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={null} profile={mockProfile} />);
|
||||
|
||||
const firstFlyerItem = screen.getByText('Metro').closest('li');
|
||||
fireEvent.click(firstFlyerItem!);
|
||||
@@ -72,9 +75,9 @@ describe('FlyerList', () => {
|
||||
});
|
||||
|
||||
it('should apply a selected style to the currently selected flyer', () => {
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={1} />);
|
||||
render(<FlyerList flyers={mockFlyers} onFlyerSelect={mockOnFlyerSelect} selectedFlyerId={1} profile={mockProfile} />);
|
||||
|
||||
const selectedItem = screen.getByText('Metro').closest('li');
|
||||
expect(selectedItem).toHaveClass('bg-brand-light');
|
||||
expect(selectedItem).toHaveClass('bg-brand-light', 'dark:bg-brand-dark/30');
|
||||
});
|
||||
});
|
||||
@@ -397,7 +397,8 @@ describe('ProfileManager Authenticated User Features', () => {
|
||||
avatar_url: 'http://example.com/avatar.png',
|
||||
});
|
||||
expect(mockOnProfileUpdate).toHaveBeenCalledWith(expect.objectContaining({ full_name: 'Updated Name' }));
|
||||
expect(notifySuccess).toHaveBeenCalledWith('Profile and address updated successfully!');
|
||||
// Match any success message containing "Profile" and "updated"
|
||||
expect(notifySuccess).toHaveBeenCalledWith(expect.stringMatching(/Profile.*updated/));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -71,9 +71,14 @@ vi.mock('../services/logger.server', () => ({
|
||||
// Mock Passport middleware
|
||||
vi.mock('./passport.routes', () => ({
|
||||
default: {
|
||||
// Mock passport.authenticate to simply call next(), allowing the request to proceed.
|
||||
// The actual user object will be injected by the mockAuth middleware.
|
||||
authenticate: vi.fn(() => (req: express.Request, res: express.Response, next: express.NextFunction) => next()),
|
||||
authenticate: vi.fn(() => (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
// If we are testing the unauthenticated state (no user injected), simulate 401.
|
||||
// If a user WAS injected by our test helper, proceed.
|
||||
if (!req.user) {
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
next();
|
||||
}),
|
||||
},
|
||||
// We also need to provide mocks for any other named exports from passport.routes.ts
|
||||
isAdmin: vi.fn((req: express.Request, res: express.Response, next: express.NextFunction) => next()),
|
||||
|
||||
@@ -30,13 +30,19 @@ vi.mock('@google/genai', () => ({
|
||||
GoogleGenAI: MockGoogleGenAIImplementation,
|
||||
}));
|
||||
|
||||
// 3. Mock fs/promises
|
||||
// 3. Mock fs/promises AND node:fs/promises
|
||||
// Return a factory function to ensure fresh mocks if needed,
|
||||
// and satisfy both default and named imports.
|
||||
vi.mock('fs/promises', () => ({
|
||||
default: {
|
||||
readFile: mockReadFile,
|
||||
},
|
||||
readFile: mockReadFile,
|
||||
}));
|
||||
vi.mock('node:fs/promises', () => ({
|
||||
default: { readFile: mockReadFile },
|
||||
readFile: mockReadFile,
|
||||
}));
|
||||
|
||||
// 4. Mock sharp
|
||||
vi.mock('sharp', () => ({
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { describe, it, expect, vi, beforeEach, beforeAll } from 'vitest';
|
||||
|
||||
// FIX: Mock the local re-export with explicit spies
|
||||
// FIX: Mock the local re-export with explicit spies on a function object
|
||||
vi.mock('../lib/toast', () => {
|
||||
const success = vi.fn();
|
||||
const error = vi.fn();
|
||||
// Create separate mocks for the main function and its methods
|
||||
const mainToastFn = vi.fn();
|
||||
const successFn = vi.fn();
|
||||
const errorFn = vi.fn();
|
||||
|
||||
// Combine them into a single object that is also a function
|
||||
const mockToast = Object.assign(mainToastFn, { success: successFn, error: errorFn });
|
||||
|
||||
return {
|
||||
default: {
|
||||
success,
|
||||
error,
|
||||
},
|
||||
// Also export named versions if used
|
||||
success,
|
||||
error
|
||||
default: mockToast,
|
||||
__esModule: true,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user