import pytest async def test_update_product_returns_200(auth_client, product): response = await auth_client.patch(f"/api/product/{product.id}", json={"name": "Updated Name"}) assert response.status_code == 200 assert response.json()["name"] == "Updated Name" async def test_update_product_recalculates_calories_when_macros_change(auth_client, product): response = await auth_client.patch(f"/api/product/{product.id}", json={"protein": 10.0}) # protein=10, carb=0, fat=3.6, fiber=0 → 10*4 + 3.6*9 = 40 + 32.4 = 72.4 assert response.json()["calories"] == pytest.approx(72.4) async def test_update_product_uses_explicit_calories(auth_client, product): response = await auth_client.patch( f"/api/product/{product.id}", json={"protein": 10.0, "calories": 99.0} ) assert response.json()["calories"] == 99.0 async def test_update_product_not_found_returns_404(auth_client): response = await auth_client.patch("/api/product/99999", json={"name": "Ghost"}) assert response.status_code == 404 async def test_update_product_duplicate_barcode_returns_409(auth_client, product, product_payload): await auth_client.post("/api/product", json={**product_payload, "name": "Other", "barcode": "AAA"}) response = await auth_client.patch(f"/api/product/{product.id}", json={"barcode": "AAA"}) assert response.status_code == 409 async def test_update_product_without_auth_returns_401(client, product): response = await client.patch(f"/api/product/{product.id}", json={"name": "x"}) assert response.status_code == 401 async def test_create_product_returns_201(auth_client, product_payload): response = await auth_client.post("/api/product", json=product_payload) assert response.status_code == 201 async def test_create_product_returns_correct_fields(auth_client, product_payload): response = await auth_client.post("/api/product", json=product_payload) body = response.json() assert body["name"] == product_payload["name"] assert body["protein"] == product_payload["protein"] assert body["carb"] == product_payload["carb"] assert body["fat"] == product_payload["fat"] assert body["fiber"] == product_payload["fiber"] assert "id" in body async def test_create_product_calculates_calories(auth_client, product_payload): response = await auth_client.post("/api/product", json=product_payload) # 31*4 + 0*4 + 3.6*9 + 0*2 = 124 + 32.4 = 156.4 assert response.json()["calories"] == pytest.approx(156.4) async def test_create_product_uses_explicit_calories(auth_client, product_payload): response = await auth_client.post("/api/product", json={**product_payload, "calories": 50.0}) assert response.json()["calories"] == 50.0 async def test_create_product_duplicate_barcode_returns_409(auth_client, product_payload): await auth_client.post("/api/product", json={**product_payload, "barcode": "123456"}) response = await auth_client.post("/api/product", json={**product_payload, "barcode": "123456"}) assert response.status_code == 409 async def test_create_product_invalid_protein_returns_422(auth_client, product_payload): response = await auth_client.post("/api/product", json={**product_payload, "protein": -1.0}) assert response.status_code == 422 async def test_create_product_protein_over_100_returns_422(auth_client, product_payload): response = await auth_client.post("/api/product", json={**product_payload, "protein": 101.0}) assert response.status_code == 422 async def test_create_product_without_auth_returns_401(client, product_payload): response = await client.post("/api/product", json=product_payload) assert response.status_code == 401 async def test_list_products_returns_200(auth_client, product): response = await auth_client.get("/api/product") assert response.status_code == 200 assert isinstance(response.json(), list) async def test_list_products_contains_created(auth_client, product): response = await auth_client.get("/api/product") ids = [p["id"] for p in response.json()] assert product.id in ids async def test_list_products_filters_by_name(auth_client, product): response = await auth_client.get("/api/product", params={"q": product.name}) assert all(product.name.lower() in p["name"].lower() for p in response.json()) async def test_list_products_without_auth_returns_401(client): response = await client.get("/api/product") assert response.status_code == 401