feat(monitor): match motion to report intervals
This commit is contained in:
@@ -2,7 +2,7 @@ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-libra
|
||||
import { afterEach, expect, test, vi } from 'vitest';
|
||||
import type { MonitorMapResponse } from '../../api/types';
|
||||
import { wgs84ToGcj02, type AMapLike, type AMapMap, type AMapMassPoint } from '../../integrations/amap';
|
||||
import { FleetMap, interpolateMassPoints, massPointFingerprint } from './FleetMap';
|
||||
import { FleetMap, interpolateMassPoints, interpolateMassPointsByElapsed, massPointFingerprint, pointMoveDurationMs } from './FleetMap';
|
||||
|
||||
const setData = vi.fn<(data: AMapMassPoint[]) => void>();
|
||||
const setStyle = vi.fn();
|
||||
@@ -118,6 +118,7 @@ const pointMap: MonitorMapResponse = {
|
||||
socPercent: 80,
|
||||
totalMileageKm: 1234,
|
||||
lastSeen: '2026-07-14T01:00:00Z',
|
||||
reportIntervalMs: 10_000,
|
||||
status: 'driving'
|
||||
}, {
|
||||
vin: 'LTEST000000000002',
|
||||
@@ -130,6 +131,7 @@ const pointMap: MonitorMapResponse = {
|
||||
socPercent: 72,
|
||||
totalMileageKm: 2234,
|
||||
lastSeen: '2026-07-14T01:00:00Z',
|
||||
reportIntervalMs: 30_000,
|
||||
status: 'idle'
|
||||
}]
|
||||
};
|
||||
@@ -151,7 +153,7 @@ test('keeps large fleet redraw fingerprints constant-size and sensitive to point
|
||||
expect(massPointFingerprint('points', [], manyPoints, [])).toBe(fingerprint);
|
||||
});
|
||||
|
||||
test('interpolates existing mass points with easing while keeping new points stable', () => {
|
||||
test('interpolates existing mass points at constant speed while keeping new points stable', () => {
|
||||
const previous: AMapMassPoint[] = [{ id: 'moving', label: 'A', style: 0, lnglat: [10, 20] }];
|
||||
const target: AMapMassPoint[] = [
|
||||
{ id: 'moving', label: 'A', style: 2, lnglat: [14, 24] },
|
||||
@@ -162,10 +164,34 @@ test('interpolates existing mass points with easing while keeping new points sta
|
||||
{ ...target[0], lnglat: [10, 20] },
|
||||
target[1]
|
||||
]);
|
||||
expect(interpolateMassPoints(previous, target, .5)[0]).toEqual({ ...target[0], lnglat: [13.5, 23.5] });
|
||||
expect(interpolateMassPoints(previous, target, .5)[0]).toEqual({ ...target[0], lnglat: [12, 22] });
|
||||
expect(interpolateMassPoints(previous, target, 1)).toEqual(target);
|
||||
});
|
||||
|
||||
test('uses each protocol report interval with bounded fallbacks for point motion', () => {
|
||||
expect(pointMoveDurationMs(10_000)).toBe(10_000);
|
||||
expect(pointMoveDurationMs(30_000)).toBe(30_000);
|
||||
expect(pointMoveDurationMs(60_000)).toBe(60_000);
|
||||
expect(pointMoveDurationMs(undefined)).toBe(15_000);
|
||||
expect(pointMoveDurationMs(100)).toBe(1_000);
|
||||
expect(pointMoveDurationMs(300_000)).toBe(120_000);
|
||||
});
|
||||
|
||||
test('advances each vehicle independently according to its report interval', () => {
|
||||
const previous: AMapMassPoint[] = [
|
||||
{ id: 'JT808', label: 'A', style: 0, lnglat: [0, 0] },
|
||||
{ id: 'GB32960', label: 'B', style: 0, lnglat: [0, 0] }
|
||||
];
|
||||
const target: AMapMassPoint[] = previous.map((point) => ({ ...point, lnglat: [30, 30] }));
|
||||
const frame = interpolateMassPointsByElapsed(previous, target, 10_000, new Map([
|
||||
['JT808', 10_000],
|
||||
['GB32960', 30_000]
|
||||
]));
|
||||
|
||||
expect(frame[0].lnglat).toEqual([30, 30]);
|
||||
expect(frame[1].lnglat).toEqual([10, 10]);
|
||||
});
|
||||
|
||||
function amapMock(): AMapLike {
|
||||
return {
|
||||
Map: TestMap as unknown as AMapLike['Map'],
|
||||
@@ -429,7 +455,7 @@ test('renders one selected plate and smoothly follows it until the map is dragge
|
||||
/>
|
||||
);
|
||||
await waitFor(() => expect(markerSetPosition).toHaveBeenLastCalledWith(wgs84ToGcj02(113.27, 23.14)), { timeout: 1_800 });
|
||||
expect(panTo).toHaveBeenLastCalledWith(wgs84ToGcj02(113.27, 23.14), 5_000);
|
||||
expect(panTo).toHaveBeenLastCalledWith(wgs84ToGcj02(113.27, 23.14), 10_000);
|
||||
expect(setZoomAndCenter).toHaveBeenCalledTimes(1);
|
||||
|
||||
const follow = screen.getByRole('button', { name: '跟随车辆' });
|
||||
|
||||
Reference in New Issue
Block a user