Spaces:
Sleeping
Sleeping
| import pytest | |
| from unittest.mock import AsyncMock, patch | |
| from fastapi import HTTPException | |
| from datetime import datetime, timezone, date, time | |
| from uuid import uuid4 | |
| from app.services.appointment import ( | |
| create_new_appointment, | |
| reschedule_appointment, | |
| cancel_appointment_service, | |
| get_appointment_details, | |
| get_appointments_by_customer_id, | |
| ) | |
| from app.models.appointment import Appointment, AppointmentStatus, PaymentMode, PaymentStatus | |
| from app.repositories.appointment import ( | |
| create_appointment, | |
| update_appointment, | |
| cancel_appointment, | |
| get_appointment_by_id, | |
| fetch_appointments_from_db, | |
| ) | |
| # Mock data | |
| MOCK_APPOINTMENT_ID = str(uuid4()) | |
| MOCK_CUSTOMER_ID = str(uuid4()) | |
| MOCK_MERCHANT_ID = str(uuid4()) | |
| MOCK_ORDER_ID = "order_123" | |
| # Test data | |
| TEST_APPOINTMENT = Appointment( | |
| appointment_id=MOCK_APPOINTMENT_ID, | |
| customer_id=MOCK_CUSTOMER_ID, | |
| merchant_id=MOCK_MERCHANT_ID, | |
| merchant_name="Test Merchant", | |
| city="Test City", | |
| merchant_address={"street": "123 Test St", "city": "Test City"}, | |
| location_id="LOC001", | |
| appointment_date="2023-12-25", | |
| appointment_time="10:00", | |
| associates=[{"associate_id": "STAFF1", "name": "John Doe"}], | |
| status=AppointmentStatus.PENDING, | |
| services=[{"service_id": "SERV1", "name": "Test Service", "price": 100.0, "duration": "30 minutes", "quantity": 1}], | |
| total_amount=100.0, | |
| payment_mode=PaymentMode.ONLINE, | |
| order_id=MOCK_ORDER_ID, | |
| ) | |
| # Mock functions | |
| def mock_create_appointment(): | |
| with patch("app.repositories.appointment.create_appointment", new_callable=AsyncMock) as mock: | |
| yield mock | |
| def mock_get_order_by_id(): | |
| with patch("app.repositories.payment.get_order_by_id", new_callable=AsyncMock) as mock: | |
| mock.return_value = {"status": "pending"} | |
| yield mock | |
| def mock_get_appointment_by_id(): | |
| with patch("app.repositories.appointment.get_appointment_by_id", new_callable=AsyncMock) as mock: | |
| yield mock | |
| def mock_update_appointment(): | |
| with patch("app.repositories.appointment.update_appointment", new_callable=AsyncMock) as mock: | |
| yield mock | |
| def mock_cancel_appointment(): | |
| with patch("app.repositories.appointment.cancel_appointment", new_callable=AsyncMock) as mock: | |
| yield mock | |
| def mock_fetch_appointments_from_db(): | |
| with patch("app.repositories.appointment.fetch_appointments_from_db", new_callable=AsyncMock) as mock: | |
| yield mock | |
| # Tests | |
| async def test_create_new_appointment_success(mock_create_appointment, mock_get_order_by_id): | |
| result = await create_new_appointment(TEST_APPOINTMENT) | |
| assert result["appointment_id"] == MOCK_APPOINTMENT_ID | |
| mock_create_appointment.assert_called_once() | |
| mock_get_order_by_id.assert_called_once_with(MOCK_ORDER_ID) | |
| async def test_create_new_appointment_invalid_order(mock_get_order_by_id): | |
| mock_get_order_by_id.return_value = None | |
| with pytest.raises(HTTPException) as exc_info: | |
| await create_new_appointment(TEST_APPOINTMENT) | |
| assert exc_info.value.status_code == 400 | |
| assert "Invalid Razorpay Order ID" in str(exc_info.value.detail) | |
| async def test_reschedule_appointment_success(mock_get_appointment_by_id, mock_update_appointment): | |
| mock_get_appointment_by_id.return_value = { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "status": AppointmentStatus.CONFIRMED.value, | |
| "appointment_date": "2023-12-25", | |
| "appointment_time": "10:00:00", | |
| } | |
| result = await reschedule_appointment(MOCK_APPOINTMENT_ID, "2023-12-26", "11:00:00", MOCK_CUSTOMER_ID) | |
| assert result["message"] == "Appointment rescheduled successfully" | |
| mock_update_appointment.assert_called_once() | |
| async def test_reschedule_appointment_past_date(mock_get_appointment_by_id): | |
| mock_get_appointment_by_id.return_value = { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "status": AppointmentStatus.CONFIRMED.value, | |
| "appointment_date": "2023-12-25", | |
| "appointment_time": "10:00:00", | |
| } | |
| with pytest.raises(HTTPException) as exc_info: | |
| await reschedule_appointment(MOCK_APPOINTMENT_ID, "2023-12-24", "11:00:00", MOCK_CUSTOMER_ID) | |
| assert exc_info.value.status_code == 400 | |
| assert "Cannot reschedule to a past time" in str(exc_info.value.detail) | |
| async def test_cancel_appointment_service_success(mock_get_appointment_by_id, mock_cancel_appointment): | |
| mock_get_appointment_by_id.return_value = { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "status": AppointmentStatus.CONFIRMED.value, | |
| "appointment_date": "2023-12-25", | |
| "appointment_time": "10:00:00", | |
| } | |
| result = await cancel_appointment_service(MOCK_APPOINTMENT_ID, "change_of_plans", MOCK_CUSTOMER_ID) | |
| assert result["message"] == "Appointment canceled successfully" | |
| mock_cancel_appointment.assert_called_once() | |
| async def test_cancel_appointment_service_already_canceled(mock_get_appointment_by_id): | |
| mock_get_appointment_by_id.return_value = { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "status": AppointmentStatus.CANCELED.value, | |
| "appointment_date": "2023-12-25", | |
| "appointment_time": "10:00:00", | |
| } | |
| with pytest.raises(HTTPException) as exc_info: | |
| await cancel_appointment_service(MOCK_APPOINTMENT_ID, "change_of_plans", MOCK_CUSTOMER_ID) | |
| assert exc_info.value.status_code == 400 | |
| assert "Appointment is already canceled" in str(exc_info.value.detail) | |
| async def test_get_appointment_details_success(mock_get_appointment_by_id): | |
| mock_get_appointment_by_id.return_value = { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "status": AppointmentStatus.CONFIRMED.value, | |
| "appointment_date": "2023-12-25", | |
| "appointment_time": "10:00:00", | |
| } | |
| result = await get_appointment_details(MOCK_APPOINTMENT_ID) | |
| assert result["appointment_id"] == MOCK_APPOINTMENT_ID | |
| async def test_get_appointments_by_customer_id_success(mock_fetch_appointments_from_db): | |
| mock_fetch_appointments_from_db.return_value = ( | |
| [ | |
| { | |
| "appointment_id": MOCK_APPOINTMENT_ID, | |
| "merchant_id": MOCK_MERCHANT_ID, | |
| "merchant_name": "Test Merchant", | |
| "merchant_address": "123 Test St", | |
| "location_id": str(uuid4()), | |
| "appointment_date": date(2023, 12, 25), | |
| "appointment_time": "10:00:00", | |
| "status": "confirmed", | |
| "associates": [], | |
| "services": [], | |
| "notes": "", | |
| "total_amount": 100.0, | |
| "discount": 0.0, | |
| "payment_status": "Paid", | |
| "payment_id": "pay_123", | |
| "cleared_amount": 100.0, | |
| #"created_at": datetime(2023, 12, 1, 10, 0, 0), | |
| #"modified_at": datetime(2023, 12, 1, 10, 0, 0), | |
| } | |
| ], | |
| 1, | |
| ) | |
| result = await get_appointments_by_customer_id(MOCK_CUSTOMER_ID) | |
| assert result.customer_id == MOCK_CUSTOMER_ID | |
| assert len(result.appointments) == 1 | |
| assert result.appointments[0].appointment_id == MOCK_APPOINTMENT_ID |