feat: 第二期 — Tier 2 场景级 mock + 错误/流程/依赖测试
This commit is contained in:
118
tests/agent/e2e-flow.test.ts
Normal file
118
tests/agent/e2e-flow.test.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
||||
import { createRunner } from "./tier1-command.ts";
|
||||
import {
|
||||
setupTempDir,
|
||||
cleanupTempDir,
|
||||
getTempDir,
|
||||
createFreshProject,
|
||||
changeFileExists,
|
||||
} from "./fixtures.ts";
|
||||
import { assertAllTasksDone } from "./validators.ts";
|
||||
import { scanChanges, scanArchives } from "../../src/core/scanner.ts";
|
||||
import { assembleDiscussPrompt } from "../../src/core/assembler.ts";
|
||||
import { validateChangeName } from "../../src/cli.ts";
|
||||
|
||||
describe("e2e: 全流程", () => {
|
||||
let runner: ReturnType<typeof createRunner>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await setupTempDir();
|
||||
runner = createRunner();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await cleanupTempDir();
|
||||
});
|
||||
|
||||
it("完整四阶段流程(discuss → plan → build → archive)", async () => {
|
||||
const config = await createFreshProject();
|
||||
|
||||
const discussPrompt = assembleDiscussPrompt(config);
|
||||
expect(typeof discussPrompt).toBe("string");
|
||||
expect(discussPrompt.length).toBeGreaterThan(0);
|
||||
|
||||
await runner.runPlan(getTempDir(), "full-flow", "design", config);
|
||||
await runner.runPlan(getTempDir(), "full-flow", "task", config);
|
||||
|
||||
let changes = await scanChanges(getTempDir(), config);
|
||||
expect(changes).toHaveLength(1);
|
||||
expect(changes[0]!.name).toBe("full-flow");
|
||||
expect(changes[0]!.planCompleted).toBe(true);
|
||||
expect(changes[0]!.buildUnlocked).toBe(true);
|
||||
|
||||
const buildResult = await runner.runBuild(getTempDir(), "full-flow", config);
|
||||
expect(buildResult.files.length).toBeGreaterThan(0);
|
||||
|
||||
changes = await scanChanges(getTempDir(), config);
|
||||
expect(changes).toHaveLength(1);
|
||||
assertAllTasksDone(changes[0]!);
|
||||
|
||||
await runner.runArchive(getTempDir(), "full-flow", config);
|
||||
|
||||
expect(changeFileExists("full-flow", "task.md")).toBe(false);
|
||||
|
||||
const archives = await scanArchives(getTempDir());
|
||||
expect(archives.length).toBeGreaterThanOrEqual(1);
|
||||
|
||||
changes = await scanChanges(getTempDir(), config);
|
||||
expect(changes.find((c) => c.name === "full-flow")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("多变更并行互不干扰", async () => {
|
||||
const config = await createFreshProject();
|
||||
|
||||
await runner.runPlan(getTempDir(), "变更A", "design", config);
|
||||
await runner.runPlan(getTempDir(), "变更A", "task", config);
|
||||
|
||||
await runner.runPlan(getTempDir(), "变更B", "design", config);
|
||||
await runner.runPlan(getTempDir(), "变更B", "task", config);
|
||||
|
||||
let changes = await scanChanges(getTempDir(), config);
|
||||
expect(changes).toHaveLength(2);
|
||||
|
||||
const changeA = changes.find((c) => c.name === "变更A");
|
||||
const changeB = changes.find((c) => c.name === "变更B");
|
||||
expect(changeA).toBeDefined();
|
||||
expect(changeB).toBeDefined();
|
||||
expect(changeA!.planCompleted).toBe(true);
|
||||
expect(changeB!.planCompleted).toBe(true);
|
||||
|
||||
await runner.runBuild(getTempDir(), "变更A", config);
|
||||
await runner.runBuild(getTempDir(), "变更B", config);
|
||||
|
||||
changes = await scanChanges(getTempDir(), config);
|
||||
expect(changes).toHaveLength(2);
|
||||
|
||||
assertAllTasksDone(changes.find((c) => c.name === "变更A")!);
|
||||
assertAllTasksDone(changes.find((c) => c.name === "变更B")!);
|
||||
|
||||
expect(changes[0]!.taskProgress?.completed).toBe(changes[0]!.taskProgress?.total);
|
||||
expect(changes[1]!.taskProgress?.completed).toBe(changes[1]!.taskProgress?.total);
|
||||
});
|
||||
|
||||
describe("变更名非法字符拒绝", () => {
|
||||
it("空字符串抛出错误", () => {
|
||||
expect(() => validateChangeName("")).toThrow();
|
||||
});
|
||||
|
||||
it("包含 / 抛出错误", () => {
|
||||
expect(() => validateChangeName("变更/A")).toThrow();
|
||||
});
|
||||
|
||||
it("包含 . 抛出错误", () => {
|
||||
expect(() => validateChangeName("变更.A")).toThrow();
|
||||
});
|
||||
|
||||
it("合法中文名称不抛出错误", () => {
|
||||
expect(() => validateChangeName("变更名")).not.toThrow();
|
||||
});
|
||||
|
||||
it("合法英文名称不抛出错误", () => {
|
||||
expect(() => validateChangeName("my-change")).not.toThrow();
|
||||
});
|
||||
|
||||
it("合法短横线名称不抛出错误", () => {
|
||||
expect(() => validateChangeName("abc-def-xyz")).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user