from __future__ import annotations from fastapi.testclient import TestClient from app.main import app, create_app client = TestClient(app) def test_service_exposes_only_match_endpoint() -> None: application_paths = [route.path for route in app.routes] assert application_paths == ["/match"] def test_match_contract_and_message_order() -> None: messages = [ "бур sds 10х210", "где находится ваш магазин", "нужен кабель", ] response = client.post("/match", json={"messages": messages}) assert response.status_code == 200 body = response.json() assert set(body) == {"results"} assert [result["message"] for result in body["results"]] == messages assert [result["status"] for result in body["results"]] == [ "matched", "not_found", "ambiguous", ] for result in body["results"]: assert set(result) == {"message", "status", "candidates"} assert len(result["candidates"]) <= 3 for candidate in result["candidates"]: assert set(candidate) == {"sku", "confidence"} assert 0.0 <= candidate["confidence"] <= 1.0 def test_task_example_uses_required_request_and_response_shape() -> None: message = "саморезы по дереву 4.2 на 75, пачку" response = client.post("/match", json={"messages": [message]}) assert response.status_code == 200 body = response.json() assert set(body) == {"results"} assert len(body["results"]) == 1 result = body["results"][0] assert set(result) == {"message", "status", "candidates"} assert result["message"] == message assert result["status"] in {"matched", "ambiguous", "not_found"} for candidate in result["candidates"]: assert set(candidate) == {"sku", "confidence"} assert isinstance(candidate["sku"], str) assert isinstance(candidate["confidence"], float) def test_empty_message_list_is_valid() -> None: response = client.post("/match", json={"messages": []}) assert response.status_code == 200 assert response.json() == {"results": []} def test_messages_field_is_required() -> None: response = client.post("/match", json={}) assert response.status_code == 422 def test_unknown_request_fields_are_rejected() -> None: response = client.post("/match", json={"messages": [], "debug": True}) assert response.status_code == 422 def test_opt_in_info_route_returns_catalog_item() -> None: test_app = create_app(enable_test_info_route=True) test_client = TestClient(test_app) assert [route.path for route in test_app.routes] == [ "/match", "/get_info_by/{sku}", ] response = test_client.get("/get_info_by/bit-0073") assert response.status_code == 200 assert set(response.json()) == {"sku", "name", "unit", "price"} assert response.json()["sku"] == "BIT-0073" assert response.json()["name"] assert response.json()["unit"] assert float(response.json()["price"]) > 0 def test_opt_in_info_route_returns_404_for_unknown_sku() -> None: test_client = TestClient(create_app(enable_test_info_route=True)) response = test_client.get("/get_info_by/UNKNOWN-0000") assert response.status_code == 404 assert response.json() == {"detail": "SKU not found"} def test_opt_in_routes_allow_requests_from_local_html_page() -> None: test_client = TestClient(create_app(enable_test_info_route=True)) response = test_client.options( "/match", headers={ "Origin": "null", "Access-Control-Request-Method": "POST", "Access-Control-Request-Headers": "content-type", }, ) assert response.status_code == 200 assert response.headers["access-control-allow-origin"] == "*" assert "POST" in response.headers["access-control-allow-methods"] assert "GET" in response.headers["access-control-allow-methods"]