"""Tests for the backend profiles (D2) — now wired (Fase 2), no longer skeletons.""" import pytest from agent_framework import BaseChatClient from portfolio_optimiser.backends import ( AzureFoundryBackend, ChatBackend, LocalBackend, Profile, get_backend, resolve_model, ) def test_get_backend_by_string() -> None: assert isinstance(get_backend("azure"), AzureFoundryBackend) assert isinstance(get_backend("local"), LocalBackend) def test_get_backend_by_enum() -> None: assert get_backend(Profile.AZURE).profile is Profile.AZURE assert get_backend(Profile.LOCAL).profile is Profile.LOCAL def test_backends_satisfy_seam() -> None: # Structural conformance to the ChatBackend Protocol (the D2 seam). assert isinstance(get_backend("azure"), ChatBackend) assert isinstance(get_backend("local"), ChatBackend) def test_unknown_profile_fails_fast() -> None: with pytest.raises(ValueError): get_backend("on-prem") def test_local_backend_returns_client_no_network(monkeypatch: pytest.MonkeyPatch) -> None: # Construction is offline (no network); the default base_url is loopback. monkeypatch.delenv("PORTFOLIO_LOCAL_BASE_URL", raising=False) client = get_backend("local").create_chat_client(model="qwen3:4b") assert isinstance(client, BaseChatClient) def test_azure_backend_fails_fast_without_endpoint(monkeypatch: pytest.MonkeyPatch) -> None: # Fail-fast (no silent default endpoint) — the operator must supply the Foundry endpoint. monkeypatch.delenv("PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT", raising=False) with pytest.raises(ValueError): get_backend("azure").create_chat_client(model="dummy-deployment") def test_model_map_resolves_role_to_model() -> None: assert resolve_model("local", "proposer") == "qwen3:4b" # Unknown role falls back to the profile default (still a non-empty id). assert resolve_model(Profile.LOCAL, "no-such-role")