import { existsSync, readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' // Every showcase visit 404'd on both /favicon.ico and /favicon.svg (stage sweep, // 2026-10-11) because the template shipped no favicon at all. `app/favicon.ico` is // Next's own file convention for /favicon.ico; `public/favicon.svg` is a plain static // file for /favicon.svg, which Next's convention does not cover (it only serves // `icon.svg` at /icon.svg). The root layout's `metadata.icons` must name both, so the // rendered tags match what is actually shipped. describe('favicon', () => { it('ships a valid favicon.ico for Next’s /favicon.ico convention', () => { const path = fileURLToPath(new URL('../app/favicon.ico', import.meta.url)) expect(existsSync(path)).toBe(true) const bytes = readFileSync(path) // ICO header: reserved=0, type=1 (icon), at least one image. expect(bytes.readUInt16LE(0)).toBe(0) expect(bytes.readUInt16LE(2)).toBe(1) expect(bytes.readUInt16LE(4)).toBeGreaterThan(0) }) it('ships public/favicon.svg, served verbatim at /favicon.svg', () => { const path = fileURLToPath(new URL('../public/favicon.svg', import.meta.url)) expect(existsSync(path)).toBe(true) expect(readFileSync(path, 'utf8')).toContain(' { const layout = readFileSync( new URL('../src/app/layouts/root.tsx', import.meta.url), 'utf8', ) expect(layout).toMatch(/\/favicon\.svg/) expect(layout).toMatch(/\/favicon\.ico/) }) })