* chore(agent): baseline — uncommitted work from the local directory * HH-549: serve the default favicon * Revert "chore(agent): baseline — uncommitted work from the local directory" This reverts commit 4a3fabe624bfdc52bf935b62cb9871b7de9b3083. --------- Co-authored-by: Rogee <rogee@ipao.vip>
67 lines
2.2 KiB
JavaScript
67 lines
2.2 KiB
JavaScript
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 id="app"><\/div>/);
|
|
assert.match(html, /<link\s+rel="manifest"\s+href="\/manifest\.json"\s*\/?>/);
|
|
assert.match(
|
|
html,
|
|
/<script\b[^>]*\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(!/<script(?![^>]*\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'
|
|
);
|