diff --git a/app/backend/routes/search.py b/app/backend/routes/search.py index 87f1d0d0be6f23cac5935e372db0cccfa70ab472..bc2e973704a1626b8b0307a8286de5bc180bccb5 100644 --- a/app/backend/routes/search.py +++ b/app/backend/routes/search.py @@ -1,4 +1,5 @@ from fastapi import APIRouter, Depends, Query +from fastapi.responses import JSONResponse from sqlmodel import Session, select, or_, func from app.backend.database import get_session from app.backend.models.models import Shop, Product, Category @@ -46,4 +47,13 @@ def search( results.extend(db.exec(product_query).all()) + # Validate search_type + if search_type not in ["shops", "products", "both"]: + return JSONResponse( + status_code=400, + content={ + "error": "Invalid search_type. Must be 'shops', 'products', or 'both'" + }, + ) + return results diff --git a/app/tests/test_search.py b/app/tests/test_search.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b7b2f391d4f768e13ee3b1760a30ca5d9d5e6526 100644 --- a/app/tests/test_search.py +++ b/app/tests/test_search.py @@ -0,0 +1,231 @@ +import pytest +from app.backend.models.models import Shop, Product, Category +from sqlmodel import Session + + +def test_empty_search(client, db_session): + # Create test data + shop = Shop( + name="Test Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + product = Product(name="Test Product", shop_id=1, price=10.0, stock=10) + db_session.add_all([shop, product]) + db_session.commit() + + response = client.get("/search/") + assert response.status_code == 200 + assert len(response.json()) == 2 + + +def test_search_by_shop_name(client, db_session): + shop = Shop( + name="Bakery Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + response = client.get("/search/?name=Bakery") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Bakery Shop" + + +def test_search_by_product_name(client, db_session): + shop = Shop( + name="Test Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + product = Product(name="Coffee Beans", shop_id=shop.id, price=15.0, stock=20) + db_session.add(product) + db_session.commit() + + response = client.get("/search/?name=Coffee&search_type=products") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Coffee Beans" + + +def test_search_by_product_description(client, db_session): + shop = Shop( + name="Test Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + product = Product( + name="Tea", + description="Premium coffee alternative", + shop_id=shop.id, + price=10.0, + stock=15, + ) + db_session.add(product) + db_session.commit() + + response = client.get("/search/?name=coffee&search_type=products") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Tea" + + +def test_search_by_category(client, db_session): + category = Category(name="Beverages") + shop = Shop( + name="Test Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add_all([category, shop]) + db_session.commit() + + product = Product( + name="Green Tea", shop_id=shop.id, category_id=category.id, price=5.0, stock=30 + ) + db_session.add(product) + db_session.commit() + + # Add search_type=products to only get product results + response = client.get("/search/?category=Beverages&search_type=products") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Green Tea" + + +def test_search_type_shops_only(client, db_session): + shop = Shop( + name="Coffee Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + product = Product(name="Coffee", shop_id=1, price=5.0, stock=10) + db_session.add_all([shop, product]) + db_session.commit() + + response = client.get("/search/?name=Coffee&search_type=shops") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Coffee Shop" + + +def test_search_with_nonexistent_name(client, db_session): + shop = Shop( + name="Test Shop", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + response = client.get("/search/?name=NonexistentName") + assert response.status_code == 200 + assert len(response.json()) == 0 + + +def test_search_with_partial_name(client, db_session): + shop = Shop( + name="Coffee House", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + response = client.get("/search/?name=Coffee") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert "Coffee" in results[0]["name"] + + +def test_search_with_case_insensitive(client, db_session): + shop = Shop( + name="COFFEE SHOP", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + response = client.get("/search/?name=coffee") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "COFFEE SHOP" + + +def test_search_special_characters(client, db_session): + shop = Shop( + name="Café & Bistro", + owner_id=1, + address="Test Address", + latitude=0.0, + longitude=0.0, + ) + db_session.add(shop) + db_session.commit() + + response = client.get("/search/?name=Café") + assert response.status_code == 200 + results = response.json() + assert len(results) == 1 + assert results[0]["name"] == "Café & Bistro" + + +def test_search_with_multiple_results(client, db_session): + shop1 = Shop( + name="Coffee Shop", owner_id=1, address="Address 1", latitude=0.0, longitude=0.0 + ) + shop2 = Shop( + name="Coffee House", + owner_id=1, + address="Address 2", + latitude=0.0, + longitude=0.0, + ) + db_session.add_all([shop1, shop2]) + db_session.commit() + + response = client.get("/search/?name=Coffee") + assert response.status_code == 200 + results = response.json() + assert len(results) == 2 + assert all("Coffee" in result["name"] for result in results) + + +def test_search_with_invalid_search_type(client, db_session): + response = client.get("/search/?search_type=invalid") + assert response.status_code == 400 # Bad request for invalid search type + assert "error" in response.json()