refactor: 修复代码审查发现的问题
- Bug修复: formatChangeStatus 使用实际配置而非 defaultConfig - 统一 assembler 中所有错误抛出为 CommandError - 提取 writeIfChanged 到 adapters/utils.ts,消除 claude-code/opencode 重复代码 - 导出 SUPPORTED_TOOLS,cli.ts update 命令复用同一工具注册表 - 提取 mapError/mapCacError 函数,支持单元测试 - 补充 claude-code 适配器测试(10 个用例) - 补充 validateChangeName、formatChangeStatus、suggestNextStep、mapError 单元测试(18 个用例) - 共新增 3 个测试文件,测试从 96 增至 133,全部通过
This commit is contained in:
127
tests/adapters/claude-code.test.ts
Normal file
127
tests/adapters/claude-code.test.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
||||
import { existsSync } from "node:fs";
|
||||
import { mkdir, rm, readFile, readdir, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { injectClaudeCode, updateClaudeCode } from "../../src/adapters/claude-code.ts";
|
||||
|
||||
const TMP_DIR = join(import.meta.dir, "__tmp_claude_code_test__");
|
||||
|
||||
beforeEach(async () => {
|
||||
await mkdir(TMP_DIR, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(TMP_DIR, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe("injectClaudeCode", () => {
|
||||
it("生成 discuss、plan、build、archive 的 command 文件", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
|
||||
const commands = await readdir(join(TMP_DIR, ".claude", "commands"));
|
||||
for (const stage of ["discuss", "plan", "build", "archive"]) {
|
||||
expect(commands).toContain(`rune-${stage}.md`);
|
||||
}
|
||||
});
|
||||
|
||||
it("生成 rune-status command 文件", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
|
||||
const commands = await readdir(join(TMP_DIR, ".claude", "commands"));
|
||||
expect(commands).toContain("rune-status.md");
|
||||
});
|
||||
|
||||
it("command 文件包含 bash 命令", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).toContain("rune discuss");
|
||||
expect(content).toContain("```bash");
|
||||
});
|
||||
|
||||
it("plan/build/archive command 包含变更名称提示", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
|
||||
for (const stage of ["plan", "build", "archive"]) {
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", `rune-${stage}.md`),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).toContain("变更名");
|
||||
expect(content).toContain("如果用户没有指定变更名称");
|
||||
}
|
||||
});
|
||||
|
||||
it("discuss command 不包含变更名称提示", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).not.toContain("如果用户没有指定变更名称");
|
||||
});
|
||||
|
||||
it("重复注入时不覆盖已存在的文件", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
const originalContent = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).toBe(originalContent);
|
||||
});
|
||||
});
|
||||
|
||||
describe("updateClaudeCode", () => {
|
||||
it("文件不存在时创建", async () => {
|
||||
await updateClaudeCode(TMP_DIR);
|
||||
expect(
|
||||
existsSync(join(TMP_DIR, ".claude", "commands", "rune-discuss.md")),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("文件存在且内容一致时不覆盖", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
const originalContent = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
await updateClaudeCode(TMP_DIR);
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).toBe(originalContent);
|
||||
});
|
||||
|
||||
it("文件存在但内容不一致时覆盖", async () => {
|
||||
await injectClaudeCode(TMP_DIR);
|
||||
await writeFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"旧内容",
|
||||
);
|
||||
|
||||
await updateClaudeCode(TMP_DIR);
|
||||
const content = await readFile(
|
||||
join(TMP_DIR, ".claude", "commands", "rune-discuss.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(content).not.toBe("旧内容");
|
||||
expect(content).toContain("rune discuss");
|
||||
});
|
||||
|
||||
it("更新 status 命令", async () => {
|
||||
await updateClaudeCode(TMP_DIR);
|
||||
expect(
|
||||
existsSync(join(TMP_DIR, ".claude", "commands", "rune-status.md")),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user