mirror of https://github.com/openclaw/openclaw.git
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { afterEach, describe, expect, it } from "vitest";
|
|
import {
|
|
hasNodeErrorCode,
|
|
isNodeError,
|
|
isNotFoundPathError,
|
|
isPathInside,
|
|
isSymlinkOpenError,
|
|
normalizeWindowsPathForComparison,
|
|
} from "./path-guards.js";
|
|
|
|
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
|
|
|
|
function setPlatform(platform: NodeJS.Platform): void {
|
|
Object.defineProperty(process, "platform", {
|
|
value: platform,
|
|
configurable: true,
|
|
});
|
|
}
|
|
|
|
afterEach(() => {
|
|
if (originalPlatformDescriptor) {
|
|
Object.defineProperty(process, "platform", originalPlatformDescriptor);
|
|
}
|
|
});
|
|
|
|
describe("normalizeWindowsPathForComparison", () => {
|
|
it.each([
|
|
["\\\\?\\C:\\Users\\Peter/Repo", "c:\\users\\peter\\repo"],
|
|
["\\\\?\\UNC\\Server\\Share\\Folder", "\\\\server\\share\\folder"],
|
|
["\\\\?\\unc\\Server\\Share\\Folder", "\\\\server\\share\\folder"],
|
|
])("normalizes windows path %s", (input, expected) => {
|
|
expect(normalizeWindowsPathForComparison(input)).toBe(expected);
|
|
});
|
|
});
|
|
|
|
describe("node path error helpers", () => {
|
|
it.each([
|
|
[{ code: "ENOENT" }, true],
|
|
[{ message: "nope" }, false],
|
|
])("detects node-style error %j", (value, expected) => {
|
|
expect(isNodeError(value)).toBe(expected);
|
|
});
|
|
|
|
it.each([
|
|
[{ code: "ENOENT" }, "ENOENT", true],
|
|
[{ code: "ENOENT" }, "EACCES", false],
|
|
])("matches node error code for %j", (value, code, expected) => {
|
|
expect(hasNodeErrorCode(value, code)).toBe(expected);
|
|
});
|
|
|
|
it.each([
|
|
[{ code: "ENOENT" }, true],
|
|
[{ code: "ENOTDIR" }, true],
|
|
[{ code: "EACCES" }, false],
|
|
[{ code: 404 }, false],
|
|
])("classifies not-found path error for %j", (value, expected) => {
|
|
expect(isNotFoundPathError(value)).toBe(expected);
|
|
});
|
|
|
|
it.each([
|
|
[{ code: "ELOOP" }, true],
|
|
[{ code: "EINVAL" }, true],
|
|
[{ code: "ENOTSUP" }, true],
|
|
[{ code: "ENOENT" }, false],
|
|
[{ code: null }, false],
|
|
])("classifies symlink-open error for %j", (value, expected) => {
|
|
expect(isSymlinkOpenError(value)).toBe(expected);
|
|
});
|
|
});
|
|
|
|
describe("isPathInside", () => {
|
|
it.each([
|
|
["/workspace/root", "/workspace/root", true],
|
|
["/workspace/root", "/workspace/root/nested/file.txt", true],
|
|
["/workspace/root", "/workspace/root/../escape.txt", false],
|
|
])("checks posix containment %s -> %s", (basePath, targetPath, expected) => {
|
|
expect(isPathInside(basePath, targetPath)).toBe(expected);
|
|
});
|
|
|
|
it("uses win32 path semantics for windows containment checks", () => {
|
|
setPlatform("win32");
|
|
|
|
for (const [basePath, targetPath, expected] of [
|
|
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root`, true],
|
|
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root\Nested\File.txt`, true],
|
|
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root\..\escape.txt`, false],
|
|
[String.raw`C:\workspace\root`, String.raw`D:\workspace\root\file.txt`, false],
|
|
] as const) {
|
|
expect(isPathInside(basePath, targetPath)).toBe(expected);
|
|
}
|
|
});
|
|
});
|