35 lines
1.8 KiB
JavaScript
35 lines
1.8 KiB
JavaScript
const ProjectAiService = require('../src/services/projectAiService');
|
|
const { buildRisk, diffValues } = require('../src/services/projectAiService');
|
|
|
|
describe('ProjectAiService', () => {
|
|
test('computes deterministic risk and a bounded before/after diff', () => {
|
|
const risk = buildRisk({
|
|
project: { description: '' }, geometry: {}, materials: [], rentals: [], labor: []
|
|
});
|
|
expect(risk.level).toBe('high');
|
|
expect(risk.score).toBeGreaterThanOrEqual(60);
|
|
expect(diffValues({ total: 100 }, { total: 120 })).toEqual([{ field: 'total', before: 100, after: 120 }]);
|
|
});
|
|
|
|
test('fact-lock rejects numbers not present in the project', () => {
|
|
const service = new ProjectAiService({}, { codexRunner: jest.fn() });
|
|
expect(() => service.assertFactLockedText({ customerText: 'Pris 999 kr.', internalText: null }, { price: 100 }))
|
|
.toThrow('introducerede nye tal');
|
|
});
|
|
|
|
test('turns fact-locked customer text into a confirmable stored suggestion', async () => {
|
|
const execute = jest.fn().mockResolvedValue([{}]);
|
|
const service = new ProjectAiService({ pool: { execute } }, {
|
|
codexRunner: jest.fn().mockResolvedValue({
|
|
feature: 'customer_text', status: 'passed', summary: 'Klar', score: null, level: null,
|
|
findings: [], suggestions: [], customerText: 'Arbejdet omfatter 10 m2 tag.', internalText: null
|
|
})
|
|
});
|
|
const context = { snapshot: { project: { id: 7 }, area: 10, stateHash: 'abc' } };
|
|
const result = await service.runFeature({ feature: 'customer_text', context }, { id: 'job', projectId: 7, type: 'customer_text' });
|
|
expect(result.suggestions[0]).toMatchObject({ action: 'update_customer_text', targetId: '7' });
|
|
expect(result.stateHash).toBe('abc');
|
|
expect(execute).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO ai_suggestions'), expect.any(Array));
|
|
});
|
|
});
|