ollie/skills/skills_test.go

161 lines
3.4 KiB
Go

package skills
import (
"os"
"path/filepath"
"testing"
)
func TestLoadSkill(t *testing.T) {
// Create a temp skill
dir := t.TempDir()
skillDir := filepath.Join(dir, "test-skill")
os.MkdirAll(skillDir, 0755)
content := `---
name: test-skill
description: A test skill for unit testing. Use when testing skill loading.
---
# Test Skill
This is test content.
`
os.WriteFile(filepath.Join(skillDir, "SKILL.md"), []byte(content), 0644)
skill, err := loadSkill(filepath.Join(skillDir, "SKILL.md"))
if err != nil {
t.Fatalf("loadSkill: %v", err)
}
if skill.Name != "test-skill" {
t.Errorf("name = %q, want %q", skill.Name, "test-skill")
}
if skill.Description != "A test skill for unit testing. Use when testing skill loading." {
t.Errorf("description = %q", skill.Description)
}
}
func TestParseFrontmatter(t *testing.T) {
tests := []struct {
name string
input string
wantN string
wantD string
wantErr bool
}{
{
name: "valid",
input: `---
name: my-skill
description: My description
---
content`,
wantN: "my-skill",
wantD: "My description",
},
{
name: "no frontmatter",
input: "# Just content",
wantErr: true,
},
{
name: "missing name",
input: `---
description: test
---`,
wantErr: true,
},
{
name: "missing description",
input: `---
name: test
---`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
n, d, err := parseFrontmatter([]byte(tt.input))
if tt.wantErr {
if err == nil {
t.Error("expected error")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if n != tt.wantN {
t.Errorf("name = %q, want %q", n, tt.wantN)
}
if d != tt.wantD {
t.Errorf("description = %q, want %q", d, tt.wantD)
}
})
}
}
func TestIndexMatch(t *testing.T) {
// Find model directory
home, _ := os.UserHomeDir()
modelDir := ""
candidates := []string{
"../data/models",
filepath.Join(home, ".local/share/ollie/models"),
}
for _, c := range candidates {
if _, err := os.Stat(filepath.Join(c, "model.onnx")); err == nil {
modelDir = c
break
}
}
if modelDir == "" {
t.Skip("model not found")
}
// Create temp skill directory
dir := t.TempDir()
skills := []struct {
name string
desc string
}{
{"jira-cli", "Interact with Jira for issue tracking. Use for tickets, sprints, and project management."},
{"github-cli", "Interact with GitHub repositories, issues, and pull requests."},
{"bash-exec", "Execute bash commands locally or remotely."},
}
for _, s := range skills {
skillDir := filepath.Join(dir, s.name)
os.MkdirAll(skillDir, 0755)
content := "---\nname: " + s.name + "\ndescription: " + s.desc + "\n---\n# " + s.name
os.WriteFile(filepath.Join(skillDir, "SKILL.md"), []byte(content), 0644)
}
idx, err := NewIndex(modelDir, []string{dir})
if err != nil {
t.Fatalf("NewIndex: %v", err)
}
defer idx.Close()
// Test matching
results, err := idx.Match("create a jira ticket for the bug", 0.1, 3)
if err != nil {
t.Fatalf("Match: %v", err)
}
if len(results) == 0 {
t.Fatal("expected results")
}
t.Logf("Query: 'create a jira ticket for the bug'")
for _, r := range results {
t.Logf(" %s: %.4f", r.Skill.Name, r.Score)
}
// Jira should be top result
if results[0].Skill.Name != "jira-cli" {
t.Errorf("expected jira-cli as top result, got %s", results[0].Skill.Name)
}
}