170 lines
4.8 KiB
Go
170 lines
4.8 KiB
Go
package skill
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestManager_LoadAll(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
// Create valid skill files.
|
|
os.WriteFile(filepath.Join(dir, "greeting.md"), []byte("---\nname: greeting\ndescription: Say hello\n---\nHello!"), 0o644)
|
|
os.WriteFile(filepath.Join(dir, "farewell.md"), []byte("---\nname: farewell\ndescription: Say bye\n---\nGoodbye!"), 0o644)
|
|
|
|
// Create a non-.md file (should be skipped).
|
|
os.WriteFile(filepath.Join(dir, "notes.txt"), []byte("not a skill"), 0o644)
|
|
|
|
// Create a subdirectory (should be skipped).
|
|
os.MkdirAll(filepath.Join(dir, "subdir"), 0o755)
|
|
|
|
m := NewManager(dir)
|
|
if err := m.LoadAll(); err != nil {
|
|
t.Fatalf("LoadAll: %v", err)
|
|
}
|
|
|
|
skills := m.All()
|
|
if len(skills) != 2 {
|
|
t.Fatalf("loaded %d skills, want 2", len(skills))
|
|
}
|
|
|
|
names := map[string]bool{}
|
|
for _, s := range skills {
|
|
names[s.Name] = true
|
|
}
|
|
if !names["greeting"] {
|
|
t.Error("missing 'greeting' skill")
|
|
}
|
|
if !names["farewell"] {
|
|
t.Error("missing 'farewell' skill")
|
|
}
|
|
}
|
|
|
|
func TestManager_LoadAll_NoFrontmatter(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
// File without frontmatter uses filename as name.
|
|
os.WriteFile(filepath.Join(dir, "plain.md"), []byte("Just content, no frontmatter"), 0o644)
|
|
|
|
m := NewManager(dir)
|
|
if err := m.LoadAll(); err != nil {
|
|
t.Fatalf("LoadAll: %v", err)
|
|
}
|
|
|
|
skills := m.All()
|
|
if len(skills) != 1 {
|
|
t.Fatalf("loaded %d skills, want 1", len(skills))
|
|
}
|
|
if skills[0].Name != "plain" {
|
|
t.Errorf("Name = %q, want 'plain'", skills[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestManager_LoadAll_NonexistentDir(t *testing.T) {
|
|
m := NewManager("/nonexistent/path/that/does/not/exist")
|
|
if err := m.LoadAll(); err != nil {
|
|
t.Fatalf("LoadAll on nonexistent dir should not error, got: %v", err)
|
|
}
|
|
if len(m.All()) != 0 {
|
|
t.Errorf("expected 0 skills from nonexistent dir, got %d", len(m.All()))
|
|
}
|
|
}
|
|
|
|
func TestManager_Activate_Deactivate(t *testing.T) {
|
|
dir := t.TempDir()
|
|
os.WriteFile(filepath.Join(dir, "test.md"), []byte("---\nname: test\n---\nTest content"), 0o644)
|
|
|
|
m := NewManager(dir)
|
|
m.LoadAll()
|
|
|
|
t.Run("activate found", func(t *testing.T) {
|
|
err := m.Activate("test")
|
|
if err != nil {
|
|
t.Fatalf("Activate: %v", err)
|
|
}
|
|
skill := m.All()[0]
|
|
if !skill.Active {
|
|
t.Error("skill should be active after Activate")
|
|
}
|
|
})
|
|
|
|
t.Run("activate not found", func(t *testing.T) {
|
|
err := m.Activate("nonexistent")
|
|
if err == nil {
|
|
t.Error("expected error for nonexistent skill")
|
|
}
|
|
})
|
|
|
|
t.Run("deactivate found", func(t *testing.T) {
|
|
err := m.Deactivate("test")
|
|
if err != nil {
|
|
t.Fatalf("Deactivate: %v", err)
|
|
}
|
|
skill := m.All()[0]
|
|
if skill.Active {
|
|
t.Error("skill should be inactive after Deactivate")
|
|
}
|
|
})
|
|
|
|
t.Run("deactivate not found", func(t *testing.T) {
|
|
err := m.Deactivate("nonexistent")
|
|
if err == nil {
|
|
t.Error("expected error for nonexistent skill")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestManager_ActiveContent(t *testing.T) {
|
|
dir := t.TempDir()
|
|
os.WriteFile(filepath.Join(dir, "alpha.md"), []byte("---\nname: alpha\n---\nAlpha content"), 0o644)
|
|
os.WriteFile(filepath.Join(dir, "beta.md"), []byte("---\nname: beta\n---\nBeta content"), 0o644)
|
|
|
|
m := NewManager(dir)
|
|
m.LoadAll()
|
|
|
|
t.Run("none active returns empty", func(t *testing.T) {
|
|
content := m.ActiveContent()
|
|
if content != "" {
|
|
t.Errorf("expected empty content, got %q", content)
|
|
}
|
|
})
|
|
|
|
t.Run("one active returns its content", func(t *testing.T) {
|
|
m.Activate("alpha")
|
|
content := m.ActiveContent()
|
|
if content == "" {
|
|
t.Fatal("expected non-empty content")
|
|
}
|
|
if !contains(content, "Alpha content") {
|
|
t.Errorf("content missing 'Alpha content': %q", content)
|
|
}
|
|
if contains(content, "Beta content") {
|
|
t.Errorf("content should not contain inactive 'Beta content': %q", content)
|
|
}
|
|
m.Deactivate("alpha")
|
|
})
|
|
|
|
t.Run("multiple active returns combined", func(t *testing.T) {
|
|
m.Activate("alpha")
|
|
m.Activate("beta")
|
|
content := m.ActiveContent()
|
|
if !contains(content, "Alpha content") || !contains(content, "Beta content") {
|
|
t.Errorf("combined content missing expected parts: %q", content)
|
|
}
|
|
})
|
|
}
|
|
|
|
func contains(s, substr string) bool {
|
|
return len(s) >= len(substr) && searchString(s, substr)
|
|
}
|
|
|
|
func searchString(s, substr string) bool {
|
|
for i := 0; i <= len(s)-len(substr); i++ {
|
|
if s[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|