125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
/**
|
|
* Wave G — Capability Surface Productization tests.
|
|
*
|
|
* Verifies:
|
|
* 1. Pack catalog structure and completeness
|
|
* 2. Pack-to-skill relationships are valid
|
|
* 3. Product language consistency (no internal categories leaked)
|
|
* 4. Capability summary data shape
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import { listCapabilityPacks, getPackManifest } from '../src/capability-packs/index.js';
|
|
|
|
describe('Wave G: Capability Surface', () => {
|
|
describe('Pack Catalog', () => {
|
|
it('has exactly 5 curated packs', () => {
|
|
const packs = listCapabilityPacks();
|
|
expect(packs).toHaveLength(5);
|
|
});
|
|
|
|
it('all packs have required fields', () => {
|
|
const packs = listCapabilityPacks();
|
|
for (const pack of packs) {
|
|
expect(pack.id).toBeTruthy();
|
|
expect(pack.name).toBeTruthy();
|
|
expect(pack.description).toBeTruthy();
|
|
expect(pack.skills.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('includes the 5 core pack IDs', () => {
|
|
const packs = listCapabilityPacks();
|
|
const ids = packs.map(p => p.id);
|
|
expect(ids).toContain('writing-suite');
|
|
expect(ids).toContain('research-workflow');
|
|
expect(ids).toContain('planning-master');
|
|
expect(ids).toContain('decision-framework');
|
|
expect(ids).toContain('team-collaboration');
|
|
});
|
|
|
|
it('each pack has user-facing name (not slug)', () => {
|
|
const packs = listCapabilityPacks();
|
|
for (const pack of packs) {
|
|
// Names should have spaces and be title-cased, not slugs
|
|
expect(pack.name).toMatch(/[A-Z]/); // Contains uppercase
|
|
expect(pack.name).not.toMatch(/^[a-z-]+$/); // Not a slug
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Pack-to-Skill Relationships', () => {
|
|
it('each pack references valid skill IDs', () => {
|
|
const packs = listCapabilityPacks();
|
|
for (const pack of packs) {
|
|
for (const skillId of pack.skills) {
|
|
expect(typeof skillId).toBe('string');
|
|
expect(skillId.length).toBeGreaterThan(0);
|
|
// Skill IDs should be kebab-case
|
|
expect(skillId).toMatch(/^[a-z][a-z0-9-]*$/);
|
|
}
|
|
}
|
|
});
|
|
|
|
it('getPackManifest returns correct pack by ID', () => {
|
|
const pack = getPackManifest('writing-suite');
|
|
expect(pack).not.toBeNull();
|
|
expect(pack!.name).toBe('Writing Suite');
|
|
expect(pack!.skills).toContain('draft-memo');
|
|
});
|
|
|
|
it('getPackManifest returns null for unknown pack', () => {
|
|
const pack = getPackManifest('nonexistent-pack');
|
|
expect(pack).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('Product Language', () => {
|
|
it('pack descriptions use user-facing language (no internal terms)', () => {
|
|
const packs = listCapabilityPacks();
|
|
const internalTerms = ['plugin', 'MCP', 'hook', 'mcp_server'];
|
|
for (const pack of packs) {
|
|
for (const term of internalTerms) {
|
|
expect(pack.description.toLowerCase()).not.toContain(term.toLowerCase());
|
|
}
|
|
}
|
|
});
|
|
|
|
it('pack names do not reference implementation details', () => {
|
|
const packs = listCapabilityPacks();
|
|
for (const pack of packs) {
|
|
expect(pack.name.toLowerCase()).not.toContain('plugin');
|
|
expect(pack.name.toLowerCase()).not.toContain('mcp');
|
|
expect(pack.name.toLowerCase()).not.toContain('hook');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Capability Summary Shape', () => {
|
|
it('can construct a unified capability count from component data', () => {
|
|
// Simulates what the UI does: merge implementation counts into product counts
|
|
const mockCapabilities = {
|
|
tools: { count: 25, native: 20, plugin: 3, mcp: 2 },
|
|
skills: [{ name: 'draft-memo' }, { name: 'research-synthesis' }],
|
|
workflows: [{ name: 'research-team' }],
|
|
plugins: [{ name: 'p1', state: 'active' }],
|
|
mcpServers: [{ name: 'm1', healthy: true }],
|
|
commands: [{ name: '/help' }, { name: '/cost' }],
|
|
};
|
|
|
|
// Product-level counts (what user sees)
|
|
const toolCount = mockCapabilities.tools.count;
|
|
const skillCount = mockCapabilities.skills.length;
|
|
const workflowCount = mockCapabilities.workflows.length;
|
|
const extensionCount = mockCapabilities.plugins.length + mockCapabilities.mcpServers.length;
|
|
const commandCount = mockCapabilities.commands.length;
|
|
|
|
expect(toolCount).toBe(25);
|
|
expect(skillCount).toBe(2);
|
|
expect(workflowCount).toBe(1);
|
|
expect(extensionCount).toBe(2); // unified plugins + MCP
|
|
expect(commandCount).toBe(2);
|
|
});
|
|
});
|
|
});
|