// @vitest-environment node import { beforeEach, describe, expect, it, vi } from 'vitest'; const mocks = vi.hoisted(() => ({ hostApiFetch: vi.fn(), gatewayRpc: vi.fn(), })); vi.mock('../src/lib/host-api', () => ({ hostApiFetch: mocks.hostApiFetch, })); vi.mock('../src/lib/gateway-client', () => ({ gatewayRpc: mocks.gatewayRpc, })); import { apiGetSkillsDir, apiInstallSkill } from '../src/lib/skills-api'; describe('skills api helpers', () => { beforeEach(() => { mocks.hostApiFetch.mockReset(); mocks.gatewayRpc.mockReset(); }); it('falls back to ~/.openclaw/skills when the host path request fails', async () => { mocks.hostApiFetch.mockRejectedValue(new Error('offline')); await expect(apiGetSkillsDir()).resolves.toBe('~/.openclaw/skills'); }); it('posts unified install requests to /api/skills/install', async () => { mocks.hostApiFetch.mockResolvedValue({ success: true, slug: 'minimax-xlsx', baseDir: 'C:/Users/Administrator/.openclaw/skills/minimax-xlsx', source: 'github-url', enabled: true, }); await expect(apiInstallSkill({ kind: 'github-url', url: 'https://github.com/MiniMax-AI/skills/blob/main/skills/minimax-xlsx/SKILL.md', })).resolves.toMatchObject({ success: true, slug: 'minimax-xlsx', source: 'github-url', }); expect(mocks.hostApiFetch).toHaveBeenCalledWith('/api/skills/install', expect.objectContaining({ method: 'POST', })); }); });