All checks were successful
ci/woodpecker/pr/pipeline Pipeline was successful
Implement full comments system: domain entities (Comment, CommentLike), value objects (CommentContent), use cases (CRUD, like toggle), SQLAlchemy repository, API v1 endpoints, web UI with comment form and nested replies, i18n translations (EN/RU/FR/DE), and E2E tests. Fix nested reply (reply-to-reply) not displaying — the flat reply_comments dict was only queried for top-level comment IDs, so deeply nested replies were saved to DB (incrementing comment count) but never rendered. Switch to a recursive Jinja2 macro that renders any nesting depth.
129 lines
3.9 KiB
Python
129 lines
3.9 KiB
Python
"""Tests for CreateCommentUseCase.
|
|
|
|
This module tests comment creation use case covering top-level comments,
|
|
replies to existing comments, and post-not-found scenarios.
|
|
"""
|
|
|
|
from unittest.mock import AsyncMock, Mock
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
|
|
from app.application.use_cases.create_comment import CreateCommentUseCase
|
|
from app.domain.entities import Post
|
|
from app.domain.exceptions import NotFoundException
|
|
|
|
|
|
@pytest.fixture
|
|
def test_post() -> Post:
|
|
"""Create a test post for comment tests."""
|
|
return Post.create(
|
|
title_str="Commentable Post",
|
|
content_str="This post will receive comments. Enough length here.",
|
|
author_id="user-123",
|
|
tags=["test"],
|
|
)
|
|
|
|
|
|
class TestCreateCommentUseCase:
|
|
"""Tests for CreateCommentUseCase.
|
|
|
|
Covers TC-UNIT-832 through TC-UNIT-834.
|
|
"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_comment_on_post(
|
|
self,
|
|
mock_post_repository: Mock,
|
|
mock_transaction_manager: Mock,
|
|
test_post: Post,
|
|
) -> None:
|
|
"""Test creating a top-level comment on a post.
|
|
|
|
TC-UNIT-832: Positive — create top-level comment.
|
|
"""
|
|
mock_comment_repository = AsyncMock()
|
|
mock_post_repository.get_by_id = AsyncMock(return_value=test_post)
|
|
|
|
use_case = CreateCommentUseCase(
|
|
post_repo=mock_post_repository,
|
|
comment_repo=mock_comment_repository,
|
|
tx_manager=mock_transaction_manager,
|
|
)
|
|
|
|
result = await use_case.execute(
|
|
post_id=test_post.id,
|
|
author_id="user-456",
|
|
content="Great post! Thanks for sharing.",
|
|
)
|
|
|
|
assert result.post_id == test_post.id
|
|
assert result.author_id == "user-456"
|
|
assert result.content == "Great post! Thanks for sharing."
|
|
assert result.parent_id is None
|
|
assert result.like_count == 0
|
|
mock_comment_repository.add.assert_called_once()
|
|
mock_transaction_manager.commit.assert_called_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_comment_reply(
|
|
self,
|
|
mock_post_repository: Mock,
|
|
mock_transaction_manager: Mock,
|
|
test_post: Post,
|
|
) -> None:
|
|
"""Test creating a reply to an existing comment.
|
|
|
|
TC-UNIT-833: Positive — reply to comment with parent_id.
|
|
"""
|
|
mock_comment_repository = AsyncMock()
|
|
mock_post_repository.get_by_id = AsyncMock(return_value=test_post)
|
|
parent_id = uuid4()
|
|
|
|
use_case = CreateCommentUseCase(
|
|
post_repo=mock_post_repository,
|
|
comment_repo=mock_comment_repository,
|
|
tx_manager=mock_transaction_manager,
|
|
)
|
|
|
|
result = await use_case.execute(
|
|
post_id=test_post.id,
|
|
author_id="user-456",
|
|
content="This is a reply.",
|
|
parent_id=parent_id,
|
|
)
|
|
|
|
assert result.parent_id == parent_id
|
|
assert result.post_id == test_post.id
|
|
mock_comment_repository.add.assert_called_once()
|
|
mock_transaction_manager.commit.assert_called_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_comment_post_not_found(
|
|
self,
|
|
mock_post_repository: Mock,
|
|
mock_transaction_manager: Mock,
|
|
) -> None:
|
|
"""Test creating a comment on a non-existent post.
|
|
|
|
TC-UNIT-834: Negative — post not found.
|
|
"""
|
|
mock_comment_repository = AsyncMock()
|
|
mock_post_repository.get_by_id = AsyncMock(return_value=None)
|
|
|
|
use_case = CreateCommentUseCase(
|
|
post_repo=mock_post_repository,
|
|
comment_repo=mock_comment_repository,
|
|
tx_manager=mock_transaction_manager,
|
|
)
|
|
|
|
with pytest.raises(NotFoundException):
|
|
await use_case.execute(
|
|
post_id=uuid4(),
|
|
author_id="user-456",
|
|
content="Comment on missing post.",
|
|
)
|
|
|
|
mock_comment_repository.add.assert_not_called()
|
|
mock_transaction_manager.commit.assert_not_called()
|