181 lines
5.6 KiB
TypeScript
181 lines
5.6 KiB
TypeScript
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)
|
|
})
|
|
})
|