import pytest from app.config import Settings from app.errors import InvalidRequest from app.injector import build_workflow, new_seed, parse_size from app.templates import load_registry @pytest.fixture(scope="module") def registry(): return load_registry(Settings(_env_file=None)) def test_parse_size(): assert parse_size("1024x1024") == (1024, 1024) assert parse_size("832X1216") == (832, 1216) @pytest.mark.parametrize("bad", ["1024", "ax1024", "1024x", "0x100", "1024x-2", "wide"]) def test_parse_size_invalid(bad): with pytest.raises(InvalidRequest): parse_size(bad) def test_seed_random_differs(): assert new_seed(None) != new_seed(None) def test_seed_fixed_and_range(): assert new_seed(42) == 42 with pytest.raises(InvalidRequest): new_seed(-1) def test_create_injection_and_template_untouched(registry): create = registry["z-image-turbo"].graph graph = build_workflow(create, {"prompt": "a cat", "seed": 77, "negative": "", "width": 832, "height": 1216}) assert graph["83:27"]["inputs"]["text"] == "a cat" assert graph["83:13"]["inputs"]["width"] == 832 assert graph["83:13"]["inputs"]["height"] == 1216 assert graph["83:3"]["inputs"]["seed"] == 77 # template still holds placeholders (deep copy, no mutation) assert create["83:27"]["inputs"]["text"] == "{prompt}" assert create["83:13"]["inputs"]["width"] == "{width}" assert create["83:3"]["inputs"]["seed"] == "{seed}" def test_injection_is_typed(registry): graph = build_workflow(registry["z-image-turbo"].graph, {"prompt": "x", "seed": 7, "negative": "", "width": 64, "height": 128}) assert isinstance(graph["83:3"]["inputs"]["seed"], int) # numeric token -> int, not "{seed}" assert isinstance(graph["83:13"]["inputs"]["width"], int) assert isinstance(graph["83:27"]["inputs"]["text"], str) def test_embedded_token_is_string_interpolated(): graph = {"1": {"class_type": "X", "inputs": {"text": "prefix {prompt} suffix"}}} out = build_workflow(graph, {"prompt": "hi"}) assert out["1"]["inputs"]["text"] == "prefix hi suffix" def test_edit_injection(registry): edit = registry["qwen-image-edit"].graph graph = build_workflow(edit, {"prompt": "make it night", "seed": 5, "negative": "", "image": "adapter_x.png"}) assert graph["115:111"]["inputs"]["prompt"] == "make it night" assert graph["115:110"]["inputs"]["prompt"] == "" assert graph["78"]["inputs"]["image"] == "adapter_x.png" assert graph["115:3"]["inputs"]["seed"] == 5 def test_edit_seed_varies_per_call(registry): edit = registry["qwen-image-edit"].graph seeds = set() for _ in range(3): g = build_workflow(edit, {"prompt": "p", "seed": new_seed(None), "negative": "", "image": "a.png"}) seeds.add(g["115:3"]["inputs"]["seed"]) assert len(seeds) == 3 def test_unrecognized_token_rejected(): graph = {"1": {"class_type": "X", "inputs": {"text": "{foo}"}}} with pytest.raises(InvalidRequest, match="unrecognized token"): build_workflow(graph, {"prompt": "p"}) def test_unfilled_token_rejected(): graph = {"1": {"class_type": "X", "inputs": {"seed": "{seed}"}}} with pytest.raises(InvalidRequest, match="no value supplied"): build_workflow(graph, {"prompt": "p"})