diff --git a/api/utils/pagination.py b/api/utils/pagination.py index 0fab89c9b..dcf0f950f 100644 --- a/api/utils/pagination.py +++ b/api/utils/pagination.py @@ -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 ): ''' @@ -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()) diff --git a/api/v1/routes/testimonial.py b/api/v1/routes/testimonial.py index 87820b736..f0304c495 100644 --- a/api/v1/routes/testimonial.py +++ b/api/v1/routes/testimonial.py @@ -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 @@ -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( diff --git a/api/v1/services/testimonial.py b/api/v1/services/testimonial.py index f3d20352a..6e38e5965 100644 --- a/api/v1/services/testimonial.py +++ b/api/v1/services/testimonial.py @@ -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): @@ -54,6 +58,6 @@ def delete_all(self, db: Session): except Exception as e: db.rollback() raise e - + testimonial_service = TestimonialService() diff --git a/tests/v1/testimonial/test_top_rated_testimonial.py b/tests/v1/testimonial/test_top_rated_testimonial.py new file mode 100644 index 000000000..993200316 --- /dev/null +++ b/tests/v1/testimonial/test_top_rated_testimonial.py @@ -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() \ No newline at end of file