feat: seed pencil-art manifest + validator

This commit is contained in:
2026-07-20 15:27:59 +01:00
parent 6b88e0fa76
commit e58d833ba2
2 changed files with 38 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
export function validateArtManifest(m) {
if (!Array.isArray(m)) return ['manifest must be an array'];
const errors = [];
m.forEach((a, i) => {
if (!a || typeof a !== 'object') { errors.push(`entry[${i}] must be an object`); return; }
if (!a.id) errors.push(`entry[${i}].id required`);
if (!a.src) errors.push(`entry[${i}].src required`);
if (!Array.isArray(a.tags)) errors.push(`entry[${i}].tags must be an array`);
});
return errors;
}
// Seed set of placeholder pencil assets. Real convention art is added here as data.
export default [
{ id: 'detective-alley', src: '/art/detective-alley.png', label: 'Detective in alley', tags: ['detective', 'alley', 'rain', 'coat', 'tired'] },
{ id: 'neon-street', src: '/art/neon-street.png', label: 'Neon street', tags: ['street', 'neon', 'rain', 'city', 'night'] },
{ id: 'worn-portrait', src: '/art/worn-portrait.png', label: 'Worn portrait', tags: ['portrait', 'face', 'worn', 'close-up'] },
{ id: 'doorway-figure', src: '/art/doorway-figure.png', label: 'Figure in a doorway', tags: ['doorway', 'figure', 'shadow', 'coat'] },
{ id: 'rain-pier', src: '/art/rain-pier.png', label: 'Pier in the rain', tags: ['pier', 'rain', 'water', 'night', 'wide'] },
];
+18
View File
@@ -0,0 +1,18 @@
import { describe, it, expect } from 'vitest';
import artManifest, { validateArtManifest } from '../../src/art/manifest.js';
describe('art manifest', () => {
it('flags malformed entries', () => {
expect(validateArtManifest([{ id: '', src: 'x', tags: [] }])).toContain('entry[0].id required');
expect(validateArtManifest([{ id: 'a', src: '', tags: [] }])).toContain('entry[0].src required');
expect(validateArtManifest([{ id: 'a', src: 'x' }])).toContain('entry[0].tags must be an array');
});
it('ships a valid, non-empty seed manifest with unique ids', () => {
expect(validateArtManifest(artManifest)).toEqual([]);
expect(artManifest.length).toBeGreaterThanOrEqual(3);
const ids = artManifest.map((a) => a.id);
expect(new Set(ids).size).toBe(ids.length);
expect(artManifest.every((a) => a.src.startsWith('/art/'))).toBe(true);
});
});