test: add coverage for toRelativePath and getDirectoryForPath (#95)

These two exported functions in src/utils/path.ts lacked unit tests.

toRelativePath wraps Node's path.relative() and keeps the absolute
path when the result would start with '..' (i.e. the target is outside
the CWD). Four tests cover: child-of-cwd, outside-cwd, cwd-itself,
and the type-safety invariant.

getDirectoryForPath uses statSync to distinguish directories from files,
falling back to dirname() for non-existent paths and bypassing the
filesystem for UNC paths (NTLM credential-leak prevention). Three tests
cover: existing directory, known file, and non-existent path.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
JiayuWang(王嘉宇)
2026-04-03 23:36:19 +08:00
committed by GitHub
parent 00b044e8b2
commit fdb2442ad4

View File

@@ -1,8 +1,11 @@
import { describe, expect, test } from "bun:test";
import { resolve } from "path";
import {
containsPathTraversal,
expandPath,
normalizePathForConfigKey,
toRelativePath,
getDirectoryForPath,
} from "../path";
// ─── containsPathTraversal ──────────────────────────────────────────────
@@ -129,3 +132,68 @@ describe("normalizePathForConfigKey", () => {
expect(result).toBe("foo/bar");
});
});
// ─── toRelativePath ─────────────────────────────────────────────────────
describe("toRelativePath", () => {
test("returns relative path for a child of cwd", () => {
// Build a path that is inside the current working directory.
// resolve() returns an absolute path, and toRelativePath should give
// back just the final segment (or relative form without ..).
const abs = resolve(process.cwd(), "package.json");
const result = toRelativePath(abs);
expect(result).toBe("package.json");
expect(result).not.toContain("..");
});
test("returns absolute path when target is outside cwd", () => {
// A well-known absolute path that is always outside any typical cwd
// (any absolute path that doesn't start with process.cwd() will work)
const cwd = process.cwd();
// Build a path guaranteed to be outside cwd by going to the root's parent
// of cwd, then a sibling directory with an unlikely name
const outsidePath = resolve(cwd, "../../__unlikely_dir_xyz__");
const result = toRelativePath(outsidePath);
// relative(cwd, outsidePath) will start with '../..' so function returns absolute
expect(result).toBe(outsidePath);
});
test("returns empty string for cwd itself", () => {
const cwd = process.cwd();
const result = toRelativePath(cwd);
// relative(cwd, cwd) === '' which does not start with '..'
expect(result).toBe("");
});
test("returns a string for any absolute path", () => {
const abs = resolve(process.cwd(), "src");
const result = toRelativePath(abs);
expect(typeof result).toBe("string");
});
});
// ─── getDirectoryForPath ─────────────────────────────────────────────────
describe("getDirectoryForPath", () => {
test("returns the path itself when given an existing directory", () => {
// The src directory is guaranteed to exist in this repo
const dir = resolve(process.cwd(), "src");
const result = getDirectoryForPath(dir);
expect(result).toBe(dir);
});
test("returns parent directory for a known file", () => {
// package.json is at the repo root
const file = resolve(process.cwd(), "package.json");
const expectedParent = process.cwd();
const result = getDirectoryForPath(file);
expect(result).toBe(expectedParent);
});
test("returns parent directory for a non-existent path", () => {
const nonExistent = resolve(process.cwd(), "does-not-exist-xyz123.ts");
const expectedParent = process.cwd();
const result = getDirectoryForPath(nonExistent);
expect(result).toBe(expectedParent);
});
});