innercontext/backend/tests/test_routines_auth.py

112 lines
3.4 KiB
Python

from __future__ import annotations
from datetime import UTC, datetime, timedelta
from unittest.mock import patch
from uuid import uuid4
from innercontext.api.auth_deps import get_current_user
from innercontext.auth import CurrentUser, IdentityData, TokenClaims
from innercontext.models import Role
from main import app
def _user(subject: str, *, role: Role = Role.MEMBER) -> CurrentUser:
claims = TokenClaims(
issuer="https://auth.test",
subject=subject,
audience=("innercontext-web",),
expires_at=datetime.now(UTC) + timedelta(hours=1),
raw_claims={"iss": "https://auth.test", "sub": subject},
)
return CurrentUser(
user_id=uuid4(),
role=role,
identity=IdentityData.from_claims(claims),
claims=claims,
)
def _set_current_user(user: CurrentUser) -> None:
app.dependency_overrides[get_current_user] = lambda: user
def test_suggest_uses_current_user_profile_and_visible_products_only(client):
owner = _user("owner")
other = _user("other")
_set_current_user(owner)
owner_profile = client.patch(
"/profile", json={"birth_date": "1991-01-15", "sex_at_birth": "male"}
)
owner_product = client.post(
"/products",
json={
"name": "Owner Serum",
"brand": "Test",
"category": "serum",
"recommended_time": "both",
"leave_on": True,
},
)
assert owner_profile.status_code == 200
assert owner_product.status_code == 201
_set_current_user(other)
other_profile = client.patch(
"/profile", json={"birth_date": "1975-06-20", "sex_at_birth": "female"}
)
other_product = client.post(
"/products",
json={
"name": "Other Serum",
"brand": "Test",
"category": "serum",
"recommended_time": "both",
"leave_on": True,
},
)
assert other_profile.status_code == 200
assert other_product.status_code == 201
_set_current_user(owner)
with patch(
"innercontext.api.routines.call_gemini_with_function_tools"
) as mock_gemini:
mock_response = type(
"Response",
(),
{
"text": '{"steps": [{"product_id": null, "action_type": "shaving_razor"}], "reasoning": "ok", "summary": {"primary_goal": "safe", "constraints_applied": [], "confidence": 0.7}}'
},
)
mock_gemini.return_value = (mock_response, None)
response = client.post(
"/routines/suggest",
json={
"routine_date": "2026-03-05",
"part_of_day": "am",
"include_minoxidil_beard": False,
},
)
assert response.status_code == 200
kwargs = mock_gemini.call_args.kwargs
prompt = kwargs["contents"]
assert "Birth date: 1991-01-15" in prompt
assert "Birth date: 1975-06-20" not in prompt
assert "Owner Serum" in prompt
assert "Other Serum" not in prompt
handler = kwargs["function_handlers"]["get_product_details"]
payload = handler(
{
"product_ids": [
owner_product.json()["id"],
other_product.json()["id"],
]
}
)
assert len(payload["products"]) == 1
assert payload["products"][0]["name"] == "Owner Serum"