import asyncio from uuid import UUID import pytest from unittest.mock import MagicMock from app.core.tenant_context import ( set_current_account_id, clear_current_account_id, get_current_account_id, ) def test_contextvar_is_none_by_default(): assert get_current_account_id() is None def test_set_and_clear(): account_id = UUID("aaaaaaaa-0000-0000-0000-000000000001") token = set_current_account_id(account_id) assert get_current_account_id() == str(account_id) clear_current_account_id(token) assert get_current_account_id() is None def test_tasks_are_isolated(): """Each asyncio task has its own ContextVar value.""" results = {} async def set_in_task(name: str, value: str): token = set_current_account_id(UUID(value)) await asyncio.sleep(0) results[name] = get_current_account_id() clear_current_account_id(token) async def run(): await asyncio.gather( set_in_task("a", "aaaaaaaa-0000-0000-0000-000000000001"), set_in_task("b", "bbbbbbbb-0000-0000-0000-000000000002"), ) asyncio.run(run()) assert results["a"] == "aaaaaaaa-0000-0000-0000-000000000001" assert results["b"] == "bbbbbbbb-0000-0000-0000-000000000002" @pytest.mark.asyncio async def test_require_tenant_context_raises_403_when_no_account(): from fastapi import HTTPException from app.api.deps import require_tenant_context user = MagicMock() user.account_id = None gen = require_tenant_context(current_user=user) with pytest.raises(HTTPException) as exc_info: await gen.__anext__() assert exc_info.value.status_code == 403 assert "account required" in exc_info.value.detail.lower()