feat(rulebook): service layer — Topic CRUD

This commit is contained in:
2026-05-27 21:17:54 -04:00
parent cfd801d181
commit 38e4220015
2 changed files with 158 additions and 0 deletions
+55
View File
@@ -101,3 +101,58 @@ async def test_delete_rulebook_calls_delete():
from fabledassistant.services.rulebooks import delete_rulebook
await delete_rulebook(rulebook_id=1, user_id=7)
assert mock_session.delete.called
# ── Topic CRUD ───────────────────────────────────────────────────────────
def _fake_topic(id=1, rulebook_id=1, title="git-workflow", description="", order_index=0):
t = MagicMock()
t.id = id
t.rulebook_id = rulebook_id
t.title = title
t.description = description
t.order_index = order_index
t.created_at = datetime.now(timezone.utc)
t.updated_at = datetime.now(timezone.utc)
t.to_dict.return_value = {
"id": id, "rulebook_id": rulebook_id, "title": title,
"description": description or "", "order_index": order_index,
}
return t
@pytest.mark.asyncio
async def test_create_topic_requires_owned_rulebook():
"""create_topic raises ValueError if the rulebook isn't owned by user."""
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 create_topic
with pytest.raises(ValueError, match="not found"):
await create_topic(
rulebook_id=999, user_id=7, title="git-workflow",
)
@pytest.mark.asyncio
async def test_list_topics_returns_topics_for_owned_rulebook():
rb = _fake_rulebook(id=1)
topic = _fake_topic(id=10, rulebook_id=1, title="git-workflow")
# Two execute calls: ownership check, then topic select.
mock_session = _make_mock_session()
rb_result = MagicMock()
rb_result.scalar_one_or_none.return_value = rb
topic_result = MagicMock()
topic_result.scalars.return_value.all.return_value = [topic]
mock_session.execute = AsyncMock(side_effect=[rb_result, topic_result])
with patch("fabledassistant.services.rulebooks.async_session") as mock_cls:
mock_cls.return_value = mock_session
from fabledassistant.services.rulebooks import list_topics
results = await list_topics(rulebook_id=1, user_id=7)
assert len(results) == 1
assert results[0].title == "git-workflow"