Merge branch 'organizations' (cherry-picked)
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"""Unit tests for OrganizationService."""
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest # type: ignore[import-not-found]
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.organization import Organization
|
||||
from app.models.organization_member import OrganizationMember, OrganizationRole
|
||||
from app.repositories.org_repo import OrganizationRepository
|
||||
from app.services.organization_service import (
|
||||
OrganizationAccessDeniedError,
|
||||
OrganizationContext,
|
||||
OrganizationContextMissingError,
|
||||
OrganizationForbiddenError,
|
||||
OrganizationService,
|
||||
)
|
||||
|
||||
|
||||
class StubOrganizationRepository(OrganizationRepository):
|
||||
"""Simple in-memory stand-in for OrganizationRepository."""
|
||||
|
||||
def __init__(self, membership: OrganizationMember | None) -> None:
|
||||
super().__init__(session=MagicMock(spec=AsyncSession))
|
||||
self._membership = membership
|
||||
|
||||
async def get_membership(self, organization_id: int, user_id: int) -> OrganizationMember | None: # pragma: no cover - helper
|
||||
if (
|
||||
self._membership
|
||||
and self._membership.organization_id == organization_id
|
||||
and self._membership.user_id == user_id
|
||||
):
|
||||
return self._membership
|
||||
return None
|
||||
|
||||
|
||||
def make_membership(role: OrganizationRole, *, organization_id: int = 1, user_id: int = 10) -> OrganizationMember:
|
||||
organization = Organization(name="Acme Inc")
|
||||
organization.id = organization_id
|
||||
membership = OrganizationMember(
|
||||
organization_id=organization_id,
|
||||
user_id=user_id,
|
||||
role=role,
|
||||
)
|
||||
membership.organization = organization
|
||||
return membership
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_context_success() -> None:
|
||||
membership = make_membership(OrganizationRole.MANAGER)
|
||||
service = OrganizationService(StubOrganizationRepository(membership))
|
||||
|
||||
context = await service.get_context(user_id=membership.user_id, organization_id=membership.organization_id)
|
||||
|
||||
assert context.organization_id == membership.organization_id
|
||||
assert context.role == OrganizationRole.MANAGER
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_context_missing_header() -> None:
|
||||
service = OrganizationService(StubOrganizationRepository(None))
|
||||
|
||||
with pytest.raises(OrganizationContextMissingError):
|
||||
await service.get_context(user_id=1, organization_id=None)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_context_access_denied() -> None:
|
||||
service = OrganizationService(StubOrganizationRepository(None))
|
||||
|
||||
with pytest.raises(OrganizationAccessDeniedError):
|
||||
await service.get_context(user_id=1, organization_id=99)
|
||||
|
||||
|
||||
def test_ensure_can_manage_settings_blocks_manager() -> None:
|
||||
membership = make_membership(OrganizationRole.MANAGER)
|
||||
organization = membership.organization
|
||||
assert organization is not None
|
||||
context = OrganizationContext(organization=organization, membership=membership)
|
||||
service = OrganizationService(StubOrganizationRepository(membership))
|
||||
|
||||
with pytest.raises(OrganizationForbiddenError):
|
||||
service.ensure_can_manage_settings(context)
|
||||
|
||||
|
||||
def test_member_must_own_entity() -> None:
|
||||
membership = make_membership(OrganizationRole.MEMBER)
|
||||
organization = membership.organization
|
||||
assert organization is not None
|
||||
context = OrganizationContext(organization=organization, membership=membership)
|
||||
service = OrganizationService(StubOrganizationRepository(membership))
|
||||
|
||||
with pytest.raises(OrganizationForbiddenError):
|
||||
service.ensure_member_owns_entity(context=context, owner_id=999)
|
||||
|
||||
# Same owner should pass silently.
|
||||
service.ensure_member_owns_entity(context=context, owner_id=membership.user_id)
|
||||
Reference in New Issue
Block a user