28 lines
1.5 KiB
TypeScript
28 lines
1.5 KiB
TypeScript
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());
|
||
});
|