const ProjectFlowValidationService = require('../src/services/projectFlowValidationService'); describe('ProjectFlowValidationService', () => { test('sends compact project data to Codex and normalizes the result', async () => { const codexRunner = jest.fn().mockResolvedValue({ status: 'warnings', summary: 'Timerne bør kontrolleres.', issues: [{ severity: 'warning', section: 'Timer', field: 'Montage', message: 'Timetallet virker lavt.', suggestion: 'Kontrollér opmålingen.' }], _codex: { model: 'gpt-5.6-terra', reasoningEffort: 'medium', usage: { inputTokens: 100, cachedInputTokens: 0, outputTokens: 20 } } }); const service = new ProjectFlowValidationService({ codexRunner }); const result = await service.validate(42, { project: { name: 'Tagprojekt', customerName: 'Testkunde', description: 'Nyt tag' }, geometry: { roofType: 'sadeltag', roofArea: 120 }, materials: [{ name: 'Tagplade', quantity: 130, unit: 'm2', unitPrice: 200 }], laborTasks: [{ name: 'Montage', totalHours: 8, rate: 600 }], totals: { total: 100000 } }); expect(codexRunner).toHaveBeenCalledWith(expect.objectContaining({ payload: expect.objectContaining({ projectId: 42, materials: [expect.objectContaining({ name: 'Tagplade', quantity: 130 })], labor: [expect.objectContaining({ name: 'Montage', hours: 8 })] }), schemaPath: expect.stringContaining('projectFlowValidation.schema.json'), model: 'gpt-5.6-terra', reasoningEffort: 'medium' })); expect(result).toMatchObject({ status: 'warnings', provider: 'codex-cli', _codex: expect.objectContaining({ usage: expect.objectContaining({ outputTokens: 20 }) }) }); }); });