storebound/tests/skill-guide.test.ts

27 lines
1.6 KiB
TypeScript

// "Open guide" on a finding: skill name -> the shipped SKILL.md; the known list matches the skills/ folder.
import { expect, test } from 'bun:test';
import { existsSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { KNOWN_SKILLS, SKILLS_BASE, skillGuideUrl } from '../cli/lib/skill-guide';
const dir = join(import.meta.dir, '..', 'skills');
test('KNOWN_SKILLS is exactly the skills/ folder', () => {
const real = readdirSync(dir).filter(n => existsSync(join(dir, n, 'SKILL.md'))).sort();
expect([...KNOWN_SKILLS].sort()).toEqual(real);
});
test('a skill name, a skills/ path or a SKILL.md path resolve to the guide', () => {
expect(skillGuideUrl('store-api')).toBe(`${SKILLS_BASE}/store-api/SKILL.md`);
expect(skillGuideUrl('skills/store-api')).toBe(`${SKILLS_BASE}/store-api/SKILL.md`);
expect(skillGuideUrl(' skills/game-services/SKILL.md ')).toBe(`${SKILLS_BASE}/game-services/SKILL.md`);
});
test('unknown or empty: no link', () => {
for (const s of ['', null, undefined, 'not-a-skill', '../etc', 'store-api/../x']) expect(skillGuideUrl(s)).toBeNull();
});
test('every skill a scan rule names is a known skill', async () => {
const { readFileSync } = await import('node:fs');
const src = readdirSync(join(import.meta.dir, '..', 'cli', 'lib', 'scan')).filter(f => f.endsWith('.ts')).map(f => readFileSync(join(import.meta.dir, '..', 'cli', 'lib', 'scan', f), 'utf8')).join('\n');
const named = [...src.matchAll(/skill: '([a-z0-9-]+)'/g)].map(m => m[1]!);
expect(named.length).toBeGreaterThan(0);
for (const s of new Set(named)) expect(skillGuideUrl(s)).not.toBeNull();
});