From 57ced7930dee5c232488db9cdd0f588c2cf975c3 Mon Sep 17 00:00:00 2001 From: chengyongru Date: Thu, 11 Jun 2026 15:17:33 +0800 Subject: [PATCH] refactor: simplify dynamic provider settings tests maintainer edit: keep the WebUI dynamic-provider behavior unchanged while reducing repeated test setup and tightening the small dynamic-provider helper. --- nanobot/webui/settings_api.py | 10 +-- tests/webui/test_settings_api.py | 105 +++++++++++++------------------ 2 files changed, 49 insertions(+), 66 deletions(-) diff --git a/nanobot/webui/settings_api.py b/nanobot/webui/settings_api.py index 5194f23d7..0fbc4657b 100644 --- a/nanobot/webui/settings_api.py +++ b/nanobot/webui/settings_api.py @@ -334,11 +334,11 @@ def _provider_configured_for_settings(spec: Any, provider_config: Any) -> bool: def _dynamic_provider_items(config: Any) -> list[tuple[str, ProviderConfig]]: - items: list[tuple[str, ProviderConfig]] = [] - for name, provider_config in (config.providers.model_extra or {}).items(): - if isinstance(provider_config, ProviderConfig): - items.append((name, provider_config)) - return items + return [ + (name, provider_config) + for name, provider_config in (config.providers.model_extra or {}).items() + if isinstance(provider_config, ProviderConfig) + ] def _resolve_settings_provider( diff --git a/tests/webui/test_settings_api.py b/tests/webui/test_settings_api.py index 3e8e9061e..f01a51812 100644 --- a/tests/webui/test_settings_api.py +++ b/tests/webui/test_settings_api.py @@ -22,6 +22,31 @@ from nanobot.webui.settings_api import ( update_transcription_settings, ) +DYNAMIC_PROVIDER_NAME = "my-company-api" +DYNAMIC_PROVIDER_API_BASE = "https://example.test/v1" + + +def _dynamic_provider_config( + *, + api_base: str = DYNAMIC_PROVIDER_API_BASE, + defaults: bool = False, +) -> Config: + raw_config = { + "providers": { + DYNAMIC_PROVIDER_NAME: { + "apiBase": api_base, + } + } + } + if defaults: + raw_config["agents"] = { + "defaults": { + "provider": DYNAMIC_PROVIDER_NAME, + "model": "gpt-4o-mini", + } + } + return Config.model_validate(raw_config) + def test_create_model_configuration_writes_label_and_selects( tmp_path, @@ -70,30 +95,21 @@ def test_create_model_configuration_accepts_dynamic_custom_provider( monkeypatch: pytest.MonkeyPatch, ) -> None: config_path = tmp_path / "config.json" - config = Config.model_validate( - { - "providers": { - "my-company-api": { - "apiBase": "https://example.test/v1", - } - } - } - ) - save_config(config, config_path) + save_config(_dynamic_provider_config(), config_path) monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path) payload = create_model_configuration( { "label": ["Tenant model"], - "provider": ["my-company-api"], + "provider": [DYNAMIC_PROVIDER_NAME], "model": ["gpt-4o-mini"], } ) assert payload["agent"]["model_preset"] == "tenant-model" - assert payload["agent"]["provider"] == "my-company-api" + assert payload["agent"]["provider"] == DYNAMIC_PROVIDER_NAME saved = load_config(config_path) - assert saved.model_presets["tenant-model"].provider == "my-company-api" + assert saved.model_presets["tenant-model"].provider == DYNAMIC_PROVIDER_NAME assert saved.model_presets["tenant-model"].model == "gpt-4o-mini" @@ -162,31 +178,22 @@ def test_update_provider_settings_updates_dynamic_custom_provider( monkeypatch: pytest.MonkeyPatch, ) -> None: config_path = tmp_path / "config.json" - config = Config.model_validate( - { - "providers": { - "my-company-api": { - "apiBase": "https://old.example/v1", - } - } - } - ) - save_config(config, config_path) + save_config(_dynamic_provider_config(api_base="https://old.example/v1"), config_path) monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path) payload = update_provider_settings( { - "provider": ["my-company-api"], + "provider": [DYNAMIC_PROVIDER_NAME], "apiBase": ["https://new.example/v1"], "apiKey": ["sk-test"], } ) providers = {row["name"]: row for row in payload["providers"]} - assert providers["my-company-api"]["api_base"] == "https://new.example/v1" - assert providers["my-company-api"]["api_key_hint"] == "••••" + assert providers[DYNAMIC_PROVIDER_NAME]["api_base"] == "https://new.example/v1" + assert providers[DYNAMIC_PROVIDER_NAME]["api_key_hint"] == "••••" saved = load_config(config_path) - dynamic_provider = saved.providers.model_extra["my-company-api"] + dynamic_provider = saved.providers.model_extra[DYNAMIC_PROVIDER_NAME] assert dynamic_provider.api_base == "https://new.example/v1" assert dynamic_provider.api_key == "sk-test" @@ -295,32 +302,17 @@ def test_settings_payload_includes_dynamic_custom_provider( monkeypatch: pytest.MonkeyPatch, ) -> None: config_path = tmp_path / "config.json" - config = Config.model_validate( - { - "agents": { - "defaults": { - "provider": "my-company-api", - "model": "gpt-4o-mini", - } - }, - "providers": { - "my-company-api": { - "apiBase": "https://example.test/v1", - } - }, - } - ) - save_config(config, config_path) + save_config(_dynamic_provider_config(defaults=True), config_path) monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path) payload = settings_payload() providers = {row["name"]: row for row in payload["providers"]} - assert payload["agent"]["provider"] == "my-company-api" - assert payload["agent"]["resolved_provider"] == "my-company-api" - assert providers["my-company-api"]["configured"] is True - assert providers["my-company-api"]["api_key_required"] is False - assert providers["my-company-api"]["api_base"] == "https://example.test/v1" + assert payload["agent"]["provider"] == DYNAMIC_PROVIDER_NAME + assert payload["agent"]["resolved_provider"] == DYNAMIC_PROVIDER_NAME + assert providers[DYNAMIC_PROVIDER_NAME]["configured"] is True + assert providers[DYNAMIC_PROVIDER_NAME]["api_key_required"] is False + assert providers[DYNAMIC_PROVIDER_NAME]["api_base"] == DYNAMIC_PROVIDER_API_BASE def test_settings_payload_includes_network_safety_fields( @@ -783,20 +775,11 @@ def test_provider_models_payload_fetches_dynamic_custom_provider_models( monkeypatch: pytest.MonkeyPatch, ) -> None: config_path = tmp_path / "config.json" - config = Config.model_validate( - { - "providers": { - "my-company-api": { - "apiBase": "https://example.test/v1", - } - } - } - ) - save_config(config, config_path) + save_config(_dynamic_provider_config(), config_path) monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path) def fake_get(url: str, **kwargs): - assert url == "https://example.test/v1/models" + assert url == f"{DYNAMIC_PROVIDER_API_BASE}/models" assert "Authorization" not in kwargs["headers"] return httpx.Response( 200, @@ -806,9 +789,9 @@ def test_provider_models_payload_fetches_dynamic_custom_provider_models( monkeypatch.setattr("nanobot.webui.settings_api.httpx.get", fake_get) - payload = provider_models_payload({"provider": ["my-company-api"]}) + payload = provider_models_payload({"provider": [DYNAMIC_PROVIDER_NAME]}) - assert payload["provider"] == "my-company-api" + assert payload["provider"] == DYNAMIC_PROVIDER_NAME assert payload["status"] == "available" assert payload["catalog_kind"] == "custom" assert payload["models"][0]["id"] == "custom-gpt"