Files
school_compare/nextjs-app/__tests__/components/rowContainerGuard.test.ts
T

41 lines
1.8 KiB
TypeScript
Raw Normal View History

import fs from 'fs';
import path from 'path';
/*
* SchoolRow and SecondarySchoolRow switch to their narrow layout with a
* container query on a `results` container, not a media query, because the
* same row fills the phone list and the narrow list beside the desktop map.
* Outside a `results` container the query never matches and the row keeps its
* wide layout on a phone, a silent regression rather than an error.
*
* HomeView provides the container on every list it renders the rows into.
* Anything else that starts rendering them must do the same; this fails so
* that the person adding it reads this first.
*/
const ROOT = path.join(__dirname, '..', '..');
const DIRS = ['app', 'components', 'lib'];
const ROW_IMPORT = /from\s+['"][^'"]*\/(SchoolRow|SecondarySchoolRow)['"]/;
function sources(dir: string): string[] {
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) return entry.name === 'node_modules' ? [] : sources(full);
return /\.tsx?$/.test(entry.name) ? [full] : [];
});
}
it('renders the results rows only where a `results` container is provided', () => {
const importers = DIRS.flatMap((d) => sources(path.join(ROOT, d)))
.filter((file) => ROW_IMPORT.test(fs.readFileSync(file, 'utf8')))
.map((file) => path.relative(ROOT, file));
expect(importers).toEqual(['components/HomeView.tsx']);
});
it('gives each of HomeView\'s row lists the `results` container', () => {
const css = fs.readFileSync(path.join(ROOT, 'components', 'HomeView.module.css'), 'utf8');
for (const list of ['.schoolList', '.compactList', '.bottomSheet']) {
const rule = new RegExp(`\\${list}\\s*\\{[^}]*container:\\s*results\\s*/\\s*inline-size`);
expect({ list, provided: rule.test(css) }).toEqual({ list, provided: true });
}
});