Files
mostovik-backend/tests/apps/parsers/test_snapshot_refresh_api.py
Aleksandr Meshchryakov 49cbfd265c
All checks were successful
Mostovik Backend CI/CD / Tests and lint (push) Successful in 9m37s
Mostovik Backend CI/CD / Build linux/amd64 release images (push) Successful in 4m18s
Mostovik Backend CI/CD / Deploy and verify internal main (push) Has been skipped
Mostovik Backend CI/CD / Deploy customer main (push) Has been skipped
Mostovik Backend CI/CD / Deploy dev (push) Successful in 1m48s
feat(registries): add SME and budget imports and fix source API workflows
2026-09-13 23:13:47 +02:00

98 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Оба публичных входа запускают один импорт и исключают конкурирующий запуск."""
from importlib import import_module
from unittest.mock import patch
import pytest
from apps.core.models import BackgroundJob
from core.celery import app as celery_app
from django.urls import reverse
from rest_framework.test import APIClient
from tests.apps.user.factories import UserFactory
SOURCES = [
("budget-process-registry", "budget_ubpandnubp", "parse_budget_registry"),
(
"sme-support-recipients-registry",
"fns_sme_support_recipients",
"parse_sme_support_recipients",
),
]
@pytest.mark.django_db
def test_openapi_exposes_refresh_conflict_and_pollable_task():
client = APIClient()
client.force_authenticate(UserFactory.create_user(is_staff=True))
response = client.get(reverse("schema-swagger-ui"), {"format": "openapi"})
assert response.status_code == 200
schema = response.data
path = next(path for path in schema["paths"] if "/parsers/run/" in path)
responses = schema["paths"][path]["post"]["responses"]
assert "409" in responses
assert responses["202"]["schema"]["$ref"].endswith("/ParserRunEnvelope")
assert "task_id" in schema["definitions"]["ParserRunResponse"]["properties"]
card_path = next(
path for path in schema["paths"] if "/sources/{slug}/refresh/" in path
)
assert "409" in schema["paths"][card_path]["post"]["responses"]
@pytest.mark.django_db
@pytest.mark.parametrize("slug,source,task", SOURCES)
@pytest.mark.parametrize("first", ["card", "parser"])
def test_refresh_is_pollable_and_other_entrypoint_conflicts(slug, source, task, first):
client = APIClient()
client.force_authenticate(UserFactory.create_user(is_staff=True))
urls = {
"card": f"/api/v1/sources/{slug}/refresh/",
"parser": f"/api/v1/parsers/run/{source}/",
}
second = "parser" if first == "card" else "card"
import_module("apps.parsers.tasks")
registered_task = celery_app.tasks[f"parsers.{source}.refresh"]
with patch.object(registered_task, "apply_async") as dispatch:
response = client.post(urls[first], {"params": {}}, format="json")
assert response.status_code == 202, response.data
payload = response.data.get("data", response.data)
job = BackgroundJob.objects.get(task_id=payload["task_id"])
assert payload["status"] == "queued"
assert dispatch.call_args.kwargs["task_id"] == job.task_id
assert dispatch.call_args.kwargs["kwargs"] == {"requested_by_id": job.user_id}
assert job.meta["refresh_task_ids"] == [job.task_id]
assert client.get(f"/api/v1/jobs/{job.task_id}/").status_code == 200
duplicate = client.post(urls[second], {}, format="json")
assert duplicate.status_code == 409, duplicate.data
assert BackgroundJob.objects.count() == 1
assert dispatch.call_count == 1
job.complete()
next_run = client.post(urls[second], {}, format="json")
assert next_run.status_code == 202
assert BackgroundJob.objects.count() == 2
@pytest.mark.django_db
@pytest.mark.parametrize("slug,source,task", SOURCES)
def test_refresh_requires_administrator_and_rejects_loader_parameters(
slug, source, task
):
client = APIClient()
client.force_authenticate(UserFactory.create_user())
import_module("apps.parsers.tasks")
registered_task = celery_app.tasks[f"parsers.{source}.refresh"]
with patch.object(registered_task, "apply_async") as dispatch:
for url in [
f"/api/v1/sources/{slug}/refresh/",
f"/api/v1/parsers/run/{source}/",
]:
assert client.post(url, {}, format="json").status_code == 403
client.force_authenticate(UserFactory.create_user(is_staff=True))
response = client.post(
f"/api/v1/sources/{slug}/refresh/",
{"params": {"url": "https://example.invalid"}},
format="json",
)
assert response.status_code == 400
dispatch.assert_not_called()