import { describe, expect, it } from "vitest"; import { projectRuntimeTrackedJob, runtimeBuildStages } from "./RuntimeTaskProgress"; describe("distribution build job progress", () => { it("projects worker progress messages onto the real build stage", () => { const projection = projectRuntimeTrackedJob(runtimeBuildStages, { id: "job-build-1", state: "running", progress: { percent: 65, message: "build_compile: compiling target executable" } }); expect(projection).toMatchObject({ status: "running", percent: 65, currentStageKey: "build_compile" }); expect(projection.stageStatus).toMatchObject({ git_sync: "completed", env_check: "completed", deps_download: "completed", build_compile: "running", package_finalize: "pending" }); }); it("keeps a failed worker stage failed instead of timer-completing later stages", () => { const projection = projectRuntimeTrackedJob(runtimeBuildStages, { id: "job-build-2", state: "failed", progress: { percent: 65, message: "build_compile: Go compilation failed" } }); expect(projection).toMatchObject({ status: "failed", percent: 65, currentStageKey: "build_compile" }); expect(projection.stageStatus.build_compile).toBe("failed"); expect(projection.stageStatus.package_finalize).toBe("pending"); }); it("marks every stage complete only when the backend job succeeds", () => { const projection = projectRuntimeTrackedJob(runtimeBuildStages, { id: "job-build-3", state: "succeeded", progress: { percent: 100, message: "package_finalize: build artifact available" } }); expect(projection.status).toBe("succeeded"); expect(projection.percent).toBe(100); expect(Object.values(projection.stageStatus)).toEqual(runtimeBuildStages.map(() => "completed")); }); it("keeps durable retry-wait jobs active and exposes the next attempt", () => { const projection = projectRuntimeTrackedJob(runtimeBuildStages, { id: "job-build-retry", state: "retrying", progress: { percent: 10 }, attempt: 1, retryPolicy: { maxAttempts: 3 }, nextAttemptAt: "2026-07-18T12:00:02Z" }); expect(projection.status).toBe("running"); expect(projection.message).toContain("第 2 次尝试"); }); });