Files
FabledScribe/tests/test_services_rulebooks.py
T

104 lines
3.8 KiB
Python

"""Tests for services/rulebooks.py — mocks async_session, no real DB.
Mirrors the pattern in tests/test_events_service.py.
"""
from unittest.mock import AsyncMock, MagicMock, patch
from datetime import datetime, timezone
import pytest
def _make_mock_session():
s = AsyncMock()
s.__aenter__ = AsyncMock(return_value=s)
s.__aexit__ = AsyncMock(return_value=False)
s.add = MagicMock()
s.commit = AsyncMock()
s.refresh = AsyncMock()
return s
def _fake_rulebook(id=1, owner_user_id=7, title="FabledSword family", description=""):
rb = MagicMock()
rb.id = id
rb.owner_user_id = owner_user_id
rb.title = title
rb.description = description
rb.created_at = datetime.now(timezone.utc)
rb.updated_at = datetime.now(timezone.utc)
rb.to_dict.return_value = {
"id": id, "owner_user_id": owner_user_id,
"title": title, "description": description or "",
}
return rb
@pytest.mark.asyncio
async def test_create_rulebook_stores_to_db():
mock_session = _make_mock_session()
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import create_rulebook
await create_rulebook(
user_id=7, title="FabledSword family", description="rules for the family",
)
assert mock_session.add.called
assert mock_session.commit.called
@pytest.mark.asyncio
async def test_list_rulebooks_returns_owned_only():
rb = _fake_rulebook(id=1)
mock_session = _make_mock_session()
mock_result = MagicMock()
mock_result.scalars.return_value.all.return_value = [rb]
mock_session.execute = AsyncMock(return_value=mock_result)
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import list_rulebooks
results = await list_rulebooks(user_id=7)
assert len(results) == 1
@pytest.mark.asyncio
async def test_get_rulebook_returns_none_when_not_owner():
"""get_rulebook scopes by owner_user_id — wrong user gets None."""
mock_session = _make_mock_session()
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = None
mock_session.execute = AsyncMock(return_value=mock_result)
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import get_rulebook
result = await get_rulebook(rulebook_id=1, user_id=99)
assert result is None
@pytest.mark.asyncio
async def test_update_rulebook_only_sets_provided_fields():
rb = _fake_rulebook(id=1, title="old")
mock_session = _make_mock_session()
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = rb
mock_session.execute = AsyncMock(return_value=mock_result)
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import update_rulebook
await update_rulebook(rulebook_id=1, user_id=7, title="new")
assert rb.title == "new"
@pytest.mark.asyncio
async def test_delete_rulebook_calls_delete():
rb = _fake_rulebook(id=1)
mock_session = _make_mock_session()
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = rb
mock_session.execute = AsyncMock(return_value=mock_result)
mock_session.delete = AsyncMock()
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import delete_rulebook
await delete_rulebook(rulebook_id=1, user_id=7)
assert mock_session.delete.called