perf(web): release track map listeners explicitly
This commit is contained in:
117
vehicle-data-platform/apps/web/src/v2/map/TrackMap.test.tsx
Normal file
117
vehicle-data-platform/apps/web/src/v2/map/TrackMap.test.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { cleanup, render, waitFor } from '@testing-library/react';
|
||||
import { afterEach, expect, test, vi } from 'vitest';
|
||||
import type { HistoryLocationRow, TrackStop } from '../../api/types';
|
||||
import type { AMapLike } from '../../integrations/amap';
|
||||
import { TrackMap } from './TrackMap';
|
||||
|
||||
const overlayOff = vi.fn();
|
||||
const overlaySetMap = vi.fn();
|
||||
const mapOff = vi.fn();
|
||||
const mapDestroy = vi.fn();
|
||||
const markerListeners: Array<{ overlay: TestOverlay; event: string; handler: () => void }> = [];
|
||||
|
||||
class TestOverlay {
|
||||
on = vi.fn((event: string, handler: () => void) => markerListeners.push({ overlay: this, event, handler }));
|
||||
off = overlayOff;
|
||||
setMap = overlaySetMap;
|
||||
setPosition = vi.fn();
|
||||
setPath = vi.fn();
|
||||
}
|
||||
|
||||
class TestMap {
|
||||
add = vi.fn();
|
||||
addControl = vi.fn();
|
||||
setFitView = vi.fn();
|
||||
destroy = mapDestroy;
|
||||
on = vi.fn();
|
||||
off = mapOff;
|
||||
panTo = vi.fn();
|
||||
}
|
||||
|
||||
class TestScale {}
|
||||
class TestToolBar {}
|
||||
class TestSize {}
|
||||
class TestPixel {}
|
||||
class TestMassMarks {}
|
||||
|
||||
function amapMock(): AMapLike {
|
||||
return {
|
||||
Map: TestMap as unknown as AMapLike['Map'],
|
||||
Marker: TestOverlay as unknown as AMapLike['Marker'],
|
||||
Polyline: TestOverlay as unknown as AMapLike['Polyline'],
|
||||
Scale: TestScale,
|
||||
ToolBar: TestToolBar,
|
||||
Size: TestSize as unknown as AMapLike['Size'],
|
||||
Pixel: TestPixel as unknown as AMapLike['Pixel'],
|
||||
MassMarks: TestMassMarks as unknown as AMapLike['MassMarks']
|
||||
};
|
||||
}
|
||||
|
||||
const points = [{
|
||||
vin: 'LTEST000000000001',
|
||||
plate: '粤A12345',
|
||||
protocol: 'JT808',
|
||||
deviceTime: '2026-07-16T00:00:00Z',
|
||||
serverTime: '2026-07-16T00:00:01Z',
|
||||
longitude: 113.26,
|
||||
latitude: 23.13,
|
||||
speedKmh: 0,
|
||||
totalMileageKm: 100
|
||||
}, {
|
||||
vin: 'LTEST000000000001',
|
||||
plate: '粤A12345',
|
||||
protocol: 'JT808',
|
||||
deviceTime: '2026-07-16T00:10:00Z',
|
||||
serverTime: '2026-07-16T00:10:01Z',
|
||||
longitude: 113.28,
|
||||
latitude: 23.15,
|
||||
speedKmh: 30,
|
||||
totalMileageKm: 105
|
||||
}] as HistoryLocationRow[];
|
||||
|
||||
const stops = [{
|
||||
index: 0,
|
||||
startTime: '2026-07-16T00:00:00Z',
|
||||
endTime: '2026-07-16T00:05:00Z',
|
||||
durationSeconds: 300,
|
||||
pointCount: 1,
|
||||
longitude: 113.26,
|
||||
latitude: 23.13,
|
||||
sampledIndex: 0,
|
||||
evidence: 'GPS 推断'
|
||||
}] as TrackStop[];
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
delete window.__LINGNIU_APP_CONFIG__;
|
||||
delete window.AMapLoader;
|
||||
overlayOff.mockReset();
|
||||
overlaySetMap.mockReset();
|
||||
mapOff.mockReset();
|
||||
mapDestroy.mockReset();
|
||||
markerListeners.length = 0;
|
||||
});
|
||||
|
||||
test('detaches every marker listener and map listener on unmount', async () => {
|
||||
window.__LINGNIU_APP_CONFIG__ = { amapWebJsKey: 'amap-web-key' };
|
||||
window.AMapLoader = { load: vi.fn(async () => amapMock()) };
|
||||
const view = render(<TrackMap
|
||||
points={points}
|
||||
stops={stops}
|
||||
activeIndex={0}
|
||||
showStops
|
||||
follow
|
||||
onSelectIndex={() => undefined}
|
||||
onFollowChange={() => undefined}
|
||||
/>);
|
||||
|
||||
await waitFor(() => expect(markerListeners).toHaveLength(3));
|
||||
view.unmount();
|
||||
|
||||
for (const listener of markerListeners) {
|
||||
expect(overlayOff).toHaveBeenCalledWith(listener.event, listener.handler);
|
||||
}
|
||||
expect(mapOff).toHaveBeenCalledWith('dragstart', expect.any(Function));
|
||||
expect(overlaySetMap).toHaveBeenCalled();
|
||||
expect(mapDestroy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
Reference in New Issue
Block a user