59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
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()
|