Team Ai
Apppublic

KillerKing93/Transformers-InferenceServer-OpenAPI

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
test_marketplace.py582 linesDownload Raw Back to tests
1#!/usr/bin/env python2# -*- coding: utf-8 -*-3"""4Comprehensive test suite for marketplace API endpoints5 6Tests cover:7- Supplier registration and management8- Product creation and search9- User registration and management10- Location-aware product search11- AI-powered natural language search12 13Run with: pytest tests/test_marketplace.py -v14"""15 16import pytest17import sys18import os19from datetime import datetime20 21# Add parent directory to path for imports22sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))23 24from fastapi.testclient import TestClient25from sqlalchemy import create_engine26from sqlalchemy.orm import sessionmaker27 28from main import app29from database import get_db30from models import Base, Supplier, Product, User31 32# Test database33SQLALCHEMY_DATABASE_URL = "sqlite:///./test_marketplace.db"34engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})35TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)36 37 38def override_get_db():39    """Override database dependency for testing."""40    try:41        db = TestingSessionLocal()42        yield db43    finally:44        db.close()45 46 47app.dependency_overrides[get_db] = override_get_db48 49client = TestClient(app)50 51 52@pytest.fixture(scope="module")53def setup_database():54    """Create test database tables before tests."""55    Base.metadata.create_all(bind=engine)56    yield57    Base.metadata.drop_all(bind=engine)58 59 60@pytest.fixture(scope="function")61def clean_database():62    """Clean database before each test."""63    db = TestingSessionLocal()64    try:65        db.query(Product).delete()66        db.query(Supplier).delete()67        db.query(User).delete()68        db.commit()69    finally:70        db.close()71    yield72 73 74class TestSupplierEndpoints:75    """Test supplier management endpoints."""76 77    def test_register_supplier_success(self, setup_database, clean_database):78        """Test successful supplier registration."""79        response = client.post(80            "/api/suppliers/register",81            json={82                "name": "Test Supplier",83                "business_name": "Test Electronics",84                "email": "test@supplier.com",85                "phone": "+62812345678",86                "address": "Jl. Test No. 1",87                "latitude": -6.2088,88                "longitude": 106.8456,89                "city": "Jakarta",90                "province": "DKI Jakarta"91            }92        )93        assert response.status_code == 20094        data = response.json()95        assert data["email"] == "test@supplier.com"96        assert data["business_name"] == "Test Electronics"97        assert data["city"] == "Jakarta"98        assert "id" in data99        assert data["is_active"] is True100 101    def test_register_supplier_duplicate_email(self, setup_database, clean_database):102        """Test supplier registration with duplicate email."""103        # Register first supplier104        client.post(105            "/api/suppliers/register",106            json={107                "name": "Supplier 1",108                "business_name": "Store 1",109                "email": "duplicate@test.com",110                "latitude": -6.2088,111                "longitude": 106.8456,112                "city": "Jakarta"113            }114        )115 116        # Try to register with same email117        response = client.post(118            "/api/suppliers/register",119            json={120                "name": "Supplier 2",121                "business_name": "Store 2",122                "email": "duplicate@test.com",123                "latitude": -6.2088,124                "longitude": 106.8456,125                "city": "Bandung"126            }127        )128        assert response.status_code == 400129        assert "already registered" in response.json()["detail"]130 131    def test_list_suppliers(self, setup_database, clean_database):132        """Test listing suppliers."""133        # Create test suppliers134        for i in range(3):135            client.post(136                "/api/suppliers/register",137                json={138                    "name": f"Supplier {i}",139                    "business_name": f"Store {i}",140                    "email": f"supplier{i}@test.com",141                    "latitude": -6.2088,142                    "longitude": 106.8456,143                    "city": "Jakarta" if i < 2 else "Bandung"144                }145            )146 147        # List all suppliers148        response = client.get("/api/suppliers")149        assert response.status_code == 200150        data = response.json()151        assert len(data) == 3152 153        # List suppliers by city154        response = client.get("/api/suppliers?city=Jakarta")155        assert response.status_code == 200156        data = response.json()157        assert len(data) == 2158 159    def test_get_supplier_by_id(self, setup_database, clean_database):160        """Test getting supplier by ID."""161        # Create supplier162        create_response = client.post(163            "/api/suppliers/register",164            json={165                "name": "Test Supplier",166                "business_name": "Test Store",167                "email": "test@supplier.com",168                "latitude": -6.2088,169                "longitude": 106.8456,170                "city": "Jakarta"171            }172        )173        supplier_id = create_response.json()["id"]174 175        # Get supplier176        response = client.get(f"/api/suppliers/{supplier_id}")177        assert response.status_code == 200178        data = response.json()179        assert data["id"] == supplier_id180        assert data["business_name"] == "Test Store"181 182    def test_get_nonexistent_supplier(self, setup_database, clean_database):183        """Test getting non-existent supplier."""184        response = client.get("/api/suppliers/99999")185        assert response.status_code == 404186 187 188class TestProductEndpoints:189    """Test product management endpoints."""190 191    def test_create_product_success(self, setup_database, clean_database):192        """Test successful product creation."""193        # Create supplier first194        supplier_response = client.post(195            "/api/suppliers/register",196            json={197                "name": "Supplier",198                "business_name": "Electronics Store",199                "email": "supplier@test.com",200                "latitude": -6.2088,201                "longitude": 106.8456,202                "city": "Jakarta"203            }204        )205        supplier_id = supplier_response.json()["id"]206 207        # Create product208        response = client.post(209            f"/api/suppliers/{supplier_id}/products",210            json={211                "name": "Test Laptop",212                "description": "A test laptop",213                "price": 10000000,214                "stock_quantity": 5,215                "category": "laptop",216                "tags": "test,laptop,gaming",217                "sku": "TEST-LAP-001"218            }219        )220        assert response.status_code == 200221        data = response.json()222        assert data["name"] == "Test Laptop"223        assert data["price"] == 10000000224        assert data["supplier_id"] == supplier_id225        assert "supplier_name" in data226 227    def test_create_product_invalid_supplier(self, setup_database, clean_database):228        """Test creating product with invalid supplier ID."""229        response = client.post(230            "/api/suppliers/99999/products",231            json={232                "name": "Test Product",233                "price": 1000000,234                "stock_quantity": 1,235                "category": "test"236            }237        )238        assert response.status_code == 404239 240    def test_update_product(self, setup_database, clean_database):241        """Test updating product."""242        # Create supplier and product243        supplier_response = client.post(244            "/api/suppliers/register",245            json={246                "name": "Supplier",247                "business_name": "Store",248                "email": "supplier@test.com",249                "latitude": -6.2088,250                "longitude": 106.8456,251                "city": "Jakarta"252            }253        )254        supplier_id = supplier_response.json()["id"]255 256        product_response = client.post(257            f"/api/suppliers/{supplier_id}/products",258            json={259                "name": "Product",260                "price": 1000000,261                "stock_quantity": 10,262                "category": "test"263            }264        )265        product_id = product_response.json()["id"]266 267        # Update product268        response = client.put(269            f"/api/products/{product_id}",270            json={271                "price": 1500000,272                "stock_quantity": 5273            }274        )275        assert response.status_code == 200276        data = response.json()277        assert data["price"] == 1500000278        assert data["stock_quantity"] == 5279 280    def test_list_products_with_filters(self, setup_database, clean_database):281        """Test listing products with filters."""282        # Create supplier283        supplier_response = client.post(284            "/api/suppliers/register",285            json={286                "name": "Supplier",287                "business_name": "Store",288                "email": "supplier@test.com",289                "latitude": -6.2088,290                "longitude": 106.8456,291                "city": "Jakarta"292            }293        )294        supplier_id = supplier_response.json()["id"]295 296        # Create products297        products = [298            {"name": "Laptop 1", "price": 5000000, "stock_quantity": 5, "category": "laptop"},299            {"name": "Laptop 2", "price": 15000000, "stock_quantity": 3, "category": "laptop"},300            {"name": "Phone 1", "price": 8000000, "stock_quantity": 10, "category": "smartphone"},301        ]302        for product in products:303            client.post(f"/api/suppliers/{supplier_id}/products", json=product)304 305        # List all products306        response = client.get("/api/products")307        assert response.status_code == 200308        assert len(response.json()) == 3309 310        # Filter by category311        response = client.get("/api/products?category=laptop")312        assert response.status_code == 200313        assert len(response.json()) == 2314 315        # Filter by price range316        response = client.get("/api/products?min_price=6000000&max_price=12000000")317        assert response.status_code == 200318        data = response.json()319        assert len(data) == 2320        for product in data:321            assert 6000000 <= product["price"] <= 12000000322 323    def test_search_products_by_keyword(self, setup_database, clean_database):324        """Test searching products by keyword."""325        # Create supplier and products326        supplier_response = client.post(327            "/api/suppliers/register",328            json={329                "name": "Supplier",330                "business_name": "Store",331                "email": "supplier@test.com",332                "latitude": -6.2088,333                "longitude": 106.8456,334                "city": "Jakarta"335            }336        )337        supplier_id = supplier_response.json()["id"]338 339        client.post(340            f"/api/suppliers/{supplier_id}/products",341            json={342                "name": "ASUS Gaming Laptop",343                "price": 10000000,344                "stock_quantity": 5,345                "category": "laptop",346                "tags": "gaming,asus,rtx"347            }348        )349        client.post(350            f"/api/suppliers/{supplier_id}/products",351            json={352                "name": "Samsung Smartphone",353                "price": 5000000,354                "stock_quantity": 10,355                "category": "smartphone",356                "tags": "samsung,android"357            }358        )359 360        # Search by name361        response = client.get("/api/products/search?q=gaming")362        assert response.status_code == 200363        data = response.json()364        assert len(data) == 1365        assert "Gaming" in data[0]["name"]366 367        # Search by tags368        response = client.get("/api/products/search?q=samsung")369        assert response.status_code == 200370        data = response.json()371        assert len(data) == 1372 373    def test_search_products_with_location_sorting(self, setup_database, clean_database):374        """Test location-aware product search."""375        # Create suppliers at different locations376        suppliers = [377            {"name": "Supplier 1", "business_name": "Store 1", "email": "s1@test.com",378             "latitude": -6.2088, "longitude": 106.8456, "city": "Jakarta"},379            {"name": "Supplier 2", "business_name": "Store 2", "email": "s2@test.com",380             "latitude": -6.9175, "longitude": 107.6191, "city": "Bandung"},381        ]382 383        for supplier_data in suppliers:384            supplier_response = client.post("/api/suppliers/register", json=supplier_data)385            supplier_id = supplier_response.json()["id"]386 387            # Create product for each supplier388            client.post(389                f"/api/suppliers/{supplier_id}/products",390                json={391                    "name": "Test Laptop",392                    "price": 10000000,393                    "stock_quantity": 5,394                    "category": "laptop"395                }396            )397 398        # Search from Jakarta location399        response = client.get(400            "/api/products/search?q=laptop&user_lat=-6.2088&user_lon=106.8456"401        )402        assert response.status_code == 200403        data = response.json()404        assert len(data) == 2405        # First result should be Jakarta (closer)406        assert data[0]["distance_km"] < data[1]["distance_km"]407 408 409class TestUserEndpoints:410    """Test user management endpoints."""411 412    def test_register_user_success(self, setup_database, clean_database):413        """Test successful user registration."""414        response = client.post(415            "/api/users/register",416            json={417                "name": "Test User",418                "email": "user@test.com",419                "phone": "+62812345678",420                "latitude": -6.2088,421                "longitude": 106.8456,422                "city": "Jakarta",423                "province": "DKI Jakarta",424                "ai_access_enabled": True425            }426        )427        assert response.status_code == 200428        data = response.json()429        assert data["email"] == "user@test.com"430        assert data["name"] == "Test User"431        assert data["ai_access_enabled"] is True432 433    def test_register_user_duplicate_email(self, setup_database, clean_database):434        """Test user registration with duplicate email."""435        client.post(436            "/api/users/register",437            json={438                "name": "User 1",439                "email": "duplicate@test.com",440                "city": "Jakarta"441            }442        )443 444        response = client.post(445            "/api/users/register",446            json={447                "name": "User 2",448                "email": "duplicate@test.com",449                "city": "Bandung"450            }451        )452        assert response.status_code == 400453 454    def test_get_user_by_id(self, setup_database, clean_database):455        """Test getting user by ID."""456        create_response = client.post(457            "/api/users/register",458            json={459                "name": "Test User",460                "email": "user@test.com",461                "city": "Jakarta"462            }463        )464        user_id = create_response.json()["id"]465 466        response = client.get(f"/api/users/{user_id}")467        assert response.status_code == 200468        data = response.json()469        assert data["id"] == user_id470 471    def test_get_nonexistent_user(self, setup_database, clean_database):472        """Test getting non-existent user."""473        response = client.get("/api/users/99999")474        assert response.status_code == 404475 476 477class TestAISearchEndpoint:478    """Test AI-powered search endpoint."""479 480    def test_ai_search_without_ai_access(self, setup_database, clean_database):481        """Test AI search for user without AI access."""482        # Create user without AI access483        user_response = client.post(484            "/api/users/register",485            json={486                "name": "Regular User",487                "email": "regular@test.com",488                "city": "Jakarta",489                "ai_access_enabled": False490            }491        )492        user_id = user_response.json()["id"]493 494        # Try AI search495        response = client.post(496            "/api/chat/search",497            json={498                "user_id": user_id,499                "query": "laptop gaming"500            }501        )502        assert response.status_code == 403503        assert "AI access not enabled" in response.json()["detail"]504 505    def test_ai_search_with_nonexistent_user(self, setup_database, clean_database):506        """Test AI search with non-existent user."""507        response = client.post(508            "/api/chat/search",509            json={510                "user_id": 99999,511                "query": "laptop gaming"512            }513        )514        assert response.status_code == 404515 516    def test_ai_search_no_products_found(self, setup_database, clean_database):517        """Test AI search when no products match."""518        # Create user with AI access519        user_response = client.post(520            "/api/users/register",521            json={522                "name": "Premium User",523                "email": "premium@test.com",524                "city": "Jakarta",525                "ai_access_enabled": True526            }527        )528        user_id = user_response.json()["id"]529 530        # Mock get_engine to avoid loading actual model in tests531        # In real scenario, this would return AI response532        # For now, we just test the endpoint structure533        response = client.post(534            "/api/chat/search",535            json={536                "user_id": user_id,537                "query": "nonexistent product xyz123"538            }539        )540 541        # This will fail on AI inference if model not loaded542        # In production tests, mock the engine543        # For now, we verify the request structure is valid544        assert response.status_code in [200, 500]  # 500 if model not loaded545 546 547class TestUtilityFunctions:548    """Test utility functions."""549 550    def test_haversine_distance(self):551        """Test Haversine distance calculation."""552        from utils import haversine_distance553 554        # Jakarta to Bandung (approximately 126 km)555        distance = haversine_distance(-6.2088, 106.8456, -6.9175, 107.6191)556        assert 120 < distance < 135  # Allow some margin557 558        # Same location559        distance = haversine_distance(-6.2088, 106.8456, -6.2088, 106.8456)560        assert distance < 0.1  # Should be very close to 0561 562    def test_extract_location_query(self):563        """Test location extraction from query."""564        from utils import extract_location_query565 566        assert extract_location_query("laptop di Jakarta") == "Jakarta"567        assert extract_location_query("smartphone Bandung murah") == "Bandung"568        assert extract_location_query("cari laptop Jakarta Selatan") == "Jakarta Selatan"569        assert extract_location_query("laptop gaming") is None570 571    def test_format_price_idr(self):572        """Test IDR price formatting."""573        from utils import format_price_idr574 575        assert format_price_idr(10000000) == "Rp 10.000.000"576        assert format_price_idr(1500000) == "Rp 1.500.000"577        assert format_price_idr(999) == "Rp 999"578 579 580if __name__ == "__main__":581    pytest.main([__file__, "-v"])582