Files
kunail0804-ComfyUI-Scene-Co…/tests/test_configuration_node.py
T
87d9525176 feat(resolver): opt-in semantic nearest-neighbour fallback (#34) (#140)
Closes #114, #115, #116, #117.

- Deterministic, offline, dependency-free char-ngram embedding backend + config
  section (semantic.enabled default false, min_similarity, backend).
- Committed embedding index (data/kb_embedding_index.json) mapping vectors to real
  KB entry ids only; built by scripts/build_embedding_index.py, loaded once/cached.
- Resolver falls back to the nearest entry on a deterministic miss when enabled,
  accepting >= min_similarity and emitting SC0020; NSFW-gated neighbours are
  skipped. Disabled => byte-identical to before.
- Guarantee tests: deterministic lookup always wins (exact hit never queries the
  index), fallback emits only KB tags (no invention), identical input => identical
  output. SC0020 registered.

Co-authored-by: kunail0804 <kunail0804@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 18:23:38 +02:00

92 lines
3.3 KiB
Python

"""Tests for the Configuration ComfyUI node (issue #26)."""
from __future__ import annotations
import nodes
from compiler.common.config import Config
from nodes.configuration_node import ConfigurationNode
def default_inputs() -> dict:
return {
"analyzer_model": "llama3",
"analyzer_temperature": 0.0,
"analyzer_max_retries": 3,
"analyzer_timeout": 60,
"knowledge_base": "knowledge_base/",
"resolver_strict_mode": True,
"resolver_allow_aliases": True,
"resolver_expansion_enabled": True,
"resolver_max_expansion_depth": 8,
"resolver_include_nsfw": False,
"validator_allow_unknown_fields": False,
"prompt_target": "easy_illustrious",
"prompt_separator": ",",
"prompt_remove_duplicate_tags": True,
"debug_enabled": False,
"debug_level": "basic",
"semantic_enabled": False,
"semantic_min_similarity": 0.5,
"semantic_backend": "char_ngram",
}
def test_node_metadata() -> None:
assert ConfigurationNode.RETURN_TYPES == ("COMPILER_CONFIG", "STRING")
assert ConfigurationNode.RETURN_NAMES == ("config", "errors")
required = ConfigurationNode.INPUT_TYPES()["required"]
assert "analyzer_model" in required
assert "debug_level" in required
assert "analyzer_system_prompt" in ConfigurationNode.INPUT_TYPES()["optional"]
def test_default_inputs_produce_default_config() -> None:
config, errors = ConfigurationNode().run(**default_inputs())
assert isinstance(config, Config)
assert config == Config()
assert errors == ""
def test_inputs_flow_into_config() -> None:
inputs = default_inputs()
inputs["analyzer_model"] = "mistral"
inputs["resolver_max_expansion_depth"] = 4
inputs["resolver_include_nsfw"] = True
inputs["validator_allow_unknown_fields"] = True
inputs["prompt_separator"] = " | "
inputs["debug_enabled"] = True
inputs["debug_level"] = "verbose"
config, _ = ConfigurationNode().run(**inputs)
assert config.analyzer.model == "mistral"
assert config.resolver.max_expansion_depth == 4
assert config.resolver.include_nsfw is True
assert config.validator.allow_unknown_fields is True
assert config.prompt_builder.separator == " | "
assert config.debug.enabled is True
assert config.debug.level == "verbose"
def test_system_prompt_override_is_applied() -> None:
config, _ = ConfigurationNode().run(**default_inputs(), analyzer_system_prompt="CUSTOM")
assert config.analyzer.system_prompt == "CUSTOM"
def test_empty_system_prompt_is_omitted() -> None:
config, _ = ConfigurationNode().run(**default_inputs(), analyzer_system_prompt="")
assert config.analyzer.system_prompt is None
def test_debug_level_options_match_config_schema() -> None:
options = ConfigurationNode.INPUT_TYPES()["required"]["debug_level"][0]
for level in options:
inputs = default_inputs()
inputs["debug_level"] = level
config, errors = ConfigurationNode().run(**inputs)
assert isinstance(config, Config)
assert errors == ""
def test_registered_for_comfyui() -> None:
assert nodes.NODE_CLASS_MAPPINGS["SceneCompilerConfiguration"] is ConfigurationNode
assert nodes.NODE_DISPLAY_NAME_MAPPINGS["SceneCompilerConfiguration"] == "Configuration"