| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import { test, expect } from "bun:test"
- import { Skill } from "../../src/skill"
- import { Instance } from "../../src/project/instance"
- import { tmpdir } from "../fixture/fixture"
- import path from "path"
- import fs from "fs/promises"
- async function createGlobalSkill(homeDir: string) {
- const skillDir = path.join(homeDir, ".claude", "skills", "global-test-skill")
- await fs.mkdir(skillDir, { recursive: true })
- await Bun.write(
- path.join(skillDir, "SKILL.md"),
- `---
- name: global-test-skill
- description: A global skill from ~/.claude/skills for testing.
- ---
- # Global Test Skill
- This skill is loaded from the global home directory.
- `,
- )
- }
- test("discovers skills from .opencode/skill/ directory", async () => {
- await using tmp = await tmpdir({
- git: true,
- init: async (dir) => {
- const skillDir = path.join(dir, ".opencode", "skill", "test-skill")
- await Bun.write(
- path.join(skillDir, "SKILL.md"),
- `---
- name: test-skill
- description: A test skill for verification.
- ---
- # Test Skill
- Instructions here.
- `,
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills.length).toBe(1)
- const testSkill = skills.find((s) => s.name === "test-skill")
- expect(testSkill).toBeDefined()
- expect(testSkill!.description).toBe("A test skill for verification.")
- expect(testSkill!.location).toContain("skill/test-skill/SKILL.md")
- },
- })
- })
- test("discovers multiple skills from .opencode/skill/ directory", async () => {
- await using tmp = await tmpdir({
- git: true,
- init: async (dir) => {
- const skillDir1 = path.join(dir, ".opencode", "skill", "skill-one")
- const skillDir2 = path.join(dir, ".opencode", "skill", "skill-two")
- await Bun.write(
- path.join(skillDir1, "SKILL.md"),
- `---
- name: skill-one
- description: First test skill.
- ---
- # Skill One
- `,
- )
- await Bun.write(
- path.join(skillDir2, "SKILL.md"),
- `---
- name: skill-two
- description: Second test skill.
- ---
- # Skill Two
- `,
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills.length).toBe(2)
- expect(skills.find((s) => s.name === "skill-one")).toBeDefined()
- expect(skills.find((s) => s.name === "skill-two")).toBeDefined()
- },
- })
- })
- test("skips skills with missing frontmatter", async () => {
- await using tmp = await tmpdir({
- git: true,
- init: async (dir) => {
- const skillDir = path.join(dir, ".opencode", "skill", "no-frontmatter")
- await Bun.write(
- path.join(skillDir, "SKILL.md"),
- `# No Frontmatter
- Just some content without YAML frontmatter.
- `,
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills).toEqual([])
- },
- })
- })
- test("discovers skills from .claude/skills/ directory", async () => {
- await using tmp = await tmpdir({
- git: true,
- init: async (dir) => {
- const skillDir = path.join(dir, ".claude", "skills", "claude-skill")
- await Bun.write(
- path.join(skillDir, "SKILL.md"),
- `---
- name: claude-skill
- description: A skill in the .claude/skills directory.
- ---
- # Claude Skill
- `,
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills.length).toBe(1)
- const claudeSkill = skills.find((s) => s.name === "claude-skill")
- expect(claudeSkill).toBeDefined()
- expect(claudeSkill!.location).toContain(".claude/skills/claude-skill/SKILL.md")
- },
- })
- })
- test("discovers global skills from ~/.claude/skills/ directory", async () => {
- await using tmp = await tmpdir({ git: true })
- const originalHome = process.env.OPENCODE_TEST_HOME
- process.env.OPENCODE_TEST_HOME = tmp.path
- try {
- await createGlobalSkill(tmp.path)
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills.length).toBe(1)
- expect(skills[0].name).toBe("global-test-skill")
- expect(skills[0].description).toBe("A global skill from ~/.claude/skills for testing.")
- expect(skills[0].location).toContain(".claude/skills/global-test-skill/SKILL.md")
- },
- })
- } finally {
- process.env.OPENCODE_TEST_HOME = originalHome
- }
- })
- test("returns empty array when no skills exist", async () => {
- await using tmp = await tmpdir({ git: true })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const skills = await Skill.all()
- expect(skills).toEqual([])
- },
- })
- })
|