import { PIPELINE_TEMPLATES, getPipelineTemplate, SCOPE_PRESETS, } from '../src/features/company/pipelineTemplates'; describe('Pipeline templates registry', () => { test('exposes plan-only / dev-only / full-product-dev in expected order', () => { const ids = PIPELINE_TEMPLATES.map((t) => t.templateId); expect(ids).toEqual(['plan-only', 'dev-only', 'full-product-dev']); }); test('getPipelineTemplate returns each by id', () => { expect(getPipelineTemplate('plan-only')?.suggestedPipelineId).toBe('plan-only'); expect(getPipelineTemplate('dev-only')?.suggestedPipelineId).toBe('dev-only'); expect(getPipelineTemplate('full-product-dev')?.suggestedPipelineId).toBe('product-dev'); expect(getPipelineTemplate('does-not-exist')).toBeUndefined(); }); test('SCOPE_PRESETS keys are 1:1 with template ids', () => { const presetIds = SCOPE_PRESETS.map((p) => p.templateId); for (const id of presetIds) { expect(getPipelineTemplate(id)).toBeDefined(); } }); }); describe('DEV_ONLY template stage shape', () => { test('has 10 stages and ends at dev-impl', () => { const tpl = getPipelineTemplate('dev-only'); expect(tpl).toBeDefined(); expect(tpl!.stages).toHaveLength(10); const last = tpl!.stages[tpl!.stages.length - 1]; expect(last.id).toBe('dev-impl'); }); test('does NOT include qa / deploy stages', () => { const tpl = getPipelineTemplate('dev-only')!; const stageIds = tpl.stages.map((s) => s.id); expect(stageIds).not.toContain('qa'); expect(stageIds).not.toContain('deploy'); }); test('keeps planner → design-review chain intact', () => { const tpl = getPipelineTemplate('dev-only')!; const stageIds = tpl.stages.map((s) => s.id); expect(stageIds).toEqual(expect.arrayContaining([ 'plan-discuss', 'plan-draft', 'plan-final', 'dev-design', 'design-review', 'dev-impl', ])); }); test('shares stage objects with FULL_PRODUCT_DEV (read-only template safety)', () => { // Slice(0, 10) — full 의 stages 배열에서 자른 references. // 사용자가 dev-only template 을 stamp 하면 _normalizePipeline 이 deep-copy 하므로 // 본 template 의 stage 객체 자체는 절대 mutate 되지 않아야 함. const dev = getPipelineTemplate('dev-only')!; const full = getPipelineTemplate('full-product-dev')!; expect(dev.stages[0]).toBe(full.stages[0]); // shared reference (intentional) expect(dev.stages.length).toBeLessThan(full.stages.length); }); }); describe('PLAN_ONLY template (existing) sanity', () => { test('still has 3 stages ending at plan-doc', () => { const tpl = getPipelineTemplate('plan-only')!; expect(tpl.stages).toHaveLength(3); expect(tpl.stages[tpl.stages.length - 1].id).toBe('plan-doc'); }); });