import { expect, test } from 'vitest'; import { buildMonitorPath, monitorReturnFromParams, parseMonitorRouteContext, preserveMonitorReturn, validatedMonitorReturn, withMonitorReturn } from './monitorContext'; test('round trips the selected vehicle, filters, panel state, pagination and map viewport', () => { const path = buildMonitorPath({ mode: 'list', keyword: '粤A12345', protocol: 'JT808', status: 'online', selectedVin: 'LTEST000000000001', detailOpen: false, viewport: { zoom: 13.25, bounds: '113.100000,23.000000,113.400000,23.300000' }, listOffset: 100, listLimit: 100 }); const parsed = parseMonitorRouteContext(new URL(path, 'https://vehicle-platform.invalid').searchParams); expect(parsed).toMatchObject({ mode: 'list', keyword: '粤A12345', protocol: 'JT808', status: 'online', selectedVin: 'LTEST000000000001', detailOpen: false, viewport: { zoom: 13.25, bounds: '113.100000,23.000000,113.400000,23.300000' }, listOffset: 100, listLimit: 100, hasViewport: true }); }); test('carries only an internal monitor return and preserves it through child query changes', () => { const monitor = '/monitor?selectedVin=LTEST000000000001&detail=open&zoom=15&bounds=113.1%2C23%2C113.4%2C23.3'; const child = withMonitorReturn('/tracks?vin=LTEST000000000001', monitor); const childParams = new URL(child, 'https://vehicle-platform.invalid').searchParams; const monitorReturn = monitorReturnFromParams(childParams); const changed = preserveMonitorReturn(new URLSearchParams({ keyword: 'LTEST000000000001', protocol: 'JT808' }), monitorReturn); expect(monitorReturn).toContain('/monitor?'); expect(changed.get('monitorReturn')).toBe(monitorReturn); expect(validatedMonitorReturn('https://attacker.invalid/monitor?selectedVin=SECRET')).toBe(''); expect(validatedMonitorReturn('/vehicles/LTEST')).toBe(''); }); test('rejects malformed viewport input instead of restoring unsafe map state', () => { const context = parseMonitorRouteContext('?zoom=999&bounds=120,20,110,10&listOffset=-1&listLimit=500'); expect(context.viewport).toEqual({ zoom: 5, bounds: '' }); expect(context.listOffset).toBe(0); expect(context.listLimit).toBe(50); });