136 lines
5.1 KiB
TypeScript
136 lines
5.1 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import type { HydrogenDailyRow } from '../types.js';
|
|
import {
|
|
filterHydrogenRows,
|
|
getQuickRange,
|
|
getRangeModeLabel,
|
|
normalizeRange,
|
|
summarizeHydrogenRows,
|
|
} from './model.js';
|
|
|
|
test('快捷日期继续使用本地自然日并覆盖本周、本月和近15天', () => {
|
|
const now = new Date(2026, 7, 12, 23, 30);
|
|
assert.deepEqual(getQuickRange('thisWeek', now), {
|
|
start: '2026-08-10',
|
|
end: '2026-08-12',
|
|
});
|
|
assert.deepEqual(getQuickRange('thisMonth', now), {
|
|
start: '2026-08-01',
|
|
end: '2026-08-12',
|
|
});
|
|
assert.deepEqual(getQuickRange('last15', now), {
|
|
start: '2026-07-29',
|
|
end: '2026-08-12',
|
|
});
|
|
});
|
|
|
|
test('自定义日期倒置时仅交换查询边界', () => {
|
|
assert.deepEqual(normalizeRange('2026-08-12', '2026-08-01'), {
|
|
start: '2026-08-01',
|
|
end: '2026-08-12',
|
|
});
|
|
assert.equal(getRangeModeLabel('custom'), '自定义区间');
|
|
assert.equal(getRangeModeLabel('last15'), '近 15 天');
|
|
});
|
|
|
|
test('每日加氢统计保持排序、有效天、站点去重和峰谷口径', () => {
|
|
const rows: HydrogenDailyRow[] = [
|
|
{
|
|
date: '2026-08-12',
|
|
totalKg: 0,
|
|
chainPct: -1,
|
|
customerType: 'lingniu',
|
|
stations: [{ name: 'A站', kg: 0, pricePerKg: 0, chainPct: -1 }],
|
|
},
|
|
{
|
|
date: '2026-08-10',
|
|
totalKg: 100,
|
|
chainPct: 0,
|
|
customerType: 'lingniu',
|
|
stations: [{ name: 'A站', kg: 100, pricePerKg: 20, chainPct: 0 }],
|
|
},
|
|
{
|
|
date: '2026-08-11',
|
|
totalKg: 300,
|
|
chainPct: 2,
|
|
customerType: 'lingniu',
|
|
stations: [{ name: 'B站', kg: 300, pricePerKg: 25, chainPct: 2 }],
|
|
},
|
|
];
|
|
|
|
const summary = summarizeHydrogenRows(rows);
|
|
assert.deepEqual(rows.map(row => row.date), ['2026-08-12', '2026-08-10', '2026-08-11']);
|
|
assert.deepEqual(summary.trendData.map(row => row.date), ['2026-08-10', '2026-08-11', '2026-08-12']);
|
|
assert.equal(summary.totalKg, 400);
|
|
assert.equal(summary.activeDays, 2);
|
|
assert.equal(summary.avgKg, 200);
|
|
assert.equal(summary.stationCount, 2);
|
|
assert.equal(summary.peakDay?.date, '2026-08-11');
|
|
assert.equal(summary.lowDay?.date, '2026-08-10');
|
|
assert.equal(summary.zeroDays, 1);
|
|
});
|
|
|
|
test('空数据保持零值且没有峰谷日', () => {
|
|
assert.deepEqual(summarizeHydrogenRows(null), {
|
|
trendData: [],
|
|
totalKg: 0,
|
|
activeDays: 0,
|
|
stationCount: 0,
|
|
avgKg: 0,
|
|
peakDay: null,
|
|
lowDay: null,
|
|
zeroDays: 0,
|
|
});
|
|
});
|
|
|
|
const searchRows: HydrogenDailyRow[] = [
|
|
{ date: '2026-09-17', totalKg: 50, chainPct: -0.75, customerType: 'all', stations: [
|
|
{ name: '嘉兴站', kg: 50, pricePerKg: 30, chainPct: 0 },
|
|
] },
|
|
{ date: '2026-09-16', totalKg: 200, chainPct: 1, customerType: 'all', stations: [
|
|
{ name: '佛山南海羚牛加氢站', kg: 30, pricePerKg: 38, chainPct: 2 },
|
|
{ name: '佛山豪汇石油加氢站', kg: 10, pricePerKg: 35, chainPct: 0 },
|
|
{ name: '嘉兴站', kg: 160, pricePerKg: 30, chainPct: 1 },
|
|
] },
|
|
{ date: '2026-09-15', totalKg: 100, chainPct: 0, customerType: 'all', stations: [
|
|
{ name: '佛山南海羚牛加氢站', kg: 10, pricePerKg: 38, chainPct: 0 },
|
|
{ name: '嘉兴站', kg: 90, pricePerKg: 30, chainPct: 0 },
|
|
] },
|
|
];
|
|
|
|
test('站名搜索同步更新日明细、总量、趋势和环比,保留完整日期及原始数据', () => {
|
|
const before = structuredClone(searchRows);
|
|
const filtered = filterHydrogenRows(searchRows, ' 佛山 ')!;
|
|
assert.deepEqual(filtered.map(row => row.date), searchRows.map(row => row.date));
|
|
assert.deepEqual(filtered.map(row => row.totalKg), [0, 40, 10]);
|
|
assert.deepEqual(filtered.map(row => row.chainPct), [-1, 3, 0]);
|
|
assert.equal(filtered[1].stations.length, 2);
|
|
assert.equal(filtered[1].stations[0].pricePerKg, 38);
|
|
assert.equal(filtered[1].stations[0].chainPct, 2);
|
|
const summary = summarizeHydrogenRows(filtered);
|
|
assert.equal(summary.totalKg, 50);
|
|
assert.equal(summary.stationCount, 2);
|
|
assert.equal(summary.activeDays, 2);
|
|
assert.equal(summary.avgKg, 25);
|
|
assert.equal(summary.zeroDays, 1);
|
|
assert.deepEqual(summary.trendData.map(row => row.totalKg), [10, 40, 0]);
|
|
assert.deepEqual(searchRows, before);
|
|
});
|
|
|
|
test('无匹配关键词显示零结果,清除或空白搜索恢复全量,加载中保持加载状态', () => {
|
|
const missing = filterHydrogenRows(searchRows, '不存在的站点')!;
|
|
assert.equal(missing.length, 3);
|
|
assert.ok(missing.every(row => row.totalKg === 0 && row.chainPct === 0 && row.stations.length === 0));
|
|
assert.strictEqual(filterHydrogenRows(searchRows, ''), searchRows);
|
|
assert.strictEqual(filterHydrogenRows(searchRows, ' '), searchRows);
|
|
assert.equal(summarizeHydrogenRows(filterHydrogenRows(searchRows, '')).totalKg, 350);
|
|
assert.equal(filterHydrogenRows(null, '佛山'), null);
|
|
assert.deepEqual(filterHydrogenRows([], '佛山'), []);
|
|
});
|
|
|
|
test('完整站名可定位单站,搜索将特殊字符按普通文字匹配', () => {
|
|
assert.equal(summarizeHydrogenRows(filterHydrogenRows(searchRows, '佛山南海羚牛加氢站')).totalKg, 40);
|
|
assert.equal(summarizeHydrogenRows(filterHydrogenRows(searchRows, '%')).totalKg, 0);
|
|
});
|