feat(FN-4579): complete Step 2 — milestone acceptance criteria in mission routes

Fusion-Task-Id: FN-4579
Fusion-Task-Lineage: b0f3b436-599f-4b7b-a598-b8789e0e4cb7
This commit is contained in:
Fusion
2026-05-15 06:22:45 -07:00
committed by gsxdsm
parent 719dc6e1c5
commit 56d7bfb564
2 changed files with 29 additions and 2 deletions

View File

@@ -193,7 +193,7 @@ function createMockMissionStore() {
missions.delete(id);
}),
addMilestone: vi.fn((missionId: string, input: { title: string; description?: string; dependencies?: string[]; verification?: string }) => {
addMilestone: vi.fn((missionId: string, input: { title: string; description?: string; dependencies?: string[]; verification?: string; acceptanceCriteria?: string }) => {
const milestone: Milestone = {
id: generateMilestoneId(),
missionId,
@@ -204,6 +204,7 @@ function createMockMissionStore() {
interviewState: "not_started",
dependencies: input.dependencies ?? [],
verification: input.verification,
acceptanceCriteria: input.acceptanceCriteria,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
@@ -1346,6 +1347,7 @@ describe("Mission API", () => {
title: "Milestone A",
description: "Detailed milestone",
dependencies: ["MS-UPSTREAM-1"],
acceptanceCriteria: "Milestone acceptance bar",
}),
{ "content-type": "application/json" },
);
@@ -1354,6 +1356,18 @@ describe("Mission API", () => {
expect(created.body.title).toBe("Milestone A");
expect(created.body.description).toBe("Detailed milestone");
expect(created.body.dependencies).toEqual(["MS-UPSTREAM-1"]);
expect(created.body.acceptanceCriteria).toBe("Milestone acceptance bar");
const afterCreate = await get(app, `/api/missions/${mission.id}/milestones`);
expect(afterCreate.status).toBe(200);
expect(afterCreate.body).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: created.body.id,
acceptanceCriteria: "Milestone acceptance bar",
}),
]),
);
const missingMission = await request(
app,
@@ -1440,6 +1454,17 @@ describe("Mission API", () => {
expect(updateAcceptanceCriteria.status).toBe(200);
expect(updateAcceptanceCriteria.body.acceptanceCriteria).toBe("Acceptance ready");
const afterPatch = await get(app, `/api/missions/${mission.id}/milestones`);
expect(afterPatch.status).toBe(200);
expect(afterPatch.body).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: milestone.id,
acceptanceCriteria: "Acceptance ready",
}),
]),
);
const malformedAcceptanceCriteria = await request(
app,
"PATCH",

View File

@@ -1145,7 +1145,7 @@ export function createMissionRouter(
"/:missionId/milestones",
catchTypedHandler(async (req, res) => {
const { missionId } = req.params;
const { title, description, dependencies } = req.body;
const { title, description, dependencies, acceptanceCriteria } = req.body;
if (!validateMissionId(missionId)) {
throw badRequest("Invalid mission ID format");
@@ -1159,11 +1159,13 @@ export function createMissionRouter(
const validatedTitle = validateTitle(title);
const validatedDescription = validateDescription(description);
const validatedDependencies = validateStringArray(dependencies, "dependencies");
const validatedAcceptanceCriteria = validateDescription(acceptanceCriteria);
const input: MilestoneCreateInput = {
title: validatedTitle,
description: validatedDescription,
dependencies: validatedDependencies,
acceptanceCriteria: validatedAcceptanceCriteria,
};
const milestone = missionStore.addMilestone(missionId, input);