mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-12 09:40:10 +08:00
【调整】申请证书配置CA选项增加liteSSL证书
This commit is contained in:
@@ -1,276 +0,0 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { performAutoCommit } from "../../src/core/autoCommitHandler";
|
||||
import path from "path";
|
||||
import fs from "fs-extra";
|
||||
|
||||
// 模拟依赖
|
||||
vi.mock("simple-git", () => {
|
||||
// 创建简单的模拟实现
|
||||
const mockGit = {
|
||||
checkIsRepo: vi.fn().mockResolvedValue(true),
|
||||
branchLocal: vi.fn().mockResolvedValue({ current: "develop" }),
|
||||
log: vi.fn().mockResolvedValue({
|
||||
all: [
|
||||
{ hash: "1234567", message: "一般提交1" },
|
||||
{ hash: "2345678", message: "一般提交2" },
|
||||
{ hash: "3456789", message: "/** 提交分隔符 **/" },
|
||||
{ hash: "4567890", message: "之前的提交" },
|
||||
],
|
||||
}),
|
||||
status: vi
|
||||
.fn()
|
||||
.mockResolvedValue({ isClean: vi.fn().mockReturnValue(true) }),
|
||||
add: vi.fn().mockResolvedValue(undefined),
|
||||
commit: vi.fn().mockResolvedValue(undefined),
|
||||
push: vi.fn().mockResolvedValue(undefined),
|
||||
checkout: vi.fn().mockResolvedValue(undefined),
|
||||
reset: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
return {
|
||||
default: vi.fn().mockReturnValue(mockGit),
|
||||
__esModule: true,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("fs-extra", () => ({
|
||||
existsSync: vi.fn().mockReturnValue(true),
|
||||
__esModule: true,
|
||||
}));
|
||||
|
||||
// 模拟日志记录器
|
||||
const mockLogger = {
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
info: vi.fn(),
|
||||
verbose: vi.fn(),
|
||||
setLogLevel: vi.fn(),
|
||||
};
|
||||
|
||||
describe("performAutoCommit", () => {
|
||||
const mockViteRoot = "/test/root";
|
||||
const mockSharedCommitMessagesHolder = { current: null as string[] | null };
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("应该处理单个项目的自动提交 (独立模块)", async () => {
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/api-gateway",
|
||||
projectName: "api-gateway",
|
||||
watchAuthor: "张三",
|
||||
push: true,
|
||||
},
|
||||
],
|
||||
enableSharedCommits: true,
|
||||
insertSeparator: true,
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证日志和基本操作
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("开始自动提交操作...");
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("已重置共享提交信息缓冲区");
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"处理自动提交项目: api-gateway",
|
||||
);
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("自动提交操作完成");
|
||||
|
||||
// 验证Git操作
|
||||
const simpleGit = require("simple-git").default;
|
||||
const mockGit = simpleGit();
|
||||
expect(mockGit.log).toHaveBeenCalled();
|
||||
expect(mockGit.commit).toHaveBeenCalledTimes(2); // 一次正常提交,一次分隔符
|
||||
expect(mockGit.push).toHaveBeenCalledTimes(2); // 一次正常推送,一次分隔符推送
|
||||
});
|
||||
|
||||
it("应该在禁用共享提交时不重置共享缓冲区", async () => {
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/api-gateway",
|
||||
projectName: "api-gateway",
|
||||
watchAuthor: "张三",
|
||||
},
|
||||
],
|
||||
enableSharedCommits: false,
|
||||
insertSeparator: true,
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证没有重置共享缓冲区
|
||||
expect(mockLogger.info).not.toHaveBeenCalledWith(
|
||||
"已重置共享提交信息缓冲区",
|
||||
);
|
||||
});
|
||||
|
||||
it("应该在项目不存在时跳过处理", async () => {
|
||||
// 模拟文件不存在
|
||||
vi.mocked(fs.existsSync).mockReturnValueOnce(false);
|
||||
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/non-existent",
|
||||
projectName: "non-existent",
|
||||
watchAuthor: "张三",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
expect(mockLogger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining("不存在,跳过此项目"),
|
||||
);
|
||||
// 验证没有进行Git操作
|
||||
const simpleGit = require("simple-git").default;
|
||||
expect(simpleGit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("应该使用共享提交信息", async () => {
|
||||
// 设置共享提交信息
|
||||
mockSharedCommitMessagesHolder.current = ["[abcdef1] 共享的提交信息"];
|
||||
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/consumer",
|
||||
projectName: "consumer",
|
||||
useSharedCommits: true,
|
||||
push: true,
|
||||
},
|
||||
],
|
||||
enableSharedCommits: true,
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证使用了共享提交信息
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("[consumer] 使用共享提交信息");
|
||||
|
||||
// 验证提交操作
|
||||
const simpleGit = require("simple-git").default;
|
||||
const mockGit = simpleGit();
|
||||
expect(mockGit.commit).toHaveBeenCalled();
|
||||
expect(mockGit.push).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("应该在没有提交时跳过", async () => {
|
||||
// 模拟没有提交记录
|
||||
const simpleGit = require("simple-git").default;
|
||||
const mockGit = simpleGit();
|
||||
vi.mocked(mockGit.log).mockResolvedValueOnce({ all: [] });
|
||||
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/no-commits",
|
||||
projectName: "no-commits",
|
||||
watchAuthor: "张三",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证没有进行提交操作
|
||||
expect(mockGit.commit).not.toHaveBeenCalled();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"[no-commits] 没有要处理的新提交",
|
||||
);
|
||||
});
|
||||
|
||||
it("应该处理分支切换", async () => {
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/branch-test",
|
||||
projectName: "branch-test",
|
||||
watchAuthor: "张三",
|
||||
branch: "feature/test",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 模拟当前分支不是目标分支
|
||||
const simpleGit = require("simple-git").default;
|
||||
const mockGit = simpleGit();
|
||||
vi.mocked(mockGit.branchLocal).mockResolvedValueOnce({ current: "main" });
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证分支切换
|
||||
expect(mockGit.checkout).toHaveBeenCalledWith("feature/test");
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("切换到分支 feature/test...");
|
||||
});
|
||||
|
||||
it("应该支持多项目并发处理", async () => {
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
targetDir: "services/api-gateway",
|
||||
projectName: "api-gateway",
|
||||
watchAuthor: "张三",
|
||||
push: true,
|
||||
},
|
||||
{
|
||||
targetDir: "services/user-service",
|
||||
projectName: "user-service",
|
||||
useSharedCommits: true,
|
||||
push: true,
|
||||
},
|
||||
],
|
||||
enableSharedCommits: true,
|
||||
};
|
||||
|
||||
await performAutoCommit(
|
||||
config,
|
||||
mockViteRoot,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 验证处理了两个项目
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"处理自动提交项目: api-gateway",
|
||||
);
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"处理自动提交项目: user-service",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,211 +0,0 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { loadConfig, processTasks } from "../../src/core/config";
|
||||
import path from "path";
|
||||
|
||||
// 模拟依赖
|
||||
vi.mock("../../src/core/logger", () => ({
|
||||
createLogger: vi.fn(() => ({
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
info: vi.fn(),
|
||||
verbose: vi.fn(),
|
||||
setLogLevel: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("../../src/core/localSync", () => ({
|
||||
performLocalSync: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("../../src/core/gitHandler", () => ({
|
||||
updateGitProjects: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
// 导入模拟的模块
|
||||
import { performLocalSync } from "../../src/core/localSync";
|
||||
import { updateGitProjects } from "../../src/core/gitHandler";
|
||||
|
||||
describe("loadConfig", () => {
|
||||
it("应该返回空对象当没有提供选项时", () => {
|
||||
const config = loadConfig(undefined, "/test/root");
|
||||
expect(config).toEqual({});
|
||||
});
|
||||
|
||||
it("应该验证并返回有效的配置", () => {
|
||||
const options = {
|
||||
localSync: [{ source: "src", target: "dist" }],
|
||||
gitProjects: [
|
||||
{
|
||||
repo: "https://github.com/example/repo.git",
|
||||
branch: "main",
|
||||
targetDir: "services/repo",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const config = loadConfig(options, "/test/root");
|
||||
expect(config).toEqual(options);
|
||||
});
|
||||
|
||||
it("应该在无效配置时抛出错误", () => {
|
||||
const invalidOptions = {
|
||||
localSync: [
|
||||
{ source: "", target: "dist" }, // 无效的source
|
||||
],
|
||||
};
|
||||
|
||||
expect(() => loadConfig(invalidOptions, "/test/root")).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("processTasks", () => {
|
||||
const mockLogger = {
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
info: vi.fn(),
|
||||
verbose: vi.fn(),
|
||||
setLogLevel: vi.fn(),
|
||||
};
|
||||
|
||||
const mockViteConfig = {
|
||||
root: "/test/root",
|
||||
} as any;
|
||||
|
||||
const mockSharedCommitMessagesHolder = { current: null as string[] | null };
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("应该按顺序执行配置的任务", async () => {
|
||||
const config = {
|
||||
localSync: [{ source: "src", target: "dist" }],
|
||||
gitProjects: [
|
||||
{
|
||||
repo: "https://github.com/example/repo.git",
|
||||
branch: "main",
|
||||
targetDir: "services/repo",
|
||||
},
|
||||
],
|
||||
taskOrder: ["localSync", "updateGitProjects"],
|
||||
};
|
||||
|
||||
await processTasks(
|
||||
config,
|
||||
mockViteConfig,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"执行任务顺序: localSync, updateGitProjects",
|
||||
);
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("开始任务: localSync");
|
||||
expect(performLocalSync).toHaveBeenCalledWith(
|
||||
config.localSync,
|
||||
mockViteConfig.root,
|
||||
mockLogger,
|
||||
);
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("任务 localSync 完成。");
|
||||
|
||||
expect(mockLogger.info).toHaveBeenCalledWith("开始任务: updateGitProjects");
|
||||
expect(updateGitProjects).toHaveBeenCalledWith(
|
||||
config.gitProjects,
|
||||
mockViteConfig.root,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"任务 updateGitProjects 完成。",
|
||||
);
|
||||
});
|
||||
|
||||
it("应该使用默认任务顺序当未指定时", async () => {
|
||||
const config = {
|
||||
localSync: [{ source: "src", target: "dist" }],
|
||||
gitProjects: [
|
||||
{
|
||||
repo: "https://github.com/example/repo.git",
|
||||
branch: "main",
|
||||
targetDir: "services/repo",
|
||||
},
|
||||
],
|
||||
// 未指定taskOrder
|
||||
};
|
||||
|
||||
await processTasks(
|
||||
config,
|
||||
mockViteConfig,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
// 默认顺序: localSync, updateGitProjects
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
"执行任务顺序: localSync, updateGitProjects",
|
||||
);
|
||||
expect(performLocalSync).toHaveBeenCalled();
|
||||
expect(updateGitProjects).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("应该处理任务错误并继续执行", async () => {
|
||||
const config = {
|
||||
localSync: [{ source: "src", target: "dist" }],
|
||||
gitProjects: [
|
||||
{
|
||||
repo: "https://github.com/example/repo.git",
|
||||
branch: "main",
|
||||
targetDir: "services/repo",
|
||||
},
|
||||
],
|
||||
taskOrder: ["localSync", "updateGitProjects"],
|
||||
};
|
||||
|
||||
const error = new Error("测试错误");
|
||||
(performLocalSync as any).mockRejectedValueOnce(error);
|
||||
|
||||
await processTasks(
|
||||
config,
|
||||
mockViteConfig,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
);
|
||||
|
||||
expect(mockLogger.error).toHaveBeenCalledWith(
|
||||
"任务 localSync 执行错误: 测试错误",
|
||||
error,
|
||||
);
|
||||
expect(updateGitProjects).toHaveBeenCalled(); // 第二个任务仍然执行
|
||||
});
|
||||
|
||||
it("应该在关键错误时中断流程", async () => {
|
||||
const config = {
|
||||
localSync: [{ source: "src", target: "dist" }],
|
||||
gitProjects: [
|
||||
{
|
||||
repo: "https://github.com/example/repo.git",
|
||||
branch: "main",
|
||||
targetDir: "services/repo",
|
||||
},
|
||||
],
|
||||
taskOrder: ["localSync", "updateGitProjects"],
|
||||
};
|
||||
|
||||
const criticalError = new Error("关键错误") as Error & {
|
||||
isCritical: boolean;
|
||||
};
|
||||
criticalError.isCritical = true;
|
||||
(performLocalSync as any).mockRejectedValueOnce(criticalError);
|
||||
|
||||
await expect(
|
||||
processTasks(
|
||||
config,
|
||||
mockViteConfig,
|
||||
mockLogger,
|
||||
mockSharedCommitMessagesHolder,
|
||||
),
|
||||
).rejects.toThrow("关键错误");
|
||||
|
||||
expect(updateGitProjects).not.toHaveBeenCalled(); // 第二个任务不应执行
|
||||
});
|
||||
});
|
||||
@@ -1,270 +0,0 @@
|
||||
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("/");
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user