registry.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, it, expect } from 'vitest';
import {
hookModules,
panelHooks,
commandAvailability,
resolvePickOne,
formatTierList,
planEnhanceInstalled,
findSubtitleModule,
scoreMusicModules,
} from './registry.mjs';
const registry = {
catalog: [
{ name: 'keyframe', cardinality: 'pick_one', blurb: 'keyframes' },
{ name: 'motion.backend', cardinality: 'pick_one', blurb: 'i2v' },
{ name: 'finish', cardinality: 'chain', blurb: 'finish' },
{ name: 'score', cardinality: 'chain' },
{ name: 'dialogue', cardinality: 'pick_one' },
{ name: 'plan.enhance', cardinality: 'chain' },
{ name: 'cast.image', cardinality: 'pick_one' },
{ name: 'notify', cardinality: 'chain' },
{ name: 'film.finish', cardinality: 'chain' },
],
hooks: {
keyframe: ['keyframe-mod'],
'motion.backend': ['own-gpu', 'kling'],
finish: ['finish-rife'],
score: ['score-music'],
dialogue: ['aura-dialogue'],
'plan.enhance': ['shot-director'],
'cast.image': ['cast-sdxl'],
'film.finish': ['film-titles', 'subtitles-burn'],
},
modules: [
{ name: 'keyframe-mod', hooks: ['keyframe'], config_schema: { steps: { type: 'int', scope: 'render' } } },
{ name: 'own-gpu', hooks: ['motion.backend'], ui: { locality: 'byo' } },
{ name: 'kling', hooks: ['motion.backend'], ui: { locality: 'cloud' }, config_schema: { quality: { type: 'enum', values: ['draft'], scope: 'render' } } },
{ name: 'finish-rife', hooks: ['finish'] },
{ name: 'score-music', hooks: ['score'], config_schema: { prompt: { type: 'string', scope: 'render' } } },
{ name: 'aura-dialogue', hooks: ['dialogue'] },
{ name: 'shot-director', hooks: ['plan.enhance'] },
{ name: 'cast-sdxl', hooks: ['cast.image'] },
{ name: 'film-titles', hooks: ['film.finish'] },
{ name: 'subtitles-burn', hooks: ['film.finish'], config_schema: { burn_subtitles: { type: 'bool', scope: 'render' } } },
{ name: 'notify-email', hooks: ['notify'], config_schema: { notify_email: { type: 'string', scope: 'install' } } },
],
render: {
quality_tiers: [{ value: 'draft', label: 'draft' }, { value: 'final', label: 'final' }],
default_tier: 'draft',
},
};
describe('hookModules', () => {
it('returns modules in registry hook order', () => {
expect(hookModules(registry, 'motion.backend').map((m) => m.name)).toEqual(['own-gpu', 'kling']);
});
});
describe('panelHooks', () => {
it('skips bespoke-surface hooks like score and plan.enhance', () => {
const names = panelHooks(registry).map((h) => h.hook);
expect(names).toContain('keyframe');
expect(names).toContain('motion.backend');
expect(names).not.toContain('score');
expect(names).not.toContain('plan.enhance');
expect(names).not.toContain('dialogue');
});
});
describe('commandAvailability', () => {
it('gates backend on motion.backend modules', () => {
const a = commandAvailability(registry, true);
expect(a.backend.ok).toBe(true);
expect(a.backend.modules).toEqual(['own-gpu', 'kling']);
});
it('blocks score-music when no score module with prompt', () => {
const empty = commandAvailability({ modules: [], hooks: {}, catalog: [] }, true);
expect(empty['score-music'].ok).toBe(false);
expect(scoreMusicModules(registry).length).toBe(1);
});
it('enables autodirect when plan.enhance is installed', () => {
expect(planEnhanceInstalled(registry)).toBe(true);
expect(commandAvailability(registry, true).autodirect.ok).toBe(true);
});
it('finds subtitle module in film.finish chain', () => {
expect(findSubtitleModule(registry)?.name).toBe('subtitles-burn');
});
});
describe('resolvePickOne', () => {
it('resolves auto to null', () => {
expect(resolvePickOne(registry, 'motion.backend', 'auto')).toEqual({ value: null });
});
it('errors on unknown backend', () => {
expect(resolvePickOne(registry, 'motion.backend', 'nope').error).toContain('Unknown backend');
});
});
describe('formatTierList', () => {
it('marks the active tier', () => {
expect(formatTierList(registry, 'draft')).toContain('**<-- active**');
});
});