Files
cloudflare__vinext/tests/font-google-build.test.ts
T
Divanshu Chauhan (divkix) 8d29f76512 fix(plugins): track font call ranges during transform (#785)
* fix(plugins): track font call ranges during transform

The injectSelfHostedCss function was calling s.overwrite() to transform
font calls but not adding the call range to overwrittenRanges. This
could potentially cause issues when multiple font calls exist in the
same file, as subsequent transforms might not properly detect that
a previous call was already processed.

Add the call range to overwrittenRanges after each font call
transformation to ensure proper tracking.

Related to #751 - defensive consistency fix

* test(fonts): remove duplicate test and add E2E build test for #751

Removes the near-duplicate unit test 'transforms multiple fonts with
identical options patterns' from font-google.test.ts. This test was
a duplicate of 'handles multiple font imports in one file' and did not
actually reproduce issue #751.

Adds a proper integration test in font-google-build.test.ts that uses
createBuilder + buildApp to exercise the actual Vite build pipeline
where issue #751 occurred. Includes fixture at
app-basic/app/font-google-multiple/ with Geist + Geist_Mono fonts
matching the original issue reproduction.

The actual #751 bug (Unexpected token error) was already fixed in
previous commits #719 (double-comma) and #723 (nested-brace).
The defensive overwrittenRanges tracking remains in fonts.ts as
correct defensive code.

All 78 font-related tests pass, plus 291 app-router tests.

* style(fonts): fix lint and formatting issues in #751 test

- Remove unused beforeAll import
- Remove unnecessary Plugin type import and cast
- Fix formatting from vp check --fix

* style: fix formatting in font-google-multiple layout

* refactor(tests): move font-google-multiple to standalone fixture and improve assertions

Moves the font-google-multiple fixture from a nested location inside
app-basic to a standalone fixture at tests/fixtures/font-google-multiple/.
This prevents side effects for other tests that build the app-basic fixture.

Updates the build test to remove misleading comments about reproducing #751.
The overwrittenRanges.push() fix in fonts.ts is a defensive consistency
improvement, not a fix for issue #751.

- Removes the nested fixture from app-basic/app/font-google-multiple/
- Creates minimal standalone fixture with package.json and vite.config.ts
- Updates test comments to clarify this tests general build validation
- Removes incorrect claim about reproducing #751

* fix(tests): address PR review feedback on font transform build test

- Fix vite import to vite-plus per repo conventions
- Strengthen build test assertions to verify font transform output
- Add missing package.json to font-google-multiple fixture
- Remove unused vite.config.ts from fixture
- Remove #751 references (this is a defensive fix, not a fix for that issue)

* chore: update pnpm-lock.yaml for font-google-multiple fixture

* fix(tests): handle pre-existing node_modules and correct build output extension in font-google-build test

Two issues causing CI failure:
1. EEXIST on symlink: fixture's node_modules could be a real directory
   (from pnpm install), not just a stale symlink. Use fs.rm with
   force:true before creating the symlink to handle both cases.
2. Wrong output extension: build produces index.js not index.mjs
   (likely a Vite 8/Rolldown default extension change).
2026-04-09 07:19:14 +01:00

81 lines
2.5 KiB
TypeScript

import { describe, it, expect, afterAll } from "vite-plus/test";
import path from "node:path";
import fs from "node:fs/promises";
import os from "node:os";
import { createBuilder } from "vite-plus";
import vinext from "../packages/vinext/src/index.js";
const APP_FIXTURE_DIR = path.resolve(import.meta.dirname, "./fixtures/font-google-multiple");
async function buildFontGoogleMultipleFixture(): Promise<string> {
const outDir = await fs.mkdtemp(path.join(os.tmpdir(), "vinext-font-google-multiple-"));
const rscOutDir = path.join(outDir, "server");
const ssrOutDir = path.join(outDir, "server", "ssr");
const clientOutDir = path.join(outDir, "client");
const originalFetch = globalThis.fetch;
globalThis.fetch = async (input: any) => {
const url = String(input);
if (url.includes("Geist") && !url.includes("Mono")) {
return new Response("@font-face { font-family: 'Geist'; src: url(/geist.woff2); }", {
status: 200,
headers: { "content-type": "text/css" },
});
}
return new Response("@font-face { font-family: 'Geist Mono'; src: url(/geist-mono.woff2); }", {
status: 200,
headers: { "content-type": "text/css" },
});
};
const nodeModulesLink = path.join(APP_FIXTURE_DIR, "node_modules");
try {
const projectNodeModules = path.resolve(import.meta.dirname, "../node_modules");
await fs.rm(nodeModulesLink, { recursive: true, force: true });
await fs.symlink(projectNodeModules, nodeModulesLink);
const builder = await createBuilder({
root: APP_FIXTURE_DIR,
configFile: false,
plugins: [
vinext({
appDir: APP_FIXTURE_DIR,
rscOutDir,
ssrOutDir,
clientOutDir,
}),
],
logLevel: "silent",
});
await builder.buildApp();
return path.join(outDir, "server", "index.js");
} finally {
globalThis.fetch = originalFetch;
await fs.unlink(nodeModulesLink).catch(() => {});
}
}
describe("font-google build integration", () => {
let buildOutputPath: string;
let outDir: string;
afterAll(async () => {
if (outDir) {
await fs.rm(outDir, { recursive: true, force: true });
}
});
it("should build and transform multiple Google fonts (Geist + Geist_Mono)", async () => {
buildOutputPath = await buildFontGoogleMultipleFixture();
outDir = path.dirname(path.dirname(buildOutputPath));
const content = await fs.readFile(buildOutputPath, "utf-8");
expect(content).toContain("Geist");
expect(content).toContain("_selfHostedCSS");
}, 120000);
});