allinssl/frontend/plugin/vite-plugin-turborepo-deploy/tests/unit/utils.test.ts

271 lines
8.3 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from "vitest";
import path from "path";
import fs from "fs-extra";
import {
resolvePath,
createError,
formatDate,
isAbsolutePath,
safeRemoveFile,
isSubdirectoryOf,
normalizePaths,
analyzePathRelationship,
} from "../../src/core/utils";
// 创建临时测试文件的路径
const tmpDir = path.join(process.cwd(), "tests", "tmp");
const tmpFile = path.join(tmpDir, "test-file.txt");
// 确保临时目录存在
beforeAll(async () => {
await fs.ensureDir(tmpDir);
});
// 测试后清理
afterAll(async () => {
await fs.remove(tmpDir);
});
describe("resolvePath", () => {
it("应该正确解析相对路径", () => {
const viteRoot = "/test/root";
const relativePath = "src/components";
const expected = path.resolve(viteRoot, relativePath);
expect(resolvePath(viteRoot, relativePath)).toBe(expected);
});
it("应该保留绝对路径", () => {
const viteRoot = "/test/root";
const absolutePath = "/absolute/path";
expect(resolvePath(viteRoot, absolutePath)).toBe(absolutePath);
});
});
describe("createError", () => {
it("应该创建非关键错误", () => {
const message = "Test error";
const error = createError(message);
expect(error.message).toBe(message);
expect(error.isCritical).toBe(false);
expect(error.timestamp).toBeInstanceOf(Date);
});
it("应该创建关键错误", () => {
const message = "Critical error";
const error = createError(message, true);
expect(error.message).toBe(message);
expect(error.isCritical).toBe(true);
expect(error.timestamp).toBeInstanceOf(Date);
});
});
describe("formatDate", () => {
it("应该正确格式化日期", () => {
const date = new Date(2023, 0, 1); // 2023-01-01
expect(formatDate(date)).toBe("2023-01-01");
const date2 = new Date(2023, 11, 31); // 2023-12-31
expect(formatDate(date2)).toBe("2023-12-31");
});
it("应该在月份和日期前补零", () => {
const date = new Date(2023, 0, 1); // 2023-01-01
expect(formatDate(date)).toBe("2023-01-01");
const date2 = new Date(2023, 8, 9); // 2023-09-09
expect(formatDate(date2)).toBe("2023-09-09");
});
});
describe("isAbsolutePath", () => {
it("应该识别绝对路径", () => {
const absolutePath = path.resolve("/absolute/path");
expect(isAbsolutePath(absolutePath)).toBe(true);
});
it("应该识别相对路径", () => {
expect(isAbsolutePath("relative/path")).toBe(false);
expect(isAbsolutePath("./relative/path")).toBe(false);
});
});
describe("safeRemoveFile", () => {
it("应该删除存在的文件", async () => {
// 创建测试文件
await fs.writeFile(tmpFile, "test content");
expect(fs.existsSync(tmpFile)).toBe(true);
// 删除文件
await safeRemoveFile(tmpFile);
expect(fs.existsSync(tmpFile)).toBe(false);
});
it("应该安全地处理不存在的文件", async () => {
const nonExistentFile = path.join(tmpDir, "non-existent.txt");
// 确保文件不存在
if (fs.existsSync(nonExistentFile)) {
await fs.remove(nonExistentFile);
}
// 不应抛出错误
await expect(safeRemoveFile(nonExistentFile)).resolves.not.toThrow();
});
});
describe("normalizePaths", () => {
it("应该正规化单个路径", () => {
const paths = normalizePaths("C:/test\\path//file.txt");
expect(paths).toHaveLength(1);
expect(paths[0]).toBe(path.normalize("C:/test\\path//file.txt"));
});
it("应该正规化多个路径", () => {
const input = ["C:/test\\path1", "D:\\test/path2", "./relative\\path"];
const result = normalizePaths(...input);
expect(result).toHaveLength(3);
expect(result[0]).toBe(path.normalize("C:/test\\path1"));
expect(result[1]).toBe(path.normalize("D:\\test/path2"));
expect(result[2]).toBe(path.normalize("./relative\\path"));
});
it("应该处理空路径数组", () => {
const result = normalizePaths();
expect(result).toHaveLength(0);
});
});
describe("isSubdirectoryOf", () => {
describe("Unix/Linux 路径格式", () => {
it("应该识别子目录", () => {
expect(isSubdirectoryOf("/root/sub", "/root")).toBe(true);
expect(isSubdirectoryOf("/root/sub/deep", "/root")).toBe(true);
expect(isSubdirectoryOf("/root/sub/deep/file.txt", "/root")).toBe(true);
});
it("应该识别相同目录", () => {
expect(isSubdirectoryOf("/root", "/root")).toBe(true);
expect(isSubdirectoryOf("/root/", "/root")).toBe(true);
expect(isSubdirectoryOf("/root", "/root/")).toBe(true);
});
it("应该拒绝非子目录", () => {
expect(isSubdirectoryOf("/other", "/root")).toBe(false);
expect(isSubdirectoryOf("/root-similar", "/root")).toBe(false);
expect(isSubdirectoryOf("/", "/root")).toBe(false);
});
});
describe("Windows 路径格式", () => {
it("应该识别子目录", () => {
expect(isSubdirectoryOf("C:\\root\\sub", "C:\\root")).toBe(true);
expect(isSubdirectoryOf("C:\\root\\sub\\deep", "C:\\root")).toBe(true);
});
it("应该识别相同目录", () => {
expect(isSubdirectoryOf("C:\\root", "C:\\root")).toBe(true);
expect(isSubdirectoryOf("C:\\root\\", "C:\\root")).toBe(true);
});
it("应该拒绝非子目录", () => {
expect(isSubdirectoryOf("D:\\root", "C:\\root")).toBe(false);
expect(isSubdirectoryOf("C:\\other", "C:\\root")).toBe(false);
});
});
describe("混合路径分隔符處理", () => {
it("应该处理混合的路径分隔符", () => {
// 這是實際錯誤場景:正規化應該統一分隔符
expect(isSubdirectoryOf("C:/root\\.sync-git\\target", "C:\\root")).toBe(
true,
);
expect(isSubdirectoryOf("C:\\root/.sync-git/target", "C:/root")).toBe(
true,
);
});
it("应该处理尾随分隔符", () => {
expect(isSubdirectoryOf("C:/root/sub/", "C:/root/")).toBe(true);
expect(isSubdirectoryOf("C:\\root\\sub\\", "C:\\root\\")).toBe(true);
});
});
describe("邊界條件測試", () => {
it("应该处理根目录", () => {
if (process.platform === "win32") {
expect(isSubdirectoryOf("C:\\", "C:\\")).toBe(true);
expect(isSubdirectoryOf("C:\\sub", "C:\\")).toBe(true);
} else {
expect(isSubdirectoryOf("/", "/")).toBe(true);
expect(isSubdirectoryOf("/sub", "/")).toBe(true);
}
});
it("应该处理相对路径", () => {
expect(isSubdirectoryOf("./sub", ".")).toBe(true);
expect(isSubdirectoryOf("../other", ".")).toBe(false);
expect(isSubdirectoryOf("sub/deep", "sub")).toBe(true);
});
it("应该处理空字符串和特殊字符", () => {
expect(isSubdirectoryOf("", "")).toBe(true);
expect(isSubdirectoryOf("a", "")).toBe(false);
expect(isSubdirectoryOf("", "a")).toBe(false);
});
});
});
describe("analyzePathRelationship", () => {
it("应该提供详细的路径分析", () => {
const targetPath = "C:/root\\.sync-git\\target";
const sourcePath = "C:\\root";
const analysis = analyzePathRelationship(targetPath, sourcePath);
expect(analysis.isSubdirectory).toBe(true);
expect(analysis.normalizedTarget).toBe(path.normalize(targetPath));
expect(analysis.normalizedSource).toBe(path.normalize(sourcePath));
expect(analysis.startsWithCheck).toBe(true);
expect(analysis.equalityCheck).toBe(false);
expect(analysis.separator).toBe(path.sep);
});
it("应该分析相同路径", () => {
const targetPath = "C:\\root";
const sourcePath = "C:/root";
const analysis = analyzePathRelationship(targetPath, sourcePath);
expect(analysis.isSubdirectory).toBe(true);
expect(analysis.startsWithCheck).toBe(false);
expect(analysis.equalityCheck).toBe(true);
});
it("应该分析非子目录关系", () => {
const targetPath = "/other/path";
const sourcePath = "/root";
const analysis = analyzePathRelationship(targetPath, sourcePath);
expect(analysis.isSubdirectory).toBe(false);
expect(analysis.startsWithCheck).toBe(false);
expect(analysis.equalityCheck).toBe(false);
});
it("应该包含正確的分隔符信息", () => {
const analysis = analyzePathRelationship("any", "path");
expect(analysis.separator).toBe(path.sep);
if (process.platform === "win32") {
expect(analysis.separator).toBe("\\");
} else {
expect(analysis.separator).toBe("/");
}
});
});