import uuid import pytest from app.api.routes.events.gifts import router as gifts_router from app.models.gift import GiftStatus, GiftPriority @pytest.fixture def gift_item_data(mock_event, mock_user): return { "name": "Animal Plushie", "description": "A cute animal plushie for Emma", "price": 19.99, "currency": "USD", "quantity_requested": 2, "priority": GiftPriority.HIGH.value, "event_id": str(mock_event.id), "added_by": str(mock_user.id) } @pytest.fixture def gift_category_data(mock_event, mock_user): return { "name": "Toys", "description": "Animal-themed toys for Emma", "icon": "toy-icon", "color": "#FF5733", "event_id": str(mock_event.id), "created_by": str(mock_user.id) } @pytest.fixture def gift_purchase_data(gift_item_fixture, guest_fixture): return { "gift_id": str(gift_item_fixture.id), "guest_id": str(guest_fixture.id), "quantity": 1, "purchase_price": 19.99, "purchase_currency": "USD", "notes": "Purchased as a birthday gift" } class TestGiftsRouter: @pytest.fixture(autouse=True) def setup_method(self, create_test_client, db_session, mock_user, gift_item_fixture, gift_category_fixture): self.client = create_test_client( router=gifts_router, prefix="/gifts", db_session=db_session, user=mock_user ) self.db_session = db_session self.mock_user = mock_user self.endpoint = "/gifts" self.gift_item = gift_item_fixture self.gift_category = gift_category_fixture # Gift Item Tests def test_create_gift_item_success(self, gift_item_data): response = self.client.post(f"{self.endpoint}/items", json=gift_item_data) assert response.status_code == 200 data = response.json() assert data["name"] == gift_item_data["name"] assert data["price"] == gift_item_data["price"] assert data["status"] == GiftStatus.AVAILABLE.value def test_read_gift_item_success(self): response = self.client.get(f"{self.endpoint}/items/{self.gift_item.id}") assert response.status_code == 200 data = response.json() assert data["id"] == str(self.gift_item.id) assert data["name"] == self.gift_item.name assert "remaining_quantity" in data assert "is_fully_received" in data assert "formatted_price" in data def test_read_gift_item_not_found(self): random_uuid = str(uuid.uuid4()) response = self.client.get(f"{self.endpoint}/items/{random_uuid}") assert response.status_code == 404 assert response.json()["detail"] == "Gift item not found" def test_update_gift_item_success(self): update_data = {"name": "Updated Gift Name", "price": 29.99} response = self.client.put(f"{self.endpoint}/items/{self.gift_item.id}", json=update_data) assert response.status_code == 200 assert response.json()["name"] == "Updated Gift Name" assert response.json()["price"] == 29.99 def test_update_gift_item_not_found(self): fake_uuid = str(uuid.uuid4()) update_data = {"name": "Nobody's Gift"} response = self.client.put(f"{self.endpoint}/items/{fake_uuid}", json=update_data) assert response.status_code == 404 def test_delete_gift_item_success(self): response = self.client.delete(f"{self.endpoint}/items/{self.gift_item.id}") assert response.status_code == 200 assert response.json()["id"] == str(self.gift_item.id) def test_delete_gift_item_not_found(self): fake_uuid = str(uuid.uuid4()) response = self.client.delete(f"{self.endpoint}/items/{fake_uuid}") assert response.status_code == 404 assert response.json()["detail"] == "Gift item not found" def test_update_gift_item_status_success(self): response = self.client.put( f"{self.endpoint}/items/{self.gift_item.id}/status", params={"status": GiftStatus.RESERVED.value} ) assert response.status_code == 200 assert response.json()["status"] == GiftStatus.RESERVED.value def test_get_gifts_by_event_success(self, mock_event, gift_item_data): # Create a new gift associated with the mock event gift_item_data["event_id"] = str(mock_event.id) self.client.post(f"{self.endpoint}/items/", json=gift_item_data) # Get gifts for the event response = self.client.get(f"{self.endpoint}/items/event/{mock_event.id}") assert response.status_code == 200 assert isinstance(response.json(), list) assert len(response.json()) >= 1 assert any(gift["event_id"] == str(mock_event.id) for gift in response.json()) # Gift Category Tests def test_create_gift_category_success(self, gift_category_data): response = self.client.post(f"{self.endpoint}/categories/", json=gift_category_data) assert response.status_code == 200 data = response.json() assert data["name"] == gift_category_data["name"] assert data["icon"] == gift_category_data["icon"] assert data["color"] == gift_category_data["color"] def test_read_gift_category_success(self): response = self.client.get(f"{self.endpoint}/categories/{self.gift_category.id}") assert response.status_code == 200 data = response.json() assert data["id"] == str(self.gift_category.id) assert data["name"] == self.gift_category.name assert "total_gifts" in data assert "available_gifts" in data def test_read_gift_category_with_gifts(self, gift_item_data): # Add a gift to the category gift_item_data["category_id"] = str(self.gift_category.id) self.client.post(f"{self.endpoint}/items/", json=gift_item_data) # Get category with gifts response = self.client.get( f"{self.endpoint}/categories/{self.gift_category.id}", params={"include_gifts": True} ) assert response.status_code == 200 data = response.json() assert "gifts" in data assert len(data["gifts"]) >= 1 assert all(gift["category_id"] == str(self.gift_category.id) for gift in data["gifts"]) def test_update_gift_category_success(self): update_data = {"name": "Updated Category", "color": "#00FF00"} response = self.client.put( f"{self.endpoint}/categories/{self.gift_category.id}", json=update_data ) assert response.status_code == 200 assert response.json()["name"] == "Updated Category" assert response.json()["color"] == "#00FF00" def test_delete_gift_category_success(self): response = self.client.delete(f"{self.endpoint}/categories/{self.gift_category.id}") assert response.status_code == 200 assert response.json()["id"] == str(self.gift_category.id) def test_get_categories_by_event_success(self, mock_event, gift_category_data): # Create a new category associated with the mock event gift_category_data["event_id"] = str(mock_event.id) self.client.post(f"{self.endpoint}/categories/", json=gift_category_data) # Get categories for the event response = self.client.get(f"{self.endpoint}/categories/event/{mock_event.id}") assert response.status_code == 200 assert isinstance(response.json(), list) assert len(response.json()) >= 1 assert any(cat["event_id"] == str(mock_event.id) for cat in response.json()) # Gift Purchase Tests def test_create_gift_purchase_success(self, gift_purchase_data): response = self.client.post(f"{self.endpoint}/purchases/", json=gift_purchase_data) assert response.status_code == 200 data = response.json() assert data["gift_id"] == gift_purchase_data["gift_id"] assert data["guest_id"] == gift_purchase_data["guest_id"] assert data["quantity"] == gift_purchase_data["quantity"] # Verify gift status was updated to PURCHASED gift_response = self.client.get(f"{self.endpoint}/items/{gift_purchase_data['gift_id']}") assert gift_response.status_code == 200 assert gift_response.json()["status"] == GiftStatus.PURCHASED.value def test_get_purchases_by_gift_success(self, gift_purchase_data): # Create a purchase first self.client.post(f"{self.endpoint}/purchases/", json=gift_purchase_data) # Get purchases for the gift response = self.client.get(f"{self.endpoint}/purchases/gift/{gift_purchase_data['gift_id']}") assert response.status_code == 200 assert isinstance(response.json(), list) assert len(response.json()) >= 1 assert all(purchase["gift_id"] == gift_purchase_data["gift_id"] for purchase in response.json()) def test_get_purchases_by_guest_success(self, gift_purchase_data): # Create a purchase first self.client.post(f"{self.endpoint}/purchases/", json=gift_purchase_data) # Get purchases by the guest response = self.client.get(f"{self.endpoint}/purchases/guest/{gift_purchase_data['guest_id']}") assert response.status_code == 200 assert isinstance(response.json(), list) assert len(response.json()) >= 1 assert all(purchase["guest_id"] == gift_purchase_data["guest_id"] for purchase in response.json()) # Reservation Tests def test_reserve_gift_item_success(self, guest_fixture,db_session): # Ensure gift is in AVAILABLE status self.gift_item.status = GiftStatus.AVAILABLE self.db_session.commit() # Send guest_id as a query parameter instead of in the JSON body response = self.client.post( f"{self.endpoint}/items/{self.gift_item.id}/reserve", params={"guest_id": str(guest_fixture.id), "notes": "I'll bring this gift"} ) assert response.status_code == 200 assert response.json()["status"] == GiftStatus.RESERVED.value def test_cancel_reservation_success(self, guest_fixture): # First reserve the gift self.gift_item.status = GiftStatus.RESERVED self.db_session.commit() cancel_data = { "guest_id": str(guest_fixture.id) } response = self.client.post( f"{self.endpoint}/items/{self.gift_item.id}/cancel-reservation", params=cancel_data ) assert response.status_code == 200 assert response.json()["status"] == GiftStatus.AVAILABLE.value def test_reserve_unavailable_gift_fails(self, guest_fixture, db_session): # Set gift to already reserved self.gift_item.status = GiftStatus.PURCHASED self.db_session.commit() reservation_data = { "guest_id": str(guest_fixture.id) } response = self.client.post( f"{self.endpoint}/items/{self.gift_item.id}/reserve", params=reservation_data ) assert response.status_code == 400 assert response.json()["detail"] == "Gift is not available for reservation"