package projectinstance import ( "context" "errors" "testing" "chat-agent-system/internal/workflowdef" ) func TestService_PlanPreviewActivate(t *testing.T) { ctx := context.Background() store := newMemStore() _ = SeedProjectMeta(store, 42, LifecyclePlanning, "", 1, 0) svc := NewService(store, testResolver(), nil, nil) settings, err := svc.SaveWorkflowPlan(ctx, 42, 1, true, SavePlanInput{ Plan: validPlan(), ExpectedPlanRevision: 0, ExpectedSelectionVersion: 1, }) if err != nil { t.Fatalf("SaveWorkflowPlan: %v", err) } if settings.Plan == nil || settings.Plan.WorkflowDefinitionKey != workflowdef.OfficialKeyMain { t.Fatalf("expected saved plan, got %+v", settings.Plan) } preview, err := svc.ActivationPreview(ctx, 42, 1, true) if err != nil { t.Fatalf("ActivationPreview: %v", err) } if preview.ConfirmationToken == "" || preview.PlanHash == "" { t.Fatal("expected confirmation token and plan hash") } result, err := svc.Activate(ctx, 42, 1, true, ActivateInput{ ConfirmationToken: preview.ConfirmationToken, ExpectedProjectVersion: preview.ExpectedProjectVersion, ExpectedPlanRevision: preview.ExpectedPlanRevision, }) if err != nil { t.Fatalf("Activate: %v", err) } if result.LifecycleStatus != LifecycleActive || result.ActiveWorkflowKey != workflowdef.OfficialKeyMain { t.Fatalf("unexpected activate result: %+v", result) } live, _ := store.HasLiveInstance(ctx, 42) if !live { t.Fatal("expected live instance after activation") } } func TestService_BlockPlanEditWhenActive(t *testing.T) { ctx := context.Background() store := newMemStore() _ = SeedProjectMeta(store, 7, LifecycleActive, "main", 2, 1) svc := NewService(store, testResolver(), nil, nil) _, err := svc.SaveWorkflowPlan(ctx, 7, 1, true, SavePlanInput{ Plan: validPlan(), ExpectedPlanRevision: 1, }) if !errors.Is(err, ErrPlanFrozen) { t.Fatalf("expected ErrPlanFrozen, got %v", err) } } func TestService_SeparationOfDutyValidation(t *testing.T) { bad := validPlan() bad.Stages[0].DocTasks[0].Duties.ReviewerUserID = 1 res := validatePlan(bad, testResolver().versions[workflowdef.OfficialKeyMain]) if res.Valid { t.Fatal("expected separation of duty violation") } } func TestService_SavePlanReturnsValidationIssues(t *testing.T) { ctx := context.Background() store := newMemStore() _ = SeedProjectMeta(store, 8, LifecyclePlanning, "", 1, 0) svc := NewService(store, testResolver(), nil, nil) bad := validPlan() bad.Stages[0].DocTasks[0].Duties = DocDuty{} _, err := svc.SaveWorkflowPlan(ctx, 8, 1, true, SavePlanInput{ Plan: bad, ExpectedPlanRevision: 0, ExpectedSelectionVersion: 1, }) var validationErr *ValidationError if !errors.As(err, &validationErr) { t.Fatalf("expected ValidationError, got %v", err) } if len(validationErr.Issues) != 3 { t.Fatalf("expected three missing-duty issues, got %+v", validationErr.Issues) } }