Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT]: GET /api/v1/blogs/{blog_id}/engagement #1173

Closed
41 changes: 41 additions & 0 deletions api/v1/routes/blog.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,44 @@ def delete_blog_dislike(

# delete blog dislike
return blog_dislike_service.delete(blog_dislike_id, current_user.id)


@blog.get("/{blog_id}/engagement", response_model=success_response)
def get_blog_engagement(
blog_id: str,
db: Session = Depends(get_db),
):
"""Endpoint to get engagement statistics for a blog post.

Args:
blog_id (str): The ID of the blog post.
db (Session): The database session.

Returns:
JSON response with engagement statistics including likes, dislikes, and comment count.
"""
blog_service = BlogService(db)
comment_service = CommentService()

# Fetch blog post to ensure it exists
blog_post = blog_service.fetch(blog_id)
if not blog_post:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Blog post not found"
)

# Get engagement stats
likes_count = blog_service.num_of_likes(blog_id)
dislikes_count = blog_service.num_of_dislikes(blog_id)
comments_count = comment_service.get_comment_count(blog_id, db)

return success_response(
message="Engagement statistics retrieved successfully",
status_code=status.HTTP_200_OK,
data={
"blog_id": blog_id,
"likes": likes_count,
"dislikes": dislikes_count,
"comments": comments_count,
},
)
68 changes: 68 additions & 0 deletions tests/v1/blog/test_blog_engagement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import pytest
from fastapi.testclient import TestClient
from main import app
from api.v1.services.user import user_service
from api.v1.services.blog import BlogService
from api.v1.services.comment import CommentService
from sqlalchemy.orm import Session
from api.db.database import get_db
from api.v1.models import User, Blog
from uuid_extensions import uuid7
from unittest.mock import MagicMock

client = TestClient(app)

@pytest.fixture
def mock_db_session(mocker):
db_session_mock = mocker.MagicMock(spec=Session)
app.dependency_overrides[get_db] = lambda: db_session_mock
return db_session_mock

@pytest.fixture
def test_user():
return User(
id=str(uuid7()),
email="[email protected]",
password="hashedpassword",
first_name="Test",
last_name="User",
is_active=True,
)

@pytest.fixture
def test_blog(test_user):
return Blog(
id=str(uuid7()),
author_id=test_user.id,
title="Test Blog",
content="Testing blog engagement."
)

@pytest.fixture
def engagement_url(test_blog):
return f"/api/v1/blogs/{test_blog.id}/engagement"

@pytest.fixture
def test_user_access_token(test_user):
return user_service.create_access_token(user_id=test_user.id)

def test_get_blog_engagement(mock_db_session, test_blog, engagement_url, test_user_access_token, mocker):
# Mock BlogService methods
mock_blog_service = mocker.patch("api.v1.services.blog.BlogService", autospec=True)
blog_service_instance = mock_blog_service.return_value
blog_service_instance.fetch.return_value = test_blog
blog_service_instance.num_of_likes.return_value = 5
blog_service_instance.num_of_dislikes.return_value = 2

# Mock CommentService method
mock_comment_service = mocker.patch("api.v1.services.comment.CommentService", autospec=True)
comment_service_instance = mock_comment_service.return_value
comment_service_instance.get_comment_count.return_value = 3

headers = {'Authorization': f'Bearer {test_user_access_token}'}
response = client.get(engagement_url, headers=headers)

assert response.status_code == 200, f"Expected status code 200, got {response.status_code}"
assert response.json()['data']['likes'] == 5
assert response.json()['data']['dislikes'] == 2
assert response.json()['data']['comments'] == 3
Loading