105 lines
4.3 KiB
Python
105 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from collections import Counter
|
|
from inspect import signature
|
|
|
|
from govoplan_files.backend.router import router
|
|
from govoplan_files.backend.routes.assets import router as assets_router
|
|
from govoplan_files.backend.routes.connector_io import router as connector_io_router
|
|
from govoplan_files.backend.routes.connector_profiles import router as connector_profiles_router
|
|
from govoplan_files.backend.routes.connector_settings import router as connector_settings_router
|
|
from govoplan_files.backend.routes.folders import router as folders_router
|
|
from govoplan_files.backend.routes.integrity import router as integrity_router
|
|
from govoplan_files.backend.routes.listing import router as listing_router
|
|
from govoplan_files.backend.routes.shares import router as shares_router
|
|
from govoplan_files.backend.routes.spaces import router as spaces_router
|
|
from govoplan_files.backend.routes.transfers import router as transfers_router
|
|
from govoplan_files.backend.routes.uploads import router as uploads_router
|
|
|
|
|
|
class FilesRouterContractTests(unittest.TestCase):
|
|
@staticmethod
|
|
def _operation_keys(candidate_router) -> list[tuple[str, str]]:
|
|
return [
|
|
(method, route.path)
|
|
for route in candidate_router.routes
|
|
for method in sorted(route.methods or ())
|
|
]
|
|
|
|
def test_composed_router_contains_every_workflow_operation_once(self) -> None:
|
|
workflow_routers = (
|
|
spaces_router,
|
|
folders_router,
|
|
integrity_router,
|
|
listing_router,
|
|
uploads_router,
|
|
connector_settings_router,
|
|
connector_io_router,
|
|
connector_profiles_router,
|
|
assets_router,
|
|
shares_router,
|
|
transfers_router,
|
|
)
|
|
expected = [
|
|
operation
|
|
for workflow_router in workflow_routers
|
|
for operation in self._operation_keys(workflow_router)
|
|
]
|
|
actual = self._operation_keys(router)
|
|
|
|
self.assertEqual(expected, actual)
|
|
self.assertEqual(50, len(actual))
|
|
self.assertFalse(
|
|
[operation for operation, count in Counter(actual).items() if count > 1]
|
|
)
|
|
|
|
def test_connector_routes_keep_existing_api_paths(self) -> None:
|
|
routes = {(tuple(sorted(route.methods or ())), route.path) for route in router.routes}
|
|
|
|
expected = {
|
|
(("GET",), "/files/connectors/providers"),
|
|
(("GET",), "/files/connectors/settings/delta"),
|
|
(("GET",), "/files/connectors/profiles"),
|
|
(("POST",), "/files/connectors/profiles"),
|
|
(("GET",), "/files/connectors/profiles/{profile_id}/browse"),
|
|
(("POST",), "/files/connectors/profiles/{profile_id}/import"),
|
|
(("POST",), "/files/connectors/profiles/{profile_id}/sync"),
|
|
(("GET",), "/files/connectors/credentials"),
|
|
(("POST",), "/files/connectors/credentials"),
|
|
(("GET",), "/files/connector-spaces"),
|
|
(("POST",), "/files/connector-spaces"),
|
|
}
|
|
|
|
self.assertTrue(expected.issubset(routes))
|
|
|
|
def test_bulk_organize_routes_keep_existing_api_paths(self) -> None:
|
|
routes = {(tuple(sorted(route.methods or ())), route.path) for route in router.routes}
|
|
|
|
self.assertIn((("POST",), "/files/bulk-rename"), routes)
|
|
self.assertIn((("POST",), "/files/transfer"), routes)
|
|
|
|
def test_share_lifecycle_routes_are_exposed(self) -> None:
|
|
routes = {(tuple(sorted(route.methods or ())), route.path) for route in router.routes}
|
|
|
|
self.assertIn((("GET",), "/files/{file_id}/shares"), routes)
|
|
self.assertIn((("POST",), "/files/{file_id}/shares"), routes)
|
|
self.assertIn((("DELETE",), "/files/{file_id}/shares/{share_id}"), routes)
|
|
self.assertIn((("GET",), "/files/{file_id}/share-target-options"), routes)
|
|
|
|
def test_file_listing_exposes_structured_property_filters(self) -> None:
|
|
route = next(
|
|
route
|
|
for route in listing_router.routes
|
|
if route.path == "/files" and "GET" in (route.methods or ())
|
|
)
|
|
parameters = signature(route.endpoint).parameters
|
|
|
|
self.assertIn("campaign_usage", parameters)
|
|
self.assertIn("audit_relevant", parameters)
|
|
self.assertIn("total", route.response_model.model_fields)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|