fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
626
ai-compliance-sdk/internal/api/handlers/ucca_handlers_test.go
Normal file
626
ai-compliance-sdk/internal/api/handlers/ucca_handlers_test.go
Normal file
@@ -0,0 +1,626 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/ucca"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gin.SetMode(gin.TestMode)
|
||||
}
|
||||
|
||||
// getProjectRoot returns the project root directory
|
||||
func getProjectRoot(t *testing.T) string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get working directory: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
||||
return dir
|
||||
}
|
||||
parent := filepath.Dir(dir)
|
||||
if parent == dir {
|
||||
t.Fatalf("Could not find project root (no go.mod found)")
|
||||
}
|
||||
dir = parent
|
||||
}
|
||||
}
|
||||
|
||||
// mockTenantContext sets up a gin context with tenant ID
|
||||
func mockTenantContext(c *gin.Context, tenantID, userID uuid.UUID) {
|
||||
c.Set("tenant_id", tenantID)
|
||||
c.Set("user_id", userID)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Policy Engine Integration Tests (No DB)
|
||||
// ============================================================================
|
||||
|
||||
func TestUCCAHandlers_ListPatterns(t *testing.T) {
|
||||
root := getProjectRoot(t)
|
||||
policyPath := filepath.Join(root, "policies", "ucca_policy_v1.yaml")
|
||||
|
||||
engine, err := ucca.NewPolicyEngineFromPath(policyPath)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test - could not load policy engine: %v", err)
|
||||
}
|
||||
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: engine,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListPatterns(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
patterns, ok := response["patterns"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected patterns array in response")
|
||||
}
|
||||
|
||||
if len(patterns) == 0 {
|
||||
t.Error("Expected at least some patterns")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListControls(t *testing.T) {
|
||||
root := getProjectRoot(t)
|
||||
policyPath := filepath.Join(root, "policies", "ucca_policy_v1.yaml")
|
||||
|
||||
engine, err := ucca.NewPolicyEngineFromPath(policyPath)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test - could not load policy engine: %v", err)
|
||||
}
|
||||
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: engine,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListControls(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
controls, ok := response["controls"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected controls array in response")
|
||||
}
|
||||
|
||||
if len(controls) == 0 {
|
||||
t.Error("Expected at least some controls")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListRules(t *testing.T) {
|
||||
root := getProjectRoot(t)
|
||||
policyPath := filepath.Join(root, "policies", "ucca_policy_v1.yaml")
|
||||
|
||||
engine, err := ucca.NewPolicyEngineFromPath(policyPath)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test - could not load policy engine: %v", err)
|
||||
}
|
||||
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: engine,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListRules(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
rules, ok := response["rules"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected rules array in response")
|
||||
}
|
||||
|
||||
if len(rules) == 0 {
|
||||
t.Error("Expected at least some rules")
|
||||
}
|
||||
|
||||
// Check that policy version is returned
|
||||
if _, ok := response["policy_version"]; !ok {
|
||||
t.Error("Expected policy_version in response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListExamples(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListExamples(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
examples, ok := response["examples"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected examples array in response")
|
||||
}
|
||||
|
||||
if len(examples) == 0 {
|
||||
t.Error("Expected at least some examples")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListProblemSolutions_WithEngine(t *testing.T) {
|
||||
root := getProjectRoot(t)
|
||||
policyPath := filepath.Join(root, "policies", "ucca_policy_v1.yaml")
|
||||
|
||||
engine, err := ucca.NewPolicyEngineFromPath(policyPath)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test - could not load policy engine: %v", err)
|
||||
}
|
||||
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: engine,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListProblemSolutions(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
if _, ok := response["problem_solutions"]; !ok {
|
||||
t.Error("Expected problem_solutions in response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListProblemSolutions_WithoutEngine(t *testing.T) {
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: nil,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListProblemSolutions(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
if _, ok := response["message"]; !ok {
|
||||
t.Error("Expected message when policy engine not available")
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Request Validation Tests
|
||||
// ============================================================================
|
||||
|
||||
func TestUCCAHandlers_Assess_MissingTenantID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest("POST", "/assess", nil)
|
||||
|
||||
// Don't set tenant ID
|
||||
handler.Assess(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_Assess_InvalidJSON(t *testing.T) {
|
||||
root := getProjectRoot(t)
|
||||
policyPath := filepath.Join(root, "policies", "ucca_policy_v1.yaml")
|
||||
|
||||
engine, _ := ucca.NewPolicyEngineFromPath(policyPath)
|
||||
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: engine,
|
||||
legacyRuleEngine: ucca.NewRuleEngine(),
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest("POST", "/assess", bytes.NewBufferString("invalid json"))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
c.Set("tenant_id", uuid.New())
|
||||
c.Set("user_id", uuid.New())
|
||||
|
||||
handler.Assess(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400 for invalid JSON, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_GetAssessment_InvalidID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Params = gin.Params{{Key: "id", Value: "not-a-uuid"}}
|
||||
c.Request = httptest.NewRequest("GET", "/assessments/not-a-uuid", nil)
|
||||
|
||||
handler.GetAssessment(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400 for invalid ID, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_DeleteAssessment_InvalidID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Params = gin.Params{{Key: "id", Value: "invalid"}}
|
||||
c.Request = httptest.NewRequest("DELETE", "/assessments/invalid", nil)
|
||||
|
||||
handler.DeleteAssessment(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400 for invalid ID, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_Export_InvalidID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Params = gin.Params{{Key: "id", Value: "not-valid"}}
|
||||
c.Request = httptest.NewRequest("GET", "/export/not-valid", nil)
|
||||
|
||||
handler.Export(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400 for invalid ID, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_Explain_InvalidID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Params = gin.Params{{Key: "id", Value: "bad-id"}}
|
||||
c.Request = httptest.NewRequest("POST", "/assessments/bad-id/explain", nil)
|
||||
|
||||
handler.Explain(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400 for invalid ID, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListAssessments_MissingTenantID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest("GET", "/assessments", nil)
|
||||
|
||||
handler.ListAssessments(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_GetStats_MissingTenantID(t *testing.T) {
|
||||
handler := &UCCAHandlers{}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest("GET", "/stats", nil)
|
||||
|
||||
handler.GetStats(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("Expected status 400, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Markdown Export Generation Tests
|
||||
// ============================================================================
|
||||
|
||||
func TestGenerateMarkdownExport(t *testing.T) {
|
||||
assessment := &ucca.Assessment{
|
||||
ID: uuid.New(),
|
||||
Title: "Test Assessment",
|
||||
Domain: ucca.DomainEducation,
|
||||
Feasibility: ucca.FeasibilityCONDITIONAL,
|
||||
RiskLevel: ucca.RiskLevelMEDIUM,
|
||||
RiskScore: 45,
|
||||
Complexity: ucca.ComplexityMEDIUM,
|
||||
TriggeredRules: []ucca.TriggeredRule{
|
||||
{Code: "R-A001", Title: "Test Rule", Severity: "WARN", ScoreDelta: 10},
|
||||
},
|
||||
RequiredControls: []ucca.RequiredControl{
|
||||
{ID: "C-001", Title: "Test Control", Description: "Test Description"},
|
||||
},
|
||||
DSFARecommended: true,
|
||||
Art22Risk: false,
|
||||
TrainingAllowed: ucca.TrainingCONDITIONAL,
|
||||
PolicyVersion: "1.0.0",
|
||||
}
|
||||
|
||||
markdown := generateMarkdownExport(assessment)
|
||||
|
||||
// Check for expected content
|
||||
if markdown == "" {
|
||||
t.Error("Expected non-empty markdown")
|
||||
}
|
||||
|
||||
expectedContents := []string{
|
||||
"# UCCA Use-Case Assessment",
|
||||
"CONDITIONAL",
|
||||
"MEDIUM",
|
||||
"45/100",
|
||||
"Test Rule",
|
||||
"Test Control",
|
||||
"DSFA",
|
||||
"1.0.0",
|
||||
}
|
||||
|
||||
for _, expected := range expectedContents {
|
||||
if !bytes.Contains([]byte(markdown), []byte(expected)) {
|
||||
t.Errorf("Expected markdown to contain '%s'", expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateMarkdownExport_WithExplanation(t *testing.T) {
|
||||
explanation := "Dies ist eine KI-generierte Erklärung."
|
||||
assessment := &ucca.Assessment{
|
||||
ID: uuid.New(),
|
||||
Feasibility: ucca.FeasibilityYES,
|
||||
RiskLevel: ucca.RiskLevelMINIMAL,
|
||||
RiskScore: 10,
|
||||
ExplanationText: &explanation,
|
||||
PolicyVersion: "1.0.0",
|
||||
}
|
||||
|
||||
markdown := generateMarkdownExport(assessment)
|
||||
|
||||
if !bytes.Contains([]byte(markdown), []byte("KI-Erklärung")) {
|
||||
t.Error("Expected markdown to contain explanation section")
|
||||
}
|
||||
|
||||
if !bytes.Contains([]byte(markdown), []byte(explanation)) {
|
||||
t.Error("Expected markdown to contain the explanation text")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateMarkdownExport_WithForbiddenPatterns(t *testing.T) {
|
||||
assessment := &ucca.Assessment{
|
||||
ID: uuid.New(),
|
||||
Feasibility: ucca.FeasibilityNO,
|
||||
RiskLevel: ucca.RiskLevelHIGH,
|
||||
RiskScore: 85,
|
||||
ForbiddenPatterns: []ucca.ForbiddenPattern{
|
||||
{PatternID: "FP-001", Title: "Forbidden Pattern", Reason: "Not allowed"},
|
||||
},
|
||||
PolicyVersion: "1.0.0",
|
||||
}
|
||||
|
||||
markdown := generateMarkdownExport(assessment)
|
||||
|
||||
if !bytes.Contains([]byte(markdown), []byte("Verbotene Patterns")) {
|
||||
t.Error("Expected markdown to contain forbidden patterns section")
|
||||
}
|
||||
|
||||
if !bytes.Contains([]byte(markdown), []byte("Not allowed")) {
|
||||
t.Error("Expected markdown to contain forbidden pattern reason")
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Explanation Prompt Building Tests
|
||||
// ============================================================================
|
||||
|
||||
func TestBuildExplanationPrompt(t *testing.T) {
|
||||
assessment := &ucca.Assessment{
|
||||
Feasibility: ucca.FeasibilityCONDITIONAL,
|
||||
RiskLevel: ucca.RiskLevelMEDIUM,
|
||||
RiskScore: 50,
|
||||
Complexity: ucca.ComplexityMEDIUM,
|
||||
TriggeredRules: []ucca.TriggeredRule{
|
||||
{Code: "R-001", Title: "Test", Severity: "WARN"},
|
||||
},
|
||||
RequiredControls: []ucca.RequiredControl{
|
||||
{Title: "Control", Description: "Desc"},
|
||||
},
|
||||
DSFARecommended: true,
|
||||
Art22Risk: true,
|
||||
}
|
||||
|
||||
prompt := buildExplanationPrompt(assessment, "de", "")
|
||||
|
||||
// Check prompt contains expected elements
|
||||
expectedElements := []string{
|
||||
"CONDITIONAL",
|
||||
"MEDIUM",
|
||||
"50/100",
|
||||
"Ausgelöste Regeln",
|
||||
"Erforderliche Maßnahmen",
|
||||
"DSFA",
|
||||
"Art. 22",
|
||||
}
|
||||
|
||||
for _, expected := range expectedElements {
|
||||
if !bytes.Contains([]byte(prompt), []byte(expected)) {
|
||||
t.Errorf("Expected prompt to contain '%s'", expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildExplanationPrompt_WithLegalContext(t *testing.T) {
|
||||
assessment := &ucca.Assessment{
|
||||
Feasibility: ucca.FeasibilityYES,
|
||||
RiskLevel: ucca.RiskLevelLOW,
|
||||
RiskScore: 15,
|
||||
Complexity: ucca.ComplexityLOW,
|
||||
}
|
||||
|
||||
legalContext := "**Relevante Rechtsgrundlagen:**\nArt. 6 DSGVO - Rechtmäßigkeit"
|
||||
|
||||
prompt := buildExplanationPrompt(assessment, "de", legalContext)
|
||||
|
||||
if !bytes.Contains([]byte(prompt), []byte("Relevante Rechtsgrundlagen")) {
|
||||
t.Error("Expected prompt to contain legal context")
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Legacy Rule Engine Fallback Tests
|
||||
// ============================================================================
|
||||
|
||||
func TestUCCAHandlers_ListRules_LegacyFallback(t *testing.T) {
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: nil, // No YAML engine
|
||||
legacyRuleEngine: ucca.NewRuleEngine(),
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListRules(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
// Should have legacy policy version
|
||||
policyVersion, ok := response["policy_version"].(string)
|
||||
if !ok {
|
||||
t.Fatal("Expected policy_version string")
|
||||
}
|
||||
|
||||
if policyVersion != "1.0.0-legacy" {
|
||||
t.Errorf("Expected legacy policy version, got %s", policyVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListPatterns_LegacyFallback(t *testing.T) {
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: nil, // No YAML engine
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListPatterns(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
patterns, ok := response["patterns"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected patterns array in response")
|
||||
}
|
||||
|
||||
// Legacy patterns should still be returned
|
||||
if len(patterns) == 0 {
|
||||
t.Error("Expected at least some legacy patterns")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUCCAHandlers_ListControls_LegacyFallback(t *testing.T) {
|
||||
handler := &UCCAHandlers{
|
||||
policyEngine: nil, // No YAML engine
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
|
||||
handler.ListControls(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("Expected status 200, got %d", w.Code)
|
||||
}
|
||||
|
||||
var response map[string]interface{}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("Failed to parse response: %v", err)
|
||||
}
|
||||
|
||||
controls, ok := response["controls"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatal("Expected controls array in response")
|
||||
}
|
||||
|
||||
// Legacy controls should still be returned
|
||||
if len(controls) == 0 {
|
||||
t.Error("Expected at least some legacy controls")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user