mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 08:13:37 +00:00
Changes: - Move subprocess-manager tests to @automaker/platform package - Tests need to be co-located with source for proper mocking - Add vitest configuration to platform package - 17/17 platform tests pass - Update server vitest.config.ts to alias @automaker/* packages - Resolve to source files for proper mocking in tests - Enables vi.mock() and vi.spyOn() to work correctly - Fix security.test.ts imports - Update dynamic imports from @/lib/security.js to @automaker/platform - Module was moved to shared package - Rewrite prompt-builder.test.ts - Use fs/promises mock instead of trying to spy on internal calls - 10/10 tests pass Test Results: ✅ Server: 536/536 tests pass ✅ Platform: 17/17 tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
208 lines
6.4 KiB
TypeScript
208 lines
6.4 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
import path from "path";
|
|
|
|
/**
|
|
* Note: security.ts maintains module-level state (allowed paths Set).
|
|
* We need to reset modules and reimport for each test to get fresh state.
|
|
*/
|
|
describe("security.ts", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
});
|
|
|
|
describe("initAllowedPaths", () => {
|
|
it("should parse comma-separated directories from environment", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/path1,/path2,/path3";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toContain(path.resolve("/path1"));
|
|
expect(allowed).toContain(path.resolve("/path2"));
|
|
expect(allowed).toContain(path.resolve("/path3"));
|
|
});
|
|
|
|
it("should trim whitespace from paths", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = " /path1 , /path2 , /path3 ";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toContain(path.resolve("/path1"));
|
|
expect(allowed).toContain(path.resolve("/path2"));
|
|
});
|
|
|
|
it("should always include DATA_DIR if set", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "";
|
|
process.env.DATA_DIR = "/data/dir";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toContain(path.resolve("/data/dir"));
|
|
});
|
|
|
|
it("should handle empty ALLOWED_PROJECT_DIRS", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "";
|
|
process.env.DATA_DIR = "/data";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toHaveLength(1);
|
|
expect(allowed[0]).toBe(path.resolve("/data"));
|
|
});
|
|
|
|
it("should skip empty entries in comma list", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/path1,,/path2, ,/path3";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toHaveLength(3);
|
|
});
|
|
});
|
|
|
|
describe("addAllowedPath", () => {
|
|
it("should add path to allowed list", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, addAllowedPath, getAllowedPaths } =
|
|
await import("@automaker/platform");
|
|
initAllowedPaths();
|
|
|
|
addAllowedPath("/new/path");
|
|
|
|
const allowed = getAllowedPaths();
|
|
expect(allowed).toContain(path.resolve("/new/path"));
|
|
});
|
|
|
|
it("should resolve relative paths before adding", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, addAllowedPath, getAllowedPaths } =
|
|
await import("@automaker/platform");
|
|
initAllowedPaths();
|
|
|
|
addAllowedPath("./relative/path");
|
|
|
|
const allowed = getAllowedPaths();
|
|
const cwd = process.cwd();
|
|
expect(allowed).toContain(path.resolve(cwd, "./relative/path"));
|
|
});
|
|
});
|
|
|
|
describe("isPathAllowed", () => {
|
|
it("should allow all paths (permissions disabled)", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/allowed/project";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, isPathAllowed } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
// All paths are now allowed regardless of configuration
|
|
expect(isPathAllowed("/allowed/project/file.txt")).toBe(true);
|
|
expect(isPathAllowed("/not/allowed/file.txt")).toBe(true);
|
|
expect(isPathAllowed("/tmp/file.txt")).toBe(true);
|
|
expect(isPathAllowed("/etc/passwd")).toBe(true);
|
|
expect(isPathAllowed("/any/path")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("validatePath", () => {
|
|
it("should return resolved path for any path (permissions disabled)", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/allowed";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, validatePath } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const result = validatePath("/allowed/file.txt");
|
|
expect(result).toBe(path.resolve("/allowed/file.txt"));
|
|
});
|
|
|
|
it("should not throw error for any path (permissions disabled)", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/allowed";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, validatePath } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
// All paths are now allowed, no errors thrown
|
|
expect(() => validatePath("/disallowed/file.txt")).not.toThrow();
|
|
expect(validatePath("/disallowed/file.txt")).toBe(
|
|
path.resolve("/disallowed/file.txt")
|
|
);
|
|
});
|
|
|
|
it("should resolve relative paths", async () => {
|
|
const cwd = process.cwd();
|
|
process.env.ALLOWED_PROJECT_DIRS = cwd;
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, validatePath } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const result = validatePath("./file.txt");
|
|
expect(result).toBe(path.resolve(cwd, "./file.txt"));
|
|
});
|
|
});
|
|
|
|
describe("getAllowedPaths", () => {
|
|
it("should return array of allowed paths", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/path1,/path2";
|
|
process.env.DATA_DIR = "/data";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const result = getAllowedPaths();
|
|
expect(Array.isArray(result)).toBe(true);
|
|
expect(result.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("should return resolved paths", async () => {
|
|
process.env.ALLOWED_PROJECT_DIRS = "/test";
|
|
process.env.DATA_DIR = "";
|
|
|
|
const { initAllowedPaths, getAllowedPaths } = await import(
|
|
"@automaker/platform"
|
|
);
|
|
initAllowedPaths();
|
|
|
|
const result = getAllowedPaths();
|
|
expect(result[0]).toBe(path.resolve("/test"));
|
|
});
|
|
});
|
|
});
|