chore: snapshot workflow migration progress

This commit is contained in:
2026-04-12 11:49:04 +02:00
parent 0cd02513d5
commit 3e810c74a3
163 changed files with 31774 additions and 2753 deletions
@@ -1,6 +1,7 @@
import pytest
from pydantic import ValidationError
from app.core.process_steps import StepName
from app.domains.rendering.workflow_schema import WorkflowConfig
@@ -72,6 +73,35 @@ def test_workflow_schema_rejects_unknown_node_params():
)
def test_workflow_schema_rejects_unregistered_nodes_from_registry(monkeypatch):
from app.domains.rendering import workflow_schema as schema_module
original = schema_module.get_node_definition
def fake_get_node_definition(step):
if step == StepName.GLB_BBOX:
return None
return original(step)
monkeypatch.setattr(schema_module, "get_node_definition", fake_get_node_definition)
with pytest.raises(ValidationError, match="is not registered in workflow_node_registry"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "bbox",
"step": StepName.GLB_BBOX.value,
"params": {},
},
],
"edges": [],
"ui": {"family": "order_line"},
}
)
def test_workflow_schema_accepts_known_node_params():
config = WorkflowConfig.model_validate(
{
@@ -92,6 +122,149 @@ def test_workflow_schema_accepts_known_node_params():
assert config.ui.family == "order_line"
def test_workflow_schema_rejects_invalid_glb_path_format():
with pytest.raises(ValidationError, match="must point to a .glb file"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "bbox",
"step": "glb_bbox",
"params": {"glb_path": "/tmp/model.gltf"},
},
],
"edges": [],
}
)
def test_workflow_schema_rejects_invalid_template_id_override_format():
with pytest.raises(ValidationError, match="must be a valid UUID"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "template",
"step": "resolve_template",
"params": {"template_id_override": "not-a-uuid"},
},
],
"edges": [],
}
)
def test_workflow_schema_rejects_invalid_material_library_path_format():
with pytest.raises(ValidationError, match="must point to a .blend file"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "template",
"step": "resolve_template",
"params": {"material_library_path": "/tmp/library.txt"},
},
],
"edges": [],
}
)
def test_workflow_schema_rejects_invalid_noise_threshold_format():
with pytest.raises(ValidationError, match="must be a valid numeric string"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "render",
"step": "blender_still",
"params": {"noise_threshold": "fast"},
},
],
"edges": [],
}
)
def test_workflow_schema_rejects_invalid_bg_color_format():
with pytest.raises(ValidationError, match="must be a hex color"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "turntable",
"step": "blender_turntable",
"params": {"bg_color": "blue"},
},
],
"edges": [],
}
)
def test_workflow_schema_rejects_invalid_output_name_suffix_format():
with pytest.raises(ValidationError, match="may only contain letters, numbers"):
WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "blend",
"step": "export_blend",
"params": {"output_name_suffix": "../unsafe"},
},
],
"edges": [],
}
)
def test_workflow_schema_accepts_empty_optional_text_overrides():
config = WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{
"id": "template",
"step": "resolve_template",
"params": {
"template_id_override": "",
"material_library_path": "",
},
},
{
"id": "render",
"step": "blender_still",
"params": {
"noise_threshold": "",
"material_override": "",
},
},
{
"id": "turntable",
"step": "blender_turntable",
"params": {"bg_color": ""},
},
{
"id": "blend",
"step": "export_blend",
"params": {"output_name_suffix": ""},
},
],
"edges": [],
"ui": {"family": "order_line"},
}
)
assert config.ui is not None
assert config.ui.family == "order_line"
def test_workflow_schema_rejects_ui_family_mismatch():
with pytest.raises(ValidationError, match="ui.family"):
WorkflowConfig.model_validate(
@@ -226,6 +399,32 @@ def test_workflow_schema_accepts_transitive_contract_wiring():
assert config.ui.execution_mode == "graph"
def test_workflow_schema_accepts_cad_intake_contract_wiring_with_shared_bbox_node():
config = WorkflowConfig.model_validate(
{
"version": 1,
"nodes": [
{"id": "resolve_step", "step": "resolve_step_path", "params": {}},
{"id": "export_glb", "step": "occ_glb_export", "params": {}},
{"id": "bbox", "step": "glb_bbox", "params": {}},
{"id": "threejs_thumb", "step": "threejs_render", "params": {}},
{"id": "save", "step": "thumbnail_save", "params": {}},
],
"edges": [
{"from": "resolve_step", "to": "export_glb"},
{"from": "export_glb", "to": "bbox"},
{"from": "export_glb", "to": "threejs_thumb"},
{"from": "bbox", "to": "threejs_thumb"},
{"from": "threejs_thumb", "to": "save"},
],
"ui": {"family": "cad_file", "execution_mode": "graph"},
}
)
assert config.ui is not None
assert config.ui.family == "cad_file"
def test_workflow_schema_rejects_mixed_family_graph_execution():
with pytest.raises(ValidationError, match="single-family"):
WorkflowConfig.model_validate(