From 8e3829f63a3b23da1ed9cf554ebe2ae5898b44c0 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 12 Mar 2026 18:18:37 +0900 Subject: [PATCH] test(auto-slash-command): add tests for skills as slash commands --- src/hooks/auto-slash-command/index.test.ts | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/hooks/auto-slash-command/index.test.ts b/src/hooks/auto-slash-command/index.test.ts index 074fb61e9..37fa4ab6f 100644 --- a/src/hooks/auto-slash-command/index.test.ts +++ b/src/hooks/auto-slash-command/index.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it, beforeEach, mock, spyOn } from "bun:test" +import type { LoadedSkill } from "../../features/opencode-skill-loader/types" import type { AutoSlashCommandHookInput, AutoSlashCommandHookOutput, @@ -328,5 +329,89 @@ describe("createAutoSlashCommandHook", () => { }) ) }) + + }) + describe("skills as slash commands", () => { + function createTestSkill(name: string, template: string): LoadedSkill { + return { + name, + path: `/test/skills/${name}/SKILL.md`, + definition: { + name, + description: `Test skill: ${name}`, + template, + }, + scope: "user", + } + } + + it("should replace message with skill template when skill is used as slash command via chat.message", async () => { + // given a hook with a skill + const skill = createTestSkill("my-test-skill", "This is the skill template content") + const hook = createAutoSlashCommandHook({ skills: [skill] }) + const sessionID = `test-session-skill-chat-${Date.now()}` + const input = createMockInput(sessionID) + const output = createMockOutput("/my-test-skill some arguments") + + // when hook processes the message + await hook["chat.message"](input, output) + + // then should replace message with skill template + expect(output.parts[0].text).toContain("") + expect(output.parts[0].text).toContain("/my-test-skill Command") + expect(output.parts[0].text).toContain("This is the skill template content") + }) + + it("should inject skill template via command.execute.before", async () => { + // given a hook with a skill + const skill = createTestSkill("my-test-skill", "Skill template for command execute") + const hook = createAutoSlashCommandHook({ skills: [skill] }) + const input: CommandExecuteBeforeInput = { + command: "my-test-skill", + sessionID: `test-session-skill-cmd-${Date.now()}-${Math.random()}`, + arguments: "extra args", + } + const output: CommandExecuteBeforeOutput = { + parts: [{ type: "text", text: "original" }], + } + + // when hook processes the command + await hook["command.execute.before"](input, output) + + // then should inject skill template + expect(output.parts[0].text).toContain("") + expect(output.parts[0].text).toContain("/my-test-skill Command") + expect(output.parts[0].text).toContain("Skill template for command execute") + expect(output.parts[0].text).toContain("extra args") + }) + + it("should handle skill with lazy content loader", async () => { + // given a skill with lazy content (no inline template) + const skill: LoadedSkill = { + name: "lazy-skill", + path: "/test/skills/lazy-skill/SKILL.md", + definition: { + name: "lazy-skill", + description: "A lazy-loaded skill", + template: "", + }, + scope: "user", + lazyContent: { + loaded: false, + load: async () => "Lazy loaded skill content here", + }, + } + const hook = createAutoSlashCommandHook({ skills: [skill] }) + const sessionID = `test-session-lazy-skill-${Date.now()}` + const input = createMockInput(sessionID) + const output = createMockOutput("/lazy-skill") + + // when hook processes the message + await hook["chat.message"](input, output) + + // then should replace message with lazily loaded content + expect(output.parts[0].text).toContain("") + expect(output.parts[0].text).toContain("Lazy loaded skill content here") + }) }) })