Files
gstack/test/gstack2-runtime-path.test.ts
T

62 lines
2.8 KiB
TypeScript

import { afterEach, describe, expect, test } from "bun:test";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { main } from "../runtime/cli.js";
const roots: string[] = [];
afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })));
});
describe("managed runtime asset resolution", () => {
test("resolves only an existing asset inside the active immutable version", async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "gstack-runtime-path-"));
roots.push(root);
const home = path.join(root, "home with spaces");
const versionRoot = path.join(home, "versions", "2.0.0");
const asset = path.join(versionRoot, "lib", "diagram-render", "dist", "diagram-render.html");
await fs.mkdir(path.dirname(asset), { recursive: true });
await fs.writeFile(asset, "offline diagram bundle\n");
await fs.writeFile(path.join(home, "versions", "current.json"), `${JSON.stringify({ current: "2.0.0" })}\n`);
let stdout = "";
let stderr = "";
const output = { write(value: string) { stdout += value; } };
const errors = { write(value: string) { stderr += value; } };
const options = { env: { GSTACK_HOME: home }, cwd: root, stdout: output, stderr: errors };
expect(await main(["runtime", "path", "lib/diagram-render/dist/diagram-render.html"], options)).toBe(0);
expect(stdout.trim()).toBe(asset);
expect(stderr).toBe("");
stdout = "";
expect(await main(["runtime", "path", "../secrets.json"], options)).toBe(2);
expect(stderr).toContain("safe relative path");
stderr = "";
expect(await main(["runtime", "path", "missing.txt"], options)).toBe(1);
expect(stderr).toContain("Managed runtime asset is unavailable");
});
test("does not follow a managed asset symlink", async () => {
if (process.platform === "win32") return;
const root = await fs.mkdtemp(path.join(os.tmpdir(), "gstack-runtime-path-link-"));
roots.push(root);
const home = path.join(root, "home");
const versionRoot = path.join(home, "versions", "2.0.0");
await fs.mkdir(versionRoot, { recursive: true });
await fs.writeFile(path.join(root, "outside"), "private\n");
await fs.symlink(path.join(root, "outside"), path.join(versionRoot, "asset"));
await fs.writeFile(path.join(home, "versions", "current.json"), `${JSON.stringify({ current: "2.0.0" })}\n`);
let stderr = "";
const sink = { write(_value: string) {} };
const errors = { write(value: string) { stderr += value; } };
expect(await main(["runtime", "path", "asset"], {
env: { GSTACK_HOME: home }, cwd: root, stdout: sink, stderr: errors,
})).toBe(1);
expect(stderr).toContain("Managed runtime asset is unavailable");
});
});