package skills import ( "os" "path/filepath" "testing" ) func TestParseSkillWithYAML(t *testing.T) { data := []byte(`--- name: test-skill description: A test skill author: test version: "1.0" target: both tags: - test - demo --- # Test Skill Content This is the body. `) skill, err := parseSkill(data) if err != nil { t.Fatalf("parseSkill failed: %v", err) } if skill.Description != "A test skill" { t.Errorf("Expected 'A test skill', got %s", skill.Description) } if skill.Author != "test" { t.Errorf("Expected 'test', got %s", skill.Author) } if skill.Version != "1.0" { t.Errorf("Expected '1.0', got %s", skill.Version) } if skill.Target != "both" { t.Errorf("Expected 'both', got %s", skill.Target) } if len(skill.Tags) != 2 { t.Errorf("Expected 2 tags, got %d", len(skill.Tags)) } if skill.Content == "" { t.Error("Content should not be empty") } } func TestParseSkillNoFrontmatter(t *testing.T) { data := []byte("Just plain content here") skill, err := parseSkill(data) if err != nil { t.Fatalf("parseSkill failed: %v", err) } if skill.Content != "Just plain content here" { t.Errorf("Unexpected content: %s", skill.Content) } } func TestParseSkillIncompleteFrontmatter(t *testing.T) { data := []byte("---\nname: incomplete\n---\nBody content") skill, err := parseSkill(data) if err != nil { t.Fatalf("parseSkill failed: %v", err) } if skill.Content != "Body content" { t.Errorf("Expected 'Body content', got %s", skill.Content) } } func TestRenderSkill(t *testing.T) { skill := &Skill{ Name: "test", Description: "A test", Author: "author", Version: "1.0", Target: "both", Tags: []string{"a", "b"}, Content: "Body", } rendered := renderSkill(skill) if rendered == "" { t.Error("Rendered skill should not be empty") } if len(rendered) < 20 { t.Error("Rendered skill seems too short") } } func TestListEmpty(t *testing.T) { tmpDir := t.TempDir() origHome := os.Getenv("HOME") os.Setenv("HOME", tmpDir) defer os.Setenv("HOME", origHome) skills, err := List() if err != nil { t.Fatalf("List failed: %v", err) } if len(skills) != 0 { t.Errorf("Expected 0 skills, got %d", len(skills)) } } func TestCreateAndGet(t *testing.T) { tmpDir := t.TempDir() origHome := os.Getenv("HOME") os.Setenv("HOME", tmpDir) defer os.Setenv("HOME", origHome) skill := &Skill{ Name: "test-skill", Description: "Test description", Content: "Test content body", Author: "tester", Version: "0.1", Target: "both", } if err := Create(skill); err != nil { t.Fatalf("Create failed: %v", err) } dir, _ := SkillsDir() skillPath := filepath.Join(dir, "test-skill", "SKILL.md") if _, err := os.Stat(skillPath); os.IsNotExist(err) { t.Error("Skill file should exist") } got, err := Get("test-skill") if err != nil { t.Fatalf("Get failed: %v", err) } if got.Name != "test-skill" { t.Errorf("Expected test-skill, got %s", got.Name) } } func TestDelete(t *testing.T) { tmpDir := t.TempDir() origHome := os.Getenv("HOME") os.Setenv("HOME", tmpDir) defer os.Setenv("HOME", origHome) skill := &Skill{ Name: "to-delete", Description: "Will be deleted", Content: "content", Target: "both", } Create(skill) if err := Delete("to-delete"); err != nil { t.Fatalf("Delete failed: %v", err) } _, err := Get("to-delete") if err == nil { t.Error("Skill should be deleted") } } func TestBuildAIGeneratePrompt(t *testing.T) { prompt := BuildAIGeneratePrompt("docker", "Set up Docker", "both") if prompt == "" { t.Error("Prompt should not be empty") } if len(prompt) < 50 { t.Error("Prompt seems too short") } } func TestInstallBuiltinSkills(t *testing.T) { tmpDir := t.TempDir() origHome := os.Getenv("HOME") os.Setenv("HOME", tmpDir) defer os.Setenv("HOME", origHome) if err := InstallBuiltinSkills(); err != nil { t.Fatalf("InstallBuiltinSkills failed: %v", err) } skills, err := List() if err != nil { t.Fatalf("List failed: %v", err) } if len(skills) == 0 { t.Error("Expected at least one builtin skill") } found := false for _, s := range skills { if s.Name == "env-setup" { found = true } } if !found { t.Error("Expected env-setup skill") } }