feat(5-plan-02-t1,t6): add backend search endpoint with comprehensive test coverage

This commit is contained in:
2026-04-22 17:44:00 +03:00
parent fd13f63c28
commit 42fb8a1d63

View File

@@ -2,6 +2,232 @@ import pytest
from fastapi import status
class TestItemSearch:
"""Test item search functionality."""
def test_search_items_by_name_exact_match(self, test_client, test_db, user_token):
"""Test exact name match in search."""
from backend.models import Item
item = Item(
name="Resistor 10K",
category="Electronics",
barcode="RES-10K-001",
part_number="R-10K",
quantity=100
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=Resistor 10K",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
assert data[0]["name"] == "Resistor 10K"
def test_search_items_by_part_number(self, test_client, test_db, user_token):
"""Test search by part number."""
from backend.models import Item
item = Item(
name="Capacitor",
category="Electronics",
barcode="CAP-100U-001",
part_number="CAP-100UF",
quantity=50
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=CAP-100UF",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
assert any(item["part_number"] == "CAP-100UF" for item in data)
def test_search_items_by_barcode(self, test_client, test_db, user_token):
"""Test search by barcode."""
from backend.models import Item
item = Item(
name="Diode",
category="Electronics",
barcode="BAR-123456789",
part_number="D-1N4007",
quantity=200
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=BAR-123456789",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
assert any(item["barcode"] == "BAR-123456789" for item in data)
def test_search_items_by_category(self, test_client, test_db, user_token):
"""Test search by category."""
from backend.models import Item
item = Item(
name="Test Item",
category="Networking",
barcode="NET-001",
part_number="NET-PN",
quantity=10
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=Networking",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
def test_search_items_partial_match(self, test_client, test_db, user_token):
"""Test substring matching in search."""
from backend.models import Item
item = Item(
name="Power Supply 500W",
category="Power",
barcode="PSU-500W",
part_number="PSU-500",
quantity=5
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=Power",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
def test_search_items_no_results(self, test_client, test_db, user_token):
"""Test search with no matching results."""
response = test_client.get(
"/items/search?q=NonexistentItemXYZ",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) == 0
def test_search_items_empty_query(self, test_client, test_db, user_token):
"""Test search with empty query returns empty list."""
response = test_client.get(
"/items/search?q=",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) == 0
def test_search_items_max_length_query(self, test_client, test_db, user_token):
"""Test search with query exceeding max length returns empty."""
long_query = "x" * 101
response = test_client.get(
f"/items/search?q={long_query}",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) == 0
def test_search_items_case_insensitive(self, test_client, test_db, user_token):
"""Test that search is case-insensitive."""
from backend.models import Item
item = Item(
name="Transistor",
category="Electronics",
barcode="TRN-001",
part_number="TRN-2N2222",
quantity=75
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=transistor",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) >= 1
def test_search_items_relevance_ordering(self, test_client, test_db, user_token):
"""Test that results are ordered by relevance (name match first)."""
from backend.models import Item
# Create items where query matches different fields
item1 = Item(
name="Resistor",
category="Electronics",
barcode="RES-100",
part_number="R-100K",
quantity=100
)
item2 = Item(
name="Component",
category="Resistor Components",
barcode="RES-200",
part_number="R-200K",
quantity=50
)
test_db.add_all([item1, item2])
test_db.commit()
response = test_client.get(
"/items/search?q=Resistor",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
# Name match should be first
assert len(data) >= 1
assert data[0]["name"] == "Resistor"
def test_search_items_max_50_results(self, test_client, test_db, user_token):
"""Test that search returns max 50 results."""
from backend.models import Item
# Create 60 items with same category
for i in range(60):
item = Item(
name=f"Item {i}",
category="Test",
barcode=f"TEST-{i}",
part_number=f"P-{i}",
quantity=i
)
test_db.add(item)
test_db.commit()
response = test_client.get(
"/items/search?q=Test",
headers={"Authorization": f"Bearer {user_token}"}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) <= 50
class TestItemCRUD:
"""Test item creation, read, update, delete."""