"""Integration tests for the ingest endpoint."""
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import pytest
from httpx import AsyncClient
from vmk_data_collector.api.v1 import router_properties
class TestIngest:
@pytest.mark.asyncio
async def test_ingest_returns_202_and_pending(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(
router_properties.RawDataRepository,
"create",
AsyncMock(return_value=MagicMock(id=42)),
)
response = await async_client.post(
"/api/v1/ingest",
json={
"source_slug": "test",
"external_id": "ext-1",
"payload": {
"title": "2-комнатная квартира",
"price": 100000,
},
},
)
assert response.status_code == 202
data = response.json()
assert data["status"] == "pending"
assert data["job_id"] == 42
assert "Queued" in data["message"]
@pytest.mark.asyncio
async def test_ingest_invalid_payload_returns_422(
self,
async_client: AsyncClient,
) -> None:
response = await async_client.post(
"/api/v1/ingest",
json={
"source_slug": "test",
"external_id": "ext-1",
"payload": {}, # missing title and description
},
)
assert response.status_code == 422
class TestArchiveCheck:
@pytest.mark.asyncio
async def test_not_found_returns_404(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(
router_properties.PropertyRepository,
"get_by_id",
AsyncMock(return_value=None),
)
response = await async_client.post("/api/v1/listings/99/archive-check")
assert response.status_code == 404
@pytest.mark.asyncio
async def test_no_url_returns_422(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
listing = MagicMock()
listing.url_source = None
monkeypatch.setattr(
router_properties.PropertyRepository,
"get_by_id",
AsyncMock(return_value=listing),
)
response = await async_client.post("/api/v1/listings/1/archive-check")
assert response.status_code == 422
@pytest.mark.asyncio
async def test_archived_on_404(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
listing = MagicMock()
listing.url_source = "http://example.com/ad/1"
monkeypatch.setattr(
router_properties.PropertyRepository,
"get_by_id",
AsyncMock(return_value=listing),
)
monkeypatch.setattr(
router_properties.PropertyRepository,
"mark_archived",
AsyncMock(return_value=listing),
)
# Patch httpx.AsyncClient.head
async def fake_head(*_a, **_k) -> Any:
resp = MagicMock()
resp.status_code = 404
return resp
monkeypatch.setattr(
"httpx.AsyncClient.head",
fake_head,
)
response = await async_client.post("/api/v1/listings/1/archive-check")
assert response.status_code == 200
data = response.json()
assert data["was_archived"] is True
assert data["reason"] == "status_404"
@pytest.mark.asyncio
async def test_not_archived_on_200(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
listing = MagicMock()
listing.url_source = "http://example.com/ad/1"
monkeypatch.setattr(
router_properties.PropertyRepository,
"get_by_id",
AsyncMock(return_value=listing),
)
async def fake_head(*_a, **_k) -> Any:
resp = MagicMock()
resp.status_code = 200
return resp
monkeypatch.setattr("httpx.AsyncClient.head", fake_head)
response = await async_client.post("/api/v1/listings/1/archive-check")
assert response.status_code == 200
data = response.json()
assert data["was_archived"] is False
assert data["reason"] == "status_200"
class TestCleanupRaw:
@pytest.mark.asyncio
async def test_cleanup_returns_deleted_count(
self,
async_client: AsyncClient,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(
router_properties.RawDataRepository,
"delete_old_completed",
AsyncMock(return_value=5),
)
response = await async_client.post("/api/v1/admin/cleanup-raw?days=30")
assert response.status_code == 200
data = response.json()
assert data["deleted_count"] == 5