111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import {
|
|
listStarterSkills,
|
|
installStarterSkills,
|
|
getStarterSkillsDir,
|
|
} from '../src/starter-skills/index.js';
|
|
|
|
describe('starter-skills', () => {
|
|
let tmpDir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-starter-skills-'));
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('getStarterSkillsDir() returns a directory that exists', () => {
|
|
const dir = getStarterSkillsDir();
|
|
expect(fs.existsSync(dir)).toBe(true);
|
|
});
|
|
|
|
it('listStarterSkills() returns 18 skill names', () => {
|
|
const skills = listStarterSkills();
|
|
expect(skills).toHaveLength(18);
|
|
});
|
|
|
|
it('all expected skill names are present', () => {
|
|
const skills = listStarterSkills();
|
|
const expected = [
|
|
'brainstorm',
|
|
'catch-up',
|
|
'code-review',
|
|
'compare-docs',
|
|
'daily-plan',
|
|
'decision-matrix',
|
|
'draft-memo',
|
|
'explain-concept',
|
|
'extract-actions',
|
|
'meeting-prep',
|
|
'plan-execute',
|
|
'research-synthesis',
|
|
'research-team',
|
|
'retrospective',
|
|
'review-pair',
|
|
'risk-assessment',
|
|
'status-update',
|
|
'task-breakdown',
|
|
];
|
|
expect(skills).toEqual(expected);
|
|
});
|
|
|
|
it('each starter skill file exists and has content (> 50 chars)', () => {
|
|
const dir = getStarterSkillsDir();
|
|
const skills = listStarterSkills();
|
|
for (const name of skills) {
|
|
const filePath = path.join(dir, `${name}.md`);
|
|
expect(fs.existsSync(filePath), `${name}.md should exist`).toBe(true);
|
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
expect(content.length, `${name}.md should have > 50 chars`).toBeGreaterThan(50);
|
|
}
|
|
});
|
|
|
|
it('all skill names are valid (alphanumeric + hyphens only)', () => {
|
|
const skills = listStarterSkills();
|
|
for (const name of skills) {
|
|
expect(name, `${name} should match [a-z0-9-]+`).toMatch(/^[a-z0-9-]+$/);
|
|
}
|
|
});
|
|
|
|
it('installStarterSkills() copies files to target directory', () => {
|
|
const installed = installStarterSkills(tmpDir);
|
|
expect(installed).toHaveLength(18);
|
|
|
|
// Verify files exist in target
|
|
for (const name of installed) {
|
|
const filePath = path.join(tmpDir, `${name}.md`);
|
|
expect(fs.existsSync(filePath), `${name}.md should be installed`).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('installStarterSkills() does NOT overwrite existing skills', () => {
|
|
// Pre-create a skill with custom content
|
|
const customContent = '# Custom catch-up skill\nMy custom version.';
|
|
fs.writeFileSync(path.join(tmpDir, 'catch-up.md'), customContent, 'utf-8');
|
|
|
|
const installed = installStarterSkills(tmpDir);
|
|
|
|
// catch-up should NOT be in the installed list (was skipped)
|
|
expect(installed).not.toContain('catch-up');
|
|
expect(installed).toHaveLength(17);
|
|
|
|
// Verify custom content was preserved
|
|
const content = fs.readFileSync(path.join(tmpDir, 'catch-up.md'), 'utf-8');
|
|
expect(content).toBe(customContent);
|
|
});
|
|
|
|
it('installStarterSkills() creates target directory if missing', () => {
|
|
const nestedDir = path.join(tmpDir, 'nested', 'skills');
|
|
expect(fs.existsSync(nestedDir)).toBe(false);
|
|
|
|
const installed = installStarterSkills(nestedDir);
|
|
expect(installed).toHaveLength(18);
|
|
expect(fs.existsSync(nestedDir)).toBe(true);
|
|
});
|
|
});
|