import { isValidElement } from 'react'; import { Navigate } from 'react-router'; import { expect, it } from 'vitest'; import { routes } from './routes'; // scripts/shot.mjs держит СВОЙ список маршрутов — Node не умеет загрузить TSX без сборки, // и это сознательный размен на простоту. Цена размена: новый экран, забытый в shot.mjs, // не снимается и не проверяется axe, а `npm run shot` при этом возвращает успех. // Замок дешевле дисциплины: расхождение двух списков падает тестом. const shot = Object.values( import.meta.glob('../scripts/shot.mjs', { query: '?raw', eager: true, import: 'default' }), )[0] as string; it('список маршрутов в scripts/shot.mjs совпадает с routes.tsx', () => { const declared = /const KNOWN_ROUTES = \[(.*?)\];/s.exec(shot)?.[1]; expect(declared, 'KNOWN_ROUTES не найден в scripts/shot.mjs').toBeDefined(); const known = [...(declared as string).matchAll(/'([^']+)'/g)].map((m) => m[1]); // Редиректы снимать нечего: своего экрана у них нет. const screens = routes .filter((route) => !(isValidElement(route.element) && route.element.type === Navigate)) .map((route) => route.path) .filter((path) => path !== undefined); expect(known.toSorted()).toEqual(screens.toSorted()); });