Files
connectai/tests/pipelineTemplates.test.ts
T

70 lines
2.9 KiB
TypeScript

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');
});
});