nub/internal/skill/skill_test.go
Tom a97013d876 initial commit
- v 0.1.0 siehe CHANGELOG.md
2026-07-25 11:08:01 +02:00

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))
}
}