test_decorator.py 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. # -*- coding: utf-8 -*-
  2. import typing
  3. from http import HTTPStatus
  4. from hapic.context import ContextInterface
  5. from hapic.data import HapicData
  6. from hapic.decorator import ControllerWrapper
  7. from hapic.decorator import InputControllerWrapper
  8. from hapic.decorator import OutputControllerWrapper
  9. from hapic.processor import RequestParameters
  10. from hapic.processor import ProcessValidationError
  11. from hapic.processor import ProcessorInterface
  12. from tests.base import Base
  13. class MyContext(ContextInterface):
  14. def get_request_parameters(self, *args, **kwargs) -> RequestParameters:
  15. return RequestParameters(
  16. path_parameters={'fake': args},
  17. query_parameters={},
  18. body_parameters={},
  19. form_parameters={},
  20. header_parameters={},
  21. )
  22. def get_response(
  23. self,
  24. response: dict,
  25. http_code: int,
  26. ) -> typing.Any:
  27. return {
  28. 'original_response': response,
  29. 'http_code': http_code,
  30. }
  31. def get_validation_error_response(
  32. self,
  33. error: ProcessValidationError,
  34. http_code: HTTPStatus=HTTPStatus.BAD_REQUEST,
  35. ) -> typing.Any:
  36. return {
  37. 'original_error': error,
  38. 'http_code': http_code,
  39. }
  40. class MyProcessor(ProcessorInterface):
  41. def process(self, value):
  42. return value + 1
  43. def get_validation_error(
  44. self,
  45. request_context: RequestParameters,
  46. ) -> ProcessValidationError:
  47. return ProcessValidationError(
  48. error_details={
  49. 'original_request_context': request_context,
  50. },
  51. error_message='ERROR',
  52. )
  53. class MyControllerWrapper(ControllerWrapper):
  54. def before_wrapped_func(
  55. self,
  56. func_args: typing.Tuple[typing.Any, ...],
  57. func_kwargs: typing.Dict[str, typing.Any],
  58. ) -> typing.Union[None, typing.Any]:
  59. if func_args and func_args[0] == 666:
  60. return {
  61. 'error_response': 'we are testing'
  62. }
  63. func_kwargs['added_parameter'] = 'a value'
  64. def after_wrapped_function(self, response: typing.Any) -> typing.Any:
  65. return response * 2
  66. class MyInputControllerWrapper(InputControllerWrapper):
  67. def get_processed_data(
  68. self,
  69. request_parameters: RequestParameters,
  70. ) -> typing.Any:
  71. return {'we_are_testing': request_parameters.path_parameters}
  72. def update_hapic_data(
  73. self,
  74. hapic_data: HapicData,
  75. processed_data: typing.Dict[str, typing.Any],
  76. ) -> typing.Any:
  77. hapic_data.query = processed_data
  78. class TestControllerWrapper(Base):
  79. def test_unit__base_controller_wrapper__ok__no_behaviour(self):
  80. context = MyContext()
  81. processor = MyProcessor()
  82. wrapper = ControllerWrapper(context, processor)
  83. @wrapper.get_wrapper
  84. def func(foo):
  85. return foo
  86. result = func(42)
  87. assert result == 42
  88. def test_unit__base_controller__ok__replaced_response(self):
  89. context = MyContext()
  90. processor = MyProcessor()
  91. wrapper = MyControllerWrapper(context, processor)
  92. @wrapper.get_wrapper
  93. def func(foo):
  94. return foo
  95. # see MyControllerWrapper#before_wrapped_func
  96. result = func(666)
  97. # result have been replaced by MyControllerWrapper#before_wrapped_func
  98. assert {'error_response': 'we are testing'} == result
  99. def test_unit__controller_wrapper__ok__overload_input(self):
  100. context = MyContext()
  101. processor = MyProcessor()
  102. wrapper = MyControllerWrapper(context, processor)
  103. @wrapper.get_wrapper
  104. def func(foo, added_parameter=None):
  105. # see MyControllerWrapper#before_wrapped_func
  106. assert added_parameter == 'a value'
  107. return foo
  108. result = func(42)
  109. # See MyControllerWrapper#after_wrapped_function
  110. assert result == 84
  111. class TestInputControllerWrapper(Base):
  112. def test_unit__input_data_wrapping__ok__nominal_case(self):
  113. context = MyContext()
  114. processor = MyProcessor()
  115. wrapper = MyInputControllerWrapper(context, processor)
  116. @wrapper.get_wrapper
  117. def func(foo, hapic_data=None):
  118. assert hapic_data
  119. assert isinstance(hapic_data, HapicData)
  120. # see MyControllerWrapper#before_wrapped_func
  121. assert hapic_data.query == {'we_are_testing': {'fake': (42,)}}
  122. return foo
  123. result = func(42)
  124. assert result == 42
  125. class TestOutputControllerWrapper(Base):
  126. def test_unit__output_data_wrapping__ok__nominal_case(self):
  127. context = MyContext()
  128. processor = MyProcessor()
  129. wrapper = OutputControllerWrapper(context, processor)
  130. @wrapper.get_wrapper
  131. def func(foo, hapic_data=None):
  132. # If no use of input wrapper, no hapic_data is given
  133. assert not hapic_data
  134. return foo
  135. result = func(42)
  136. # see MyProcessor#process
  137. assert {
  138. 'http_code': HTTPStatus.OK,
  139. 'original_response': 43,
  140. } == result