Co-authored-by: Clément Drouin <clement.drouin@mistral.ai> Co-authored-by: Corentin André <corentin.andre@mistral.ai> Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com> Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com> Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai> Co-authored-by: Nelson PROIA <144663685+Nelson-PROIA@users.noreply.github.com> Co-authored-by: Peter Evers <pevers90@gmail.com> Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai> Co-authored-by: Quentin <quentin.torroba@mistral.ai> Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com> Co-authored-by: MichisGitIsKing <MichisGitIsKing@users.noreply.github.com> Co-authored-by: Mistral Vibe <vibe@mistral.ai>
224 lines
6.5 KiB
Python
224 lines
6.5 KiB
Python
from __future__ import annotations
|
|
|
|
import httpx
|
|
import pytest
|
|
import respx
|
|
|
|
from tests.conftest import build_test_vibe_config
|
|
from vibe.cli.plan_offer.adapters.http_whoami_gateway import HttpWhoAmIGateway
|
|
from vibe.cli.plan_offer.ports.whoami_gateway import (
|
|
WhoAmIGatewayError,
|
|
WhoAmIGatewayUnauthorized,
|
|
WhoAmIPlanType,
|
|
WhoAmIResponse,
|
|
)
|
|
from vibe.core.config import DEFAULT_CONSOLE_BASE_URL
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_returns_plan_flags(respx_mock: respx.MockRouter) -> None:
|
|
route = respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "CHAT",
|
|
"plan_name": "INDIVIDUAL",
|
|
"prompt_switching_to_pro_plan": False,
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
response = await gateway.whoami("api-key")
|
|
|
|
assert route.called
|
|
request = route.calls.last.request
|
|
assert request.headers["Authorization"] == "Bearer api-key"
|
|
assert response.plan_type == "CHAT"
|
|
assert response.plan_name == "INDIVIDUAL"
|
|
assert response.prompt_switching_to_pro_plan is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("status_code", [401, 403])
|
|
async def test_raises_on_unauthorized(
|
|
respx_mock: respx.MockRouter, status_code: int
|
|
) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(status_code, json={"error": "unauthorized"})
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
|
|
with pytest.raises(WhoAmIGatewayUnauthorized):
|
|
await gateway.whoami("bad-key")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_raises_on_non_success(respx_mock: respx.MockRouter) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(500, json={"error": "boom"})
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
|
|
with pytest.raises(WhoAmIGatewayError):
|
|
await gateway.whoami("api-key")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_incomplete_payload_defaults_missing_flags_to_false(
|
|
respx_mock: respx.MockRouter,
|
|
) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200, json={"plan_type": "CHAT", "plan_name": "INDIVIDUAL"}
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
response = await gateway.whoami("api-key")
|
|
assert response == WhoAmIResponse(
|
|
plan_type=WhoAmIPlanType.CHAT,
|
|
plan_name="INDIVIDUAL",
|
|
prompt_switching_to_pro_plan=False,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_raises_on_missing_plan_info(respx_mock: respx.MockRouter) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(200, json={"prompt_switching_to_pro_plan": False})
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
with pytest.raises(WhoAmIGatewayError):
|
|
await gateway.whoami("api-key")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_wraps_request_error(respx_mock: respx.MockRouter) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
side_effect=httpx.ConnectError("boom")
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
|
|
with pytest.raises(WhoAmIGatewayError):
|
|
await gateway.whoami("api-key")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parses_boolean_strings(respx_mock: respx.MockRouter) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "API",
|
|
"plan_name": "FREE",
|
|
"prompt_switching_to_pro_plan": "false",
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
response = await gateway.whoami("api-key")
|
|
assert response == WhoAmIResponse(
|
|
plan_type=WhoAmIPlanType.API,
|
|
plan_name="FREE",
|
|
prompt_switching_to_pro_plan=False,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_raises_on_invalid_boolean_string(respx_mock: respx.MockRouter) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "CHAT",
|
|
"plan_name": "INDIVIDUAL",
|
|
"prompt_switching_to_pro_plan": "something",
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
|
|
with pytest.raises(WhoAmIGatewayError):
|
|
await gateway.whoami("api-key")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_return_unknown_plan_on_unsupported_plan_type(
|
|
respx_mock: respx.MockRouter,
|
|
) -> None:
|
|
respx_mock.get("http://test/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "SOMETHING",
|
|
"plan_name": "INDIVIDUAL",
|
|
"prompt_switching_to_pro_plan": "false",
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url="http://test")
|
|
|
|
response = await gateway.whoami("api-key")
|
|
assert response == WhoAmIResponse(
|
|
plan_type=WhoAmIPlanType.UNKNOWN,
|
|
plan_name="INDIVIDUAL",
|
|
prompt_switching_to_pro_plan=False,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_gateway_calls_custom_console_base_url_from_config(
|
|
respx_mock: respx.MockRouter,
|
|
) -> None:
|
|
custom_url = "https://custom-console.example.com"
|
|
config = build_test_vibe_config(console_base_url=custom_url)
|
|
|
|
route = respx_mock.get(f"{custom_url}/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "CHAT",
|
|
"plan_name": "INDIVIDUAL",
|
|
"prompt_switching_to_pro_plan": False,
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url=config.console_base_url)
|
|
response = await gateway.whoami("api-key")
|
|
|
|
assert route.called
|
|
assert response.plan_type == "CHAT"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_gateway_uses_default_console_url_when_not_configured(
|
|
respx_mock: respx.MockRouter,
|
|
) -> None:
|
|
config = build_test_vibe_config()
|
|
|
|
assert config.console_base_url == DEFAULT_CONSOLE_BASE_URL
|
|
|
|
route = respx_mock.get(f"{DEFAULT_CONSOLE_BASE_URL}/api/vibe/whoami").mock(
|
|
return_value=httpx.Response(
|
|
200,
|
|
json={
|
|
"plan_type": "CHAT",
|
|
"plan_name": "INDIVIDUAL",
|
|
"prompt_switching_to_pro_plan": False,
|
|
},
|
|
)
|
|
)
|
|
|
|
gateway = HttpWhoAmIGateway(base_url=config.console_base_url)
|
|
await gateway.whoami("api-key")
|
|
|
|
assert route.called
|