7c776bdd3a
BUG-430 loaded Inter via next/font/google, which failed Gitea publish run 2408 when the Docker build could not reach fonts.googleapis.com. Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
3.8 KiB
TypeScript
81 lines
3.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { extname, join } from "node:path";
|
|
import test from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const layout = readFileSync(new URL("../src/app/layout.tsx", import.meta.url), "utf8");
|
|
const siteStyles = readFileSync(new URL("../src/app/site-styles.ts", import.meta.url), "utf8");
|
|
const adminLayout = readFileSync(new URL("../src/app/admin/layout.tsx", import.meta.url), "utf8");
|
|
const adminCss = readFileSync(new URL("../src/app/admin/admin.css", import.meta.url), "utf8");
|
|
const homePage = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
|
|
const loginPage = readFileSync(new URL("../src/app/login/page.tsx", import.meta.url), "utf8");
|
|
|
|
test("Inter is loaded through next/font and applied as a CSS variable", () => {
|
|
assert.match(layout, /import localFont from "next\/font\/local"/);
|
|
assert.doesNotMatch(layout, /from ["']next\/font\/google["']/);
|
|
assert.match(layout, /src: "\.\/fonts\/InterVariable-latin\.woff2"/);
|
|
assert.match(layout, /display: "swap"/);
|
|
assert.match(layout, /variable: "--font-inter"/);
|
|
assert.match(layout, /className=\{inter\.variable\}/);
|
|
assert.match(readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8"), /var\(--font-inter, Inter\)/);
|
|
assert.match(
|
|
readFileSync(new URL("../src/components/admin/admin-app.tsx", import.meta.url), "utf8"),
|
|
/var\(--font-inter, Inter\)/,
|
|
);
|
|
});
|
|
|
|
test("Inter is vendored locally so production builds do not fetch Google Fonts", () => {
|
|
const font = readFileSync(new URL("../src/app/fonts/InterVariable-latin.woff2", import.meta.url));
|
|
assert.equal(Buffer.from(font.subarray(0, 4)).toString(), "wOF2");
|
|
assert.ok(font.byteLength > 20_000);
|
|
const srcRoot = fileURLToPath(new URL("../src/", import.meta.url));
|
|
const stack = [srcRoot];
|
|
while (stack.length > 0) {
|
|
const dir = stack.pop()!;
|
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
const fullPath = join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
stack.push(fullPath);
|
|
continue;
|
|
}
|
|
if (![".ts", ".tsx", ".js", ".jsx", ".css"].includes(extname(entry.name))) continue;
|
|
const source = readFileSync(fullPath, "utf8");
|
|
assert.doesNotMatch(
|
|
source,
|
|
/from ["']next\/font\/google["']|fonts\.googleapis\.com/,
|
|
`${fullPath} must not fetch Google Fonts at build time`,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
test("site chrome owns globals.css; admin does not import it", () => {
|
|
assert.match(siteStyles, /import "\.\/globals\.css"/);
|
|
assert.match(siteStyles, /import "\.\/birth-time-choice\.css"/);
|
|
assert.doesNotMatch(layout, /globals\.css|birth-time-choice\.css|site-styles/);
|
|
assert.match(homePage, /import "@\/app\/site-styles"/);
|
|
assert.match(loginPage, /import "\.\.\/site-styles"/);
|
|
assert.doesNotMatch(adminLayout, /globals\.css|site-styles/);
|
|
assert.doesNotMatch(
|
|
readFileSync(new URL("../src/app/error.tsx", import.meta.url), "utf8"),
|
|
/site-styles|globals\.css/,
|
|
);
|
|
assert.doesNotMatch(
|
|
readFileSync(new URL("../src/app/not-found.tsx", import.meta.url), "utf8"),
|
|
/site-styles|globals\.css/,
|
|
);
|
|
assert.match(adminCss, /--font-body: StyreneB, var\(--font-inter, Inter\)/);
|
|
});
|
|
|
|
test("root error and not-found pages do not depend on Tailwind utilities or Button", () => {
|
|
const errorPage = readFileSync(new URL("../src/app/error.tsx", import.meta.url), "utf8");
|
|
const notFoundPage = readFileSync(new URL("../src/app/not-found.tsx", import.meta.url), "utf8");
|
|
for (const source of [errorPage, notFoundPage]) {
|
|
assert.doesNotMatch(source, /className="flex/);
|
|
assert.doesNotMatch(source, /min-h-svh/);
|
|
assert.doesNotMatch(source, /text-muted-foreground/);
|
|
assert.doesNotMatch(source, /@\/components\/ui\/button/);
|
|
}
|
|
});
|