import assert from "node:assert/strict"; import { test } from "node:test"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { execFileSync } from "node:child_process"; import { zipSync, strToU8 } from "fflate"; // The command is also an importable module, so tests never trigger a real upload. import { deploymentFiles, deploymentPayload, deploy, } from "../scripts/deploy-vercel.mjs"; function fixture( run: ( root: string, write: (file: string, data: string | Uint8Array) => void, ) => void, ) { const root = fs.mkdtempSync(path.join(os.tmpdir(), "minegeo-deploy-test-")); function write(file: string, data: string | Uint8Array) { fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); fs.writeFileSync(path.join(root, file), data); } try { write( "package.json", JSON.stringify({ name: "minegeo", scripts: { worker: "private worker" }, repository: "https://private.invalid/repository", }), ); write("app/layout.tsx", "export default function Layout() {}"); run(root, write); } finally { assert.ok(root.startsWith(path.join(os.tmpdir(), "minegeo-deploy-test-"))); fs.rmSync(root, { recursive: true, force: true }); } } test("deployment collects web assets and excludes local secrets, Git and build outputs", () => { fixture((root, write) => { write(".env.local", "SUPABASE_SERVICE_ROLE_KEY=secret"); write(".env.deploy.local", "VERCEL_TOKEN=secret"); write(".git/config", "private Git configuration"); write("public/.hidden", "secret"); write("public/generated/capture.png", "private capture"); write("public/downloads/old.jar", "generated artifact"); write("app/downloads/page.tsx", "export default function Downloads() {}"); write("worker/main.ts", "private worker"); write("public/images/map.svg", ""); write("components/Example.tsx", "export const Example = 1;"); const files = deploymentFiles(root); assert.deepEqual( files.map((entry: { file: string }) => entry.file).sort(), [ "app/downloads/page.tsx", "app/layout.tsx", "components/Example.tsx", "package.json", "public/images/map.svg", ], ); const pkg = JSON.parse( Buffer.from( files.find((entry: { file: string }) => entry.file === "package.json") .data, "base64", ).toString(), ); assert.equal(pkg.repository, undefined); assert.equal(pkg.scripts.worker, undefined); const payload = deploymentPayload(files); assert.equal(payload.target, "production"); assert.equal(deploymentPayload(files, true).target, undefined); assert.equal(Object.hasOwn(payload, "gitSource"), false); assert.equal(Object.hasOwn(payload, "gitMetadata"), false); assert.equal( JSON.stringify(payload).includes("SUPABASE_SERVICE_ROLE_KEY"), false, ); }); }); test("privacy scan rejects the private Git hostname in public files and bundled JARs", () => { fixture((root, write) => { execFileSync("git", ["init", root], { windowsHide: true, stdio: "ignore" }); execFileSync( "git", [ "-C", root, "remote", "add", "origin", "https://private.example.invalid/user/minegeo.git", ], { windowsHide: true }, ); write("public/leak.txt", "https://private.example.invalid"); assert.throws( () => deploymentFiles(root), /Private Git server reference found in public\/leak.txt/, ); fs.unlinkSync(path.join(root, "public/leak.txt")); write( "public/tools/mod.jar", zipSync({ "metadata.json": strToU8('"private.example.invalid"') }), ); assert.throws( () => deploymentFiles(root), /Private Git server reference found in public\/tools\/mod.jar/, ); }); }); test("deploy sends every file in one POST, then polls until READY", async () => { const requests: { url: string; init: RequestInit }[] = []; const states = ["QUEUED", "BUILDING", "READY"]; const logs: string[] = []; const payload = deploymentPayload([ { file: "app/page.tsx", data: "YWJj", encoding: "base64" }, ]); const result = await deploy(payload, { token: "test-token", wait: async () => {}, log: (message: string) => logs.push(message), request: async (url, init = {}) => { requests.push({ url: String(url), init }); return new Response( JSON.stringify({ id: "test-deployment", readyState: states.shift(), url: "preview.example.invalid", }), { status: 200 }, ); }, }); assert.equal(result.readyState, "READY"); assert.equal( requests.filter((item) => item.init.method === "POST").length, 1, ); assert.deepEqual( JSON.parse(requests[0].init.body as string).files, payload.files, ); assert.equal( requests.slice(1).every((item) => item.init.method === "GET"), true, ); assert.equal( logs.some((message) => message.includes("test-token")), false, ); }); test("failed builds and rejected authentication never report success", async () => { const payload = deploymentPayload([]); await assert.rejects( deploy(payload, { token: "test", log: () => {}, request: async () => new Response( JSON.stringify({ id: "failed", readyState: "ERROR", errorMessage: "Build failed", }), { status: 200 }, ), }), /Build failed/, ); await assert.rejects( deploy(payload, { token: "test", log: () => {}, request: async () => new Response(JSON.stringify({ error: { message: "Unauthorized" } }), { status: 401, }), }), /Vercel 401/, ); });