/** * The `icon` field's refinement (openspec/changes/module-icons, D3). * * This is the trust boundary: `manifest.yml` is hand-edited and the value ends * up drawn in a coloured row, so the check that it is monochrome-capable lives * here rather than in any consumer. */ import { describe, expect, test } from 'bun:test'; import { ModuleManifestSchema } from './schema'; function manifestWith(icon?: string): Record { return { celilo_contract: '1.0', id: 'icon-fixture', name: 'Icon Fixture', version: '1.0.0', ...(icon === undefined ? {} : { icon }), }; } describe('manifest icon', () => { test('accepts a BMP non-emoji scalar', () => { const parsed = ModuleManifestSchema.parse(manifestWith('⛨')); expect(parsed.icon).toBe('⛨'); }); test('accepts absence', () => { const parsed = ModuleManifestSchema.parse(manifestWith()); expect(parsed.icon).toBeUndefined(); }); test('rejects U+1F512, naming the monochrome reason rather than the range', () => { const result = ModuleManifestSchema.safeParse(manifestWith('🔒')); expect(result.success).toBe(false); if (result.success) throw new Error('expected the padlock to be rejected'); const message = result.error.issues[0]?.message ?? ''; expect(message).toContain('monochrome'); expect(message).toContain('U+1F512'); }); test('rejects a two-character string', () => { const result = ModuleManifestSchema.safeParse(manifestWith('⛨⛨')); expect(result.success).toBe(false); if (result.success) throw new Error('expected two characters to be rejected'); expect(result.error.issues[0]?.message ?? '').toContain('exactly one character'); }); });