import { describe, it, expect, beforeEach, afterEach } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { createRunner } from "./tier1-command.ts"; import { setupTempDir, cleanupTempDir, getTempDir, createFreshProject, writeDoc, } from "./fixtures.ts"; import { scanChanges } from "../../src/core/scanner.ts"; import { getChangeDir } from "../../src/core/config.ts"; describe("e2e: build 阶段", () => { let runner: ReturnType; beforeEach(async () => { await setupTempDir(); runner = createRunner(); }); afterEach(async () => { await cleanupTempDir(); }); it("单任务执行,勾选并产出文件", async () => { const config = await createFreshProject(); await writeDoc("auth", "task", "- [ ] 实现登录 API\n"); const result = await runner.runBuild(getTempDir(), "auth", config); expect(result.files).toContain("task.md"); expect(result.files.length).toBeGreaterThanOrEqual(2); const tasks = await scanChanges(getTempDir(), config); expect(tasks[0].taskProgress).toEqual({ completed: 1, total: 1 }); }); it("多任务按顺序逐个勾选", async () => { const config = await createFreshProject(); await writeDoc("multi-task", "task", `- [ ] 任务A\n- [ ] 任务B\n- [ ] 任务C\n`); const result = await runner.runBuild(getTempDir(), "multi-task", config); expect(result.files).toHaveLength(4); expect(result.files).toContain("task.md"); const taskContent = readFileSync( join(getChangeDir(getTempDir(), "multi-task"), "task.md"), "utf-8", ); expect(taskContent).toContain("- [x] 任务A"); expect(taskContent).toContain("- [x] 任务B"); expect(taskContent).toContain("- [x] 任务C"); const tasks = await scanChanges(getTempDir(), config); expect(tasks[0].taskProgress).toEqual({ completed: 3, total: 3 }); }); it("空 task 清单时 taskProgress 提示无任务", async () => { const config = await createFreshProject(); await writeDoc("empty", "task", "\n"); const changes = await scanChanges(getTempDir(), config); const emptyChange = changes.find((c) => c.name === "empty"); expect(emptyChange).toBeDefined(); if (emptyChange) { expect(emptyChange.taskProgress).toEqual({ completed: 0, total: 0 }); } }); it("plan 未完成时 build 不可用", async () => { const config = await createFreshProject(); await expect(runner.runBuild(getTempDir(), "no-task", config)).rejects.toThrow( "task.md 不存在", ); }); it("任务全部完成后状态为已完成", async () => { const config = await createFreshProject(); await writeDoc("done", "task", "- [x] 已完成任务\n"); const result = await runner.runBuild(getTempDir(), "done", config); expect(result.files).toEqual([]); const tasks = await scanChanges(getTempDir(), config); const doneChange = tasks.find((c) => c.name === "done"); expect(doneChange).toBeDefined(); if (doneChange) { expect(doneChange.taskProgress).toEqual({ completed: 1, total: 1 }); } }); });