import { RouteStepStatus } from './models'; import { navigate, parseRoute } from './routing'; // buildQuery/navigate читают/пишут window.location через history API — сбрасываем // адрес перед каждым тестом, чтобы тесты не зависели от порядка запуска. beforeEach(() => { window.history.replaceState({}, '', '/'); }); describe('parseRoute', () => { it('без aatab — вкладка по умолчанию dashboard, всё остальное пусто', () => { expect(parseRoute('')).toEqual({ tab: 'dashboard', routeId: undefined, resolve: undefined, manage: undefined }); }); it('незнакомое значение aatab тоже откатывается на dashboard', () => { expect(parseRoute('?aatab=bogus-tab').tab).toBe('dashboard'); }); it('manageRequests с aamtype+aamreq — даёт заполненный manage', () => { const route = parseRoute('?aatab=manageRequests&aamtype=5&aamreq=42'); expect(route.tab).toBe('manageRequests'); expect(route.manage).toEqual({ requestTypeId: '5', requestId: '42' }); }); it('manageRequests без aamreq — manage не собирается (id заявки обязателен)', () => { const route = parseRoute('?aatab=manageRequests&aamtype=5'); expect(route.manage).toBeUndefined(); }); it('aaroute учитывается только при tab=routes', () => { expect(parseRoute('?aatab=routes&aaroute=7').routeId).toBe(7); expect(parseRoute('?aatab=manageRequests&aaroute=7').routeId).toBeUndefined(); }); it('нечисловой/отсутствующий aaroute — routeId не задан', () => { expect(parseRoute('?aatab=routes&aaroute=not-a-number').routeId).toBeUndefined(); expect(parseRoute('?aatab=routes').routeId).toBeUndefined(); }); it('resolve.fieldValues парсит валидный JSON-массив', () => { const fields = encodeURIComponent(JSON.stringify([{ fieldName: 'Amount', value: '100' }])); const route = parseRoute(`?aatab=resolve&aartype=1&aafields=${fields}`); expect(route.resolve?.fieldValues).toEqual([{ fieldName: 'Amount', value: '100' }]); }); it('resolve.fieldValues на битом JSON не роняет парсинг маршрута — просто пустой массив', () => { const route = parseRoute('?aatab=resolve&aartype=1&aafields=not-json'); expect(route.resolve?.fieldValues).toEqual([]); }); it('resolve не собирается без requestTypeId, даже если tab=resolve', () => { expect(parseRoute('?aatab=resolve').resolve).toBeUndefined(); }); it('resolve.departmentId читается из aadept (шаг «Руководитель указанного отдела»)', () => { const route = parseRoute('?aatab=resolve&aartype=1&aadept=00000000-0000-0000-0000-0000000000aa'); expect(route.resolve?.departmentId).toBe('00000000-0000-0000-0000-0000000000aa'); }); it('resolve.departmentId пустой, если aadept не передан', () => { const route = parseRoute('?aatab=resolve&aartype=1'); expect(route.resolve?.departmentId).toBe(''); }); }); describe('navigate', () => { it('после navigate() параметры читаются обратно тем же parseRoute (round-trip)', () => { navigate({ tab: 'manageRequests', manage: { requestTypeId: '3', requestId: '10' } }); const roundTripped = parseRoute(window.location.search); expect(roundTripped.tab).toBe('manageRequests'); expect(roundTripped.manage).toEqual({ requestTypeId: '3', requestId: '10' }); }); it('navigate на dashboard полностью убирает параметры вкладки из адреса', () => { navigate({ tab: 'manageRequests', manage: { requestTypeId: '3', requestId: '10' } }); navigate({ tab: 'dashboard' }); expect(window.location.search).toBe(''); }); it('дописывает новую запись в историю (pushState, а не replaceState)', () => { const initialLength = window.history.length; navigate({ tab: 'requestTypes' }); expect(window.history.length).toBe(initialLength + 1); }); it('round-trip для resolve.departmentId', () => { navigate({ tab: 'resolve', resolve: { requestTypeId: '1', userEmail: '', projectId: '', projectLabel: '', status: RouteStepStatus.Approval, fieldValues: [], departmentId: '00000000-0000-0000-0000-0000000000aa' } }); const roundTripped = parseRoute(window.location.search); expect(roundTripped.resolve?.departmentId).toBe('00000000-0000-0000-0000-0000000000aa'); }); });