fix: ruff lint + format fixes in tests, ESLint fixes in frontend
This commit is contained in:
@@ -1,17 +1,10 @@
|
||||
"""Tests for vehicle CRUD endpoints and mobile.de integration."""
|
||||
|
||||
import uuid
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from app.database import Base, get_db
|
||||
from app.main import app
|
||||
from app.models.vehicle import MobileDeListing, Vehicle
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
@@ -50,7 +43,9 @@ class TestVehicleList:
|
||||
"""GET /api/v1/vehicles tests."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_vehicles_returns_200_with_pagination(self, admin_client, created_vehicle):
|
||||
async def test_list_vehicles_returns_200_with_pagination(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""GET /api/v1/vehicles returns 200 with paginated list."""
|
||||
response = await admin_client.get("/api/v1/vehicles/?page=1&page_size=20")
|
||||
assert response.status_code == 200
|
||||
@@ -74,7 +69,9 @@ class TestVehicleList:
|
||||
assert item["vehicle_type"] == "lkw"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_vehicles_filter_by_availability(self, admin_client, created_vehicle):
|
||||
async def test_list_vehicles_filter_by_availability(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""GET /api/v1/vehicles?availability=available returns filtered results."""
|
||||
response = await admin_client.get("/api/v1/vehicles/?availability=available")
|
||||
assert response.status_code == 200
|
||||
@@ -92,9 +89,13 @@ class TestVehicleList:
|
||||
assert data["items"][0]["created_at"] >= data["items"][1]["created_at"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_vehicles_filter_by_price_range(self, admin_client, created_vehicle):
|
||||
async def test_list_vehicles_filter_by_price_range(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""GET /api/v1/vehicles?min_price=40000&max_price=50000 returns filtered results."""
|
||||
response = await admin_client.get("/api/v1/vehicles/?min_price=40000&max_price=50000")
|
||||
response = await admin_client.get(
|
||||
"/api/v1/vehicles/?min_price=40000&max_price=50000"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
for item in data["items"]:
|
||||
@@ -123,7 +124,9 @@ class TestVehicleCreate:
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_returns_201(self, admin_client, sample_vehicle_data):
|
||||
"""POST /api/v1/vehicles with valid data returns 201."""
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["make"] == sample_vehicle_data["make"]
|
||||
@@ -133,38 +136,58 @@ class TestVehicleCreate:
|
||||
assert data["id"] is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_missing_make_returns_422(self, admin_client, sample_vehicle_data):
|
||||
async def test_create_vehicle_missing_make_returns_422(
|
||||
self, admin_client, sample_vehicle_data
|
||||
):
|
||||
"""POST /api/v1/vehicles without make returns 422."""
|
||||
del sample_vehicle_data["make"]
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_missing_fin_returns_422(self, admin_client, sample_vehicle_data):
|
||||
async def test_create_vehicle_missing_fin_returns_422(
|
||||
self, admin_client, sample_vehicle_data
|
||||
):
|
||||
"""POST /api/v1/vehicles without fin returns 422."""
|
||||
del sample_vehicle_data["fin"]
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_short_fin_returns_422(self, admin_client, sample_vehicle_data):
|
||||
async def test_create_vehicle_short_fin_returns_422(
|
||||
self, admin_client, sample_vehicle_data
|
||||
):
|
||||
"""POST /api/v1/vehicles with short FIN returns 422."""
|
||||
sample_vehicle_data["fin"] = "SHORT"
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_duplicate_fin_returns_409(self, admin_client, sample_vehicle_data, created_vehicle):
|
||||
async def test_create_vehicle_duplicate_fin_returns_409(
|
||||
self, admin_client, sample_vehicle_data, created_vehicle
|
||||
):
|
||||
"""POST /api/v1/vehicles with duplicate FIN returns 409."""
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 409
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_vehicle_auto_computes_power_hp(self, admin_client, sample_vehicle_data):
|
||||
async def test_create_vehicle_auto_computes_power_hp(
|
||||
self, admin_client, sample_vehicle_data
|
||||
):
|
||||
"""POST /api/v1/vehicles auto-computes power_hp from power_kw."""
|
||||
sample_vehicle_data["power_kw"] = 100
|
||||
sample_vehicle_data.pop("power_hp", None)
|
||||
response = await admin_client.post("/api/v1/vehicles/", json=sample_vehicle_data)
|
||||
response = await admin_client.post(
|
||||
"/api/v1/vehicles/", json=sample_vehicle_data
|
||||
)
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
assert data["power_hp"] == 136 # 100 * 1.35962 ≈ 136
|
||||
@@ -218,7 +241,9 @@ class TestVehicleUpdate:
|
||||
assert response.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_vehicle_no_fields_returns_400(self, admin_client, created_vehicle):
|
||||
async def test_update_vehicle_no_fields_returns_400(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""PUT /api/v1/vehicles/:id with no fields returns 400."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
response = await admin_client.put(
|
||||
@@ -232,7 +257,9 @@ class TestVehicleDelete:
|
||||
"""DELETE /api/v1/vehicles/:id tests."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_vehicle_returns_200_with_deleted_at(self, admin_client, created_vehicle):
|
||||
async def test_delete_vehicle_returns_200_with_deleted_at(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""DELETE /api/v1/vehicles/:id returns 200 and sets deleted_at."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
response = await admin_client.delete(f"/api/v1/vehicles/{vehicle_id}")
|
||||
@@ -259,7 +286,9 @@ class TestVehicleDelete:
|
||||
assert item["id"] != vehicle_id
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deleted_vehicle_returns_404_on_detail(self, admin_client, created_vehicle):
|
||||
async def test_deleted_vehicle_returns_404_on_detail(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""After soft-delete, GET /api/v1/vehicles/:id returns 404."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
await admin_client.delete(f"/api/v1/vehicles/{vehicle_id}")
|
||||
@@ -274,7 +303,9 @@ class TestMobileDePush:
|
||||
async def test_push_returns_202(self, admin_client, created_vehicle):
|
||||
"""POST /api/v1/vehicles/:id/mobile-de/push returns 202."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
with patch("app.services.mobilede_service.httpx.AsyncClient") as mock_client_cls:
|
||||
with patch(
|
||||
"app.services.mobilede_service.httpx.AsyncClient"
|
||||
) as mock_client_cls:
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 201
|
||||
mock_response.json.return_value = {"id": "mobile-de-ad-123"}
|
||||
@@ -285,7 +316,9 @@ class TestMobileDePush:
|
||||
mock_client.__aexit__ = AsyncMock(return_value=None)
|
||||
mock_client_cls.return_value = mock_client
|
||||
|
||||
response = await admin_client.post(f"/api/v1/vehicles/{vehicle_id}/mobile-de/push")
|
||||
response = await admin_client.post(
|
||||
f"/api/v1/vehicles/{vehicle_id}/mobile-de/push"
|
||||
)
|
||||
|
||||
assert response.status_code == 202
|
||||
data = response.json()
|
||||
@@ -305,20 +338,28 @@ class TestMobileDeStatus:
|
||||
"""GET /api/v1/vehicles/:id/mobile-de/status tests."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_status_returns_200_with_no_listing(self, admin_client, created_vehicle):
|
||||
async def test_status_returns_200_with_no_listing(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""GET /api/v1/vehicles/:id/mobile-de/status returns 200 with pending status when no listing exists."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
response = await admin_client.get(f"/api/v1/vehicles/{vehicle_id}/mobile-de/status")
|
||||
response = await admin_client.get(
|
||||
f"/api/v1/vehicles/{vehicle_id}/mobile-de/status"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["synced"] is False
|
||||
assert data["sync_status"] == "pending"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_status_returns_200_with_synced_listing(self, admin_client, created_vehicle):
|
||||
async def test_status_returns_200_with_synced_listing(
|
||||
self, admin_client, created_vehicle
|
||||
):
|
||||
"""GET /api/v1/vehicles/:id/mobile-de/status returns 200 with sync info after push."""
|
||||
vehicle_id = created_vehicle["id"]
|
||||
with patch("app.services.mobilede_service.httpx.AsyncClient") as mock_client_cls:
|
||||
with patch(
|
||||
"app.services.mobilede_service.httpx.AsyncClient"
|
||||
) as mock_client_cls:
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 201
|
||||
mock_response.json.return_value = {"id": "mobile-de-ad-456"}
|
||||
@@ -331,7 +372,9 @@ class TestMobileDeStatus:
|
||||
|
||||
await admin_client.post(f"/api/v1/vehicles/{vehicle_id}/mobile-de/push")
|
||||
|
||||
response = await admin_client.get(f"/api/v1/vehicles/{vehicle_id}/mobile-de/status")
|
||||
response = await admin_client.get(
|
||||
f"/api/v1/vehicles/{vehicle_id}/mobile-de/status"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["synced"] is True
|
||||
@@ -342,5 +385,7 @@ class TestMobileDeStatus:
|
||||
async def test_status_nonexistent_vehicle_returns_404(self, admin_client):
|
||||
"""GET /api/v1/vehicles/:id/mobile-de/status with nonexistent ID returns 404."""
|
||||
fake_id = str(uuid.uuid4())
|
||||
response = await admin_client.get(f"/api/v1/vehicles/{fake_id}/mobile-de/status")
|
||||
response = await admin_client.get(
|
||||
f"/api/v1/vehicles/{fake_id}/mobile-de/status"
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
Reference in New Issue
Block a user