Files
HartOMat/backend/tests/domains/test_workflow_config_utils.py
T

414 lines
14 KiB
Python

from app.domains.rendering.workflow_config_utils import (
build_preset_workflow_config,
build_workflow_blueprint_config,
build_starter_workflow_config,
canonicalize_workflow_config,
extract_runtime_workflow,
get_workflow_execution_mode,
workflow_config_requires_canonicalization,
)
def test_build_preset_workflow_config_creates_canonical_dag():
config = build_preset_workflow_config(
"still",
{"render_engine": "cycles", "samples": 256, "resolution": [1920, 1080]},
)
assert config["version"] == 1
assert config["ui"]["preset"] == "still"
assert config["ui"]["execution_mode"] == "legacy"
assert [node["step"] for node in config["nodes"]] == [
"order_line_setup",
"resolve_template",
"blender_still",
"output_save",
]
render_node = next(node for node in config["nodes"] if node["step"] == "blender_still")
assert render_node["params"]["width"] == 1920
assert render_node["params"]["height"] == 1080
def test_build_preset_workflow_config_creates_graph_still_variant():
config = build_preset_workflow_config(
"still_graph",
{"render_engine": "cycles", "samples": 128, "resolution": [1600, 900]},
)
assert config["version"] == 1
assert config["ui"]["preset"] == "still_graph"
assert config["ui"]["execution_mode"] == "graph"
assert [node["step"] for node in config["nodes"]] == [
"order_line_setup",
"resolve_template",
"auto_populate_materials",
"glb_bbox",
"material_map_resolve",
"blender_still",
"output_save",
"notify",
]
render_node = next(node for node in config["nodes"] if node["step"] == "blender_still")
assert render_node["params"]["width"] == 1600
assert render_node["params"]["height"] == 900
assert render_node["params"]["samples"] == 128
assert render_node["params"]["use_custom_render_settings"] is False
def test_canonicalize_workflow_config_migrates_legacy_preset():
legacy = {
"type": "turntable",
"params": {"render_engine": "cycles", "samples": 64, "fps": 24},
"ui": {"execution_mode": "shadow", "label": "Legacy Turntable"},
}
canonical = canonicalize_workflow_config(legacy)
assert canonical["version"] == 1
assert canonical["ui"]["preset"] == "turntable"
assert canonical["ui"]["execution_mode"] == "shadow"
assert canonical["ui"]["label"] == "Legacy Turntable"
assert any(node["step"] == "blender_turntable" for node in canonical["nodes"])
def test_get_workflow_execution_mode_uses_legacy_preset_ui_override():
legacy = {
"type": "still",
"params": {"width": 1024, "height": 768},
"ui": {"execution_mode": "graph"},
}
assert get_workflow_execution_mode(legacy) == "graph"
def test_extract_runtime_workflow_uses_canonical_render_node_params():
config = build_preset_workflow_config(
"multi_angle",
{"render_engine": "cycles", "samples": 128, "angles": [0, 45, 90]},
)
preset, params = extract_runtime_workflow(config)
assert preset == "multi_angle"
assert params["render_engine"] == "cycles"
assert params["samples"] == 128
assert params["angles"] == [0.0, 45.0, 90.0]
def test_canonicalize_legacy_custom_config_preserves_edges():
legacy = {
"type": "custom",
"nodes": [
{
"id": "input",
"type": "inputNode",
"position": {"x": 0, "y": 0},
"data": {"label": "Input", "pipeline_step": "resolve_step_path", "params": {}},
},
{
"id": "render",
"type": "renderNode",
"position": {"x": 200, "y": 0},
"data": {"label": "Render", "pipeline_step": "blender_still", "params": {"resolution": [1024, 1024]}},
},
],
"edges": [
{"id": "e1", "source": "input", "target": "render"},
],
}
canonical = canonicalize_workflow_config(legacy)
assert canonical["ui"]["preset"] == "custom"
assert canonical["ui"]["execution_mode"] == "legacy"
assert canonical["edges"] == [{"id": "e1", "from": "input", "to": "render"}]
def test_canonicalize_legacy_custom_config_without_nodes_builds_render_fallback_graph():
legacy = {
"type": "custom",
"params": {
"samples": 256,
"resolution": [2048, 2048],
"render_engine": "cycles",
},
}
canonical = canonicalize_workflow_config(legacy)
assert canonical["version"] == 1
assert canonical["ui"]["preset"] == "custom"
assert canonical["ui"]["execution_mode"] == "legacy"
assert [node["step"] for node in canonical["nodes"]] == [
"order_line_setup",
"blender_still",
]
assert canonical["edges"] == [{"from": "setup", "to": "render"}]
render_node = next(node for node in canonical["nodes"] if node["step"] == "blender_still")
assert render_node["params"]["render_engine"] == "cycles"
assert render_node["params"]["samples"] == 256
assert render_node["params"]["width"] == 2048
assert render_node["params"]["height"] == 2048
assert render_node["params"]["use_custom_render_settings"] is True
def test_extract_runtime_workflow_converts_resolution_to_dimensions():
config = build_preset_workflow_config(
"turntable",
{"resolution": [1920, 1080], "fps": 24},
)
preset, params = extract_runtime_workflow(config)
assert preset == "turntable"
assert params["width"] == 1920
assert params["height"] == 1080
assert "resolution" not in params
def test_build_preset_workflow_config_keeps_render_overrides_opt_in_disabled_by_default():
config = build_preset_workflow_config(
"still_with_exports",
{"width": 640, "height": 640, "samples": 32},
)
render_node = next(node for node in config["nodes"] if node["step"] == "blender_still")
assert "use_custom_render_settings" not in render_node["params"]
assert render_node["params"]["width"] == 640
assert render_node["params"]["height"] == 640
assert render_node["params"]["samples"] == 32
def test_canonicalize_workflow_config_preserves_unset_override_intent_for_saved_preset_configs():
canonical = canonicalize_workflow_config(
{
"version": 1,
"nodes": [
{"id": "setup", "step": "order_line_setup", "params": {}},
{
"id": "render",
"step": "blender_still",
"params": {"width": 1024, "height": 768},
},
],
"edges": [{"from": "setup", "to": "render"}],
"ui": {"preset": "still_with_exports", "execution_mode": "graph"},
}
)
render_node = next(node for node in canonical["nodes"] if node["step"] == "blender_still")
assert "use_custom_render_settings" not in render_node["params"]
def test_canonicalize_workflow_config_defaults_execution_mode_for_canonical_configs():
canonical = canonicalize_workflow_config(
{
"version": 1,
"nodes": [
{"id": "setup", "step": "order_line_setup", "params": {}},
],
"edges": [],
"ui": {"preset": "custom"},
}
)
assert canonical["ui"]["preset"] == "custom"
assert canonical["ui"]["execution_mode"] == "legacy"
def test_canonicalize_workflow_config_rebuilds_canonical_still_graph_preset():
canonical = canonicalize_workflow_config(
{
"version": 1,
"ui": {"preset": "still_graph", "execution_mode": "graph"},
"nodes": [
{"id": "setup", "step": "order_line_setup", "params": {}},
{"id": "resolve_materials", "step": "material_map_resolve", "params": {}},
{"id": "template", "step": "resolve_template", "params": {}},
{"id": "render", "step": "blender_still", "params": {"width": 1280, "height": 720, "samples": 32}},
{"id": "output", "step": "output_save", "params": {}},
{"id": "notify", "step": "notify", "params": {}},
],
"edges": [
{"from": "setup", "to": "resolve_materials"},
{"from": "resolve_materials", "to": "template"},
{"from": "template", "to": "render"},
{"from": "render", "to": "output"},
{"from": "render", "to": "notify"},
],
}
)
assert canonical["ui"]["preset"] == "still_graph"
assert canonical["ui"]["execution_mode"] == "graph"
assert [node["step"] for node in canonical["nodes"]] == [
"order_line_setup",
"resolve_template",
"auto_populate_materials",
"glb_bbox",
"material_map_resolve",
"blender_still",
"output_save",
"notify",
]
render_node = next(node for node in canonical["nodes"] if node["step"] == "blender_still")
assert render_node["params"]["width"] == 1280
assert render_node["params"]["height"] == 720
assert render_node["params"]["samples"] == 32
assert render_node["params"]["use_custom_render_settings"] is False
def test_build_workflow_blueprint_config_cad_intake_supplies_bbox_to_threejs_thumbnail():
config = build_workflow_blueprint_config("cad_intake")
assert config["ui"]["family"] == "cad_file"
assert [node["step"] for node in config["nodes"]] == [
"resolve_step_path",
"occ_object_extract",
"occ_glb_export",
"glb_bbox",
"stl_cache_generate",
"blender_render",
"threejs_render",
"thumbnail_save",
"thumbnail_save",
]
assert {"from": "export_glb", "to": "bbox"} in config["edges"]
assert {"from": "bbox", "to": "threejs_thumb"} in config["edges"]
def test_canonicalize_workflow_config_rebuilds_reference_blueprints():
canonical = canonicalize_workflow_config(
{
"version": 1,
"ui": {"preset": "custom", "execution_mode": "legacy", "blueprint": "order_rendering"},
"nodes": [
{"id": "setup", "step": "order_line_setup", "params": {}},
],
"edges": [],
}
)
assert canonical["ui"]["blueprint"] == "order_rendering"
assert canonical["ui"]["family"] == "order_line"
assert any(node["step"] == "blender_turntable" for node in canonical["nodes"])
assert any(node["step"] == "export_blend" for node in canonical["nodes"])
def test_canonicalize_workflow_config_rebuilds_starter_blueprints():
canonical = canonicalize_workflow_config(
{
"version": 1,
"ui": {"preset": "custom", "execution_mode": "legacy", "blueprint": "starter_cad_intake"},
"nodes": [],
"edges": [],
}
)
assert canonical["ui"]["blueprint"] == "starter_cad_intake"
assert canonical["ui"]["family"] == "cad_file"
assert canonical["nodes"] == [
{
"id": "resolve_step",
"step": "resolve_step_path",
"params": {},
"ui": {
"type": "inputNode",
"position": {"x": 120, "y": 140},
"label": "Resolve STEP Path",
},
}
]
def test_workflow_config_requires_canonicalization_for_legacy_payloads():
assert workflow_config_requires_canonicalization(
{
"type": "still",
"params": {"width": 1024, "height": 768},
}
)
def test_workflow_config_requires_canonicalization_skips_already_canonical_configs():
config = build_preset_workflow_config("still", {"width": 1024, "height": 768})
assert workflow_config_requires_canonicalization(config) is False
def test_build_workflow_blueprint_config_creates_cad_intake_family_graph():
config = build_workflow_blueprint_config("cad_intake")
assert config["version"] == 1
assert config["ui"]["preset"] == "custom"
assert config["ui"]["family"] == "cad_file"
assert config["ui"]["blueprint"] == "cad_intake"
assert [node["step"] for node in config["nodes"]] == [
"resolve_step_path",
"occ_object_extract",
"occ_glb_export",
"glb_bbox",
"stl_cache_generate",
"blender_render",
"threejs_render",
"thumbnail_save",
"thumbnail_save",
]
def test_build_workflow_blueprint_config_creates_order_rendering_family_graph():
config = build_workflow_blueprint_config("order_rendering")
assert config["version"] == 1
assert config["ui"]["preset"] == "custom"
assert config["ui"]["family"] == "order_line"
assert config["ui"]["blueprint"] == "order_rendering"
assert any(node["step"] == "blender_still" for node in config["nodes"])
assert any(node["step"] == "blender_turntable" for node in config["nodes"])
assert any(node["step"] == "export_blend" for node in config["nodes"])
assert sum(1 for node in config["nodes"] if node["step"] == "notify") == 3
def test_build_workflow_blueprint_config_creates_still_graph_reference():
config = build_workflow_blueprint_config("still_graph_reference")
assert config["version"] == 1
assert config["ui"]["preset"] == "custom"
assert config["ui"]["family"] == "order_line"
assert config["ui"]["blueprint"] == "still_graph_reference"
assert config["ui"]["execution_mode"] == "graph"
assert [node["step"] for node in config["nodes"]] == [
"order_line_setup",
"resolve_template",
"auto_populate_materials",
"glb_bbox",
"material_map_resolve",
"blender_still",
"output_save",
"notify",
]
render_node = next(node for node in config["nodes"] if node["step"] == "blender_still")
assert render_node["params"]["use_custom_render_settings"] is False
def test_build_starter_workflow_config_creates_minimal_valid_custom_graph():
config = build_starter_workflow_config()
assert config["version"] == 1
assert config["ui"]["preset"] == "custom"
assert config["ui"]["family"] == "order_line"
assert config["ui"]["blueprint"] == "starter_order_rendering"
assert config["nodes"] == [
{
"id": "setup",
"step": "order_line_setup",
"params": {},
"ui": {
"type": "processNode",
"position": {"x": 120, "y": 140},
"label": "Order Line Setup",
},
}
]