import { describe, expect, it, vi } from "vitest"; import type { OptimizationStreamEvent } from "../stream-events"; import { runStreamingOptimizationWorkflow } from "../streaming-optimizer"; const workflowMocks = vi.hoisted(() => ({ optimizeArticle: vi.fn(), inspectQualityWithLlm: vi.fn(), rewriteFailedSections: vi.fn(), })); vi.mock("../article-optimizer", () => ({ optimizeArticle: workflowMocks.optimizeArticle, })); vi.mock("../quality-inspector", () => ({ inspectQualityWithLlm: workflowMocks.inspectQualityWithLlm, })); vi.mock("../targeted-rewriter", () => ({ rewriteFailedSections: workflowMocks.rewriteFailedSections, })); const input = { title: "", body: "示例科技提供GEO内容优化服务。", images: [], platform: "official_site" as const, user_instructions: "", }; const factCard = { company_full_name: "", company_short_names: ["示例科技"], brand_names: [], product_names: ["GEO内容优化平台"], target_industry: "GEO内容优化", target_audience: "市场团队", experience_years: null, core_claims: ["提供GEO内容优化服务"], forbidden_claims: [], image_topics: [], uncertain_items: ["公司全称需要确认"], is_ready_for_optimization: false, confirmed_by_user: false, }; const draftArticle = { title: "示例科技 GEO 内容优化方案", summary: "面向市场团队的GEO内容优化说明。", body_markdown: "## 服务能力\n示例科技提供GEO内容优化服务。", image_suggestions: [], changed_sections: ["标题", "正文"], requires_user_confirmation: [], }; const failCheck = { rule_id: "body_quality" as const, status: "fail" as const, evidence: "句子不够顺。", reason: "正文需要润色。", suggested_fix: "润色正文。", target_agent: "body", }; describe("runStreamingOptimizationWorkflow", () => { it("emits draft and final QA events when no rewrite is needed", async () => { workflowMocks.optimizeArticle.mockResolvedValueOnce(draftArticle); workflowMocks.inspectQualityWithLlm.mockResolvedValueOnce({ overall_status: "pass", checks: [], }); const events: OptimizationStreamEvent[] = []; const result = await runStreamingOptimizationWorkflow({ jobId: "job_stream", input, factCard, onEvent: (event) => events.push(event), }); expect(events.map((event) => event.type)).toEqual([ "draft_started", "draft_ready", "qa_started", "qa_ready", ]); expect(result.article.title).toBe("示例科技 GEO 内容优化方案"); expect(result.qaReport.overall_status).toBe("pass"); expect(result.rewriteRounds).toBe(0); }); it("emits rewrite events when QA fails", async () => { workflowMocks.optimizeArticle.mockResolvedValueOnce(draftArticle); workflowMocks.inspectQualityWithLlm .mockResolvedValueOnce({ overall_status: "fail", checks: [failCheck] }) .mockResolvedValueOnce({ overall_status: "pass", checks: [] }); workflowMocks.rewriteFailedSections.mockResolvedValueOnce({ ...draftArticle, body_markdown: "## 服务能力\n示例科技提供清晰的GEO内容优化服务。", }); const events: OptimizationStreamEvent[] = []; const result = await runStreamingOptimizationWorkflow({ jobId: "job_stream", input, factCard, onEvent: (event) => events.push(event), }); expect(events.map((event) => event.type)).toEqual([ "draft_started", "draft_ready", "qa_started", "qa_ready", "rewrite_started", "rewrite_ready", "qa_started", "qa_ready", ]); expect(result.article.body_markdown).toContain("清晰的GEO内容优化服务"); expect(result.rewriteRounds).toBe(1); }); });