101 lines
3.1 KiB
Go
101 lines
3.1 KiB
Go
package skill
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func writeSkill(t *testing.T, root, dirName, frontmatter, body string) {
|
|
t.Helper()
|
|
dir := filepath.Join(root, dirName)
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
content := "---\n" + frontmatter + "---\n\n" + body
|
|
if err := os.WriteFile(filepath.Join(dir, "SKILL.md"), []byte(content), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestDiscover_ParsesFrontmatterAndBody(t *testing.T) {
|
|
root := t.TempDir()
|
|
writeSkill(t, root, "refactoring",
|
|
"name: refactoring\ndescription: Vorgehen für größere Refactorings.\n",
|
|
"# Refactoring\n\nSchritt 1: Tests lesen.\n")
|
|
|
|
skills, err := Discover([]string{root})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(skills) != 1 {
|
|
t.Fatalf("got %d skills, want 1", len(skills))
|
|
}
|
|
s := skills[0]
|
|
if s.Name != "refactoring" {
|
|
t.Errorf("name = %q", s.Name)
|
|
}
|
|
if s.Description != "Vorgehen für größere Refactorings." {
|
|
t.Errorf("description = %q", s.Description)
|
|
}
|
|
if !strings.Contains(s.Body, "Schritt 1: Tests lesen.") {
|
|
t.Errorf("body missing expected content: %q", s.Body)
|
|
}
|
|
if strings.Contains(s.Body, "---") {
|
|
t.Errorf("body should not contain frontmatter delimiters: %q", s.Body)
|
|
}
|
|
}
|
|
|
|
func TestDiscover_LaterPathOverridesEarlierByName(t *testing.T) {
|
|
global := t.TempDir()
|
|
project := t.TempDir()
|
|
writeSkill(t, global, "refactoring", "name: refactoring\ndescription: global version\n", "global body")
|
|
writeSkill(t, project, "refactoring", "name: refactoring\ndescription: project version\n", "project body")
|
|
|
|
skills, err := Discover([]string{global, project})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(skills) != 1 {
|
|
t.Fatalf("got %d skills, want 1 (deduped by name)", len(skills))
|
|
}
|
|
if skills[0].Description != "project version" {
|
|
t.Errorf("description = %q, want project version to win (later path)", skills[0].Description)
|
|
}
|
|
}
|
|
|
|
func TestDiscover_MissingPathIsSkippedNotError(t *testing.T) {
|
|
skills, err := Discover([]string{"/does/not/exist/at/all"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(skills) != 0 {
|
|
t.Errorf("got %d skills, want 0", len(skills))
|
|
}
|
|
}
|
|
|
|
// TestRenderIndex_OmitsBody ist das M5-Fertig-Kriterium aus Abschnitt 6: ein
|
|
// Skill wird erst bei Bedarf geladen — der Index darf nur Name+Description
|
|
// enthalten, ein Token-Delta zum vollen Body muss messbar sein.
|
|
func TestRenderIndex_OmitsBody(t *testing.T) {
|
|
root := t.TempDir()
|
|
longBody := strings.Repeat("Dies ist eine lange Anleitung. ", 200) // ~1400 Zeichen
|
|
writeSkill(t, root, "refactoring", "name: refactoring\ndescription: kurze Beschreibung\n", longBody)
|
|
|
|
skills, err := Discover([]string{root})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
index := RenderIndex(skills)
|
|
if strings.Contains(index, longBody) {
|
|
t.Fatal("index must not contain the full skill body")
|
|
}
|
|
if !strings.Contains(index, "refactoring") || !strings.Contains(index, "kurze Beschreibung") {
|
|
t.Errorf("index missing name/description: %q", index)
|
|
}
|
|
if len(index) >= len(longBody) {
|
|
t.Errorf("index (%d bytes) should be far smaller than the body (%d bytes)", len(index), len(longBody))
|
|
}
|
|
}
|