117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
|
|
# Copyright (C) 2026 Artificial Sweetener and contributors
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
"""Tests for the Grounded SAM Model Info node declaration."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, cast
|
|
|
|
import pytest
|
|
|
|
from simple_syrup.nodes.grounded_sam_model_info import GroundedSAMModelInfo
|
|
|
|
|
|
def test_model_info_node_contract_constants() -> None:
|
|
"""Model info node constants match the public ComfyUI contract."""
|
|
|
|
assert GroundedSAMModelInfo.RETURN_TYPES == ("STRING",)
|
|
assert GroundedSAMModelInfo.RETURN_NAMES == ("model_info",)
|
|
assert GroundedSAMModelInfo.FUNCTION == "describe"
|
|
assert GroundedSAMModelInfo.CATEGORY == "SimpleSyrup/Masking"
|
|
|
|
|
|
def test_model_info_node_declares_expected_inputs(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Model info node exposes model selectors."""
|
|
|
|
class FakeChoices:
|
|
"""Return the known downloadable selections for declaration tests."""
|
|
|
|
def sam_choices(self) -> list[str]:
|
|
"""Return the expected SAM choice."""
|
|
|
|
return ["sam_hq_vit_b (379MB)"]
|
|
|
|
def grounding_dino_choices(self) -> list[str]:
|
|
"""Return the expected GroundingDINO choice."""
|
|
|
|
return ["GroundingDINO_SwinT_OGC (694MB)"]
|
|
|
|
monkeypatch.setattr(GroundedSAMModelInfo, "_choices", cast(Any, FakeChoices()))
|
|
input_types: dict[str, dict[str, tuple[Any, ...]]] = (
|
|
GroundedSAMModelInfo.INPUT_TYPES()
|
|
)
|
|
required = input_types["required"]
|
|
|
|
assert set(required) == {"sam_model", "grounding_dino_model"}
|
|
assert "sam_hq_vit_b (379MB)" in required["sam_model"][0]
|
|
assert "GroundingDINO_SwinT_OGC (694MB)" in required["grounding_dino_model"][0]
|
|
|
|
|
|
def test_model_info_node_uses_settings_aware_choices() -> None:
|
|
"""Model metadata selectors follow the downloadable-models preference."""
|
|
|
|
class FakeChoices:
|
|
"""Return the local-only choices supplied by settings policy."""
|
|
|
|
def sam_choices(self) -> list[str]:
|
|
"""Return the available SAM choices."""
|
|
|
|
return ["local-sam"]
|
|
|
|
def grounding_dino_choices(self) -> list[str]:
|
|
"""Return the available GroundingDINO choices."""
|
|
|
|
return ["local-dino"]
|
|
|
|
def reject_sentinel(self, selection: str) -> None:
|
|
"""Accept the deterministic test selections."""
|
|
|
|
del selection
|
|
|
|
original = GroundedSAMModelInfo._choices
|
|
GroundedSAMModelInfo._choices = cast(Any, FakeChoices())
|
|
try:
|
|
required = GroundedSAMModelInfo.INPUT_TYPES()["required"]
|
|
finally:
|
|
GroundedSAMModelInfo._choices = original
|
|
|
|
assert required["sam_model"][0] == ["local-sam"]
|
|
assert required["grounding_dino_model"][0] == ["local-dino"]
|
|
|
|
|
|
def test_model_info_node_delegates_to_metadata_provider() -> None:
|
|
"""Node execution delegates metadata creation to its metadata provider."""
|
|
|
|
class FakeMetadata:
|
|
"""Metadata double for model info."""
|
|
|
|
def describe_selection(self, sam_model: str, grounding_dino_model: str) -> str:
|
|
"""Return deterministic metadata."""
|
|
|
|
return f"{sam_model}|{grounding_dino_model}"
|
|
|
|
class FakeChoices:
|
|
"""Accept all model selections while exercising metadata delegation."""
|
|
|
|
def reject_sentinel(self, selection: str) -> None:
|
|
"""Accept the deterministic test selections."""
|
|
|
|
del selection
|
|
|
|
node = GroundedSAMModelInfo()
|
|
original = GroundedSAMModelInfo._metadata
|
|
original_choices = GroundedSAMModelInfo._choices
|
|
GroundedSAMModelInfo._metadata = FakeMetadata() # type: ignore[assignment]
|
|
GroundedSAMModelInfo._choices = cast(Any, FakeChoices())
|
|
try:
|
|
result = node.describe("sam", "dino")
|
|
finally:
|
|
GroundedSAMModelInfo._metadata = original
|
|
GroundedSAMModelInfo._choices = original_choices
|
|
|
|
assert result == ("sam|dino",)
|