165 lines
6.0 KiB
Python
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
|