// +build integration package tests import ( "context" "encoding/json" "os" "testing" "time" "github.com/rockliang/poimen/workflows/internal/routing" "github.com/stretchr/testify/require" ) // TestRoutingE2E_GenerateAndValidate tests full flow against real api.riotpiao.com // Run with: go test -tags=integration -v -run TestRoutingE2E ./tests/... func TestRoutingE2E_GenerateAndValidate(t *testing.T) { if os.Getenv("RUN_INTEGRATION_TESTS") != "1" { t.Skip("Skipping integration test. Set RUN_INTEGRATION_TESTS=1 to run.") } // Load knowledge base kb, err := routing.LoadKnowledgeBaseFromDefaultPath() require.NoError(t, err, "failed to load knowledge base") // Create router router, err := routing.NewLLMRouter(kb) require.NoError(t, err, "failed to create router") // Create validator validator := routing.NewValidator(kb) tests := []struct { name string message string context map[string]interface{} isCron bool }{ { name: "one-time repo analysis", message: "Analyze https://github.com/rockliang/poimen for code quality and security issues", context: map[string]interface{}{"branch": "main"}, isCron: false, }, { name: "scheduled security scan", message: "Run daily security scan at 3 AM on https://github.com/rockliang/poimen", isCron: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() // Generate workflow spec input := routing.LLMRouterInput{ Message: tt.message, Context: tt.context, } output, err := router.Route(ctx, input) require.NoError(t, err, "LLM router failed") // Log generated spec specJSON, _ := json.MarshalIndent(output, "", " ") t.Logf("Generated spec:\n%s", string(specJSON)) // Validate based on type if tt.isCron { require.True(t, output.IsCron, "expected cron workflow") require.NotNil(t, output.CronSpec, "cron spec is nil") require.NotEmpty(t, output.CronSpec.Schedule, "cron schedule is empty") result := validator.ValidateCronWorkflowSpec(output.CronSpec) require.True(t, result.Valid, "validation failed: %v", result.Errors) t.Logf("Cron workflow validated: %s (schedule: %s)", output.CronSpec.Name, output.CronSpec.Schedule) } else { require.False(t, output.IsCron, "expected one-time workflow") require.NotNil(t, output.Spec, "spec is nil") result := validator.ValidateWorkflowSpec(output.Spec) require.True(t, result.Valid, "validation failed: %v", result.Errors) t.Logf("One-time workflow validated: %s (%d states)", output.Spec.Name, len(output.Spec.States)) } }) } } // TestRoutingE2E_FullPipeline tests LLM router -> validation -> (simulated) execution func TestRoutingE2E_FullPipeline(t *testing.T) { if os.Getenv("RUN_INTEGRATION_TESTS") != "1" { t.Skip("Skipping integration test. Set RUN_INTEGRATION_TESTS=1 to run.") } kb, err := routing.LoadKnowledgeBaseFromDefaultPath() require.NoError(t, err) router, err := routing.NewLLMRouter(kb) require.NoError(t, err) validator := routing.NewValidator(kb) ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) defer cancel() // Generate workflow output, err := router.Route(ctx, routing.LLMRouterInput{ Message: "Clone and analyze https://github.com/rockliang/poimen for security vulnerabilities", }) require.NoError(t, err) require.False(t, output.IsCron) require.NotNil(t, output.Spec) // Validate result := validator.ValidateWorkflowSpec(output.Spec) require.True(t, result.Valid, "validation failed: %v", result.Errors) // Verify structure require.NotEmpty(t, output.Spec.Name) require.NotEmpty(t, output.Spec.States) // First state should be CloneRepoActivity require.Equal(t, "CloneRepoActivity", output.Spec.States[0].Resource, "expected first activity to be CloneRepoActivity") // Check that flaky activities have retry policies for _, state := range output.Spec.States { if state.Type == routing.StateTypeTask { if kb.IsFlaky(state.Resource) { require.NotNil(t, state.Retry, "flaky activity %s should have retry policy", state.Resource) require.GreaterOrEqual(t, state.Retry.MaxAttempts, int32(2), "flaky activity %s should have at least 2 retries", state.Resource) } } } t.Logf("Full pipeline test passed: %s with %d states", output.Spec.Name, len(output.Spec.States)) }