afp-backend / tests /e2e /test_quotation_lines_patch.py
Yarin35
feat(quotations): add endpoint to update quotation line with fixed price and validation status
ed7ccec
"""End-to-end tests for quotation line update endpoint."""
import pytest
from httpx import AsyncClient
from decimal import Decimal
from app.schemas.quotation import CalculatePricesRequest
@pytest.mark.e2e
@pytest.mark.asyncio
async def test_update_quotation_line_success(
client: AsyncClient, seeded_entities, prisma
) -> None:
"""Test updating a quotation line with fixed_price and validation."""
# 1. Create a quotation first by calculating prices
ref = seeded_entities["primary_reference"]
calc_request = CalculatePricesRequest(article_references=[ref], save_quotation=True)
calc_response = await client.post(
"/api/v1/quotations/calculate-prices",
json=calc_request.model_dump(),
)
assert calc_response.status_code == 200
calc_data = calc_response.json()
quotation_id = calc_data.get("quotation_id")
assert quotation_id is not None
# We need to find the line_id. Since we don't have a GET quotation yet,
# let's assume the response might contain it or we have to fetch it.
# For now, let's check if 'calculations' has a line_id or similar.
# If not, we might need a way to get the line_id.
# Let's check the database directly or use a known line_id if available.
# Looking at the current calculate_prices implementation in quotations.py:
# it returns CalculatePricesResponse which contains calculations: list[PriceCalculation]
# PriceCalculation schema (app/schemas/quotation.py) doesn't seem to have line_id.
# Wait, I should check if I can get the line_id from the database.
line = await prisma.cotation_lines.find_first(
where={"cotation_id": quotation_id}
)
assert line is not None
line_id = line.id
# 2. Update the line
update_payload = {
"fixed_price": 55.50,
"validated": True
}
response = await client.patch(
f"/api/v1/quotations/lines/{line_id}",
json=update_payload,
)
assert response.status_code == 200
data = response.json()
assert data["id"] == line_id
assert float(data["fixed_price"]) == 55.50
assert data["validated"] is True
# 3. Verify in database
db_line = await prisma.cotation_lines.find_unique(where={"id": line_id})
assert db_line.fixed_price == Decimal("55.50")
assert db_line.validated is True
@pytest.mark.e2e
@pytest.mark.asyncio
async def test_update_quotation_line_partial_update(
client: AsyncClient, seeded_entities, prisma
) -> None:
"""Test updating only one field of a quotation line."""
# Create a line
calc_request = CalculatePricesRequest(
article_references=[seeded_entities["primary_reference"]],
save_quotation=True
)
await client.post("/api/v1/quotations/calculate-prices", json=calc_request.model_dump())
line = await prisma.cotation_lines.find_first(order={"saved_at": "desc"})
line_id = line.id
# Update only validated
response = await client.patch(
f"/api/v1/quotations/lines/{line_id}",
json={"validated": True},
)
assert response.status_code == 200
assert response.json()["validated"] is True
assert response.json()["fixed_price"] is None
# Update only fixed_price
response = await client.patch(
f"/api/v1/quotations/lines/{line_id}",
json={"fixed_price": 100.0},
)
assert response.status_code == 200
assert float(response.json()["fixed_price"]) == 100.0
assert response.json()["validated"] is True # Should remain True
@pytest.mark.e2e
@pytest.mark.asyncio
async def test_update_quotation_line_not_found(
client: AsyncClient, seeded_entities
) -> None:
"""Test updating a non-existent quotation line."""
fake_id = "00000000-0000-0000-0000-000000000000"
response = await client.patch(
f"/api/v1/quotations/lines/{fake_id}",
json={"validated": True},
)
# Now it should return 404 correctly
assert response.status_code == 404
assert "not found" in response.json()["detail"].lower()
@pytest.mark.e2e
@pytest.mark.asyncio
async def test_update_quotation_line_clear_fixed_price(
client: AsyncClient, seeded_entities, prisma
) -> None:
"""Test clearing fixed_price by setting it to null."""
# 1. Create a line with fixed_price
calc_request = CalculatePricesRequest(
article_references=[seeded_entities["primary_reference"]],
save_quotation=True
)
await client.post("/api/v1/quotations/calculate-prices", json=calc_request.model_dump())
line = await prisma.cotation_lines.find_first(order={"saved_at": "desc"})
line_id = line.id
# Set fixed_price
await client.patch(f"/api/v1/quotations/lines/{line_id}", json={"fixed_price": 50.0})
# 2. Try to clear it
response = await client.patch(
f"/api/v1/quotations/lines/{line_id}",
json={"fixed_price": None},
)
assert response.status_code == 200
# THIS WILL CURRENTLY FAIL if the implementation doesn't support null
assert response.json()["fixed_price"] is None