package projectinstance import ( "testing" "chat-agent-system/internal/workflowdef" ) func TestValidateActivationPlan_EmptyWorkflowBlocked(t *testing.T) { plan := WorkflowPlan{ WorkflowDefinitionKey: workflowdef.OfficialKeyProductManager, WorkflowVersion: 2, Stages: []StagePlan{{ StageKey: "requirements_baseline", Enabled: true, DocTasks: []DocTaskPlan{{ TaskKey: "system_reqs", Enabled: false, }}, }}, } version := &workflowdef.Version{ Status: workflowdef.StatusPublished, WorkflowKey: workflowdef.OfficialKeyProductManager, Version: 2, Definition: workflowdef.VersionDefinition{ SchemaVersion: 2, Stages: []workflowdef.StageDef{{ Key: "requirements_baseline", Position: 10, DocTasks: []workflowdef.DocTaskDef{{ Key: "system_reqs", CreatorConfigurable: true, DefaultEnabled: true, OutputDocType: "system_reqs", }}, }}, }, } res := validatePlan(plan, version) if !res.Valid { t.Fatalf("save plan should allow all docs disabled: %+v", res.Issues) } act := validateActivationPlan(plan, version) if act.Valid { t.Fatal("activation should reject empty enabled doc set") } } func TestBuildDefaultPlan_StampsApprovalConfigurable(t *testing.T) { version := optionalDutyResolver().versions[workflowdef.OfficialKeyMain] plan := buildDefaultPlan(version) if !plan.Stages[0].DocTasks[0].ApprovalConfigurable || !plan.Stages[0].DocTasks[1].ApprovalConfigurable { t.Fatalf("optional docs should stamp approval_configurable: %+v", plan.Stages[0].DocTasks) } required := requiredDutyResolver().versions[workflowdef.OfficialKeyMain] reqPlan := buildDefaultPlan(required) if reqPlan.Stages[0].DocTasks[0].ApprovalConfigurable { t.Fatal("required docs must not be approval-configurable") } } func TestBuildDefaultPlan_IncludesDisplayNames(t *testing.T) { version := testResolver().versions[workflowdef.OfficialKeyMain] plan := buildDefaultPlan(version) if len(plan.Stages) != 1 || plan.Stages[0].StageName != "V0.1 需求摸底" { t.Fatalf("expected stage display name, got %+v", plan.Stages) } if len(plan.Stages[0].DocTasks) != 1 || plan.Stages[0].DocTasks[0].TaskTitle != "用户初始需求收集表" { t.Fatalf("expected task display title, got %+v", plan.Stages[0].DocTasks) } } func TestPreviewSummary_SplitsGovernedAndUnmanaged(t *testing.T) { version := optionalDutyResolver().versions[workflowdef.OfficialKeyMain] plan := optionalDutyPlan( DocDuty{AuthorUserID: 1, ReviewerUserID: 2, ApproverUserID: 3}, DocDuty{}, ) sum := previewSummary(plan, version) if sum.EnabledDocTasks != 2 || sum.GovernedDocTasks != 1 || sum.UnmanagedDocTasks != 1 || sum.AssignedDuties != 3 { t.Fatalf("preview counts: %+v", sum) } if len(sum.UnmanagedDocuments) != 1 || sum.UnmanagedDocuments[0].TaskKey != "research" { t.Fatalf("unmanaged list: %+v", sum.UnmanagedDocuments) } } func TestValidateActivationPlan_NoGovernedDocument(t *testing.T) { version := optionalDutyResolver().versions[workflowdef.OfficialKeyMain] plan := optionalDutyPlan(DocDuty{}, DocDuty{}) if res := validatePlan(plan, version); !res.Valid { t.Fatalf("ungoverned optional docs may be saved: %+v", res.Issues) } act := validateActivationPlan(plan, version) if act.Valid || !hasIssue(act.Issues, issueNoGovernedDocument) { t.Fatalf("activation must require one full duty doc, got %+v", act.Issues) } } func TestValidatePlan_RequiredAndPartial(t *testing.T) { version := requiredDutyResolver().versions[workflowdef.OfficialKeyMain] empty := validPlan() empty.Stages[0].DocTasks[0].Duties = DocDuty{} res := validatePlan(empty, version) if res.Valid || !hasIssue(res.Issues, issueDutyAssignmentRequired) { t.Fatalf("required empty: %+v", res.Issues) } partial := validPlan() partial.Stages[0].DocTasks[0].Duties = DocDuty{AuthorUserID: 1, ReviewerUserID: 2} res = validatePlan(partial, testResolver().versions[workflowdef.OfficialKeyMain]) if res.Valid || !hasIssue(res.Issues, issueDutyPartialAssignment) || res.Issues[0].Field != "intake.duties" { t.Fatalf("partial field: %+v", res.Issues) } } func TestApplyDefinitionLabels_OverridesClientText(t *testing.T) { version := testResolver().versions[workflowdef.OfficialKeyMain] plan := validPlan() plan.Stages[0].StageName = "客户端伪造阶段" plan.Stages[0].DocTasks[0].TaskTitle = "客户端伪造文档" applyDefinitionLabels(&plan, version) if plan.Stages[0].StageName != "V0.1 需求摸底" || plan.Stages[0].DocTasks[0].TaskTitle != "用户初始需求收集表" { t.Fatalf("definition labels must win, got %+v", plan.Stages[0]) } }