| 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 () => { |
| |
| 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 () => { |
| |
| try { |
| await fs.rm(tempDir, { recursive: true, force: true }); |
| } catch (error) { |
| |
| } |
| }); |
|
|
| 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 () => { |
| |
| const firstResult = await ensureAutomakerDir(projectPath); |
|
|
| |
| 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 () => { |
| |
| const firstResult = await ensureDataDir(dataDir); |
|
|
| |
| 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); |
| }); |
| }); |
| }); |
| }); |
|
|