import { describe, expect, mock, test } from "bun:test"; mock.module("cloudflare:workers", () => ({ env: {} })); const { deploymentProblems, isLocalDev, isLoopbackUrl, requestProblems } = await import("./deployment"); const GOOD = { PUBLIC_URL: "https://gitfor.dev", USERCONTENT_ORIGIN: "https://gitforusercontent.dev", SECRETS_KEY: "k".repeat(32), ARTIFACTS_SHARDS: "1", }; const onlyArtifacts = (name: string) => name === "ARTIFACTS"; describe("deploymentProblems (DEPLOY-P2)", () => { test("a correctly configured deployment serves", () => { expect(deploymentProblems(GOOD, onlyArtifacts)).toEqual([]); }); test("loopback, plain-http or empty PUBLIC_URL is refused when deployed", () => { expect(deploymentProblems({ ...GOOD, PUBLIC_URL: "http://localhost:3000" }, onlyArtifacts)).toEqual( expect.arrayContaining(["PUBLIC_URL must use https", "PUBLIC_URL must not be a loopback host"]), ); expect(deploymentProblems({ ...GOOD, PUBLIC_URL: "http://gitfor.dev" }, onlyArtifacts)).toContain( "PUBLIC_URL must use https", ); expect(deploymentProblems({ ...GOOD, PUBLIC_URL: "" }, onlyArtifacts)).toContain( "PUBLIC_URL is not set to a valid URL", ); }); test("missing or same-origin USERCONTENT_ORIGIN is refused", () => { expect(deploymentProblems({ ...GOOD, USERCONTENT_ORIGIN: "" }, onlyArtifacts)).toContain( "USERCONTENT_ORIGIN must be set to a separate origin", ); expect(deploymentProblems({ ...GOOD, USERCONTENT_ORIGIN: "https://gitfor.dev" }, onlyArtifacts)).toContain( "USERCONTENT_ORIGIN must not be the forge host", ); }); test("missing or short SECRETS_KEY is refused", () => { for (const SECRETS_KEY of [undefined, "", "short"]) { expect(deploymentProblems({ ...GOOD, SECRETS_KEY }, onlyArtifacts).join()).toContain("SECRETS_KEY"); } }); test("local dev skips the deployment checks but not the shard bindings (GIT-P8)", () => { expect(deploymentProblems({ GITFOR_LOCAL: "true", PUBLIC_URL: "http://localhost:3000" }, onlyArtifacts)).toEqual( [], ); expect( deploymentProblems({ GITFOR_LOCAL: "true", PUBLIC_URL: "http://localhost:3000", ARTIFACTS_SHARDS: "3" }, (n) => ["ARTIFACTS", "ARTIFACTS_1"].includes(n), ), ).toEqual(["ARTIFACTS_SHARDS=3 but the ARTIFACTS_2 binding is missing"]); }); }); describe("isLocalDev", () => { test("needs both the dev flag and a loopback PUBLIC_URL", () => { expect(isLocalDev({ GITFOR_LOCAL: "true", PUBLIC_URL: "http://localhost:3000" })).toBe(true); expect(isLocalDev({ GITFOR_LOCAL: "true", PUBLIC_URL: "https://gitfor.dev" })).toBe(false); expect(isLocalDev({ PUBLIC_URL: "http://localhost:3000" })).toBe(false); }); test("unparsable URLs count as local, never as a deployment", () => { expect(isLoopbackUrl("")).toBe(true); expect(isLoopbackUrl("https://gitfor.dev")).toBe(false); }); }); describe("GITFOR_LOCAL leaking into a deployment", () => { test("the dev flag with a real PUBLIC_URL does not skip the checks", () => { expect(deploymentProblems({ ...GOOD, GITFOR_LOCAL: "true" }, onlyArtifacts)).toEqual([ "GITFOR_LOCAL=true is only valid with a loopback PUBLIC_URL", ]); }); test("a dev build answering a public host is refused per request", () => { const dev = { GITFOR_LOCAL: "true", PUBLIC_URL: "http://localhost:3000" }; expect(requestProblems(new Request("http://localhost:3000/"), dev)).toEqual([]); expect(requestProblems(new Request("https://gitfor.dev/"), dev)).toHaveLength(1); expect(requestProblems(new Request("https://gitfor.dev/"), GOOD)).toEqual([]); }); });