This commit is contained in:
124
packages/sdk/tests/wave-g-capability-surface.test.ts
Normal file
124
packages/sdk/tests/wave-g-capability-surface.test.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user