import { describe, expect, test, vi } from 'vitest' import { createPresetWorkflowConfig, createStarterWorkflowConfig, normalizeWorkflowConfig, getWorkflows, } from '../../api/workflows' import api from '../../api/client' vi.mock('../../api/client', () => ({ default: { get: vi.fn(), }, })) describe('workflow preset config builders', () => { test('builds a non-legacy still graph preset', () => { const config = createPresetWorkflowConfig('still_graph', { render_engine: 'cycles', samples: 128, resolution: [1600, 900], }) expect(config.ui?.preset).toBe('still_graph') expect(config.ui?.execution_mode).toBe('graph') expect(config.ui?.family).toBe('order_line') expect(config.nodes.map(node => node.step)).toEqual([ 'order_line_setup', 'resolve_template', 'auto_populate_materials', 'glb_bbox', 'material_map_resolve', 'blender_still', 'output_save', 'notify', ]) expect(config.nodes.find(node => node.step === 'blender_still')?.params).toMatchObject({ use_custom_render_settings: false, render_engine: 'cycles', samples: 128, width: 1600, height: 900, }) }) test('builds family-specific starter configs', () => { const cadStarter = createStarterWorkflowConfig('cad_file') const orderStarter = createStarterWorkflowConfig('order_line') expect(cadStarter.ui?.blueprint).toBe('starter_cad_intake') expect(cadStarter.ui?.family).toBe('cad_file') expect(cadStarter.nodes.map(node => node.step)).toEqual(['resolve_step_path']) expect(orderStarter.ui?.blueprint).toBe('starter_order_rendering') expect(orderStarter.ui?.family).toBe('order_line') expect(orderStarter.nodes.map(node => node.step)).toEqual(['order_line_setup']) }) test('preserves ui.family during normalization', () => { const config = normalizeWorkflowConfig({ version: 1, ui: { preset: 'custom', execution_mode: 'shadow', family: 'order_line', }, nodes: [ { id: 'setup', step: 'order_line_setup', params: {} }, ], edges: [], }) expect(config.ui?.family).toBe('order_line') expect(config.ui?.execution_mode).toBe('shadow') }) test('rebuilds canonical reference blueprints during normalization', () => { const config = normalizeWorkflowConfig({ version: 1, ui: { preset: 'custom', execution_mode: 'legacy', blueprint: 'cad_intake', }, nodes: [ { id: 'resolve_step', step: 'resolve_step_path', params: {} }, ], edges: [], }) expect(config.ui?.blueprint).toBe('cad_intake') expect(config.ui?.family).toBe('cad_file') expect(config.nodes.map(node => node.step)).toEqual([ 'resolve_step_path', 'occ_object_extract', 'occ_glb_export', 'glb_bbox', 'stl_cache_generate', 'blender_render', 'threejs_render', 'thumbnail_save', 'thumbnail_save', ]) expect(config.edges).toEqual( expect.arrayContaining([ { from: 'export_glb', to: 'bbox' }, { from: 'bbox', to: 'threejs_thumb' }, ]), ) }) test('rebuilds canonical starter blueprints during normalization', () => { const config = normalizeWorkflowConfig({ version: 1, ui: { preset: 'custom', execution_mode: 'legacy', blueprint: 'starter_order_rendering', }, nodes: [], edges: [], }) expect(config.ui?.blueprint).toBe('starter_order_rendering') expect(config.ui?.family).toBe('order_line') expect(config.nodes.map(node => node.step)).toEqual(['order_line_setup']) }) test('normalizes workflow rollout summary from the API payload', async () => { vi.mocked(api.get).mockResolvedValueOnce({ data: [ { id: 'wf-1', name: 'Still Graph', output_type_id: null, config: createPresetWorkflowConfig('still_graph'), family: 'order_line', supported_artifact_kinds: ['still_image'], rollout_summary: { linked_output_type_count: 2, active_output_type_count: 1, linked_output_type_names: ['Still Render', 'Still Render Shadow'], rollout_modes: ['shadow'], has_blocking_contracts: false, blocking_reasons: [], latest_run: { workflow_run_id: 'run-1', execution_mode: 'graph', status: 'completed', created_at: '2026-04-11T10:00:00Z', completed_at: '2026-04-11T10:01:00Z', }, latest_shadow_run: { workflow_run_id: 'run-shadow-1', execution_mode: 'shadow', status: 'completed', created_at: '2026-04-11T09:00:00Z', completed_at: '2026-04-11T09:01:00Z', }, latest_rollout_gate_verdict: 'pass', latest_rollout_ready: true, latest_rollout_status: 'ready_for_rollout', latest_rollout_reasons: ['Observer output matches the authoritative legacy output byte-for-byte.'], }, is_active: true, created_at: '2026-04-11T08:00:00Z', }, ], }) const [workflow] = await getWorkflows() expect(workflow.rollout_summary.linked_output_type_count).toBe(2) expect(workflow.rollout_summary.rollout_modes).toEqual(['shadow']) expect(workflow.rollout_summary.latest_shadow_run?.execution_mode).toBe('shadow') expect(workflow.rollout_summary.latest_rollout_gate_verdict).toBe('pass') expect(workflow.rollout_summary.latest_rollout_ready).toBe(true) }) })