diff --git a/src/utils/resolve-project-path.spec.ts b/src/utils/resolve-project-path.spec.ts index 7f4f224..f143ede 100644 --- a/src/utils/resolve-project-path.spec.ts +++ b/src/utils/resolve-project-path.spec.ts @@ -1,5 +1,5 @@ import { homedir } from 'node:os' -import { join, normalize } from 'node:path' +import { isAbsolute, join, normalize, resolve } from 'node:path' import { describe, expect, it, vi, beforeEach } from 'vitest' const mockDaemonListProjects = vi.fn() @@ -21,25 +21,37 @@ describe('resolveProjectPath', () => { }) describe('path input', () => { - it('should return absolute paths as-is', async () => { - const result = await resolveProjectPath('/absolute/path') - expect(result).toBe('/absolute/path') + it('should keep absolute paths absolute', async () => { + const absolute = resolve('/absolute/path') + const result = await resolveProjectPath(absolute) + expect(result).toBe(absolute) }) - it('should return relative paths starting with dot', async () => { - const result = await resolveProjectPath('./relative') - expect(result).toBe('./relative') + it('should resolve "." to the current working directory', async () => { + const result = await resolveProjectPath('.') + expect(result).toBe(process.cwd()) }) - it('should expand tilde to home directory', async () => { - const result = await resolveProjectPath('~/projects') - // untildify keeps the input slash; normalize for Windows - expect(normalize(result)).toBe(join(homedir(), 'projects')) + it('should resolve "../x" against the current working directory', async () => { + const result = await resolveProjectPath('../x') + expect(result).toBe(resolve(process.cwd(), '../x')) }) - it('should return paths with slashes', async () => { + it('should resolve paths with slashes to absolute paths', async () => { const result = await resolveProjectPath('some/path') - expect(result).toBe('some/path') + expect(result).toBe(resolve(process.cwd(), 'some/path')) + }) + + it('should expand tilde to an absolute home directory path', async () => { + const result = await resolveProjectPath('~/x') + expect(normalize(result)).toBe(normalize(join(homedir(), 'x'))) + expect(isAbsolute(result)).toBe(true) + }) + + it('should resolve a relative CENTY_CWD to an absolute path', async () => { + Reflect.set(process.env, 'CENTY_CWD', '.') + const result = await resolveProjectPath(undefined) + expect(result).toBe(process.cwd()) }) }) @@ -75,7 +87,7 @@ describe('resolveProjectPath', () => { it('should use CENTY_CWD env var when no arg provided', async () => { Reflect.set(process.env, 'CENTY_CWD', '/env/path') const result = await resolveProjectPath(undefined) - expect(result).toBe('/env/path') + expect(result).toBe(resolve('/env/path')) }) it('should use cwd when no arg and no env var', async () => { diff --git a/src/utils/resolve-project-path.ts b/src/utils/resolve-project-path.ts index b16889a..4886aec 100644 --- a/src/utils/resolve-project-path.ts +++ b/src/utils/resolve-project-path.ts @@ -1,4 +1,4 @@ -import { isAbsolute } from 'node:path' +import { isAbsolute, resolve } from 'node:path' import untildify from 'untildify' import { daemonListProjects } from '../daemon/daemon-list-projects.js' @@ -39,7 +39,7 @@ export class ProjectNotFoundError extends Error { * * The input can be: * - undefined: uses CENTY_CWD env var or process.cwd() - * - A filesystem path: returned as-is (with tilde expansion) + * - A filesystem path: returned as an absolute path (tilde expanded) * - A project name: looked up via daemon to get the path * * @param projectArg - The project name or path from the --project flag @@ -58,9 +58,9 @@ export async function resolveProjectPath( ? CENTY_CWD : process.cwd() - // 2. If it looks like a path, return it (with tilde expansion) + // 2. If it looks like a path, return it absolute (tilde expanded, relative resolved against cwd) if (isPath(input)) { - return untildify(input) + return resolve(untildify(input)) } // 3. Otherwise treat as project name - look up in daemon