Files
iptvnator/tools/testing/website-giscus-comments.test.mjs
T
4grayandClaude Opus 5 61ac15372c perf(website): serve fonts and the avatar locally, load comments on demand
Every page pulled its three typefaces from fonts.googleapis.com and
fonts.gstatic.com, each blog post fetched the author avatar from
githubusercontent.com, and the giscus client script ran on page load. That is
four outside origins contacted before a reader does anything, each costing a
DNS lookup and a TLS handshake on the critical path.

Fonts now come from the @fontsource packages the app already uses and are
emitted as .woff2 beside the site; the avatar is a 3 KB file in public/; and
the giscus embed is created by a "Show comments" button that carries the
configuration as data attributes, so the script is only built when a reader
asks for it.

A delivered page now makes no third-party request at all, verified across the
whole build. The variable Bricolage package names itself "Bricolage Grotesque
Variable", so that exact name leads the display stack in the Tailwind config.
The giscus test now checks the button configuration and asserts the client
script is absent from the delivered HTML.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 17:19:04 +02:00

46 lines
1.7 KiB
JavaScript

import { readFile } from 'node:fs/promises';
import { test } from 'node:test';
import assert from 'node:assert/strict';
const postHtmlPath = new URL('../../dist/apps/website/blog/why-external-players-help/index.html', import.meta.url);
const expectedGiscusAttributes = {
'data-repo': '4gray/iptvnator',
'data-repo-id': 'MDEwOlJlcG9zaXRvcnkyMTMxOTQ3Mzg=',
'data-category': 'Blog comments',
'data-category-id': 'DIC_kwDODLUX8s4C9eBJ',
'data-mapping': 'pathname',
'data-strict': '1',
'data-reactions-enabled': '1',
'data-emit-metadata': '0',
'data-input-position': 'bottom',
'data-theme': 'transparent_dark',
'data-lang': 'en',
};
test('published blog posts carry the Giscus configuration on a click-to-load button', async () => {
const html = await readFile(postHtmlPath, 'utf8');
const buttonMatch = html.match(/<button\b[^>]*data-giscus-loader[^>]*>/);
assert.ok(buttonMatch, 'Expected the blog post HTML to include the Giscus loader button.');
const buttonTag = buttonMatch[0];
for (const [name, value] of Object.entries(expectedGiscusAttributes)) {
assert.match(buttonTag, new RegExp(`${name}="${value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"`));
}
});
test('a blog post loads nothing from a third party before the reader asks for comments', async () => {
const html = await readFile(postHtmlPath, 'utf8');
assert.ok(
!/<script\b[^>]*\bsrc="https:\/\/giscus\.app/.test(html),
'The giscus client must not be a script tag in the delivered HTML — it is created on click.'
);
assert.match(
html,
/data-script-src="https:\/\/giscus\.app\/client\.js"/,
'The loader button must carry the giscus client URL for its click handler.'
);
});