import { describe, it, expect, beforeEach, afterEach } from "vitest"; import fs from "fs/promises"; import path from "path"; import os from "os"; import { getAutomakerDir, getFeaturesDir, getFeatureDir, getFeatureImagesDir, getBoardDir, getImagesDir, getContextDir, getWorktreesDir, getAppSpecPath, getBranchTrackingPath, ensureAutomakerDir, getGlobalSettingsPath, getCredentialsPath, getProjectSettingsPath, ensureDataDir, } from "../src/paths"; describe("paths.ts", () => { let tempDir: string; let projectPath: string; let dataDir: string; beforeEach(async () => { // Create a temporary directory for testing tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "platform-paths-test-")); projectPath = path.join(tempDir, "test-project"); dataDir = path.join(tempDir, "user-data"); await fs.mkdir(projectPath, { recursive: true }); }); afterEach(async () => { // Clean up temporary directory try { await fs.rm(tempDir, { recursive: true, force: true }); } catch (error) { // Ignore cleanup errors } }); describe("Project-level path construction", () => { it("should return automaker directory path", () => { const result = getAutomakerDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker")); }); it("should return features directory path", () => { const result = getFeaturesDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker", "features")); }); it("should return feature directory path", () => { const featureId = "auth-feature"; const result = getFeatureDir(projectPath, featureId); expect(result).toBe( path.join(projectPath, ".automaker", "features", featureId) ); }); it("should return feature images directory path", () => { const featureId = "auth-feature"; const result = getFeatureImagesDir(projectPath, featureId); expect(result).toBe( path.join(projectPath, ".automaker", "features", featureId, "images") ); }); it("should return board directory path", () => { const result = getBoardDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker", "board")); }); it("should return images directory path", () => { const result = getImagesDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker", "images")); }); it("should return context directory path", () => { const result = getContextDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker", "context")); }); it("should return worktrees directory path", () => { const result = getWorktreesDir(projectPath); expect(result).toBe(path.join(projectPath, ".automaker", "worktrees")); }); it("should return app spec file path", () => { const result = getAppSpecPath(projectPath); expect(result).toBe( path.join(projectPath, ".automaker", "app_spec.txt") ); }); it("should return branch tracking file path", () => { const result = getBranchTrackingPath(projectPath); expect(result).toBe( path.join(projectPath, ".automaker", "active-branches.json") ); }); it("should return project settings file path", () => { const result = getProjectSettingsPath(projectPath); expect(result).toBe( path.join(projectPath, ".automaker", "settings.json") ); }); }); describe("Global settings path construction", () => { it("should return global settings path", () => { const result = getGlobalSettingsPath(dataDir); expect(result).toBe(path.join(dataDir, "settings.json")); }); it("should return credentials path", () => { const result = getCredentialsPath(dataDir); expect(result).toBe(path.join(dataDir, "credentials.json")); }); }); describe("Directory creation", () => { it("should create automaker directory", async () => { const automakerDir = await ensureAutomakerDir(projectPath); expect(automakerDir).toBe(path.join(projectPath, ".automaker")); const stats = await fs.stat(automakerDir); expect(stats.isDirectory()).toBe(true); }); it("should be idempotent when creating automaker directory", async () => { // Create directory first time const firstResult = await ensureAutomakerDir(projectPath); // Create directory second time const secondResult = await ensureAutomakerDir(projectPath); expect(firstResult).toBe(secondResult); const stats = await fs.stat(firstResult); expect(stats.isDirectory()).toBe(true); }); it("should create data directory", async () => { const result = await ensureDataDir(dataDir); expect(result).toBe(dataDir); const stats = await fs.stat(dataDir); expect(stats.isDirectory()).toBe(true); }); it("should be idempotent when creating data directory", async () => { // Create directory first time const firstResult = await ensureDataDir(dataDir); // Create directory second time const secondResult = await ensureDataDir(dataDir); expect(firstResult).toBe(secondResult); const stats = await fs.stat(firstResult); expect(stats.isDirectory()).toBe(true); }); it("should create nested directories recursively", async () => { const deepProjectPath = path.join( tempDir, "nested", "deep", "project" ); await fs.mkdir(deepProjectPath, { recursive: true }); const automakerDir = await ensureAutomakerDir(deepProjectPath); const stats = await fs.stat(automakerDir); expect(stats.isDirectory()).toBe(true); }); }); describe("Path handling with special characters", () => { it("should handle feature IDs with special characters", () => { const featureId = "feature-with-dashes_and_underscores"; const result = getFeatureDir(projectPath, featureId); expect(result).toContain(featureId); }); it("should handle paths with spaces", () => { const pathWithSpaces = path.join(tempDir, "path with spaces"); const result = getAutomakerDir(pathWithSpaces); expect(result).toBe(path.join(pathWithSpaces, ".automaker")); }); }); describe("Path relationships", () => { it("should have feature dir as child of features dir", () => { const featuresDir = getFeaturesDir(projectPath); const featureDir = getFeatureDir(projectPath, "test-feature"); expect(featureDir.startsWith(featuresDir)).toBe(true); }); it("should have all project paths under automaker dir", () => { const automakerDir = getAutomakerDir(projectPath); const paths = [ getFeaturesDir(projectPath), getBoardDir(projectPath), getImagesDir(projectPath), getContextDir(projectPath), getWorktreesDir(projectPath), getAppSpecPath(projectPath), getBranchTrackingPath(projectPath), getProjectSettingsPath(projectPath), ]; paths.forEach((p) => { expect(p.startsWith(automakerDir)).toBe(true); }); }); }); });