【调整】申请证书配置CA选项增加liteSSL证书

This commit is contained in:
cai
2026-01-13 16:45:05 +08:00
parent 6c15ae35a1
commit 190e250095
2108 changed files with 58 additions and 401539 deletions

View File

@@ -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",
);
});
});

View File

@@ -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(); // 第二个任务不应执行
});
});

View File

@@ -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("/");
}
});
});