Improve MineGeo interface and functionality
This commit is contained in:
190
tests/deploy-vercel.test.ts
Normal file
190
tests/deploy-vercel.test.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
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", "<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/,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user