import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest'; // Mock parser to avoid LLM calls vi.mock('$lib/server/parser', () => ({ extractRecipe: vi.fn().mockResolvedValue({ name: 'Test Recipe', ingredients: [], instructions: 'Test instructions', servings: 4 }), detectRecipe: vi.fn().mockResolvedValue(true) })); // Mock tandoor to avoid API calls vi.mock('$lib/server/tandoor', () => ({ uploadRecipeWithIngredientsDTO: vi.fn().mockResolvedValue({ id: 123 }), uploadRecipeImage: vi.fn().mockResolvedValue(true) })); import { queueManager } from '$lib/server/queue/QueueManager'; import * as extraction from '$lib/server/extraction'; import { queueProcessor } from '$lib/server/queue/QueueProcessor'; describe('QueueProcessor logging', () => { let consoleErrorSpy: any; beforeEach(async () => { // Stop processor first queueProcessor.stop(); // Clear queue const items = queueManager.getAll(); items.forEach(item => queueManager.remove(item.id)); // Setup console.error spy consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); // Give time for cleanup await new Promise(resolve => setTimeout(resolve, 100)); }); afterEach(() => { queueProcessor.stop(); consoleErrorSpy.mockRestore(); }); test('error logs should be properly serialized (no [object Object])', async () => { // Create complex error object const complexError = new Error('Test extraction error'); (complexError as any).code = 'ERR_TEST'; (complexError as any).details = { phase: 'extraction', retries: 3 }; // Mock extraction to fail BEFORE starting processor const extractSpy = vi.spyOn(extraction, 'extractTextAndThumbnail'); extractSpy.mockRejectedValueOnce(complexError); const item = queueManager.enqueue('https://instagram.com/p/TEST'); queueProcessor.start(); // Wait for error status await vi.waitFor(() => { const updated = queueManager.get(item.id); return updated?.status === 'error' || updated?.status === 'unhealthy'; }, { timeout: 5000 }); // Stop processor queueProcessor.stop(); // Wait a bit for all logs to finish await new Promise(resolve => setTimeout(resolve, 100)); // Check that console.error doesn't contain [object Object] const allCalls = consoleErrorSpy.mock.calls.map((call: any[]) => call.map(arg => { if (arg && typeof arg === 'object' && arg.message) { return arg.message; // Handle Error objects } return String(arg); }).join(' ') ); const hasObjectObject = allCalls.some((msg: string) => msg.includes('[object Object]')); expect(hasObjectObject).toBe(false); // Verify QueueProcessor logs are present const queueProcessorLogs = allCalls.filter((msg: string) => msg.includes('[QueueProcessor]') ); expect(queueProcessorLogs.length).toBeGreaterThan(0); }); });