Files

165 lines
6.0 KiB
Python

from types import SimpleNamespace
import pytest
from fastapi import HTTPException
from app.gateway.routers import system_settings as system_settings_router
from deerflow.config.html_runtime_config import (
DEFAULT_HTML_MAP_TILE_URL,
DEFAULT_HTML_RUNTIME_BASE_URL,
)
from deerflow.config.system_settings import HtmlRuntimeSettings, SystemSettings
from deerflow.html_runtime.addresses import (
html_map_tile_url,
html_runtime_base_url,
normalize_html_map_tile_url,
normalize_html_runtime_base_url,
)
def test_domain_only_runtime_address_receives_the_public_asset_path() -> None:
assert (
normalize_html_runtime_base_url("https://cm.example.com/")
== "https://cm.example.com/api/public/html-runtime"
)
assert (
normalize_html_runtime_base_url("https://cm.example.com/prefix/api/public/html-runtime/")
== "https://cm.example.com/prefix/api/public/html-runtime"
)
def test_runtime_address_rejects_a_bare_host_and_credentials() -> None:
with pytest.raises(ValueError, match="http://"):
normalize_html_runtime_base_url("cm.example.com")
with pytest.raises(ValueError, match="账号或密码"):
normalize_html_runtime_base_url("https://user:secret@cm.example.com")
def test_tile_address_requires_xyz_placeholders() -> None:
assert normalize_html_map_tile_url(DEFAULT_HTML_MAP_TILE_URL) == DEFAULT_HTML_MAP_TILE_URL
with pytest.raises(ValueError, match="占位符"):
normalize_html_map_tile_url("https://tiles.example/tile.png")
def test_saved_dialog_address_overrides_config(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
"deerflow.html_runtime.addresses._saved",
lambda field: {
"base_url": "https://users.example/api/public/html-runtime",
"map_tile_url": "https://tiles.example/{z}/{x}/{y}.png",
}[field],
)
monkeypatch.setattr(
"deerflow.html_runtime.addresses._config_value",
lambda _field: "http://server.internal/api/public/html-runtime",
)
assert html_runtime_base_url(fallback="http://fallback.example/api/public/html-runtime") == (
"https://users.example/api/public/html-runtime"
)
assert html_map_tile_url() == "https://tiles.example/{z}/{x}/{y}.png"
def test_unset_dialog_address_keeps_the_config_fallback(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr("deerflow.html_runtime.addresses._saved", lambda _field: "")
monkeypatch.setattr(
"deerflow.html_runtime.addresses._config_value",
lambda field: {
"base_url": "http://legacy.example/api/public/html-runtime",
"map_tile_url": "http://legacy.example/tiles/{z}/{x}/{y}.png",
}[field],
)
assert html_runtime_base_url() == "http://legacy.example/api/public/html-runtime"
assert html_map_tile_url() == "http://legacy.example/tiles/{z}/{x}/{y}.png"
def test_missing_config_uses_the_built_in_default(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr("deerflow.html_runtime.addresses._saved", lambda _field: "")
monkeypatch.setattr("deerflow.html_runtime.addresses._config_value", lambda _field: "")
assert html_runtime_base_url() == DEFAULT_HTML_RUNTIME_BASE_URL
assert html_map_tile_url() == DEFAULT_HTML_MAP_TILE_URL
def test_new_settings_leave_html_runtime_unset() -> None:
assert SystemSettings().html_runtime == HtmlRuntimeSettings()
@pytest.mark.asyncio
async def test_non_admin_cannot_change_html_runtime_addresses(
monkeypatch: pytest.MonkeyPatch,
) -> None:
async def ordinary_user(_request):
return SimpleNamespace(system_role="user")
monkeypatch.setattr(
system_settings_router,
"get_optional_user_from_request",
ordinary_user,
)
with pytest.raises(HTTPException) as error:
await system_settings_router.update_html_runtime_settings(
system_settings_router.HtmlRuntimeSettingsUpdateRequest(
base_url="https://users.example",
map_tile_url="https://tiles.example/{z}/{x}/{y}.png",
),
SimpleNamespace(),
)
assert error.value.status_code == 403
@pytest.mark.asyncio
async def test_admin_can_save_html_runtime_addresses(
monkeypatch: pytest.MonkeyPatch,
) -> None:
current = SystemSettings()
saved: list[SystemSettings] = []
async def admin_user(_request):
return SimpleNamespace(system_role="admin")
monkeypatch.setattr(system_settings_router, "get_optional_user_from_request", admin_user)
monkeypatch.setattr(system_settings_router, "load_system_settings", lambda: current)
monkeypatch.setattr(
system_settings_router,
"save_system_settings",
lambda settings: saved.append(settings) or settings,
)
response = await system_settings_router.update_html_runtime_settings(
system_settings_router.HtmlRuntimeSettingsUpdateRequest(
base_url="https://users.example",
map_tile_url="https://tiles.example/{z}/{x}/{y}.png",
),
SimpleNamespace(),
)
assert response.base_url == "https://users.example/api/public/html-runtime"
assert response.map_tile_url == "https://tiles.example/{z}/{x}/{y}.png"
assert saved[0].html_runtime.base_url == response.base_url
assert saved[0].prompt_prefix == current.prompt_prefix
@pytest.mark.asyncio
async def test_invalid_html_runtime_address_is_rejected(
monkeypatch: pytest.MonkeyPatch,
) -> None:
async def admin_user(_request):
return SimpleNamespace(system_role="admin")
monkeypatch.setattr(system_settings_router, "get_optional_user_from_request", admin_user)
with pytest.raises(HTTPException) as error:
await system_settings_router.update_html_runtime_settings(
system_settings_router.HtmlRuntimeSettingsUpdateRequest(
base_url="not a url",
map_tile_url="https://tiles.example/{z}/{x}/{y}.png",
),
SimpleNamespace(),
)
assert error.value.status_code == 400