vibe/tests/cli/plan_offer/test_decide_plan_offer.py
Mathias Gesbert eb580209d4
v2.6.0 (#524)
Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Gauthier Guinet <43207538+Gguinet@users.noreply.github.com>
Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai>
Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com>
Co-authored-by: Quentin <torroba.q@gmail.com>
Co-authored-by: Simon <80467011+sorgfresser@users.noreply.github.com>
Co-authored-by: Simon Van de Kerckhove <simon.vandekerckhove@mistral.ai>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: angelapopopo <angele.lenglemetz@mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
2026-03-23 18:45:21 +01:00

173 lines
5.1 KiB
Python

from __future__ import annotations
from collections.abc import Generator
import logging
from os import environ
import pytest
from tests.cli.plan_offer.adapters.fake_whoami_gateway import FakeWhoAmIGateway
from vibe.cli.plan_offer.decide_plan_offer import (
WhoAmIPlanType,
decide_plan_offer,
resolve_api_key_for_plan,
)
from vibe.cli.plan_offer.ports.whoami_gateway import WhoAmIResponse
from vibe.core.config import ProviderConfig
from vibe.core.types import Backend
@pytest.fixture
def mistral_api_key_env() -> Generator[str, None, None]:
original_value = environ.get("MISTRAL_API_KEY")
test_api_key = "test_mistral_api_key"
environ["MISTRAL_API_KEY"] = test_api_key
yield test_api_key
if original_value is not None:
environ["MISTRAL_API_KEY"] = original_value
else:
del environ["MISTRAL_API_KEY"]
@pytest.mark.asyncio
async def test_returns_unknown_plan_when_api_key_is_empty() -> None:
gateway = FakeWhoAmIGateway(
WhoAmIResponse(
plan_type=WhoAmIPlanType.API,
plan_name="Free plan",
prompt_switching_to_pro_plan=False,
)
)
plan_info = await decide_plan_offer("", gateway)
assert plan_info.plan_type is WhoAmIPlanType.UNKNOWN
assert plan_info.plan_name == ""
assert plan_info.prompt_switching_to_pro_plan is False
assert gateway.calls == []
@pytest.mark.parametrize(
("response", "expected_plan_type", "expected_plan_name", "expected_switch_flag"),
[
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.API,
plan_name="Free Plan",
prompt_switching_to_pro_plan=False,
),
WhoAmIPlanType.API,
"Free Plan",
False,
),
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.CHAT,
plan_name="Pro Plan",
prompt_switching_to_pro_plan=False,
),
WhoAmIPlanType.CHAT,
"Pro Plan",
False,
),
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.CHAT,
plan_name="Pro Plan",
prompt_switching_to_pro_plan=True,
),
WhoAmIPlanType.CHAT,
"Pro Plan",
True,
),
],
ids=["api-plan", "chat-plan", "chat-plan-with-prompt"],
)
@pytest.mark.asyncio
async def test_returns_plan_info_and_proposes_an_action_based_on_current_plan_status(
response: WhoAmIResponse,
expected_plan_type: WhoAmIPlanType,
expected_plan_name: str,
expected_switch_flag: bool,
) -> None:
gateway = FakeWhoAmIGateway(response)
plan_info = await decide_plan_offer("api-key", gateway)
assert plan_info.plan_type is expected_plan_type
assert plan_info.plan_name == expected_plan_name
assert plan_info.prompt_switching_to_pro_plan is expected_switch_flag
assert gateway.calls == ["api-key"]
@pytest.mark.asyncio
async def test_returns_unauthorized_plan_when_api_key_is_unauthorized() -> None:
gateway = FakeWhoAmIGateway(unauthorized=True)
plan_info = await decide_plan_offer("bad-key", gateway)
assert plan_info.plan_type is WhoAmIPlanType.UNAUTHORIZED
assert plan_info.plan_name == ""
assert plan_info.prompt_switching_to_pro_plan is False
assert gateway.calls == ["bad-key"]
@pytest.mark.asyncio
async def test_returns_unknown_plan_and_logs_warning_when_gateway_error_occurs(
caplog: pytest.LogCaptureFixture,
) -> None:
gateway = FakeWhoAmIGateway(error=True)
with caplog.at_level(logging.WARNING):
plan_info = await decide_plan_offer("api-key", gateway)
assert plan_info.plan_type is WhoAmIPlanType.UNKNOWN
assert plan_info.plan_name == ""
assert plan_info.prompt_switching_to_pro_plan is False
assert gateway.calls == ["api-key"]
assert "Failed to fetch plan status." in caplog.text
def test_resolve_api_key_for_plan_with_mistral_backend(
mistral_api_key_env: str,
) -> None:
test_api_key = mistral_api_key_env
provider = ProviderConfig(
name="test_mistral",
api_base="https://api.mistral.ai",
backend=Backend.MISTRAL,
api_key_env_var="MISTRAL_API_KEY",
)
result = resolve_api_key_for_plan(provider)
assert result == test_api_key
def test_resolve_api_key_for_plan_with_non_mistral_backend(
mistral_api_key_env: str,
) -> None:
provider = ProviderConfig(
name="test_generic",
api_base="https://api.generic.ai",
backend=Backend.GENERIC,
api_key_env_var="GENERIC_API_KEY",
)
result = resolve_api_key_for_plan(provider)
assert result == mistral_api_key_env
def test_resolve_api_key_for_plan_with_missing_env_var() -> None:
previous_api_key = environ["MISTRAL_API_KEY"]
del environ["MISTRAL_API_KEY"]
provider = ProviderConfig(
name="test_mistral",
api_base="https://api.mistral.ai",
backend=Backend.MISTRAL,
api_key_env_var="MISTRAL_API_KEY",
)
result = resolve_api_key_for_plan(provider)
assert result is None
if previous_api_key is not None:
environ["MISTRAL_API_KEY"] = previous_api_key