feat: add parser source dashboard and scheduling
Some checks failed
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 9s
CI/CD Pipeline / Run Tests (pull_request) Failing after 48s
CI/CD Pipeline / Build Docker Images (pull_request) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (pull_request) Has been skipped

This commit is contained in:
2026-04-27 23:36:28 +02:00
parent 199d871923
commit c9b350da1e
96 changed files with 15014 additions and 268 deletions

View File

@@ -1,5 +1,7 @@
"""Tests for core OpenAPI utilities"""
import json
from apps.core.openapi import (
CommonParameters,
CommonResponses,
@@ -41,6 +43,98 @@ class ApiDocsDecoratorTest(TestCase):
self.assertEqual(my_view.__name__, "my_view")
class OpenApiSchemaViewTest(TestCase):
"""Tests for generated Swagger schema."""
def _operation_tags(self, paths: dict) -> list[str]:
tags = []
for operations in paths.values():
for method, operation in operations.items():
if method == "parameters":
continue
tags.extend(operation.get("tags", []))
return tags
def test_schema_exposes_parser_and_job_tags(self):
"""Test dashboard/parser APIs are visible as separate Swagger groups."""
response = self.client.get("/?format=openapi")
self.assertEqual(response.status_code, 200)
schema = json.loads(response.content)
paths = schema["paths"]
self.assertIn("/api/v1/parsers/sources/", paths)
self.assertIn("/api/v1/parsers/records/", paths)
self.assertIn("/api/v1/parsers/run/{source_key}/", paths)
self.assertIn("/api/v1/parsers/upload/{source_key}/", paths)
self.assertIn("/api/v1/users/register/", paths)
self.assertIn("/api/v1/users/login/", paths)
self.assertIn("/api/v1/users/token/refresh/", paths)
self.assertIn("/api/v1/users/token/verify/", paths)
self.assertIn("/api/v1/users/me/", paths)
self.assertIn("/api/v1/fns/reports/", paths)
self.assertIn("/api/v1/fns/reports/{id}/", paths)
self.assertIn("/api/v1/fns/upload/", paths)
self.assertIn("/api/v1/minpromtorg/manufacturers/", paths)
self.assertIn("/api/v1/zakupki/", paths)
self.assertIn("/api/v1/zakupki/{id}/", paths)
self.assertIn("/api/v1/jobs/", paths)
self.assertNotIn("/api/v1/zakupki/procurements-44fz/", paths)
self.assertNotIn("/api/v1/zakupki/procurements-223fz/", paths)
self.assertNotIn("/api/v1/zakupki/contracts/", paths)
self.assertNotIn("/api/v1/zakupki/upload/", paths)
self.assertNotIn("/api/v2/fns/reports/", paths)
self.assertEqual(
paths["/api/v1/parsers/sources/"]["get"]["tags"],
["Parser Management"],
)
self.assertEqual(
paths["/api/v1/parsers/upload/{source_key}/"]["post"]["tags"],
["Parser Management"],
)
self.assertEqual(
paths["/api/v1/fns/reports/"]["get"]["tags"],
["FNS"],
)
self.assertEqual(
paths["/api/v1/fns/reports/{id}/"]["get"]["tags"],
["FNS"],
)
self.assertEqual(
paths["/api/v1/fns/upload/"]["post"]["tags"],
["FNS"],
)
self.assertEqual(
paths["/api/v1/minpromtorg/manufacturers/"]["get"]["tags"],
["Minpromtorg"],
)
self.assertEqual(
paths["/api/v1/zakupki/"]["get"]["tags"],
["EIS Zakupki"],
)
for path in (
"/api/v1/users/register/",
"/api/v1/users/login/",
"/api/v1/users/token/refresh/",
"/api/v1/users/token/verify/",
"/api/v1/users/me/",
):
operation = (
paths[path]["post"] if "post" in paths[path] else paths[path]["get"]
)
self.assertEqual(operation["tags"], ["Users"])
for path in (
"/api/v1/users/register/",
"/api/v1/users/login/",
"/api/v1/users/token/refresh/",
"/api/v1/users/token/verify/",
):
self.assertEqual(paths[path]["post"]["security"], [])
self.assertEqual(paths["/api/v1/jobs/"]["get"]["tags"], ["Jobs"])
for tag in self._operation_tags(paths):
self.assertFalse(any("\u0400" <= char <= "\u04ff" for char in tag), tag)
self.assertIn("Bearer", schema["securityDefinitions"])
class GetStatusDescriptionTest(TestCase):
"""Tests for _get_status_description function"""