test_ontology_dynamic_api.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. from __future__ import annotations
  2. import io
  3. import pytest
  4. class DynamicService:
  5. def generate(self, ontology_uid, payload, actor_uid):
  6. return {
  7. "change_set_uid": "change-1",
  8. "suggestions": [
  9. {
  10. "uid": "suggestion-1",
  11. "kind": "class",
  12. "confidence": 0.95,
  13. "evidence_uids": ["domain-1"],
  14. }
  15. ],
  16. }
  17. def decide(self, ontology_uid, change_set_uid, decisions, actor_uid):
  18. return {"uid": change_set_uid, "ontology_uid": ontology_uid, "decisions": decisions, "actor_uid": actor_uid}
  19. class ExchangeService:
  20. def export(self, ontology_uid, format_name):
  21. assert (ontology_uid, format_name) == ("ontology-1", "json")
  22. return b'{"ontology_uid":"ontology-1"}', "application/json", "ontology-1.json"
  23. def import_document(self, content, format_name, actor_uid):
  24. return {
  25. "ontology_uid": "ontology-2",
  26. "version": 1,
  27. "format": format_name,
  28. "actor_uid": actor_uid,
  29. "content": content.decode("utf-8"),
  30. }
  31. class SemanticService:
  32. def trace_property(self, uid, *, allowed_domains, limit, after_uid):
  33. return {"items": [{"property_uid": uid, "business_domain_uid": next(iter(allowed_domains))}], "count": 1, "truncated": False, "next_cursor": None}
  34. @pytest.fixture()
  35. def client(monkeypatch):
  36. from flask import request
  37. from app import create_app
  38. from app.api.data_development import routes
  39. from app.core.system import permissions
  40. def identity():
  41. role = request.headers.get("Authorization", "").removeprefix("Bearer ")
  42. return {"id": f"{role}-1", "roles": [role]} if role in {"viewer", "editor", "admin"} else None
  43. monkeypatch.setattr(permissions, "authenticate_request", identity)
  44. monkeypatch.setattr(routes, "get_ontology_dynamic_service", lambda: DynamicService())
  45. monkeypatch.setattr(routes, "get_ontology_exchange_service", lambda: ExchangeService())
  46. monkeypatch.setattr(routes, "get_semantic_query_service", lambda: SemanticService())
  47. app = create_app()
  48. app.config.update(TESTING=True)
  49. return app.test_client()
  50. def test_dynamic_suggestion_and_audited_decision_endpoints(client):
  51. headers = {"Authorization": "Bearer editor"}
  52. generated = client.post(
  53. "/api/development/v1/ontologies/ontology-1/suggestions",
  54. headers=headers,
  55. json={"domains": [], "data_elements": [], "foreign_keys": []},
  56. )
  57. decided = client.post(
  58. "/api/development/v1/ontologies/ontology-1/change-sets/change-1/decisions",
  59. headers=headers,
  60. json={"decisions": [{"suggestion_uid": "suggestion-1", "decision": "accept"}]},
  61. )
  62. assert generated.get_json()["data"]["change_set_uid"] == "change-1"
  63. assert generated.get_json()["data"]["suggestions"][0]["evidence_uids"] == [
  64. "domain-1"
  65. ]
  66. assert decided.get_json()["data"]["actor_uid"] == "editor-1"
  67. def test_exchange_and_read_only_semantic_query_endpoints(client):
  68. exported = client.get(
  69. "/api/development/v1/ontologies/ontology-1/export?format=json",
  70. headers={"Authorization": "Bearer viewer"},
  71. )
  72. imported = client.post(
  73. "/api/development/v1/ontologies/import?format=json",
  74. headers={"Authorization": "Bearer editor"},
  75. data=b'{"ontology_uid":"ontology-2"}',
  76. content_type="application/json",
  77. )
  78. queried = client.get(
  79. "/api/development/v1/semantic/properties/property-1?business_domain_uid=sales&limit=20",
  80. headers={"Authorization": "Bearer viewer"},
  81. )
  82. assert exported.status_code == 200 and exported.mimetype == "application/json"
  83. assert imported.status_code == 201
  84. assert queried.get_json()["data"]["items"][0]["business_domain_uid"] == "sales"
  85. def test_ontology_import_accepts_browser_multipart_upload(client):
  86. imported = client.post(
  87. "/api/development/v1/ontologies/import?format=json",
  88. headers={"Authorization": "Bearer editor"},
  89. data={
  90. "file": (
  91. io.BytesIO(b'{"ontology_uid":"ontology-2"}'),
  92. "ontology.json",
  93. )
  94. },
  95. content_type="multipart/form-data",
  96. )
  97. assert imported.status_code == 201
  98. assert imported.get_json()["data"]["content"] == (
  99. '{"ontology_uid":"ontology-2"}'
  100. )