181 lines
6.2 KiB
TypeScript
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']);
|
|
});
|