test(01-04): PIPE-01 enforcement — schema violations throw at content load
- 2 happy-path tests: empty globs, valid YAML round-trip - 3 throw assertions covering the schema-violation matrix: * numeric id (violates stable-string-ID rule) * season out of [0,7] range * Markdown frontmatter missing required id - All 5 tests pass; full Phase-1 suite remains green - Proves the throws that fail npm run build at module-eval time
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { loadFragmentsFromGlob } from './loader.ts';
|
||||
|
||||
/**
|
||||
* PIPE-01 enforcement: a schema violation in any /content/seasons/**.yaml
|
||||
* or /content/seasons/**\/fragments/*.md file MUST fail the build.
|
||||
*
|
||||
* The exported `loadFragmentsFromGlob(yamlGlob, mdGlob)` helper accepts
|
||||
* mocked glob outputs so we can prove the schema rejects bad input the
|
||||
* same way `import.meta.glob` would feed real files into the build-time
|
||||
* loader (which throws and bubbles up through Vite, exiting non-zero).
|
||||
*
|
||||
* Per .planning/phases/01-foundations-and-doctrine/01-RESEARCH.md
|
||||
* § Validation Architecture (PIPE-01 row): "Vitest run with mocked
|
||||
* import.meta.glob" — that's this file.
|
||||
*/
|
||||
describe('PIPE-01: content schema validation', () => {
|
||||
it('returns [] when both globs are empty', () => {
|
||||
expect(loadFragmentsFromGlob({}, {})).toEqual([]);
|
||||
});
|
||||
|
||||
it('parses valid YAML fragments', () => {
|
||||
const yamlGlob = {
|
||||
'/content/seasons/00-demo/fragments.yaml': `
|
||||
fragments:
|
||||
- id: season0.demo.test
|
||||
season: 0
|
||||
body: "demo body"
|
||||
`,
|
||||
};
|
||||
const result = loadFragmentsFromGlob(yamlGlob);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toMatchObject({
|
||||
id: 'season0.demo.test',
|
||||
season: 0,
|
||||
body: 'demo body',
|
||||
});
|
||||
});
|
||||
|
||||
it('THROWS on a numeric-id violation (stable-string-ID rule)', () => {
|
||||
const yamlGlob = {
|
||||
'/content/seasons/01-soil/fragments.yaml': `
|
||||
fragments:
|
||||
- id: 42
|
||||
season: 1
|
||||
body: "this should fail because id must be a string matching the season<N>.<slug> regex"
|
||||
`,
|
||||
};
|
||||
expect(() => loadFragmentsFromGlob(yamlGlob)).toThrow(/\[content\] schema violation/);
|
||||
});
|
||||
|
||||
it('THROWS when season is out of [0,7] range', () => {
|
||||
const yamlGlob = {
|
||||
'/content/seasons/99-bogus/fragments.yaml': `
|
||||
fragments:
|
||||
- id: season99.bogus.test
|
||||
season: 99
|
||||
body: "season 99 doesn't exist"
|
||||
`,
|
||||
};
|
||||
expect(() => loadFragmentsFromGlob(yamlGlob)).toThrow(/\[content\] schema violation/);
|
||||
});
|
||||
|
||||
it('THROWS when Markdown frontmatter omits required id', () => {
|
||||
const mdGlob = {
|
||||
'/content/seasons/01-soil/fragments/no-id.md': `---
|
||||
season: 1
|
||||
---
|
||||
|
||||
Body text without an id frontmatter key.
|
||||
`,
|
||||
};
|
||||
expect(() => loadFragmentsFromGlob({}, mdGlob)).toThrow(/\[content\] schema violation/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user