Files
ln-bi/src/modules/assets/faults/report-export.test.ts
T
shishengliang 39ecde55d4
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
feat(assets): 完成故障维修运维 BI 与 Excel 报表导出
2026-10-13 16:07:11 +08:00

61 lines
3.4 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import ExcelJS from 'exceljs';
import { createFaultReportWorkbook, type FaultReport } from './report-export';
const now = new Date('2026-10-13T08:00:00Z');
async function saved(report: FaultReport) {
const book = await createFaultReportWorkbook(report, undefined, now);
const reopened = new ExcelJS.Workbook();
await reopened.xlsx.load(await book.xlsx.writeBuffer());
return reopened.worksheets[0];
}
test('trend export preserves monthly range, real dates, cohort counts and weighted closure rate after serialization', async () => {
const sheet = await saved({ kind: 'trend', data: {
start: '2026-09-14', end: '2026-10-13', granularity: 'month', updatedAt: now.toISOString(),
totals: { reported: 10, closed: 7, unclosed: 3 },
periods: [{ period: '2026-09', reported: 8, closed: 5, unclosed: 3 }, { period: '2026-10', reported: 2, closed: 2, unclosed: 0 }],
} });
assert.match(String(sheet.getCell('A2').value), /2026-09-14 至 2026-10-13.*按月/);
assert.equal((sheet.getCell('A10').value as Date).toISOString(), '2026-10-01T00:00:00.000Z');
assert.equal(sheet.getCell('A10').numFmt, 'yyyy-mm');
assert.equal(sheet.getCell('B11').value, 8);
assert.equal(sheet.getCell('C11').value, 5);
assert.equal(sheet.getCell('D11').value, 3);
assert.deepEqual(sheet.getCell('B12').value, { formula: 'SUM(B10:B11)', result: 10 });
assert.deepEqual(sheet.getCell('E12').value, { formula: 'IFERROR(C12/B12,0)', result: .7 });
assert.equal(sheet.autoFilter, 'A9:E11');
assert.equal(sheet.views[0].state, 'frozen');
assert.equal(sheet.getCell('A9').fill.type, 'pattern');
});
test('weekly export keeps independent solved counts, descending dates and excludes receipt metrics', async () => {
const sheet = await saved({ kind: 'weekly', data: {
start: '2026-10-12', end: '2026-10-13', updatedAt: now.toISOString(),
totals: { reported: 3, closed: 9, received: 99 },
days: [{ date: '2026-10-12', reported: 1, closed: 3, received: 90 }, { date: '2026-10-13', reported: 2, closed: 6, received: 9 }],
} });
assert.deepEqual([1, 2, 3, 4].map(col => sheet.getCell(9, col).value), ['日期', '星期', '新增故障(单)', '解决故障(单)']);
assert.equal((sheet.getCell('A10').value as Date).toISOString(), '2026-10-13T00:00:00.000Z');
assert.match(sheet.getCell('A10').numFmt, /今天/);
assert.equal(sheet.getCell('B10').value, '周二');
assert.equal(sheet.getCell('D10').value, 6);
assert.deepEqual(sheet.getCell('D12').value, { formula: 'SUM(D10:D11)', result: 9 });
assert.deepEqual(sheet.getCell('C6').value, { formula: 'SUM(D10:D11)', result: 9 });
assert.equal(sheet.columnCount, 4);
});
test('zero-data trend exports valid guarded ratios and empty reports avoid inverted SUM ranges', async () => {
for (const periods of [[], [{ period: '2026-10-13', reported: 0, closed: 0, unclosed: 0 }]]) {
const sheet = await saved({ kind: 'trend', data: {
start: '2026-10-13', end: '2026-10-13', granularity: 'day', updatedAt: now.toISOString(),
totals: { reported: 0, closed: 0, unclosed: 0 }, periods,
} });
const total = 10 + periods.length;
assert.equal(sheet.getCell(`E${total}`).formula, `IFERROR(C${total}/B${total},0)`);
assert.equal(sheet.getCell(`B${total}`).formula, periods.length ? 'SUM(B10:B10)' : '0');
assert.equal(sheet.getCell('A6').result, 0);
}
});