Skip to content

Commit

Permalink
updated the customer_endpoints with some improvs. Added the module in…
Browse files Browse the repository at this point in the history
… the pytest.yml
  • Loading branch information
nhesusrz committed Sep 12, 2024
1 parent d759ca3 commit 0fe22fc
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: poetry install

- name: Run tests
run: poetry run pytest --cov=your_module --cov-report xml:coverage.xml --cov-report term
run: poetry run pytest --cov=app --cov-report xml:coverage.xml --cov-report term

- name: Upload coverage report
uses: actions/upload-artifact@v4
Expand Down
29 changes: 20 additions & 9 deletions app/api/v1/customers/customer_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
customer.
"""

from typing import List
from typing import List, Optional
from uuid import uuid4

from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
Expand All @@ -46,6 +46,8 @@
logger = logger.get_logger()
app_settings = settings.load_settings()

ALLOWED_EXTENSIONS = {"jpeg", "jpg", "png", "gif"}


class CustomerEndpoints:
"""Customer endpoints."""
Expand Down Expand Up @@ -223,7 +225,7 @@ async def update_customer(
async def upload_photo(
self,
customer_id: int,
file: UploadFile = File(...), # noqa
file: Optional[UploadFile] = File(None), # noqa
db_session: AsyncSession = Depends(db.get_session), # noqa
current_user: User = Depends( # noqa
user_crud.get_current_active_non_admin_user,
Expand All @@ -237,13 +239,26 @@ async def upload_photo(
detail="No file provided",
)

if not file.filename or "." not in file.filename:
file_extension = file.filename.split(".")[-1].lower()
if (
not file.filename
or "." not in file.filename
or file_extension not in ALLOWED_EXTENSIONS
):
logger.error("Invalid file format for customer photo upload")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid file format",
)

file_bytes = await file.read()
if not file_bytes:
logger.error("Uploaded file is empty")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Uploaded file is empty",
)

logger.info(f"Uploading photo for customer ID: {customer_id}")
db_customer = await customer_crud.get_customer(
db_session=db_session,
Expand All @@ -256,17 +271,13 @@ async def upload_photo(
detail="Customer not found",
)

file_extension = file.filename.split(".")[-1]
file_name = f"{uuid4()}.{file_extension}"

file_bytes = await file.read()

new_file_name = f"{uuid4()}.{file_extension}"
try:
s3_client = S3Client()
photo_url = await s3_client.upload_file(
bucket_name=app_settings.MINIO_PHOTO_BUCKET_NAME,
file_bytes=file_bytes,
file_name=file_name,
file_name=new_file_name,
)
logger.info(
f"Photo uploaded successfully for customer ID: {customer_id}",
Expand Down
175 changes: 172 additions & 3 deletions tests/endpoints/test_customer_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,11 @@ async def test_update_customer_success(mocker, authenticated_user_client):


@pytest.mark.asyncio
async def test_update_customer_failure(mocker, authenticated_user_client):
"""Test failing to update a customer by ID by mocking an error response.
async def test_update_customer_failure_get_customer(
mocker,
authenticated_user_client,
):
"""Test failing to update a customer by ID by mocking get_customer.
Args:
----
Expand Down Expand Up @@ -323,6 +326,53 @@ async def test_update_customer_failure(mocker, authenticated_user_client):
assert response.json() == {"detail": "Customer not found"}


@pytest.mark.asyncio
async def test_update_customer_failure_update_customer(
mocker,
authenticated_user_client,
):
"""Test failing to update a customer by ID by mocking update_customer.
Args:
----
mocker (pytest_mock.MockerFixture): Pytest mock fixture.
authenticated_user_client (AsyncClient): Async HTTP client fixture.
"""
mocked_db_customer = Customer(
id=1,
name="Customer 1",
surname="Customer 1",
photo_url="http://photo1.jpg",
creator_id=12,
modifier_id=3,
)

mocker.patch(
"app.db.actions.customer_crud.get_customer",
return_value=mocked_db_customer,
)

mocker.patch(
"app.db.actions.customer_crud.update_customer",
return_value=None,
)

payload = {
"name": "Customer 1 Updated",
"surname": "Customer 1 Updated",
"photo_url": "http://photo1_updated.jpg",
}

response = await authenticated_user_client.put(
url=CUSTOMER_DETAIL_ENDPOINT.format(customer_id=1),
json=payload,
)

assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json() == {"detail": "Customer update failed"}


@pytest.mark.asyncio
async def test_upload_photo_success(mocker, authenticated_user_client):
"""Test uploading a photo for a customer by mocking the response.
Expand Down Expand Up @@ -423,12 +473,44 @@ async def test_upload_photo_failure(mocker, authenticated_user_client):
}


@pytest.mark.asyncio
async def test_upload_photo_failure_get_customer(
mocker,
authenticated_user_client,
):
"""Test uploading a photo for a customer by get_customer.
Args:
----
mocker (pytest_mock.MockerFixture): Pytest mock fixture.
authenticated_user_client (AsyncClient): Async HTTP client fixture.
"""
mock_upload_file = mocker.MagicMock()
mock_upload_file.filename = "photo.jpg"
mock_upload_file.read = b"photo content"
mocker.patch(
"app.db.actions.customer_crud.get_customer",
return_value=None,
)

response = await authenticated_user_client.put(
url=CUSTOMER_UPLOAD_PHOTO_ENDPOINT.format(customer_id=1),
files={"file": (mock_upload_file.filename, mock_upload_file.read)},
)

assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json() == {
"detail": "Customer not found",
}


@pytest.mark.asyncio
async def test_upload_photo_failure_updating_customer(
mocker,
authenticated_user_client,
):
"""Test uploading a photo for a customer by mocking a commit error.
"""Test uploading a photo for a customer by mocking updating_customer.
Args:
----
Expand Down Expand Up @@ -470,3 +552,90 @@ async def test_upload_photo_failure_updating_customer(
assert response.json() == {
"detail": "Failed to update customer",
}


@pytest.mark.asyncio
async def test_upload_photo_failure_without_file(
mocker, # noqa
authenticated_user_client,
):
"""Test uploading a photo for a customer by sending no file.
Args:
----
mocker (pytest_mock.MockerFixture): Pytest mock fixture.
authenticated_user_client (AsyncClient): Async HTTP client fixture.
"""
response = await authenticated_user_client.put(
url=CUSTOMER_UPLOAD_PHOTO_ENDPOINT.format(customer_id=1),
)

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.json() == {
"detail": "No file provided",
}


@pytest.mark.asyncio
async def test_upload_photo_failure_wrong_file_format(
mocker,
authenticated_user_client,
):
"""Test uploading a photo for a customer by sending the wrong file format.
Args:
----
mocker (pytest_mock.MockerFixture): Pytest mock fixture.
authenticated_user_client (AsyncClient): Async HTTP client fixture.
"""
mock_upload_file = mocker.MagicMock()
mock_upload_file.filename = "photo.exe"
mock_upload_file.read = b"photo content"
mocker.patch(
"app.db.actions.customer_crud.update_customer",
return_value=None,
)

response = await authenticated_user_client.put(
url=CUSTOMER_UPLOAD_PHOTO_ENDPOINT.format(customer_id=1),
files={"file": (mock_upload_file.filename, mock_upload_file.read)},
)

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.json() == {
"detail": "Invalid file format",
}


@pytest.mark.asyncio
async def test_upload_photo_failure_empty_file(
mocker,
authenticated_user_client,
):
"""Test uploading a photo for a customer by sending empty file.
Args:
----
mocker (pytest_mock.MockerFixture): Pytest mock fixture.
authenticated_user_client (AsyncClient): Async HTTP client fixture.
"""
mock_upload_file = mocker.MagicMock()
mock_upload_file.filename = "photo.JPg"
mock_upload_file.read = b""
mocker.patch(
"app.db.actions.customer_crud.update_customer",
return_value=None,
)

response = await authenticated_user_client.put(
url=CUSTOMER_UPLOAD_PHOTO_ENDPOINT.format(customer_id=1),
files={"file": (mock_upload_file.filename, mock_upload_file.read)},
)

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.json() == {
"detail": "Uploaded file is empty",
}

0 comments on commit 0fe22fc

Please sign in to comment.