import assert from 'node:assert/strict'; import { existsSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; const dist = fileURLToPath(new URL('../dist/', import.meta.url)); const html = readFileSync( new URL('../dist/index.html', import.meta.url), 'utf8' ); const assets = [...html.matchAll(/(?:href|src)="(\/assets\/[^"]+)"/g)].map( match => match[1] ); const manifest = JSON.parse( readFileSync(new URL('../dist/manifest.json', import.meta.url), 'utf8') ); assert.match(html, /
<\/div>/); assert.match(html, //); assert.match( html, /]*\bsrc="\/runtime-config\.js"[^>]*><\/script>/ ); assert.ok( readFileSync(new URL('../dist/favicon.ico', import.meta.url)).equals( readFileSync(new URL('../public/favicon-32x32.png', import.meta.url)) ), 'favicon.ico must reuse the GoChat favicon' ); assert.ok( html.indexOf('/runtime-config.js') < html.indexOf('type="module"'), 'runtime config must load before the app module' ); assert.ok( assets.some(asset => asset.endsWith('.js')), 'missing JS asset' ); assert.ok( assets.some(asset => asset.endsWith('.css')), 'missing CSS asset' ); assert.ok(!/]*\bsrc=)[^>]*>/i.test(html), 'inline script found'); assets.forEach(asset => assert.ok(existsSync(dist + asset.slice(1)), asset)); for (const size of [192, 512]) { const dimensions = `${size}x${size}`; const icon = manifest.icons.find(item => item.sizes === dimensions); assert.equal(icon?.type, 'image/png', `missing ${dimensions} PNG icon`); const png = readFileSync(dist + icon.src.slice(1)); assert.deepEqual( [...png.subarray(0, 8)], [137, 80, 78, 71, 13, 10, 26, 10] ); assert.equal(png.readUInt32BE(16), size, `${icon.src} width`); assert.equal(png.readUInt32BE(20), size, `${icon.src} height`); } const dashboard = assets .filter(asset => asset.endsWith('.js')) .map(asset => readFileSync(dist + asset.slice(1), 'utf8')) .join('\n'); assert.doesNotMatch( dashboard, /=\(?function\(\)\{return this\}\)?\(\);try\{([A-Za-z_$][\w$]*)=\1\|\|new Function\("return this"\)\(\)/, 'dashboard contains a CSP-blocked UMD global shim' );