summaryrefslogtreecommitdiffstats
path: root/skills_test.go
diff options
context:
space:
mode:
authorSimen A. W. Olsen <hello@simenandre.no>2026-10-25 12:41:28 +0100
committerSimen A. W. Olsen <hello@simenandre.no>2026-10-25 12:41:28 +0100
commitc596038adc7cdbd64988e61fee856d533b58c25d (patch)
treea02fde25835416d143ff56b807e640f6a7e9cf82 /skills_test.go
downloadskills-d9973e8dd70531b3a5e9a17ec74f9f582dc499e2.tar.gz
skills-d9973e8dd70531b3a5e9a17ec74f9f582dc499e2.zip
feat: skills, a package manager for agent skillsHEADv0.1.0main
Diffstat (limited to 'skills_test.go')
-rw-r--r--skills_test.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/skills_test.go b/skills_test.go
new file mode 100644
index 0000000..eedf8ae
--- /dev/null
+++ b/skills_test.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestParseSpec(t *testing.T) {
+ for in, want := range map[string]Spec{
+ "anthropics/skills": {URL: "https://github.com/anthropics/skills"},
+ "github:anthropics/skills#main": {URL: "https://github.com/anthropics/skills", Ref: "main"},
+ "git@example.com:me/skills.git#v1": {URL: "ssh://git@example.com/me/skills.git", Ref: "v1"},
+ "example.com:skills": {URL: "ssh://example.com/skills"},
+ "https://example.com/skills.git/": {URL: "https://example.com/skills.git"},
+ "git+https://example.com/skills": {URL: "https://example.com/skills"},
+ "/srv/skills": {URL: "file:///srv/skills"},
+ } {
+ got, err := parseSpec(in)
+ if err != nil || got != want {
+ t.Errorf("parseSpec(%q) = %+v, %v; want %+v", in, got, err, want)
+ }
+ }
+ for _, in := range []string{"", "#main", "skills", "a/b/c"} {
+ if _, err := parseSpec(in); err == nil {
+ t.Errorf("parseSpec(%q) succeeded, want an error", in)
+ }
+ }
+}
+
+func TestFrontmatter(t *testing.T) {
+ fm := frontmatter([]byte("---\nname: \"deploy\"\ndescription: Ship it: now\nmetadata:\n name: nested\n---\n# body\nname: no\n"))
+ if fm["name"] != "deploy" || fm["description"] != "Ship it: now" {
+ t.Errorf("frontmatter = %v", fm)
+ }
+ if fm := frontmatter([]byte("# no front matter\n")); len(fm) != 0 {
+ t.Errorf("frontmatter without front matter = %v", fm)
+ }
+}
+
+func TestDiscover(t *testing.T) {
+ root := t.TempDir()
+ write(t, root, "skills/pdf/SKILL.md", "---\nname: pdf\n---\n")
+ write(t, root, "skills/pdf/nested/SKILL.md", "---\nname: inner\n---\n")
+ write(t, root, "deploy/SKILL.md", "no front matter\n")
+ write(t, root, ".hidden/SKILL.md", "---\nname: hidden\n---\n")
+
+ got, err := discover(root)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(got) != 2 || got[0].Name != "deploy" || got[1].Name != "pdf" || got[1].Path != "skills/pdf" {
+ t.Errorf("discover = %+v", got)
+ }
+
+ write(t, root, "other/SKILL.md", "---\nname: pdf\n---\n")
+ if _, err := discover(root); err == nil {
+ t.Error("discover allowed two skills named pdf")
+ }
+}
+
+func TestLink(t *testing.T) {
+ t.Setenv("XDG_DATA_HOME", t.TempDir())
+ checkout := filepath.Join(dataDir(), "checkouts", "repo", "rev")
+ write(t, checkout, "pdf/SKILL.md", "")
+ write(t, checkout, "xlsx/SKILL.md", "")
+ a := agent{Name: "claude", Home: t.TempDir()}
+ write(t, a.skillsDir(), "mine/SKILL.md", "")
+ ws := &workspace{}
+
+ dirs := map[string]string{"pdf": filepath.Join(checkout, "pdf"), "xlsx": filepath.Join(checkout, "xlsx")}
+ if changes, conflicts, err := ws.link(dirs, []agent{a}); err != nil || len(changes) != 2 || len(conflicts) != 0 {
+ t.Fatalf("link = %v, %v, %v", changes, conflicts, err)
+ }
+ delete(dirs, "xlsx")
+ dirs["mine"] = filepath.Join(checkout, "pdf")
+ changes, conflicts, err := ws.link(dirs, []agent{a})
+ if err != nil || len(changes) != 1 || changes[0].Action != "removed" || len(conflicts) != 1 {
+ t.Fatalf("relink = %v, %v, %v", changes, conflicts, err)
+ }
+ if _, err := os.Stat(filepath.Join(a.skillsDir(), "mine", "SKILL.md")); err != nil {
+ t.Errorf("link touched a skill it did not install: %v", err)
+ }
+}
+
+func write(t *testing.T, root, rel, content string) {
+ t.Helper()
+ path := filepath.Join(root, rel)
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
+ t.Fatal(err)
+ }
+}