import { describe, expect, it } from "vitest"; import { appendTeacherNotice, isMaxTurnsError, teacherFacingRunOutcome, } from "../../src/feishu/runOutcomeNotice.js"; describe("teacherFacingRunOutcome", () => { it("explains max-turn stops with the configured ceiling", () => { const outcome = teacherFacingRunOutcome({ wallTimeExceeded: false, interrupted: false, resultStatus: "failed", resultError: "Claude Code returned an error result: Reached maximum number of turns (25)", maxTurns: 150, maxRunSeconds: 1800, hasPartialText: true, }); expect(outcome.isError).toBe(true); expect(outcome.notice).toContain("150"); expect(outcome.notice).toContain("最大步骤数"); expect(outcome.notice).toContain("部分结果"); }); it("explains wall-clock timeouts", () => { const outcome = teacherFacingRunOutcome({ wallTimeExceeded: true, interrupted: false, resultStatus: "interrupted", resultError: undefined, maxTurns: 150, maxRunSeconds: 1800, hasPartialText: false, }); expect(outcome.isError).toBe(true); expect(outcome.notice).toContain("1800"); expect(outcome.notice).toContain("超时"); }); it("is quiet on successful completion", () => { expect( teacherFacingRunOutcome({ wallTimeExceeded: false, interrupted: false, resultStatus: "completed", resultError: undefined, maxTurns: 150, maxRunSeconds: 1800, hasPartialText: true, }), ).toEqual({ isError: false, notice: undefined }); }); it("appendTeacherNotice joins body and notice", () => { expect(appendTeacherNotice("hello", "bye")).toBe("hello\n\nbye"); expect(appendTeacherNotice("", "only")).toBe("only"); }); it("detects max-turn SDK wording", () => { expect(isMaxTurnsError("Reached maximum number of turns (25)")).toBe(true); expect(isMaxTurnsError("result_error_max_turns")).toBe(true); expect(isMaxTurnsError("network glitch")).toBe(false); }); });