Files
kunail0804-ComfyUI-Scene-Co…/tests/test_knowledge_base_loader_node.py
T
712be0d30a feat(nodes): centralize duplicated settings on Configuration + add tooltips (#144)
The Scene Analyzer built its own Config from local model_name/temperature/
timeout/system_prompt widgets and ignored the Configuration node entirely, so
the analyzer model was set in two disconnected places (bug report #4).

- Scene Analyzer: add an optional `config` (COMPILER_CONFIG) input and drop the
  duplicated model/temperature/timeout widgets. Settings now come from the
  Configuration node; without one, defaults apply with a 300 s cold-load-friendly
  timeout. A non-empty `system_prompt` widget still overrides the config.
- Knowledge Base Loader: accept an optional `config`; when wired, its KB path and
  version take precedence over the node's own widgets.
- Add tooltips to every input on all six nodes.

Docs (docs/nodes.md) updated for the Analyzer/KB Loader input changes.

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

83 lines
3.2 KiB
Python

"""Tests for the Knowledge Base Loader ComfyUI node (issue #25)."""
from __future__ import annotations
import json
import nodes
from compiler.common.config import Config
from compiler.common.knowledge_base import KnowledgeBase
from nodes.knowledge_base_loader_node import KnowledgeBaseLoaderNode
def write_kb(directory, entries: list[dict]) -> str:
(directory / "hair.json").write_text(json.dumps(entries), encoding="utf-8")
return str(directory)
def test_node_metadata() -> None:
assert KnowledgeBaseLoaderNode.RETURN_TYPES == ("KNOWLEDGE_BASE", "STRING", "STRING", "STRING")
assert KnowledgeBaseLoaderNode.RETURN_NAMES == ("knowledge_base", "warnings", "errors", "raw")
inputs = KnowledgeBaseLoaderNode.INPUT_TYPES()
assert "path" in inputs["required"]
assert "reload" in inputs["optional"]
def test_loads_knowledge_base(tmp_path) -> None:
path = write_kb(tmp_path, [{"id": "long_hair", "tags": ["long hair"], "category": "hair"}])
kb, warnings, errors, *_ = KnowledgeBaseLoaderNode().run(path)
assert isinstance(kb, KnowledgeBase)
assert kb.get("long_hair") is not None
assert (warnings, errors) == ("", "")
def test_invalid_knowledge_base_surfaces_sc0004(tmp_path) -> None:
path = write_kb(tmp_path, [{"id": "x", "tags": ["x"], "category": "nope"}])
kb, warnings, errors, *_ = KnowledgeBaseLoaderNode().run(path)
assert kb is None
assert "SC0004" in errors
def test_relative_path_resolves_against_package(monkeypatch, tmp_path) -> None:
# Even with an unrelated working directory (as under ComfyUI), the default
# relative path must load the shipped Knowledge Base, not an empty one.
monkeypatch.chdir(tmp_path)
kb, warnings, errors, raw = KnowledgeBaseLoaderNode().run("knowledge_base/")
assert isinstance(kb, KnowledgeBase)
assert len(kb) > 100
assert (warnings, errors) == ("", "")
assert "entries" in raw
def test_empty_knowledge_base_warns(tmp_path) -> None:
kb, warnings, errors, raw = KnowledgeBaseLoaderNode().run(str(tmp_path))
assert len(kb) == 0
assert "empty" in warnings.lower()
def test_reload_input_is_accepted(tmp_path) -> None:
path = write_kb(tmp_path, [{"id": "long_hair", "tags": ["long hair"], "category": "hair"}])
kb, _, _, _ = KnowledgeBaseLoaderNode().run(path, reload=5)
assert isinstance(kb, KnowledgeBase)
def test_config_path_overrides_the_widget(tmp_path) -> None:
# A connected Configuration node is the single source of truth: its Knowledge
# Base path wins over the node's own ``path`` widget.
config_path = write_kb(
tmp_path, [{"id": "long_hair", "tags": ["long hair"], "category": "hair"}]
)
config = Config.from_json({"resolver": {"knowledge_base": config_path}})
kb, warnings, errors, *_ = KnowledgeBaseLoaderNode().run("does/not/exist", config=config)
assert isinstance(kb, KnowledgeBase)
assert kb.get("long_hair") is not None
assert (warnings, errors) == ("", "")
def test_registered_for_comfyui() -> None:
assert nodes.NODE_CLASS_MAPPINGS["SceneCompilerKnowledgeBaseLoader"] is KnowledgeBaseLoaderNode
assert (
nodes.NODE_DISPLAY_NAME_MAPPINGS["SceneCompilerKnowledgeBaseLoader"]
== "Knowledge Base Loader"
)