Skip to content

Commit 9adeb4f

Browse files
authored
Merge pull request #1157 from eniolaomotee/eniola-changes
[feat]:Implement an endpoint to retrieve all testimonials associated with a specific user.
2 parents a8378a3 + 1b849c7 commit 9adeb4f

3 files changed

Lines changed: 144 additions & 1 deletion

File tree

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,3 @@ alembic revision --autogenerate -m 'your migration message'
254254
- **Push Alembic migrations** if database models are modified.
255255
- Ensure your code **follows project standards** and **passes tests** before submitting a pull request.
256256
257-
💯 Happy coding!

api/v1/routes/testimonial.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515
from typing import Annotated
1616
from api.utils.pagination import paginated_response
1717
from api.v1.models.testimonial import Testimonial
18+
import json
19+
import logging
20+
from api.utils.logger import logger
1821

1922
testimonial = APIRouter(prefix="/testimonials", tags=['Testimonial'])
2023

24+
logger = logging.getLogger(__name__)
25+
2126

2227
@testimonial.get("", status_code=status.HTTP_200_OK)
2328
def get_testimonials(
@@ -90,3 +95,36 @@ def create_testimonial(
9095
data={"id": testimonial.id}
9196
)
9297
return response
98+
99+
@testimonial.get("/user/{user_id}", status_code=status.HTTP_200_OK)
100+
def get_user_testimonials(
101+
user_id: str,
102+
page_size: Annotated[int, Query(ge=1, description="Number of testimonials per page")] = 10,
103+
page: Annotated[int, Query(ge=1, description="Page number (starts from 1)")] = 0,
104+
db: Session = Depends(get_db),
105+
current_user: User = Depends(user_service.get_current_user),
106+
):
107+
"""Endpoint to get all testimonials for a specific user with pagination"""
108+
try:
109+
# Only check if user is accessing their own testimonials
110+
if user_id != str(current_user.id):
111+
return {
112+
"status_code": 403,
113+
"message": "You can only view your own testimonials"
114+
}
115+
116+
# Simply return the paginated response
117+
return paginated_response(
118+
db=db,
119+
model=Testimonial,
120+
limit=page_size,
121+
skip=max(page, 0),
122+
filters={"author_id": user_id}
123+
)
124+
125+
except Exception as e:
126+
logger.exception(f"Error retrieving testimonials: {str(e)}")
127+
return {
128+
"status_code": 500,
129+
"message": "An unexpected error occurred"
130+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from unittest.mock import patch, MagicMock
4+
from main import app
5+
from api.v1.models.user import User
6+
from api.v1.models.testimonial import Testimonial
7+
from api.v1.services.user import user_service
8+
from uuid_extensions import uuid7
9+
from api.db.database import get_db
10+
from fastapi import status
11+
from datetime import datetime, timezone
12+
13+
client = TestClient(app)
14+
15+
@pytest.fixture
16+
def mock_db_session():
17+
"""Fixture to create a mock database session."""
18+
with patch("api.v1.services.user.get_db", autospec=True) as mock_get_db:
19+
mock_db = MagicMock()
20+
app.dependency_overrides[get_db] = lambda: mock_db
21+
yield mock_db
22+
app.dependency_overrides = {}
23+
24+
@pytest.fixture
25+
def mock_user_service():
26+
"""Fixture to create a mock user service."""
27+
with patch("api.v1.services.user.user_service", autospec=True) as mock_service:
28+
yield mock_service
29+
30+
def create_mock_user(mock_user_service, mock_db_session):
31+
"""Create a mock user in the mock database session."""
32+
mock_user = User(
33+
id=str(uuid7()),
34+
email="testuser@example.com",
35+
password=user_service.hash_password("TestPassword123!"),
36+
first_name="Test",
37+
last_name="User",
38+
is_active=True,
39+
created_at=datetime.now(timezone.utc),
40+
updated_at=datetime.now(timezone.utc)
41+
)
42+
mock_db_session.query.return_value.filter.return_value.first.return_value = mock_user
43+
return mock_user
44+
45+
def test_get_user_testimonials_success(mock_user_service, mock_db_session):
46+
"""Test successful retrieval of user testimonials"""
47+
mock_user = create_mock_user(mock_user_service, mock_db_session)
48+
49+
# Setup mock query for pagination
50+
mock_query = MagicMock()
51+
mock_query.filter.return_value = mock_query
52+
mock_query.offset.return_value = mock_query
53+
mock_query.limit.return_value = mock_query
54+
mock_query.all.return_value = []
55+
mock_query.count.return_value = 0
56+
57+
mock_db_session.query.return_value = mock_query
58+
59+
# Override dependency
60+
app.dependency_overrides[user_service.get_current_user] = lambda: mock_user
61+
62+
response = client.get(
63+
f"/api/v1/testimonials/user/{mock_user.id}",
64+
headers={"Authorization": f"Bearer {user_service.create_access_token(str(mock_user.id))}"}
65+
)
66+
67+
assert response.status_code == 200
68+
data = response.json()
69+
assert "data" in data
70+
assert "items" in data["data"]
71+
assert "total" in data["data"]
72+
73+
def test_get_user_testimonials_unauthorized():
74+
"""Test testimonial retrieval without authentication"""
75+
response = client.get(f"/api/v1/testimonials/user/some-id")
76+
assert response.status_code == 401
77+
data = response.json()
78+
assert data["message"] == "Not authenticated"
79+
80+
def test_get_user_testimonials_no_testimonials(mock_user_service, mock_db_session):
81+
"""Test when user has no testimonials"""
82+
mock_user = create_mock_user(mock_user_service, mock_db_session)
83+
84+
# Setup mock query for pagination
85+
mock_query = MagicMock()
86+
mock_query.filter.return_value = mock_query
87+
mock_query.offset.return_value = mock_query
88+
mock_query.limit.return_value = mock_query
89+
mock_query.all.return_value = []
90+
mock_query.count.return_value = 0
91+
92+
mock_db_session.query.return_value = mock_query
93+
94+
# Override dependency
95+
app.dependency_overrides[user_service.get_current_user] = lambda: mock_user
96+
97+
response = client.get(
98+
f"/api/v1/testimonials/user/{mock_user.id}",
99+
headers={"Authorization": f"Bearer {user_service.create_access_token(str(mock_user.id))}"}
100+
)
101+
102+
assert response.status_code == 200
103+
data = response.json()
104+
assert "data" in data
105+
assert len(data["data"]["items"]) == 0
106+
assert data["data"]["total"] == 0

0 commit comments

Comments
 (0)