File size: 4,024 Bytes
d992912
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from unittest.mock import MagicMock
import pandas as pd
from fastapi.testclient import TestClient

from backend.app.main import app


def _make_search_results():
    df = pd.DataFrame([{
        "sku": "12345",
        "name": "Test Dress",
        "brand": "ASOS",
        "price": 29.99,
        "color_clean": "black",
        "color_family": "black",
        "category": "Dresses",
        "gender": "Women",
        "primary_image_url": "https://example.com/img.jpg",
        "hybrid_score": 0.95,
        "style_tags": ["casual"],
        "any_in_stock": True,
    }])
    df.attrs["query_info"] = {
        "original_query": "black dress",
        "processed_query": "black dress",
        "detected_language": "en",
        "was_translated": False,
        "was_spell_corrected": False,
        "spell_suggestion": None,
        "parsed_category": "Dresses",
        "parsed_color": "black",
        "parsed_price_range": [None, None],
        "parsed_gender": None,
        "parsed_style_tags": [],
        "parsed_material": None,
        "parsed_size": None,
        "parsed_exclusions": [],
        "sort_by": "relevance",
        "available_sorts": ["relevance", "price_asc", "price_desc"],
        "suggested_searches": ["navy dresses"],
    }
    return df


def _make_mock_engine():
    engine = MagicMock()
    engine._is_ready = True
    engine.search.return_value = _make_search_results()
    return engine


class TestSearchEndpoints:
    def test_text_search(self):
        app.state.engine = _make_mock_engine()
        client = TestClient(app, raise_server_exceptions=False)
        response = client.post("/api/v1/search", json={"query": "black dress"})
        assert response.status_code == 200
        data = response.json()
        assert data["total"] == 1
        assert data["results"][0]["sku"] == "12345"
        assert data["results"][0]["name"] == "Test Dress"
        assert data["query_info"]["parsed_category"] == "Dresses"

    def test_search_with_params(self):
        app.state.engine = _make_mock_engine()
        client = TestClient(app, raise_server_exceptions=False)
        response = client.post("/api/v1/search", json={
            "query": "red shoes",
            "top_n": 5,
            "sort_by": "price_asc",
        })
        assert response.status_code == 200

    def test_empty_query_rejected(self):
        app.state.engine = _make_mock_engine()
        client = TestClient(app, raise_server_exceptions=False)
        response = client.post("/api/v1/search", json={"query": ""})
        assert response.status_code == 422

    def test_engine_not_ready(self):
        app.state.engine = None
        client = TestClient(app, raise_server_exceptions=False)
        response = client.post("/api/v1/search", json={"query": "dress"})
        assert response.status_code == 503

    def test_similar_search(self):
        engine = _make_mock_engine()
        engine.get_product_detail.return_value = {
            "sku": "12345", "name": "Test Dress", "brand": "ASOS",
            "price": 29.99, "color_clean": "black", "color_family": "black",
            "category": "Dresses", "gender": "Women",
            "primary_image_url": "https://example.com/img.jpg",
            "image_urls": [], "style_tags": [], "materials": [],
            "sizes_available": [], "product_details": "", "any_in_stock": True,
        }
        engine.search_similar.return_value = pd.DataFrame([{
            "sku": "67890", "name": "Similar Dress", "brand": "ASOS",
            "price": 35.00, "color_clean": "navy", "category": "Dresses",
            "primary_image_url": "https://example.com/img2.jpg",
            "similarity_score": 0.89,
        }])
        app.state.engine = engine
        client = TestClient(app, raise_server_exceptions=False)
        response = client.get("/api/v1/search/similar/12345")
        assert response.status_code == 200
        data = response.json()
        assert data["total"] == 1
        assert data["results"][0]["similarity_score"] == 0.89