103 lines
3.2 KiB
Python
103 lines
3.2 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 legacy External LLM Prompt node."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from simple_syrup.nodes.external_llm_prompt import ExternalLLMPrompt
|
|
from simple_syrup.services.external_llm_prompt_service import CONFIGURE_EXTERNAL_LLM
|
|
|
|
|
|
class FakeExternalLLMService:
|
|
"""Service double for node tests."""
|
|
|
|
def model_choices(self) -> list[str]:
|
|
"""Return deterministic model choices."""
|
|
|
|
return ["model-a"]
|
|
|
|
def generate(
|
|
self,
|
|
model: str,
|
|
system_prompt: str,
|
|
user_prompt: str,
|
|
max_tokens: int = 1024,
|
|
reasoning_effort: str = "default",
|
|
image: object | None = None,
|
|
) -> str:
|
|
"""Return a deterministic response."""
|
|
|
|
return (
|
|
f"{model}:{system_prompt}:{user_prompt}:"
|
|
f"{max_tokens}:{reasoning_effort}:{image}"
|
|
)
|
|
|
|
|
|
def test_external_llm_prompt_input_types_are_cached_and_single_line() -> None:
|
|
"""The node exposes cached model choices and single-line prompt widgets."""
|
|
|
|
original_service = ExternalLLMPrompt._service
|
|
ExternalLLMPrompt._service = FakeExternalLLMService() # type: ignore[assignment]
|
|
try:
|
|
input_types = ExternalLLMPrompt.INPUT_TYPES()
|
|
finally:
|
|
ExternalLLMPrompt._service = original_service
|
|
|
|
inputs = input_types["required"]
|
|
assert inputs["model"][0] == ["model-a"]
|
|
assert inputs["model"][1]["default"] == "model-a"
|
|
assert inputs["system_prompt"][0] == "STRING"
|
|
assert inputs["system_prompt"][1]["multiline"] is False
|
|
assert inputs["user_prompt"][0] == "STRING"
|
|
assert inputs["user_prompt"][1]["multiline"] is False
|
|
assert inputs["max_tokens"][0] == "INT"
|
|
assert inputs["max_tokens"][1]["default"] == 1024
|
|
assert inputs["max_tokens"][1]["min"] == 1
|
|
assert inputs["max_tokens"][1]["max"] == 32768
|
|
assert inputs["reasoning_effort"][0] == [
|
|
"default",
|
|
"high",
|
|
"medium",
|
|
"low",
|
|
"off",
|
|
]
|
|
assert inputs["reasoning_effort"][1]["default"] == "default"
|
|
assert input_types["optional"]["image"][0] == "IMAGE"
|
|
|
|
|
|
def test_external_llm_prompt_output_contract() -> None:
|
|
"""The node returns one named STRING output."""
|
|
|
|
assert ExternalLLMPrompt.RETURN_TYPES == ("STRING",)
|
|
assert ExternalLLMPrompt.RETURN_NAMES == ("response",)
|
|
assert ExternalLLMPrompt.FUNCTION == "generate"
|
|
|
|
|
|
def test_external_llm_prompt_executes_service() -> None:
|
|
"""Node execution delegates to the prompt service."""
|
|
|
|
node = ExternalLLMPrompt()
|
|
original_service = node._service
|
|
node._service = FakeExternalLLMService() # type: ignore[assignment]
|
|
try:
|
|
result = node.generate(
|
|
"model-a",
|
|
"system",
|
|
"user",
|
|
128,
|
|
"off",
|
|
image="image",
|
|
)
|
|
finally:
|
|
node._service = original_service
|
|
|
|
assert result == ("model-a:system:user:128:off:image",)
|
|
|
|
|
|
def test_external_llm_prompt_sentinel_constant_matches_plan() -> None:
|
|
"""The setup sentinel is stable for dropdown fallback behavior."""
|
|
|
|
assert CONFIGURE_EXTERNAL_LLM == "Configure external LLM endpoint"
|