Improve CarPass product UX and service flows
This commit is contained in:
@@ -69,3 +69,13 @@ def auth_headers() -> dict[str, str]:
|
||||
@pytest.fixture()
|
||||
def other_auth_headers() -> dict[str, str]:
|
||||
return {"X-Telegram-Init-Data": make_init_data(2002)}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def admin_auth_headers() -> dict[str, str]:
|
||||
return {"X-Telegram-Init-Data": make_init_data(9001, "Admin")}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def internal_headers() -> dict[str, str]:
|
||||
return {"X-Internal-API-Token": TEST_INTERNAL_TOKEN}
|
||||
|
||||
@@ -87,3 +87,44 @@ async def test_stats_do_not_fail_with_insufficient_data(client, auth_headers) ->
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["avg_consumption_l_per_100km"] is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_expense_crud_and_insurance_allocation(client, auth_headers) -> None:
|
||||
car = (await client.post("/api/cars", headers=auth_headers, json={"name": "Cost car"})).json()
|
||||
created = await client.post(
|
||||
"/api/expenses",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"car_id": car["id"],
|
||||
"entry_date": "2026-01-01",
|
||||
"category": "insurance",
|
||||
"title": "Insurance",
|
||||
"total_cost": 1200,
|
||||
"period_start": "2026-01-01",
|
||||
"period_end": "2026-12-31",
|
||||
"is_recurring": True,
|
||||
},
|
||||
)
|
||||
assert created.status_code == 201
|
||||
entry_id = created.json()["id"]
|
||||
|
||||
stats = await client.get(
|
||||
f"/api/cars/{car['id']}/stats?date_from=2026-01-01&date_to=2026-01-31",
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert stats.status_code == 200
|
||||
body = stats.json()
|
||||
assert body["expenses_cost"] in {"101.92", "101.93"}
|
||||
assert body["cost_by_category"]["insurance"] in {"101.92", "101.93"}
|
||||
|
||||
patched = await client.patch(
|
||||
f"/api/expenses/{entry_id}",
|
||||
headers=auth_headers,
|
||||
json={"title": "Insurance policy"},
|
||||
)
|
||||
assert patched.status_code == 200
|
||||
assert patched.json()["title"] == "Insurance policy"
|
||||
|
||||
deleted = await client.delete(f"/api/expenses/{entry_id}", headers=auth_headers)
|
||||
assert deleted.status_code == 204
|
||||
|
||||
@@ -15,7 +15,9 @@ async def test_vin_validation_rejects_invalid_value(client, auth_headers) -> Non
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_service_visit_owner_confirmation_and_change_request(client, auth_headers) -> None:
|
||||
async def test_service_visit_owner_confirmation_and_change_request(
|
||||
client, auth_headers, admin_auth_headers, internal_headers
|
||||
) -> None:
|
||||
vehicle = (
|
||||
await client.post(
|
||||
"/api/my/vehicles",
|
||||
@@ -30,6 +32,16 @@ async def test_service_visit_owner_confirmation_and_change_request(client, auth_
|
||||
json={"display_name": "Careful Service", "country": "KR", "city": "Seoul"},
|
||||
)
|
||||
).json()
|
||||
await client.post(
|
||||
"/api/users",
|
||||
headers=internal_headers,
|
||||
json={"telegram_id": 9001, "platform_role": "admin"},
|
||||
)
|
||||
verify_response = await client.post(
|
||||
f"/api/admin/service-centers/{center['id']}/verify",
|
||||
headers=admin_auth_headers,
|
||||
)
|
||||
assert verify_response.status_code == 200
|
||||
visit = (
|
||||
await client.post(
|
||||
f"/api/service-centers/{center['id']}/visits",
|
||||
@@ -63,6 +75,71 @@ async def test_service_visit_owner_confirmation_and_change_request(client, auth_
|
||||
assert approve_response.json()["status"] == "approved"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pending_service_center_cannot_create_visit(client, auth_headers) -> None:
|
||||
vehicle = (
|
||||
await client.post(
|
||||
"/api/my/vehicles",
|
||||
headers=auth_headers,
|
||||
json={"name": "Client car"},
|
||||
)
|
||||
).json()
|
||||
center = (
|
||||
await client.post(
|
||||
"/api/service-centers",
|
||||
headers=auth_headers,
|
||||
json={"display_name": "Pending Service", "country": "KR", "city": "Seoul"},
|
||||
)
|
||||
).json()
|
||||
response = await client.post(
|
||||
f"/api/service-centers/{center['id']}/visits",
|
||||
headers=auth_headers,
|
||||
json={"vehicle_id": vehicle["id"], "visit_date": "2026-05-12"},
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_public_service_center_and_review_flow(
|
||||
client, auth_headers, admin_auth_headers, internal_headers
|
||||
) -> None:
|
||||
center = (
|
||||
await client.post(
|
||||
"/api/service-centers",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"display_name": "Review Service",
|
||||
"country": "KR",
|
||||
"city": "Seoul",
|
||||
"description": "Clean workshop",
|
||||
"specializations": ["oil", "diagnostics"],
|
||||
},
|
||||
)
|
||||
).json()
|
||||
pending_list = await client.get("/api/service-centers/public", headers=auth_headers)
|
||||
assert pending_list.json() == []
|
||||
await client.post(
|
||||
"/api/users",
|
||||
headers=internal_headers,
|
||||
json={"telegram_id": 9001, "platform_role": "admin"},
|
||||
)
|
||||
await client.post(f"/api/admin/service-centers/{center['id']}/verify", headers=admin_auth_headers)
|
||||
|
||||
public_list = await client.get("/api/service-centers/public", headers=auth_headers)
|
||||
assert public_list.status_code == 200
|
||||
assert public_list.json()[0]["display_name"] == "Review Service"
|
||||
|
||||
review = await client.post(
|
||||
f"/api/service-centers/{center['id']}/reviews",
|
||||
headers=auth_headers,
|
||||
json={"rating": 5, "text": "Accurate and transparent service"},
|
||||
)
|
||||
assert review.status_code == 201
|
||||
refreshed = await client.get(f"/api/service-centers/{center['id']}", headers=auth_headers)
|
||||
assert refreshed.json()["reviews_count"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ocr_candidates_do_not_write_vehicle_data(client, auth_headers) -> None:
|
||||
response = await client.post(
|
||||
|
||||
Reference in New Issue
Block a user