`;
const findings = await findByCode(html, "system_font_will_alias");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("Inter");
});
it("reports multiple aliased fonts in one finding", async () => {
const html = `
`;
const findings = await findByCode(html, "system_font_will_alias");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("Inter");
expect(findings[0]!.message).toContain("JetBrains Mono");
});
});
describe("font_family_without_font_face", () => {
it("flags font-family used without @font-face", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("gt walsheim");
});
it("does not flag when @font-face is declared", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag a system font declared via @font-face src: local()", async () => {
// Regression: two independent reports of this rule hard-erroring on OS
// system fonts (Hiragino Sans, Microsoft YaHei) that have no downloadable
// file. src: local(...) already satisfies the check (extractFontFaceFamilies
// only looks at the font-family declaration, not the src value) — the gap
// was that the fixHint didn't mention this as an option.
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("fixHint mentions the local() pattern for system fonts", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings[0]!.fixHint).toContain("local(");
});
it("does not flag generic font families", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("reports multiple missing families in one finding", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("aeonik");
expect(findings[0]!.message).toContain("feature deck");
});
it("does not flag fonts the producer has pre-bundled", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("geist");
});
it("does not flag a non-bundled family when a Google Fonts link loads it", async () => {
const html = `
`;
const result = await lintHyperframeHtml(html, { isSubComposition: true });
expect(result.findings.filter((f) => f.code === "google_fonts_import")).toHaveLength(1);
expect(
result.findings.filter((f) => f.code === "font_family_without_font_face"),
).toHaveLength(0);
expect(result.errorCount).toBe(0);
});
it("parses unquoted Google Fonts link href values", async () => {
const html = `
`;
const result = await lintHyperframeHtml(html, { isSubComposition: true });
expect(result.findings.filter((f) => f.code === "google_fonts_import")).toHaveLength(1);
expect(
result.findings.filter((f) => f.code === "font_family_without_font_face"),
).toHaveLength(0);
expect(result.errorCount).toBe(0);
});
it("parses multiple Google Fonts family parameters and URL-encoded spaces", async () => {
const html = `
`;
const result = await lintHyperframeHtml(html, { isSubComposition: true });
expect(result.findings.filter((f) => f.code === "google_fonts_import")).toHaveLength(1);
expect(
result.findings.filter((f) => f.code === "font_family_without_font_face"),
).toHaveLength(0);
expect(result.errorCount).toBe(0);
});
it("still flags non-bundled families not covered by the Google Fonts URL", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(1);
expect(findings[0]!.message).toContain("geist");
});
it("is case-insensitive when matching @font-face to font-family", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag vendor-prefixed system-font keywords (-apple-system, BlinkMacSystemFont)", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag installed registry blocks that declare fonts via Google Fonts", async () => {
const html =
`\n` +
`
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("matches @font-face even when a CSS comment inside the block contains a brace (#1534)", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag the -apple-system / BlinkMacSystemFont system-ui stack", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag a var() font-family indirection it cannot resolve", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("does not flag a var() with a quoted fallback font", async () => {
const html = `
`;
const findings = await findByCode(html, "font_family_without_font_face");
expect(findings).toHaveLength(0);
});
it("still flags a real undeclared font sitting next to a system stack", async () => {
const html = `