syntaxai/tdd.md · main · src / b32_sama_cli_install.test.ts

b32_sama_cli_install.test.ts 107 lines · 4020 bytes raw
import { describe, test, expect } from "bun:test";
import { buildSamaCliInstallScript } from "./b32_sama_cli_install.ts";

describe("buildSamaCliInstallScript", () => {
  test("shebang + set -eu in the header", () => {
    const out = buildSamaCliInstallScript([]);
    expect(out.startsWith("#!/usr/bin/env bash\n")).toBe(true);
    expect(out).toContain("set -eu");
  });

  test("embeds each file inside a single-quoted heredoc", () => {
    const out = buildSamaCliInstallScript([
      { path: "sama", content: "echo hi\n", executable: true },
    ]);
    expect(out).toContain("cat > \"$INSTALL_DIR/sama\" <<'__SAMACLI_INSTALL_EOF__'");
    expect(out).toContain("echo hi");
    expect(out).toContain("__SAMACLI_INSTALL_EOF__\n");
    expect(out).toContain('chmod +x "$INSTALL_DIR/sama"');
  });

  test("non-executable file omits chmod +x", () => {
    const out = buildSamaCliInstallScript([
      { path: "README.md", content: "# hi\n" },
    ]);
    expect(out).toContain('cat > "$INSTALL_DIR/README.md"');
    expect(out).not.toContain('chmod +x "$INSTALL_DIR/README.md"');
  });

  test("emits mkdir -p for nested paths", () => {
    const out = buildSamaCliInstallScript([
      { path: "src/a31_constants.sh", content: "X=1\n" },
    ]);
    expect(out).toContain('mkdir -p "$INSTALL_DIR/$(dirname "src/a31_constants.sh")"');
  });

  test("symlinks sama into $BIN_LINK", () => {
    const out = buildSamaCliInstallScript([]);
    expect(out).toContain('ln -sf "$INSTALL_DIR/sama" "$BIN_LINK"');
  });

  test("refuses to embed a file containing the heredoc marker", () => {
    expect(() =>
      buildSamaCliInstallScript([
        { path: "evil.sh", content: "innocent\n__SAMACLI_INSTALL_EOF__\noops\n" },
      ]),
    ).toThrow(/heredoc marker/);
  });

  test("refuses path escapes", () => {
    expect(() =>
      buildSamaCliInstallScript([{ path: "../evil.sh", content: "x\n" }]),
    ).toThrow(/path escape/);
    expect(() =>
      buildSamaCliInstallScript([{ path: "/etc/passwd", content: "x\n" }]),
    ).toThrow(/path escape/);
  });

  test("missing trailing newline still terminates heredoc cleanly", () => {
    // Content without trailing newline → emitter must add one so
    // the closing marker is recognized.
    const out = buildSamaCliInstallScript([
      { path: "no-nl", content: "line1\nline2" },
    ]);
    // The marker must land on its own line, preceded by the content + \n.
    expect(out).toMatch(/line2\n__SAMACLI_INSTALL_EOF__/);
  });

  test("repo + spec URLs default to tdd.md", () => {
    const out = buildSamaCliInstallScript([]);
    expect(out).toContain("https://tdd.md/GIT/tdd.md/tree/main/tools/sama-cli");
    expect(out).toContain("https://tdd.md/sama/v2");
  });

  test("custom URLs override defaults", () => {
    const out = buildSamaCliInstallScript([], {
      repoUrl: "https://example.org/repo",
      specUrl: "https://example.org/spec",
    });
    expect(out).toContain("https://example.org/repo");
    expect(out).toContain("https://example.org/spec");
  });

  test("end-to-end: produces a bash script that, when executed, writes the file content verbatim", async () => {
    // Run the emitted script in a temp dir, then read what it wrote.
    const dir = await Bun.file(`/tmp/sama-cli-install-test-${Date.now()}`).name;
    const out = buildSamaCliInstallScript([
      { path: "src/a31.sh", content: "X=1\nY=2\n" },
      { path: "sama", content: "#!/bin/sh\necho hi\n", executable: true },
    ]);
    const proc = Bun.spawnSync({
      cmd: ["bash", "-c", out],
      env: {
        ...process.env,
        SAMA_CLI_INSTALL_DIR: dir,
        SAMA_CLI_BIN_LINK: `${dir}-bin/sama`,
      },
    });
    expect(proc.exitCode).toBe(0);
    const wrote = await Bun.file(`${dir}/src/a31.sh`).text();
    expect(wrote).toBe("X=1\nY=2\n");
    const samaContent = await Bun.file(`${dir}/sama`).text();
    expect(samaContent).toBe("#!/bin/sh\necho hi\n");
    // Cleanup
    Bun.spawnSync({ cmd: ["rm", "-rf", dir, `${dir}-bin`] });
  });
});