storebound/tests/glyph-ligatures.test.ts

47 lines
3.2 KiB
TypeScript

// Regression: ligatures must not read as system-font glyphs. STAR DASH's "Outfits, ..." caption failed `shots check`
// with `i drawn with a system font` although Montserrat drew every glyph: the per-character probe spans sat side by
// side, Chrome shaped "f" + "i" into the fi ligature across them and the lone "i" span reported no glyph of ours.
// The fixture is a real Google Fonts css2 `text=` subset of Montserrat (as `shots fonts` downloads it; OFL, see
// fixtures/fonts/Montserrat-OFL.txt); it keeps the GSUB ligatures (ff, fi, ffi). Skips when no Chromium can launch.
import { afterAll, describe, expect, test } from 'bun:test';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { measureFonts } from '../cli/shots/glyphs';
import { AFTER_ALL_MS, launchTestBrowser, scaled } from './helpers/browser';
// one browser for the file, launched and killed by the shared helper (bounded, load-aware timeouts); tools/ci-plan.ts
// lists this file as HEAVY (the browser shard)
const shared = await launchTestBrowser('playwright-core');
const { browser, skipWhy } = shared;
if (!browser) console.warn(`glyph ligature test skipped: no Chromium installed (${skipWhy}). Run \`bunx playwright install chromium\`.`);
afterAll(() => shared.close(), AFTER_ALL_MS);
const font = readFileSync(join(import.meta.dir, 'fixtures', 'fonts', 'montserrat-text-subset.woff2')).toString('base64');
const TEXT = 'Outfits, fit, office, affine';
describe.skipIf(!browser)('shots font usage: ligatures', () => {
for (const weight of [400, 600, 800]) test(`"${TEXT}" in a Montserrat text= subset, weight ${weight}: zero system-font glyphs`, async () => {
const page = await browser.newPage();
try {
await page.setContent(`<style>@font-face { font-family: 'Montserrat'; font-weight: 100 900; font-synthesis: none; src: url(data:font/woff2;base64,${font}) format('woff2'); }
p { font-family: 'Montserrat'; font-weight: ${weight}; font-size: 48px; } small { font-family: 'Montserrat'; font-weight: ${weight}; }</style>
<p class="sub">${TEXT}</p><div><small>mounts and vehicles</small></div>`);
await page.evaluate('document.fonts.ready.then(() => 0)');
// the subset really ligates: the line has fewer glyphs than characters, all from our font
const cdp = await page.context().newCDPSession(page);
await cdp.send('DOM.enable'); await cdp.send('CSS.enable');
const { root } = await cdp.send('DOM.getDocument', { depth: 0 });
const { nodeId } = await cdp.send('DOM.querySelector', { nodeId: root.nodeId, selector: 'p' });
const { fonts } = await cdp.send('CSS.getPlatformFontsForNode', { nodeId }) as { fonts: { isCustomFont: boolean; glyphCount: number }[] };
await cdp.detach();
expect(fonts.every(f => f.isCustomFont)).toBe(true);
expect(fonts.reduce((n, f) => n + f.glyphCount, 0)).toBeLessThan(TEXT.length);
const measured = await measureFonts(page, ['Montserrat']);
expect(measured.map(m => m.el)).toEqual(['p.sub', 'div small']);
for (const m of measured) expect(Object.keys(m.faces)).toEqual(['Montserrat']);
expect(await page.evaluate("document.getElementById('sb-glyph-probes')")).toBeNull();
} finally { await page.close(); }
}, scaled(30_000));
});