28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
import { isValidElement } from 'react';
|
|
|
|
import { Navigate } from 'react-router';
|
|
import { expect, it } from 'vitest';
|
|
|
|
import { routes } from './routes';
|
|
|
|
// scripts/shot.mjs keeps ITS OWN list of routes — Node cannot load TSX without a build,
|
|
// and that is a deliberate trade for simplicity. The price of the trade: a new screen forgotten
|
|
// in shot.mjs is neither photographed nor checked by axe, while `npm run shot` still returns
|
|
// success. A lock is cheaper than discipline: a divergence of the two lists fails as a test.
|
|
const shot = Object.values(
|
|
import.meta.glob('../scripts/shot.mjs', { query: '?raw', eager: true, import: 'default' }),
|
|
)[0] as string;
|
|
|
|
it('the list of routes in scripts/shot.mjs matches routes.tsx', () => {
|
|
const declared = /const KNOWN_ROUTES = \[(.*?)\];/s.exec(shot)?.[1];
|
|
expect(declared, 'KNOWN_ROUTES not found in scripts/shot.mjs').toBeDefined();
|
|
|
|
const known = [...(declared as string).matchAll(/'([^']+)'/g)].map((m) => m[1]);
|
|
// There is nothing to photograph in a redirect: it has no screen of its own.
|
|
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());
|
|
});
|