Skip to content

Commit eb6bc89

Browse files
committed
fix
1 parent b8c2f63 commit eb6bc89

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { vi, describe, expect, it, beforeEach } from "vite-plus/test";
2+
3+
vi.mock("node:fs", () => ({
4+
existsSync: vi.fn(),
5+
rmSync: vi.fn(),
6+
}));
7+
8+
vi.mock("agent-install/skill", () => ({
9+
add: vi.fn(),
10+
getCanonicalSkillsDir: vi.fn(),
11+
getSkillAgentConfig: vi.fn(),
12+
getSkillAgentDir: vi.fn(),
13+
isUniversalSkillAgent: vi.fn(),
14+
}));
15+
16+
vi.mock("../src/utils/detect-agents.js", () => ({
17+
detectAvailableAgents: vi.fn(),
18+
}));
19+
20+
import { existsSync, rmSync } from "node:fs";
21+
import {
22+
add,
23+
getCanonicalSkillsDir,
24+
getSkillAgentDir,
25+
isUniversalSkillAgent,
26+
} from "agent-install/skill";
27+
import { detectAvailableAgents } from "../src/utils/detect-agents.js";
28+
import { installSkill, removeSkill } from "../src/utils/install-skill.js";
29+
30+
const mockExistsSync = vi.mocked(existsSync);
31+
const mockRmSync = vi.mocked(rmSync);
32+
const mockAdd = vi.mocked(add);
33+
const mockGetCanonicalSkillsDir = vi.mocked(getCanonicalSkillsDir);
34+
const mockGetSkillAgentDir = vi.mocked(getSkillAgentDir);
35+
const mockIsUniversalSkillAgent = vi.mocked(isUniversalSkillAgent);
36+
const mockDetectAvailableAgents = vi.mocked(detectAvailableAgents);
37+
38+
beforeEach(() => {
39+
vi.clearAllMocks();
40+
mockIsUniversalSkillAgent.mockReturnValue(false);
41+
mockGetSkillAgentDir.mockImplementation((agent, options) => `${options.cwd}/.${agent}`);
42+
mockGetCanonicalSkillsDir.mockImplementation((_global, cwd) => `${cwd}/.agents/skills`);
43+
mockAdd.mockResolvedValue({ installed: [], failed: [] } as never);
44+
});
45+
46+
describe("installSkill", () => {
47+
it("installs to detected agents by default in copy mode", async () => {
48+
mockDetectAvailableAgents.mockResolvedValue(["claude-code", "cursor"] as never);
49+
50+
await installSkill({ cwd: "/app" });
51+
52+
expect(mockDetectAvailableAgents).toHaveBeenCalledTimes(1);
53+
expect(mockAdd).toHaveBeenCalledWith(
54+
expect.objectContaining({
55+
source: expect.stringContaining("skills/react-grab"),
56+
agents: ["claude-code", "cursor"],
57+
global: false,
58+
cwd: "/app",
59+
mode: "copy",
60+
}),
61+
);
62+
});
63+
64+
it("uses explicit agents without running detection", async () => {
65+
await installSkill({ agents: ["codex"] as never, cwd: "/app", global: true });
66+
67+
expect(mockDetectAvailableAgents).not.toHaveBeenCalled();
68+
expect(mockAdd).toHaveBeenCalledWith(
69+
expect.objectContaining({ agents: ["codex"], global: true, cwd: "/app", mode: "copy" }),
70+
);
71+
});
72+
});
73+
74+
describe("removeSkill", () => {
75+
it("removes skill directories that exist and returns the removed agents", async () => {
76+
mockDetectAvailableAgents.mockResolvedValue(["claude-code", "cursor"] as never);
77+
mockExistsSync.mockImplementation((path) => `${path}`.includes(".claude-code"));
78+
79+
const removed = await removeSkill({ cwd: "/app" });
80+
81+
expect(removed).toEqual(["claude-code"]);
82+
expect(mockRmSync).toHaveBeenCalledTimes(1);
83+
expect(mockRmSync).toHaveBeenCalledWith("/app/.claude-code/react-grab", {
84+
recursive: true,
85+
force: true,
86+
});
87+
});
88+
89+
it("returns an empty array and removes nothing when no skill is installed", async () => {
90+
mockDetectAvailableAgents.mockResolvedValue(["claude-code"] as never);
91+
mockExistsSync.mockReturnValue(false);
92+
93+
const removed = await removeSkill({ cwd: "/app" });
94+
95+
expect(removed).toEqual([]);
96+
expect(mockRmSync).not.toHaveBeenCalled();
97+
});
98+
99+
it("resolves universal agents to the canonical skills directory", async () => {
100+
mockDetectAvailableAgents.mockResolvedValue(["universal"] as never);
101+
mockIsUniversalSkillAgent.mockReturnValue(true);
102+
mockExistsSync.mockReturnValue(true);
103+
104+
const removed = await removeSkill({ cwd: "/app", global: true });
105+
106+
expect(removed).toEqual(["universal"]);
107+
expect(mockGetCanonicalSkillsDir).toHaveBeenCalledWith(true, "/app");
108+
expect(mockRmSync).toHaveBeenCalledWith("/app/.agents/skills/react-grab", {
109+
recursive: true,
110+
force: true,
111+
});
112+
});
113+
});

0 commit comments

Comments
 (0)