import tempfile import unittest from pathlib import Path from render_config import render class RenderConfigSlotTests(unittest.TestCase): def test_render_config_expands_scene_slot_bindings(self): with tempfile.TemporaryDirectory() as tmpdir: root = Path(tmpdir) template_path = root / "template.json" profile_path = root / "profile.json" template_path.write_text( """ { "name": "std_service_test_stream", "slots": { "inputs": [{"name": "video_input_main", "type": "video_source", "required": true}], "services": [{"name": "object_storage_main", "type": "object_storage", "required": false}], "outputs": [{"name": "stream_output_main", "type": "stream_publish", "required": true}] }, "template": { "nodes": [ {"id": "input_rtsp_main", "type": "input_rtsp", "url": "${slot:video_input_main.url}"}, {"id": "publish_stream", "type": "publish", "outputs": [{"proto": "hls", "path": "${slot:stream_output_main.publish_hls_path}"}]} ], "edges": [] } } """.strip(), encoding="utf-8", ) profile_path.write_text( """ { "name": "line_a", "instances": [ { "name": "cam1", "template": "std_service_test_stream", "scene_meta": { "display_name": "B厂区通道1" }, "input_bindings": { "video_input_main": { "resolved": { "url": "rtsp://10.0.0.1/live" } } }, "output_bindings": { "stream_output_main": { "publish_hls_path": "./web/hls/cam1/index.m3u8" } } } ] } """.strip(), encoding="utf-8", ) rendered = render(template_path, profile_path, []) self.assertIn("templates", rendered) self.assertIn("instances", rendered) self.assertEqual(1, len(rendered["instances"])) instance = rendered["instances"][0] self.assertEqual("std_service_test_stream__cam1", instance["template"]) template = rendered["templates"][instance["template"]] self.assertEqual("rtsp://10.0.0.1/live", template["nodes"][0]["url"]) self.assertEqual("./web/hls/cam1/index.m3u8", template["nodes"][1]["outputs"][0]["path"]) if __name__ == "__main__": unittest.main()