test_resource.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import pytest
  2. from fastapi.routing import APIRouter
  3. from clean_python.fastapi import APIVersion
  4. from clean_python.fastapi import get
  5. from clean_python.fastapi import RequiresScope
  6. from clean_python.fastapi import Resource
  7. from clean_python.fastapi import Stability
  8. from clean_python.fastapi import v
  9. def test_subclass():
  10. class Cls(Resource, version=v(1), name="foo"):
  11. pass
  12. for obj in (Cls, Cls()):
  13. assert obj.name == "foo"
  14. assert obj.version == v(1)
  15. def test_get_router_no_endpoints():
  16. class Cls(Resource, version=v(1)):
  17. pass
  18. router = Cls().get_router(v(1))
  19. assert isinstance(router, APIRouter)
  20. assert len(router.routes) == 0
  21. def test_get_router_other_version():
  22. class TestResource(Resource, version=v(1), name="testing"):
  23. @get("/foo/{id}")
  24. def get_test(self, id: int):
  25. return "ok"
  26. with pytest.raises(AssertionError):
  27. TestResource().get_router(v(2))
  28. def test_get_router():
  29. class TestResource(Resource, version=v(1), name="testing"):
  30. @get("/foo/{id}")
  31. def get_test(self, id: int):
  32. return "ok"
  33. resource = TestResource()
  34. router = resource.get_router(v(1))
  35. assert len(router.routes) == 1
  36. route = router.routes[0]
  37. assert route.path == "/foo/{id}"
  38. assert route.operation_id == "get_test"
  39. assert route.name == "v1/get_test"
  40. assert route.tags == ["testing"]
  41. assert route.methods == {"GET"}
  42. assert len(route.dependencies) == 0
  43. # 'self' is missing from the parameters
  44. assert list(route.param_convertors.keys()) == ["id"]
  45. def test_get_openapi_tag():
  46. class Cls(Resource, version=v(1), name="foo"):
  47. """Docstring"""
  48. actual = Cls().get_openapi_tag()
  49. assert actual.name == "foo"
  50. assert actual.description == "Docstring"
  51. def test_v():
  52. assert v(1, "alpha") == APIVersion(version=1, stability=Stability.ALPHA)
  53. @pytest.mark.parametrize(
  54. "version,expected",
  55. [(v(1, "beta"), "v1-beta"), (v(2), "v2"), (v(3, "alpha"), "v3-alpha")],
  56. )
  57. def test_api_version_prefix(version, expected):
  58. assert version.prefix == expected
  59. def test_url_path_for():
  60. class TestResource(Resource, version=v(1), name="testing"):
  61. @get("/foo/{id}")
  62. def get_test(self, id: int):
  63. return "ok"
  64. resource = TestResource()
  65. router = resource.get_router(v(1))
  66. assert router.url_path_for("v1/get_test", id=2) == "/foo/2"
  67. def test_with_version():
  68. class TestResource(Resource, version=v(1), name="testing"):
  69. """Foo"""
  70. @get("/foo/{id}")
  71. def get_test(self, id: int):
  72. return "ok"
  73. resource_cls = TestResource.with_version(v(1, "beta"))
  74. assert resource_cls.version == v(1, "beta")
  75. assert resource_cls.name == "testing"
  76. assert resource_cls.__doc__ == "Foo"
  77. assert resource_cls.__bases__ == (TestResource,)
  78. def test_get_less_stable():
  79. class V1(Resource, version=v(1), name="testing"):
  80. pass
  81. class V1Beta(V1, version=v(1, "beta"), name="testing"):
  82. pass
  83. resources = {x.version: x() for x in [V1, V1Beta]}
  84. assert resources[v(1)].get_less_stable(resources) is resources[v(1, "beta")]
  85. v1_alpha = resources[v(1, "beta")].get_less_stable(resources)
  86. assert v1_alpha.version == v(1, "alpha")
  87. assert v1_alpha.__class__.__bases__ == (V1Beta,)
  88. def test_get_less_stable_no_subclass():
  89. class V1(Resource, version=v(1), name="testing"):
  90. pass
  91. class V1Beta(Resource, version=v(1, "beta"), name="testing"):
  92. pass
  93. resources = {x.version: x() for x in [V1, V1Beta]}
  94. with pytest.raises(RuntimeError):
  95. resources[v(1)].get_less_stable(resources)
  96. def test_get_router_with_scope():
  97. class TestResource(Resource, version=v(1), name="testing"):
  98. @get("/foo/{id}", scope="foo")
  99. def get_test(self, id: int):
  100. return "ok"
  101. resource = TestResource()
  102. router = resource.get_router(v(1))
  103. assert len(router.routes) == 1
  104. route = router.routes[0]
  105. (dep,) = route.dependencies
  106. assert isinstance(dep.dependency, RequiresScope)
  107. assert dep.dependency.scope == "foo"