73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import * as fs from 'fs/promises';
|
|
import * as path from 'path';
|
|
|
|
describe('Website boundary: pages must consume ViewModels only (no DTO imports)', () => {
|
|
it('rejects forbidden imports for specific pages', async () => {
|
|
const websiteRoot = path.resolve(__dirname, '../..');
|
|
|
|
const candidates = [
|
|
'app/races/[id]/page.tsx',
|
|
'app/leagues/[id]/stewarding/protests/[protestId]/page.tsx',
|
|
].map((p) => path.resolve(websiteRoot, p));
|
|
|
|
const forbiddenImportRegex =
|
|
/^\s*import[\s\S]*from\s+['"][^'"]*(\/mappers\/|\/lib\/types\/|\/types\/generated\/)[^'"]*['"]/gm;
|
|
|
|
const offenders: Array<{ file: string; matches: string[] }> = [];
|
|
|
|
for (const file of candidates) {
|
|
const content = await fs.readFile(file, 'utf-8');
|
|
|
|
const matches = Array.from(content.matchAll(forbiddenImportRegex))
|
|
.map((m) => m[0])
|
|
.filter(Boolean);
|
|
|
|
if (matches.length > 0) {
|
|
offenders.push({
|
|
file: path.relative(websiteRoot, file),
|
|
matches,
|
|
});
|
|
}
|
|
}
|
|
|
|
expect(
|
|
offenders,
|
|
`Forbidden imports found:\n${offenders
|
|
.map((o) => `- ${o.file}\n${o.matches.map((m) => ` ${m}`).join('\n')}`)
|
|
.join('\n')}`,
|
|
).toEqual([]);
|
|
});
|
|
|
|
it('rejects DTO identifier usage in these page modules', async () => {
|
|
const websiteRoot = path.resolve(__dirname, '../..');
|
|
|
|
const candidates = [
|
|
'app/races/[id]/page.tsx',
|
|
'app/leagues/[id]/stewarding/protests/[protestId]/page.tsx',
|
|
].map((p) => path.resolve(websiteRoot, p));
|
|
|
|
const dtoIdentifierRegex = /\b[A-Za-z0-9_]+DTO\b/g;
|
|
|
|
const offenders: Array<{ file: string; matches: string[] }> = [];
|
|
|
|
for (const file of candidates) {
|
|
const content = await fs.readFile(file, 'utf-8');
|
|
const matches = Array.from(content.matchAll(dtoIdentifierRegex)).map((m) => m[0]).filter(Boolean);
|
|
|
|
if (matches.length > 0) {
|
|
offenders.push({
|
|
file: path.relative(websiteRoot, file),
|
|
matches: Array.from(new Set(matches)).sort(),
|
|
});
|
|
}
|
|
}
|
|
|
|
expect(
|
|
offenders,
|
|
`DTO identifiers found:\n${offenders
|
|
.map((o) => `- ${o.file}\n${o.matches.map((m) => ` ${m}`).join('\n')}`)
|
|
.join('\n')}`,
|
|
).toEqual([]);
|
|
});
|
|
}); |