test_doc.py 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. # coding: utf-8
  2. import marshmallow
  3. import bottle
  4. from marshmallow.validate import OneOf
  5. from hapic import Hapic
  6. from tests.base import Base
  7. from tests.base import MyContext
  8. class TestDocGeneration(Base):
  9. def test_func__input_files_doc__ok__one_file(self):
  10. hapic = Hapic()
  11. # TODO BS 20171113: Make this test non-bottle
  12. app = bottle.Bottle()
  13. hapic.set_context(MyContext(app=app))
  14. class MySchema(marshmallow.Schema):
  15. file_abc = marshmallow.fields.Raw(required=True)
  16. @hapic.with_api_doc()
  17. @hapic.input_files(MySchema())
  18. def my_controller(hapic_data=None):
  19. assert hapic_data
  20. assert hapic_data.files
  21. app.route('/upload', method='POST', callback=my_controller)
  22. doc = hapic.generate_doc()
  23. assert doc
  24. assert '/upload' in doc['paths']
  25. assert 'consumes' in doc['paths']['/upload']['post']
  26. assert 'multipart/form-data' in doc['paths']['/upload']['post']['consumes'] # nopep8
  27. assert 'parameters' in doc['paths']['/upload']['post']
  28. assert {
  29. 'name': 'file_abc',
  30. 'required': True,
  31. 'in': 'formData',
  32. 'type': 'file',
  33. } in doc['paths']['/upload']['post']['parameters']
  34. def test_func__input_files_doc__ok__two_file(self):
  35. hapic = Hapic()
  36. # TODO BS 20171113: Make this test non-bottle
  37. app = bottle.Bottle()
  38. hapic.set_context(MyContext(app=app))
  39. class MySchema(marshmallow.Schema):
  40. file_abc = marshmallow.fields.Raw(required=True)
  41. file_def = marshmallow.fields.Raw(required=False)
  42. @hapic.with_api_doc()
  43. @hapic.input_files(MySchema())
  44. def my_controller(hapic_data=None):
  45. assert hapic_data
  46. assert hapic_data.files
  47. app.route('/upload', method='POST', callback=my_controller)
  48. doc = hapic.generate_doc()
  49. assert doc
  50. assert '/upload' in doc['paths']
  51. assert 'consumes' in doc['paths']['/upload']['post']
  52. assert 'multipart/form-data' in doc['paths']['/upload']['post']['consumes'] # nopep8
  53. assert 'parameters' in doc['paths']['/upload']['post']
  54. assert {
  55. 'name': 'file_abc',
  56. 'required': True,
  57. 'in': 'formData',
  58. 'type': 'file',
  59. } in doc['paths']['/upload']['post']['parameters']
  60. assert {
  61. 'name': 'file_def',
  62. 'required': False,
  63. 'in': 'formData',
  64. 'type': 'file',
  65. } in doc['paths']['/upload']['post']['parameters']
  66. def test_func__output_file_doc__ok__nominal_case(self):
  67. hapic = Hapic()
  68. # TODO BS 20171113: Make this test non-bottle
  69. app = bottle.Bottle()
  70. hapic.set_context(MyContext(app=app))
  71. @hapic.with_api_doc()
  72. @hapic.output_file(['image/jpeg'])
  73. def my_controller():
  74. return b'101010100101'
  75. app.route('/avatar', method='GET', callback=my_controller)
  76. doc = hapic.generate_doc()
  77. assert doc
  78. assert '/avatar' in doc['paths']
  79. assert 'produces' in doc['paths']['/avatar']['get']
  80. assert 'image/jpeg' in doc['paths']['/avatar']['get']['produces']
  81. assert 200 in doc['paths']['/avatar']['get']['responses']
  82. def test_func__input_files_doc__ok__one_file_and_text(self):
  83. hapic = Hapic()
  84. # TODO BS 20171113: Make this test non-bottle
  85. app = bottle.Bottle()
  86. hapic.set_context(MyContext(app=app))
  87. class MySchema(marshmallow.Schema):
  88. name = marshmallow.fields.String(required=True)
  89. class MyFilesSchema(marshmallow.Schema):
  90. file_abc = marshmallow.fields.Raw(required=True)
  91. @hapic.with_api_doc()
  92. @hapic.input_files(MyFilesSchema())
  93. @hapic.input_body(MySchema())
  94. def my_controller(hapic_data=None):
  95. assert hapic_data
  96. assert hapic_data.files
  97. app.route('/upload', method='POST', callback=my_controller)
  98. doc = hapic.generate_doc()
  99. assert doc
  100. assert '/upload' in doc['paths']
  101. assert 'consumes' in doc['paths']['/upload']['post']
  102. assert 'multipart/form-data' in doc['paths']['/upload']['post']['consumes'] # nopep8
  103. assert 'parameters' in doc['paths']['/upload']['post']
  104. assert {
  105. 'name': 'file_abc',
  106. 'required': True,
  107. 'in': 'formData',
  108. 'type': 'file',
  109. } in doc['paths']['/upload']['post']['parameters']
  110. def test_func__docstring__ok__simple_case(self):
  111. hapic = Hapic()
  112. app = bottle.Bottle()
  113. hapic.set_context(MyContext(app=app))
  114. # TODO BS 20171113: Make this test non-bottle
  115. @hapic.with_api_doc()
  116. def my_controller(hapic_data=None):
  117. """
  118. Hello doc
  119. """
  120. assert hapic_data
  121. assert hapic_data.files
  122. app.route('/upload', method='POST', callback=my_controller)
  123. doc = hapic.generate_doc()
  124. assert doc.get('paths')
  125. assert '/upload' in doc['paths']
  126. assert 'post' in doc['paths']['/upload']
  127. assert 'description' in doc['paths']['/upload']['post']
  128. assert 'Hello doc' == doc['paths']['/upload']['post']['description']
  129. def test_func__tags__ok__nominal_case(self):
  130. hapic = Hapic()
  131. app = bottle.Bottle()
  132. hapic.set_context(MyContext(app=app))
  133. @hapic.with_api_doc(tags=['foo', 'bar'])
  134. def my_controller(hapic_data=None):
  135. assert hapic_data
  136. assert hapic_data.files
  137. app.route('/upload', method='POST', callback=my_controller)
  138. doc = hapic.generate_doc()
  139. assert doc.get('paths')
  140. assert '/upload' in doc['paths']
  141. assert 'post' in doc['paths']['/upload']
  142. assert 'tags' in doc['paths']['/upload']['post']
  143. assert ['foo', 'bar'] == doc['paths']['/upload']['post']['tags']
  144. def test_func__errors__nominal_case(self):
  145. hapic = Hapic()
  146. app = bottle.Bottle()
  147. hapic.set_context(MyContext(app=app))
  148. @hapic.with_api_doc()
  149. @hapic.handle_exception()
  150. def my_controller(hapic_data=None):
  151. assert hapic_data
  152. app.route('/upload', method='POST', callback=my_controller)
  153. doc = hapic.generate_doc()
  154. assert doc.get('paths')
  155. assert '/upload' in doc['paths']
  156. assert 'post' in doc['paths']['/upload']
  157. assert 'responses' in doc['paths']['/upload']['post']
  158. assert 500 in doc['paths']['/upload']['post']['responses']
  159. assert {
  160. 'description': "500",
  161. 'schema': {
  162. '$ref': '#/definitions/DefaultErrorBuilder'
  163. }
  164. } == doc['paths']['/upload']['post']['responses'][500]
  165. def test_func__enum__nominal_case(self):
  166. hapic = Hapic()
  167. # TODO BS 20171113: Make this test non-bottle
  168. app = bottle.Bottle()
  169. hapic.set_context(MyContext(app=app))
  170. class MySchema(marshmallow.Schema):
  171. category = marshmallow.fields.String(
  172. validate=OneOf(['foo', 'bar'])
  173. )
  174. @hapic.with_api_doc()
  175. @hapic.input_body(MySchema())
  176. def my_controller():
  177. return
  178. app.route('/paper', method='POST', callback=my_controller)
  179. doc = hapic.generate_doc()
  180. assert ['foo', 'bar'] == doc.get('definitions', {})\
  181. .get('MySchema', {})\
  182. .get('properties', {})\
  183. .get('category', {})\
  184. .get('enum')