registry_test.go
1 package skills 2 3 import "testing" 4 5 func TestRequiredSecrets_OpenClaw(t *testing.T) { 6 s := &Skill{ 7 Metadata: map[string]any{ 8 "openclaw": map[string]any{ 9 "requires": map[string]any{ 10 "env": []any{"GEMINI_API_KEY", "ANOTHER_KEY"}, 11 }, 12 }, 13 }, 14 } 15 secrets := s.RequiredSecrets() 16 if len(secrets) != 2 { 17 t.Fatalf("expected 2 secrets, got %d", len(secrets)) 18 } 19 if secrets[0].Key != "GEMINI_API_KEY" { 20 t.Errorf("expected key GEMINI_API_KEY, got %s", secrets[0].Key) 21 } 22 if secrets[0].Label != "GEMINI_API_KEY" { 23 t.Errorf("expected label GEMINI_API_KEY, got %s", secrets[0].Label) 24 } 25 if !secrets[0].Required { 26 t.Error("expected required=true") 27 } 28 } 29 30 func TestRequiredSecrets_Clawdbot(t *testing.T) { 31 s := &Skill{ 32 Metadata: map[string]any{ 33 "clawdbot": map[string]any{ 34 "requires": map[string]any{ 35 "env": []any{"KIE_API_KEY"}, 36 }, 37 }, 38 }, 39 } 40 secrets := s.RequiredSecrets() 41 if len(secrets) != 1 { 42 t.Fatalf("expected 1 secret, got %d", len(secrets)) 43 } 44 if secrets[0].Key != "KIE_API_KEY" { 45 t.Errorf("expected key KIE_API_KEY, got %s", secrets[0].Key) 46 } 47 } 48 49 // TestRequiredSecrets_Clawdis covers the third interchangeable parent 50 // key accepted by the ClawHub spec. Rarely used in practice but 51 // documented — skills that do use it must parse correctly. 52 func TestRequiredSecrets_Clawdis(t *testing.T) { 53 s := &Skill{ 54 Metadata: map[string]any{ 55 "clawdis": map[string]any{ 56 "requires": map[string]any{ 57 "env": []any{"SOME_API_KEY"}, 58 }, 59 }, 60 }, 61 } 62 secrets := s.RequiredSecrets() 63 if len(secrets) != 1 { 64 t.Fatalf("expected 1 secret, got %d", len(secrets)) 65 } 66 if secrets[0].Key != "SOME_API_KEY" { 67 t.Errorf("expected key SOME_API_KEY, got %s", secrets[0].Key) 68 } 69 } 70 71 func TestRequiredSecrets_BothSourcesMerged(t *testing.T) { 72 s := &Skill{ 73 Metadata: map[string]any{ 74 "openclaw": map[string]any{ 75 "requires": map[string]any{ 76 "env": []any{"SHARED_KEY", "OPENCLAW_ONLY"}, 77 }, 78 }, 79 "clawdbot": map[string]any{ 80 "requires": map[string]any{ 81 "env": []any{"SHARED_KEY", "CLAWDBOT_ONLY"}, 82 }, 83 }, 84 }, 85 } 86 secrets := s.RequiredSecrets() 87 if len(secrets) != 3 { 88 t.Fatalf("expected 3 secrets (deduplicated), got %d", len(secrets)) 89 } 90 keys := map[string]bool{} 91 for _, s := range secrets { 92 keys[s.Key] = true 93 } 94 for _, expected := range []string{"SHARED_KEY", "OPENCLAW_ONLY", "CLAWDBOT_ONLY"} { 95 if !keys[expected] { 96 t.Errorf("missing expected key %s", expected) 97 } 98 } 99 } 100 101 // TestRequiredSecrets_AllThreeSourcesMerged covers the three-way dedup 102 // path when a skill author declares the same key under multiple 103 // interchangeable parent aliases (openclaw / clawdbot / clawdis). 104 func TestRequiredSecrets_AllThreeSourcesMerged(t *testing.T) { 105 s := &Skill{ 106 Metadata: map[string]any{ 107 "openclaw": map[string]any{ 108 "requires": map[string]any{"env": []any{"SHARED"}}, 109 }, 110 "clawdbot": map[string]any{ 111 "requires": map[string]any{"env": []any{"SHARED", "CLAWDBOT_ONLY"}}, 112 }, 113 "clawdis": map[string]any{ 114 "requires": map[string]any{"env": []any{"SHARED", "CLAWDIS_ONLY"}}, 115 }, 116 }, 117 } 118 secrets := s.RequiredSecrets() 119 if len(secrets) != 3 { 120 t.Fatalf("expected 3 deduplicated secrets, got %d: %v", len(secrets), secrets) 121 } 122 keys := map[string]bool{} 123 for _, s := range secrets { 124 keys[s.Key] = true 125 } 126 for _, expected := range []string{"SHARED", "CLAWDBOT_ONLY", "CLAWDIS_ONLY"} { 127 if !keys[expected] { 128 t.Errorf("missing expected key %s", expected) 129 } 130 } 131 } 132 133 func TestRequiredSecrets_NoMetadata(t *testing.T) { 134 s := &Skill{} 135 secrets := s.RequiredSecrets() 136 if len(secrets) != 0 { 137 t.Fatalf("expected 0 secrets, got %d", len(secrets)) 138 } 139 } 140 141 func TestRequiredSecrets_MalformedMetadata(t *testing.T) { 142 s := &Skill{ 143 Metadata: map[string]any{ 144 "openclaw": "not-a-map", 145 }, 146 } 147 secrets := s.RequiredSecrets() 148 if len(secrets) != 0 { 149 t.Fatalf("expected 0 secrets on malformed metadata, got %d", len(secrets)) 150 } 151 }