// Unit: PWA manifest validity (Session 27). // // The manifest IS the brand on a user's home screen. A malformed manifest // silently breaks installability, so guard the required fields + that the // icon files it references actually exist on disk. const fs = require('fs'); const path = require('path'); const WEB_PUBLIC = path.join(__dirname, '..', '..', 'web', 'public'); const MANIFEST_PATH = path.join(WEB_PUBLIC, 'manifest.json'); describe('PWA manifest', () => { let manifest; beforeAll(() => { manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8')); }); test('is valid JSON with the required installability fields', () => { expect(manifest.name).toBeTruthy(); expect(manifest.short_name).toBe('VYNDR'); expect(manifest.start_url).toBe('/dashboard'); expect(manifest.display).toBe('standalone'); expect(manifest.theme_color).toMatch(/^#[0-9A-Fa-f]{6}$/); expect(manifest.background_color).toMatch(/^#[0-9A-Fa-f]{6}$/); }); test('declares app categories', () => { expect(Array.isArray(manifest.categories)).toBe(true); expect(manifest.categories).toContain('sports'); }); test('every PNG icon it references exists on disk', () => { const pngs = manifest.icons.filter((i) => i.type === 'image/png'); expect(pngs.length).toBeGreaterThan(0); for (const icon of pngs) { const file = path.join(WEB_PUBLIC, icon.src.replace(/^\//, '')); expect(fs.existsSync(file)).toBe(true); } }); test('provides a maskable icon (Android adaptive)', () => { const maskable = manifest.icons.find((i) => (i.purpose || '').includes('maskable')); expect(maskable).toBeDefined(); }); test('theme + background match the brand dark base', () => { // Brand bg-0 is #06060B — keep manifest in lockstep so the splash / // status bar don't flash a mismatched color. expect(manifest.theme_color.toLowerCase()).toBe('#06060b'); expect(manifest.background_color.toLowerCase()).toBe('#06060b'); }); });