This commit is contained in:
108
tests/hive-950-token-guard.test.ts
Normal file
108
tests/hive-950-token-guard.test.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* H-06 · CR-2 · Residual hive-950 token guard.
|
||||
*
|
||||
* Guards against accidental reintroduction of direct hex / utility-class
|
||||
* references to `hive-950` inside apps/web/src components. The token
|
||||
* itself is legitimate — it is defined per theme in
|
||||
* `apps/web/src/index.css` (dark: #08090c, light: #fdfcf9) and consumed
|
||||
* via `var(--hive-950)` in `waggle-theme.css`. Components must go
|
||||
* through the semantic layer, never directly.
|
||||
*
|
||||
* This replaces the manual `grep -r "hive-950|#08090c"` sweep the backlog
|
||||
* describes (CR-2) with a CI-enforceable static check.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import fg from 'fast-glob';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { relative, resolve } from 'node:path';
|
||||
|
||||
const REPO_ROOT = resolve(__dirname, '..');
|
||||
const WEB_SRC = resolve(REPO_ROOT, 'apps/web/src');
|
||||
|
||||
/** Files that are allowed to reference `hive-950` or `#08090c` directly. */
|
||||
const ALLOW_LIST = new Set([
|
||||
'apps/web/src/index.css', // token definitions per theme
|
||||
'apps/web/src/waggle-theme.css', // consumes var(--hive-950)
|
||||
]);
|
||||
|
||||
/**
|
||||
* Repo-relative path with forward slashes for ALLOW_LIST lookup. Must be
|
||||
* cross-platform: a prior version normalised the ALLOW_LIST to backslashes,
|
||||
* so on Linux (CI) the allow-listed files never matched and their legitimate
|
||||
* #08090c / --hive-950 declarations were flagged as violations.
|
||||
*/
|
||||
function asRepoPath(absolute: string): string {
|
||||
return relative(REPO_ROOT, absolute).replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
describe('CR-2 · hive-950 token discipline', () => {
|
||||
it('no .tsx / .ts file outside the allow-list contains the #08090c hex literal', async () => {
|
||||
const files = await fg(['**/*.{ts,tsx}'], {
|
||||
cwd: WEB_SRC,
|
||||
absolute: true,
|
||||
ignore: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'],
|
||||
});
|
||||
|
||||
const violations: Array<{ file: string; line: number; text: string }> = [];
|
||||
for (const file of files) {
|
||||
const relPath = asRepoPath(file);
|
||||
if (ALLOW_LIST.has(relPath) || ALLOW_LIST.has(relPath.replace(/\\/g, '/'))) continue;
|
||||
const content = readFileSync(file, 'utf-8');
|
||||
content.split(/\r?\n/).forEach((line, idx) => {
|
||||
// Anchor on a quote or `#` character to avoid flagging comments
|
||||
// that merely mention `08090c` in prose. This is the same
|
||||
// false-positive the manual grep rule would hit.
|
||||
if (/['"#]08090c/i.test(line)) {
|
||||
violations.push({ file: relPath, line: idx + 1, text: line.trim() });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
expect(violations, `Direct #08090c usage outside allow-list: ${JSON.stringify(violations, null, 2)}`).toEqual([]);
|
||||
});
|
||||
|
||||
it('no .tsx file uses a hive-950 utility class inside className', async () => {
|
||||
const files = await fg(['**/*.tsx'], {
|
||||
cwd: WEB_SRC,
|
||||
absolute: true,
|
||||
ignore: ['**/node_modules/**', '**/dist/**'],
|
||||
});
|
||||
|
||||
const violations: Array<{ file: string; line: number; text: string }> = [];
|
||||
for (const file of files) {
|
||||
const relPath = asRepoPath(file);
|
||||
const content = readFileSync(file, 'utf-8');
|
||||
content.split(/\r?\n/).forEach((line, idx) => {
|
||||
// `bg-hive-950`, `text-hive-950`, `border-hive-950`, `to-hive-950`,
|
||||
// etc. Anything of shape `<prefix>-hive-950`.
|
||||
if (/\b(?:bg|text|border|from|to|via|ring|fill|stroke|divide|shadow|outline)-hive-950\b/.test(line)) {
|
||||
violations.push({ file: relPath, line: idx + 1, text: line.trim() });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
expect(violations, `Raw hive-950 utility class in component: ${JSON.stringify(violations, null, 2)}`).toEqual([]);
|
||||
});
|
||||
|
||||
it('CSS files outside the allow-list do not redeclare --hive-950 or use #08090c hex', async () => {
|
||||
const files = await fg(['**/*.css'], {
|
||||
cwd: WEB_SRC,
|
||||
absolute: true,
|
||||
ignore: ['**/node_modules/**', '**/dist/**'],
|
||||
});
|
||||
|
||||
const violations: Array<{ file: string; line: number; text: string }> = [];
|
||||
for (const file of files) {
|
||||
const relPath = asRepoPath(file);
|
||||
if (ALLOW_LIST.has(relPath) || ALLOW_LIST.has(relPath.replace(/\\/g, '/'))) continue;
|
||||
const content = readFileSync(file, 'utf-8');
|
||||
content.split(/\r?\n/).forEach((line, idx) => {
|
||||
if (/--hive-950\s*:/.test(line) || /#08090c/i.test(line)) {
|
||||
violations.push({ file: relPath, line: idx + 1, text: line.trim() });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
expect(violations, `Hive-950 declared / hex-used outside allow-list: ${JSON.stringify(violations, null, 2)}`).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user