Skip to content

feat: retrieve top rated testimonials #1171

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion api/utils/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ def paginated_response(
skip: int,
limit: int,
join: Optional[Any] = None,
filters: Optional[Dict[str, Any]]=None
filters: Optional[Dict[str, Any]]=None,
order_by: Optional[Any] = None
):

'''
Expand Down Expand Up @@ -79,6 +80,9 @@ def paginated_response(
query = query.filter(
getattr(getattr(join, "columns"),
attr).like(f"%{value}%"))

if order_by is not None:
query = query.order_by(order_by)

total = int(query.count())
results = jsonable_encoder(query.offset(skip).limit(limit).all())
Expand Down
22 changes: 21 additions & 1 deletion api/v1/routes/testimonial.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from fastapi.encoders import jsonable_encoder
from api.db.database import get_db
from sqlalchemy.orm import Session
from sqlalchemy import desc
from api.v1.models.user import User
from fastapi import Depends, APIRouter, status,Query
from api.utils.success_response import success_response
from api.utils.success_response import success_response, fail_response
from api.v1.services.testimonial import testimonial_service
from api.v1.services.user import user_service
from api.v1.schemas.testimonial import CreateTestimonial
Expand Down Expand Up @@ -39,6 +40,25 @@ def get_testimonials(
skip=max(page,0),
)

@testimonial.get("/top-rated", status_code=200)
def get_top_rated_testimonials(
page: int = Query(1, ge=1, description="Page number"),
per_page: int = Query(10, ge=1, description="Number of testimonials per page"),
db: Session = Depends(get_db),
):
"""Endpoint to fetch top-rated testimonials"""
try:
return paginated_response(
db=db,
model=Testimonial,
skip=(page - 1) * per_page,
limit=per_page,
filters={},
order_by=desc(Testimonial.ratings)
)

except Exception as e:
return fail_response(status_code=500, message="An error occurred.", data={"error": str(e)})

@testimonial.get("/{testimonial_id}", status_code=status.HTTP_200_OK)
def get_testimonial(
Expand Down
6 changes: 5 additions & 1 deletion api/v1/services/testimonial.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from sqlalchemy.orm import Session
from api.core.base.services import Service
from api.utils.db_validators import check_model_existence
from api.utils.success_response import fail_response
from api.v1.models.testimonial import Testimonial
from api.v1.models.user import User
from api.v1.schemas.testimonial import CreateTestimonial
from fastapi import HTTPException, status
from sqlalchemy import desc
from sqlalchemy.exc import SQLAlchemyError


class TestimonialService(Service):
Expand Down Expand Up @@ -54,6 +58,6 @@ def delete_all(self, db: Session):
except Exception as e:
db.rollback()
raise e


testimonial_service = TestimonialService()
83 changes: 83 additions & 0 deletions tests/v1/testimonial/test_top_rated_testimonial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import pytest
from fastapi.testclient import TestClient
from main import app
from api.db.database import get_db
from unittest.mock import MagicMock

client = TestClient(app)

mock_data = [
{
"client_name": "testclientname1",
"author_id": "066a16d8-cab5-7dd3-8000-3a167556aa11",
"content": "Amazing service!",
"id": "066a6e8b-f008-7242-8000-8f090997001a",
"updated_at": "2024-07-29T02:00:00.002967+01:00",
"client_designation": "testclient",
"comments": "Highly recommended!",
"ratings": 4.8,
"created_at": "2024-07-29T01:59:00.002967+01:00"
},
{
"client_name": "testclientname2",
"author_id": "066a16d8-cab5-7dd3-8000-3a167556ee55",
"content": "Loved the service!",
"id": "066a6e8b-f008-7242-8000-8f090997005e",
"updated_at": "2024-07-29T02:20:10.002967+01:00",
"client_designation": "testclient",
"comments": "Best experience ever!",
"ratings": 5.0,
"created_at": "2024-07-29T02:18:00.002967+01:00"
},
{
"client_name": "testclientname3",
"author_id": "066a16d8-cab5-7dd3-8000-3a167556ff66",
"content": "Decent service",
"id": "066a6e8b-f008-7242-8000-8f090997006f",
"updated_at": "2024-07-29T02:25:40.002967+01:00",
"client_designation": "testclient",
"comments": "Could be improved",
"ratings": 4.2,
"created_at": "2024-07-29T02:23:00.002967+01:00"
},
]

"""Mocking The database"""
@pytest.fixture
def db_session_mock():
db_session = MagicMock()
yield db_session

@pytest.fixture(autouse=True)
def override_get_db(db_session_mock):
def get_db_override():
yield db_session_mock

app.dependency_overrides[get_db] = get_db_override
yield
app.dependency_overrides = {}

def test_get_top_rated_testimonials(db_session_mock):

mock_query = MagicMock()
mock_query.count.return_value = len(mock_data)
mock_query.offset.return_value.limit.return_value.all.return_value = mock_data

db_session_mock.query.return_value = mock_query
mock_query.order_by.return_value = mock_query

url = 'api/v1/testimonials/top-rated'
response = client.get(url, params={'page': 1, 'per_page': 2})

assert response.status_code == 200
assert response.json()['message'] == 'Successfully fetched items'

returned_items = response.json()['data']['items']
assert len(returned_items) == 3

assert response.json()['data']['total'] == 3
assert response.json()['data']['limit'] == 2
assert response.json()['data']['skip'] == 0

db_session_mock.query.assert_called()
mock_query.order_by.assert_called()