Files
budget2.0/src/ui/basePath.test.ts
T
Lucas WintherandClaude Opus 5 d1d6735596 fix(ui): survive an unset BUN_PUBLIC_BASE_PATH in the browser
Bun inlines a literal `process.env.FOO` reference only when FOO is set. With
it unset — a bare `bun --hot src/index.ts`, which is what the README tells you
to run — the reference survived into the client bundle and the app died on
load with `ReferenceError: process is not defined`, before rendering anything.
Production builds were unaffected, because build.ts passes an explicit define.

Reading the value now goes through readBasePathEnv(), which catches. Catching
rather than a `typeof process` guard is deliberate: after inlining the literal
becomes a string, but a typeof test would still run in the browser and discard
that inlined value, silently breaking every subpath deploy. Verified all four
paths: dev unset (reference survives, caught, base "/"), dev set (inlined),
and root + subpath production builds (inlined by define).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 01:19:51 +02:00

39 lines
1.5 KiB
TypeScript

import { test, expect } from "bun:test";
import { withBase, normalizeBase, readBasePathEnv } from "./basePath.ts";
test("normalizeBase defaults to root", () => {
expect(normalizeBase(undefined)).toBe("/");
expect(normalizeBase("")).toBe("/");
});
test("normalizeBase adds the leading and trailing slash", () => {
expect(normalizeBase("budget2.0")).toBe("/budget2.0/");
expect(normalizeBase("/budget2.0")).toBe("/budget2.0/");
expect(normalizeBase("/budget2.0/")).toBe("/budget2.0/");
});
test("withBase joins without doubling slashes", () => {
expect(withBase("/manifest.webmanifest", "/budget2.0/")).toBe(
"/budget2.0/manifest.webmanifest",
);
expect(withBase("manifest.webmanifest", "/budget2.0/")).toBe(
"/budget2.0/manifest.webmanifest",
);
expect(withBase("/sw.js", "/")).toBe("/sw.js");
});
// Regression: Bun only inlines `process.env.FOO` when the variable is SET. When
// it is unset (e.g. a bare `bun --hot src/index.ts`), the reference survives
// into the browser bundle and throws `ReferenceError: process is not defined`
// before the app can boot. Reading the value must therefore tolerate `process`
// not existing at all.
test("reading the base path env does not throw when process is undefined", () => {
const saved = (globalThis as { process?: unknown }).process;
try {
delete (globalThis as { process?: unknown }).process;
expect(readBasePathEnv()).toBeUndefined();
} finally {
(globalThis as { process?: unknown }).process = saved;
}
});