"""Async scrape endpoint contract. Verifies that ``POST /api/admin/scrape``: - returns 202 + ``scrape_log_id`` synchronously, - persists a ``ScrapeLog`` row in status STARTED before the background task runs (the task is monkey-patched out so it never reaches Playwright and never opens a session outside the test transaction). """ from __future__ import annotations import os import uuid import pytest os.environ.setdefault("ADMIN_TOKEN", "test-admin-token") @pytest.fixture(autouse=True) def _admin_token(monkeypatch): monkeypatch.setenv("ADMIN_TOKEN", "test-admin-token") yield @pytest.mark.requires_postgres def test_scrape_returns_202_and_log_id(client, db, monkeypatch): """Endpoint enqueues the scrape and returns 202 + scrape_log_id. We replace the background runner with a no-op so the test does NOT spin up Playwright and does NOT open a session outside the rolled-back test transaction. """ calls: list[tuple] = [] def _fake_run(log_id, source, scrape_type): calls.append((log_id, source, scrape_type)) # Patch in BOTH the service module (definition site) and the api module # (import site) so whichever symbol the route resolved to is replaced. monkeypatch.setattr( "app.services.scraper_service._run_scrape_in_background", _fake_run ) r = client.post( "/api/admin/scrape", headers={"Authorization": "Bearer test-admin-token"}, ) assert r.status_code == 202, r.text body = r.json() assert body["status"] == "queued" assert "scrape_log_id" in body log_id = uuid.UUID(body["scrape_log_id"]) # Row was committed inside enqueue_scrape — visible on the test session. from app.models import ScrapeLog, ScrapeStatus log = db.query(ScrapeLog).filter(ScrapeLog.id == log_id).first() assert log is not None, "ScrapeLog row should exist after enqueue" assert log.status == ScrapeStatus.STARTED assert log.source == "lucky_california" assert log.scrape_type == "weekly_ad" assert log.completed_at is None # TestClient runs background tasks before returning from the context # manager exit — by the time we get here, the fake runner ran exactly once. assert len(calls) == 1 assert calls[0][0] == log_id