Files
ln-bi/src/modules/mileage/monitoring/monitoring-model.test.ts
T

181 lines
6.2 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import type { MonitoringVehicle } from '../types';
import { defaultMileageDate, getRangePreset, normalizeRangeLabel } from './date-range';
import { formatAbsoluteTime, parseOneOsTime, vehicleStatisticTime } from './oneos-time';
import {
buildExportMonitoringQuery,
buildFullscreenMonitoringQuery,
buildInitialMonitoringQuery,
buildNextPageMonitoringQuery,
type MonitoringQueryModel,
} from './query-model';
import { vehicleSourceDisplay } from './source-display';
const baseVehicle: MonitoringVehicle = {
plate: '粤A00001',
vin: 'TESTVIN',
dailyKm: 0,
totalKm: 0,
source: 'ONEOS',
sourceProtocol: null,
sourceCategory: null,
dataTime: null,
calculatedAt: null,
updatedAt: null,
isOnline: false,
isDataSynced: false,
customer: null,
department: null,
manager: null,
rentStatus: null,
entity: null,
project: null,
region: null,
inventoryLocation: null,
brand: null,
targetNames: [],
};
const queryModel: MonitoringQueryModel = {
sortBy: 'statisticTime',
sortOrder: 'asc',
searchTerm: '粤A',
department: '业务一部',
customer: '客户甲',
project: '项目甲',
entity: '主体甲',
rentStatus: '租赁',
platePrefix: '粤A',
targetNames: ['批次甲'],
region: '广州',
plates: ['粤A00001', '粤A00002'],
mileageRange: { min: '10', max: '500' },
rangeStart: '2026-08-01',
rangeEnd: '2026-08-12',
brands: ['现代'],
sourcePriority: ['instrument', 'gps'],
};
test('monitoring date rolls over at 05:00 and presets retain existing ranges', () => {
assert.equal(defaultMileageDate(new Date(2026, 7, 13, 4, 59)), '2026-08-12');
assert.equal(defaultMileageDate(new Date(2026, 7, 13, 5, 0)), '2026-08-13');
const now = new Date(2026, 7, 13, 12, 0);
assert.deepEqual(getRangePreset('today', now), { start: '2026-08-13', end: '2026-08-13' });
assert.deepEqual(getRangePreset('yesterday', now), { start: '2026-08-12', end: '2026-08-12' });
assert.deepEqual(getRangePreset('thisWeek', now), { start: '2026-08-10', end: '2026-08-13' });
assert.deepEqual(getRangePreset('thisMonth', now), { start: '2026-08-01', end: '2026-08-13' });
assert.deepEqual(getRangePreset('last7', now), { start: '2026-08-07', end: '2026-08-13' });
assert.deepEqual(getRangePreset('last15', now), { start: '2026-07-30', end: '2026-08-13' });
assert.equal(normalizeRangeLabel('', ''), '最新数据');
assert.equal(normalizeRangeLabel('2026-08-12', '2026-08-12'), '2026-08-12');
assert.equal(normalizeRangeLabel('2026-08-01', '2026-08-12'), '2026-08-01 至 2026-08-12');
});
test('OneOS timestamps keep China Standard Time parsing and relative labels', () => {
assert.equal(
parseOneOsTime('2026-08-13 09:30:05'),
Date.parse('2026-08-13T09:30:05+08:00'),
);
assert.equal(parseOneOsTime('invalid'), null);
assert.equal(formatAbsoluteTime('2026-08-13 09:30:05'), '2026/08/13 09:30:05');
const display = vehicleStatisticTime(
{
...baseVehicle,
dataTime: '2026-08-13 09:30:05',
calculatedAt: '2026-08-13 09:30:06',
updatedAt: '2026-08-13 09:30:07',
isDataSynced: true,
},
Date.parse('2026-08-13T09:31:05+08:00'),
);
assert.deepEqual(display, {
label: '1分钟前',
title: [
'数据时间:2026/08/13 09:30:05',
'计算时间:2026/08/13 09:30:06',
'更新时间:2026/08/13 09:30:07',
].join('\n'),
color: 'text-emerald-500',
});
assert.deepEqual(vehicleStatisticTime({ ...baseVehicle, isDataSynced: true }, Date.now()), {
label: '统计时间待接口',
title: 'OneOS 当前未返回车辆级数据时间',
color: 'text-amber-500',
});
});
test('vehicle source display retains all source and missing-data states', () => {
assert.deepEqual(vehicleSourceDisplay({
...baseVehicle,
sourceCategory: 'INSTRUMENT',
sourceProtocol: 'MQTT',
}), {
label: '仪表数据',
title: 'MQTT',
className: 'bg-violet-50 text-violet-600',
});
assert.equal(vehicleSourceDisplay({ ...baseVehicle, sourceCategory: 'GPS' }).title, 'JT808');
assert.equal(vehicleSourceDisplay({ ...baseVehicle, sourceCategory: 'MIXED' }).label, '仪表+GPS');
assert.equal(vehicleSourceDisplay({ ...baseVehicle, isDataSynced: true }).label, '来源待接口');
assert.equal(vehicleSourceDisplay(baseVehicle).label, '无数据');
});
test('four monitoring query builders preserve pagination and fullscreen differences', () => {
const initial = buildInitialMonitoringQuery(queryModel, 50);
assert.equal(initial.limit, 50);
assert.equal(initial.page, 1);
assert.equal(initial.project, '项目甲');
assert.equal(initial.entity, '主体甲');
assert.equal(initial.mileageMin, '10');
assert.equal(initial.mileageMax, '500');
assert.equal(initial.plate, '粤A00001,粤A00002');
const nextPage = buildNextPageMonitoringQuery(queryModel, 50, 3);
assert.deepEqual(nextPage, { ...initial, page: 3 });
const exported = buildExportMonitoringQuery(queryModel);
assert.deepEqual(exported, { ...initial, limit: 9999 });
const fullscreen = buildFullscreenMonitoringQuery(queryModel);
assert.equal(fullscreen.limit, 9999);
assert.equal(fullscreen.page, 1);
assert.equal(fullscreen.customer, '客户甲');
assert.equal('project' in fullscreen, false);
assert.equal('entity' in fullscreen, false);
assert.equal('mileageMin' in fullscreen, false);
assert.equal('mileageMax' in fullscreen, false);
});
test('query model converts empty selections exactly as the existing requests do', () => {
const query = buildInitialMonitoringQuery({
...queryModel,
searchTerm: '',
department: 'All',
customer: 'All',
project: 'All',
entity: 'All',
rentStatus: 'All',
platePrefix: 'All',
targetNames: [],
region: 'All',
plates: [],
mileageRange: { min: '', max: '' },
rangeStart: '',
rangeEnd: '',
brands: [],
}, 50);
assert.equal(query.search, undefined);
assert.equal(query.dept, undefined);
assert.equal(query.project, undefined);
assert.equal(query.plate, undefined);
assert.equal(query.mileageMin, undefined);
assert.equal(query.startDate, undefined);
assert.equal(query.brands, undefined);
assert.deepEqual(query.sourcePriority, ['instrument', 'gps']);
});