Flyt brugerrettet indholdsgenerering til Codex CLI, forbedr mobilflowet og ret CI-miljøets afhængigheder og testkonfiguration.
137 lines
4.3 KiB
JavaScript
137 lines
4.3 KiB
JavaScript
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const XLSX = require('xlsx');
|
|
const SmartPackageExcelValidationService = require('../src/services/smartPackageExcelValidationService');
|
|
|
|
const createWorkbook = () => {
|
|
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'smartpakker-validation-'));
|
|
const filePath = path.join(directory, 'smartpakker.xlsx');
|
|
const workbook = XLSX.utils.book_new();
|
|
|
|
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet([{
|
|
Pakkenavn: 'Byggepladspakke',
|
|
Kategori: 'Byggeplads',
|
|
Enhed: 'stk.',
|
|
Enhedspris: '0.00 kr.',
|
|
Beskrivelse: 'Testpakke'
|
|
}]), 'Byggeplads');
|
|
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet([{
|
|
Pakkenavn: 'Tømrerpakke',
|
|
Kategori: 'Tag',
|
|
Enhed: 'm²',
|
|
'Pris pr. enhed': '120.00 kr.',
|
|
'Timepris (kr.)': '600.00 kr.',
|
|
'Timer pr. enhed': '0.20',
|
|
Beskrivelse: 'Tømrerarbejde'
|
|
}]), 'Tømrer opgaver');
|
|
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet([{
|
|
Smartpakkenavn: 'Udlejningspakke',
|
|
Kategori: 'Maskiner',
|
|
Enhed: 'dag',
|
|
Standardpris: '500.00 kr.',
|
|
Beskrivelse: 'Leje'
|
|
}]), 'Udlejning');
|
|
|
|
XLSX.writeFile(workbook, filePath);
|
|
return { directory, filePath };
|
|
};
|
|
|
|
describe('SmartPackageExcelValidationService', () => {
|
|
let fixture;
|
|
|
|
beforeEach(() => {
|
|
fixture = createWorkbook();
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(fixture.directory, { recursive: true, force: true });
|
|
});
|
|
|
|
test('returns deterministic warnings without blocking import', () => {
|
|
const service = new SmartPackageExcelValidationService(null);
|
|
const result = service.validateStandard(fixture.filePath);
|
|
|
|
expect(result.blocksImport).toBe(false);
|
|
expect(result.summary.totalPackages).toBe(2);
|
|
expect(result.summary.skippedZeroPrice).toBe(1);
|
|
expect(result.issues).toEqual(expect.arrayContaining([
|
|
expect.objectContaining({ code: 'zero_price_skipped', packageName: 'Byggepladspakke' })
|
|
]));
|
|
});
|
|
|
|
test('combines standard validation with structured Codex findings', async () => {
|
|
const codexRunner = jest.fn().mockResolvedValue({
|
|
status: 'warnings',
|
|
summary: 'En række bør kontrolleres.',
|
|
issues: [{
|
|
severity: 'warning',
|
|
sheet: 'Byggeplads',
|
|
row: 2,
|
|
packageName: 'Byggepladspakke',
|
|
message: 'Navnet er meget generelt.',
|
|
suggestion: 'Gør navnet mere konkret.'
|
|
}]
|
|
});
|
|
const service = new SmartPackageExcelValidationService(null, { codexRunner });
|
|
|
|
const result = await service.validateWithAi(fixture.filePath);
|
|
|
|
expect(result.standard.summary.totalPackages).toBe(2);
|
|
expect(result.ai.status).toBe('warnings');
|
|
expect(result.ai.issues).toHaveLength(1);
|
|
expect(codexRunner).toHaveBeenCalled();
|
|
expect(result.ai.provider).toBe('codex-cli');
|
|
});
|
|
|
|
test('uses Codex CLI provider without requiring an API client', async () => {
|
|
const codexRunner = jest.fn().mockResolvedValue({
|
|
status: 'passed',
|
|
summary: 'Ingen semantiske problemer fundet.',
|
|
issues: []
|
|
});
|
|
const service = new SmartPackageExcelValidationService(null, {
|
|
provider: 'codex',
|
|
codexRunner
|
|
});
|
|
|
|
const result = await service.validateWithAi(fixture.filePath);
|
|
|
|
expect(codexRunner).toHaveBeenCalledWith(expect.objectContaining({
|
|
packages: expect.any(Array)
|
|
}));
|
|
expect(result.ai.provider).toBe('codex-cli');
|
|
expect(result.ai.status).toBe('passed');
|
|
});
|
|
|
|
test('resolves AI findings to an existing concrete Excel row', async () => {
|
|
const codexRunner = jest.fn().mockResolvedValue({
|
|
status: 'warnings',
|
|
summary: 'En række kræver kontrol.',
|
|
issues: [{
|
|
severity: 'warning',
|
|
sheet: 'Forkert fane',
|
|
row: 999,
|
|
packageName: 'Tømrerpakke',
|
|
field: 'Enhed',
|
|
message: 'Enheden kan være forkert.',
|
|
suggestion: 'Kontrollér enheden.',
|
|
relatedRows: []
|
|
}]
|
|
});
|
|
const service = new SmartPackageExcelValidationService(null, {
|
|
provider: 'codex',
|
|
codexRunner
|
|
});
|
|
|
|
const result = await service.validateWithAi(fixture.filePath);
|
|
|
|
expect(result.ai.issues).toEqual([expect.objectContaining({
|
|
sheet: 'Tømrer opgaver',
|
|
row: 2,
|
|
packageName: 'Tømrerpakke',
|
|
field: 'Enhed'
|
|
})]);
|
|
});
|
|
});
|