mirror of https://github.com/razor-ai/soup.git
147 lines
4.4 KiB
Python
147 lines
4.4 KiB
Python
"""v0.44.0 Part C — UI plugin registry + env knob tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from soup_cli.ui.plugins import (
|
|
clear_tabs,
|
|
get_tab,
|
|
list_tabs,
|
|
register_tab,
|
|
)
|
|
from soup_cli.utils.ui_env import UiEnv, resolve_ui_env
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _clean_tabs():
|
|
"""Each test starts with an empty tab registry."""
|
|
clear_tabs()
|
|
yield
|
|
clear_tabs()
|
|
|
|
|
|
# --- plugin registry --------------------------------------------------------
|
|
|
|
def test_register_tab_happy():
|
|
spec = register_tab(name="my-tab", title="My Tab", render=lambda: "hi")
|
|
assert spec.name == "my-tab"
|
|
assert spec.title == "My Tab"
|
|
assert get_tab("my-tab") is spec
|
|
|
|
|
|
def test_register_tab_immutable_view():
|
|
register_tab(name="t1", title="T1", render=lambda: "x")
|
|
snapshot = list_tabs()
|
|
with pytest.raises(TypeError):
|
|
snapshot["x"] = None # type: ignore[index]
|
|
|
|
|
|
def test_register_tab_rejects_invalid_name():
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="Bad Name", title="x", render=lambda: "y")
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="-leading", title="x", render=lambda: "y")
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="x" * 99, title="x", render=lambda: "y")
|
|
|
|
|
|
def test_register_tab_rejects_invalid_title():
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="t", title="", render=lambda: "x")
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="t", title="bad\x00", render=lambda: "x")
|
|
with pytest.raises(ValueError):
|
|
register_tab(name="t", title="x" * 200, render=lambda: "x")
|
|
|
|
|
|
def test_register_tab_rejects_non_callable_render():
|
|
with pytest.raises(TypeError):
|
|
register_tab(name="t", title="x", render="not callable") # type: ignore[arg-type]
|
|
|
|
|
|
def test_register_tab_idempotent_for_same_spec():
|
|
fn = lambda: "y" # noqa: E731
|
|
spec1 = register_tab(name="t", title="T", render=fn)
|
|
spec2 = register_tab(name="t", title="T", render=fn)
|
|
assert spec1 == spec2
|
|
|
|
|
|
def test_register_tab_rejects_re_register_with_different_spec():
|
|
register_tab(name="t", title="T", render=lambda: "x")
|
|
with pytest.raises(ValueError, match="already registered"):
|
|
register_tab(name="t", title="OTHER", render=lambda: "y")
|
|
|
|
|
|
def test_register_tab_too_many():
|
|
for idx in range(32):
|
|
register_tab(name=f"t{idx}", title=f"T{idx}", render=lambda: "x")
|
|
with pytest.raises(RuntimeError, match="too many tabs"):
|
|
register_tab(name="overflow", title="x", render=lambda: "x")
|
|
|
|
|
|
def test_get_tab_unknown_returns_none():
|
|
assert get_tab("nope") is None
|
|
assert get_tab(123) is None # type: ignore[arg-type]
|
|
|
|
|
|
# --- UI env knobs -----------------------------------------------------------
|
|
|
|
def test_resolve_ui_env_empty():
|
|
env = resolve_ui_env({})
|
|
assert env == UiEnv(None, None, None, None, None)
|
|
|
|
|
|
def test_resolve_ui_env_full():
|
|
env = resolve_ui_env(
|
|
{
|
|
"API_HOST": "127.0.0.1",
|
|
"API_PORT": "8080",
|
|
"API_KEY": "secret-key-1234",
|
|
"GRADIO_HOST": "0.0.0.0",
|
|
"GRADIO_PORT": "7860",
|
|
}
|
|
)
|
|
assert env.api_host == "127.0.0.1"
|
|
assert env.api_port == 8080
|
|
assert env.api_key == "secret-key-1234"
|
|
assert env.gradio_host == "0.0.0.0"
|
|
assert env.gradio_port == 7860
|
|
|
|
|
|
def test_resolve_ui_env_invalid_port():
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_PORT": "0"})
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_PORT": "99999"})
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_PORT": "not-int"})
|
|
|
|
|
|
def test_resolve_ui_env_invalid_host():
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_HOST": "bad host with spaces"})
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_HOST": "x\x00bad"})
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_HOST": "x" * 300})
|
|
|
|
|
|
def test_resolve_ui_env_blank_treated_as_missing():
|
|
env = resolve_ui_env({"API_HOST": " ", "API_KEY": " "})
|
|
assert env.api_host is None
|
|
assert env.api_key is None
|
|
|
|
|
|
def test_resolve_ui_env_invalid_key():
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_KEY": "k\x00ey"})
|
|
with pytest.raises(ValueError):
|
|
resolve_ui_env({"API_KEY": "k" * 1000})
|
|
|
|
|
|
def test_ui_env_frozen():
|
|
env = UiEnv(None, None, None, None, None)
|
|
with pytest.raises(Exception):
|
|
env.api_host = "x" # type: ignore[misc]
|