// src/routes/personalization.routes.test.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; import supertest from 'supertest'; import { createMockMasterGroceryItem, createMockDietaryRestriction, createMockAppliance, } from '../tests/utils/mockFactories'; import { createTestApp } from '../tests/utils/createTestApp'; // 1. Mock the Service Layer directly. vi.mock('../services/db/index.db', () => ({ personalizationRepo: { getAllMasterItems: vi.fn(), getDietaryRestrictions: vi.fn(), getAppliances: vi.fn(), }, })); // Import the router and mocked DB AFTER all mocks are defined. import personalizationRouter from './personalization.routes'; import * as db from '../services/db/index.db'; import { mockLogger } from '../tests/utils/mockLogger'; // Mock the logger to keep test output clean vi.mock('../services/logger.server', async () => ({ // Use async import to avoid hoisting issues with mockLogger logger: (await import('../tests/utils/mockLogger')).mockLogger, })); describe('Personalization Routes (/api/personalization)', () => { const app = createTestApp({ router: personalizationRouter, basePath: '/api/personalization' }); beforeEach(() => { vi.clearAllMocks(); }); describe('GET /master-items', () => { it('should return a list of master items', async () => { const mockItems = [createMockMasterGroceryItem({ master_grocery_item_id: 1, name: 'Milk' })]; vi.mocked(db.personalizationRepo.getAllMasterItems).mockResolvedValue(mockItems); const response = await supertest(app).get('/api/personalization/master-items'); expect(response.status).toBe(200); expect(response.body).toEqual(mockItems); }); it('should return 500 if the database call fails', async () => { const dbError = new Error('DB Error'); vi.mocked(db.personalizationRepo.getAllMasterItems).mockRejectedValue(dbError); const response = await supertest(app).get('/api/personalization/master-items'); expect(response.status).toBe(500); expect(response.body.message).toBe('DB Error'); expect(mockLogger.error).toHaveBeenCalledWith( { error: dbError }, 'Error fetching master items in /api/personalization/master-items:', ); }); }); describe('GET /dietary-restrictions', () => { it('should return a list of all dietary restrictions', async () => { const mockRestrictions = [createMockDietaryRestriction({ name: 'Gluten-Free' })]; vi.mocked(db.personalizationRepo.getDietaryRestrictions).mockResolvedValue(mockRestrictions); const response = await supertest(app).get('/api/personalization/dietary-restrictions'); expect(response.status).toBe(200); expect(response.body).toEqual(mockRestrictions); }); it('should return 500 if the database call fails', async () => { const dbError = new Error('DB Error'); vi.mocked(db.personalizationRepo.getDietaryRestrictions).mockRejectedValue(dbError); const response = await supertest(app).get('/api/personalization/dietary-restrictions'); expect(response.status).toBe(500); expect(response.body.message).toBe('DB Error'); expect(mockLogger.error).toHaveBeenCalledWith( { error: dbError }, 'Error fetching dietary restrictions in /api/personalization/dietary-restrictions:', ); }); }); describe('GET /appliances', () => { it('should return a list of all appliances', async () => { const mockAppliances = [createMockAppliance({ name: 'Air Fryer' })]; vi.mocked(db.personalizationRepo.getAppliances).mockResolvedValue(mockAppliances); const response = await supertest(app).get('/api/personalization/appliances'); expect(response.status).toBe(200); expect(response.body).toEqual(mockAppliances); }); it('should return 500 if the database call fails', async () => { const dbError = new Error('DB Error'); vi.mocked(db.personalizationRepo.getAppliances).mockRejectedValue(dbError); const response = await supertest(app).get('/api/personalization/appliances'); expect(response.status).toBe(500); expect(response.body.message).toBe('DB Error'); expect(mockLogger.error).toHaveBeenCalledWith( { error: dbError }, 'Error fetching appliances in /api/personalization/appliances:', ); }); }); });