lootsa tests fixes
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 4m26s

This commit is contained in:
2025-12-05 21:50:56 -08:00
parent 6cf9829537
commit 06fc94feb1
5 changed files with 42 additions and 26 deletions

View File

@@ -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');
});
});

View File

@@ -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/));
});
});

View File

@@ -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()),

View File

@@ -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', () => ({

View File

@@ -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,
};
});