package skills import ( "testing" "time" ) func TestCheckActivationNoConditions(t *testing.T) { skill := &Skill{ Name: "test-skill", Description: "A test skill", } result := CheckActivation(skill, []string{"terminal"}) if !result.Active { t.Error("expected skill with no conditions to be active") } } func TestCheckActivationRequiresTools(t *testing.T) { skill := &Skill{ Name: "docker-setup", RequiresTools: []string{"terminal", "docker"}, } result := CheckActivation(skill, []string{"terminal", "docker"}) if !result.Active { t.Error("expected skill to be active when all required tools present") } result = CheckActivation(skill, []string{"terminal"}) if result.Active { t.Error("expected skill to be inactive when required tool missing") } } func TestCheckActivationFallbackForTools(t *testing.T) { skill := &Skill{ Name: "basic-review", FallbackForTools: []string{"crush_run", "claude_run"}, } result := CheckActivation(skill, []string{"terminal"}) if !result.Active { t.Error("expected fallback skill to activate when primary tools absent") } result = CheckActivation(skill, []string{"crush_run", "claude_run"}) if result.Active { t.Error("expected fallback skill to stay inactive when primary tools present") } } func TestFilterActiveSkills(t *testing.T) { skills := []Skill{ {Name: "basic", Description: "basic"}, {Name: "needs-docker", RequiresTools: []string{"docker"}}, {Name: "fallback-review", FallbackForTools: []string{"crush_run"}}, } active := FilterActiveSkills(skills, []string{"terminal"}) if len(active) != 2 { t.Errorf("expected 2 active skills, got %d", len(active)) } } func TestGroupByReadiness(t *testing.T) { skills := []Skill{ {Name: "basic", Description: "basic"}, {Name: "needs-docker", RequiresTools: []string{"docker"}}, } available, needsSetup, unsupported := GroupByReadiness(skills, []string{}) if len(available) != 1 { t.Errorf("expected 1 available, got %d", len(available)) } if len(unsupported) != 1 { t.Errorf("expected 1 unsupported, got %d", len(unsupported)) } _ = needsSetup } func TestAnalyzeConversation(t *testing.T) { snippets := []ConversationSnippet{ {Role: "assistant", Content: "go test ./... -race", Timestamp: time.Now()}, {Role: "assistant", Content: "go test ./... -race -cover", Timestamp: time.Now()}, {Role: "assistant", Content: "go test ./internal/... -v", Timestamp: time.Now()}, } proposals := AnalyzeConversation(snippets) if len(proposals) == 0 { t.Error("expected at least one proposal from recurring patterns") } for _, p := range proposals { if p.Confidence <= 0 { t.Error("expected positive confidence") } if p.CreatedFrom != "conversation" { t.Errorf("expected created_from=conversation, got %s", p.CreatedFrom) } } } func TestCategorize(t *testing.T) { tests := []struct { pattern string want string }{ {"go test", "testing"}, {"docker build", "devops"}, {"git commit", "workflow"}, {"npm test", "testing"}, {"make", "build"}, {"unknown", "general"}, } for _, tt := range tests { got := categorize(tt.pattern) if got != tt.want { t.Errorf("categorize(%q) = %q, want %q", tt.pattern, got, tt.want) } } } func TestImproverAnalyze(t *testing.T) { improver, err := NewSkillImprover() if err != nil { t.Fatalf("new improver: %v", err) } skill := &Skill{ Name: "test-skill", Description: "A test skill", Content: "# Test\n\nSome basic content without structure.", } suggestions, err := improver.Analyze(skill, "") if err != nil { t.Fatalf("analyze: %v", err) } if len(suggestions) == 0 { t.Error("expected improvement suggestions for minimal skill") } } func TestImproverAnalyzeComplete(t *testing.T) { improver, _ := NewSkillImprover() skill := &Skill{ Name: "complete-skill", Description: "A well-structured skill", Content: `# Complete Skill ## Steps 1. Do step one 2. Do step two ## Error Handling - Handle error A - Handle error B ## When to use Use this skill when doing X. `, Tags: []string{"testing", "go"}, } suggestions, _ := improver.Analyze(skill, "testing go code") if len(suggestions) > 2 { t.Errorf("expected few suggestions for complete skill, got %d", len(suggestions)) } }