test_patch_dispatch.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. from __future__ import unicode_literals
  2. from rest_framework.exceptions import ValidationError as ApiValidationError
  3. from django.core.exceptions import PermissionDenied, ValidationError
  4. from django.http import Http404
  5. from django.test import TestCase
  6. from misago.api.patch import ApiPatch
  7. class MockRequest(object):
  8. def __init__(self, data=None):
  9. self.data = data
  10. class MockObject(object):
  11. def __init__(self, pk):
  12. self.id = pk
  13. self.pk = pk
  14. class ApiPatchDispatchTests(TestCase):
  15. def test_dispatch(self):
  16. """dispatch calls actions and returns response"""
  17. patch = ApiPatch()
  18. def action_error(request, target, value):
  19. if value == '404':
  20. raise Http404()
  21. if value == '404_reason':
  22. raise Http404("something was removed")
  23. if value == 'perm':
  24. raise PermissionDenied("yo ain't doing that!")
  25. if value == 'invalid':
  26. raise ValidationError("invalid data here!")
  27. if value == 'api_invalid':
  28. raise ApiValidationError("invalid api data here!")
  29. patch.replace('error', action_error)
  30. def action_mutate(request, target, value):
  31. return {'value': value * 2}
  32. patch.replace('mutate', action_mutate)
  33. # dispatch requires list as an argument
  34. response = patch.dispatch(MockRequest({}), {})
  35. self.assertEqual(response.status_code, 400)
  36. self.assertEqual(response.data['detail'], "PATCH request should be list of operations.")
  37. # valid dispatch
  38. response = patch.dispatch(
  39. MockRequest([
  40. {
  41. 'op': 'replace',
  42. 'path': 'mutate',
  43. 'value': 2,
  44. },
  45. {
  46. 'op': 'replace',
  47. 'path': 'mutate',
  48. 'value': 6,
  49. },
  50. {
  51. 'op': 'replace',
  52. 'path': 'mutate',
  53. 'value': 7,
  54. },
  55. ]), MockObject(13)
  56. )
  57. self.assertEqual(response.status_code, 200)
  58. self.assertEqual(response.data, {'value': 14, 'id': 13})
  59. # invalid action in dispatch
  60. response = patch.dispatch(
  61. MockRequest([
  62. {
  63. 'op': 'replace',
  64. 'path': 'mutate',
  65. 'value': 2,
  66. },
  67. {
  68. 'op': 'replace',
  69. 'path': 'mutate',
  70. 'value': 6,
  71. },
  72. {
  73. 'op': 'replace',
  74. },
  75. {
  76. 'op': 'replace',
  77. 'path': 'mutate',
  78. 'value': 7,
  79. },
  80. ]), MockObject(13)
  81. )
  82. self.assertEqual(response.status_code, 400)
  83. self.assertEqual(response.data['detail'], '"replace" op has to specify path.')
  84. # op raised validation error
  85. response = patch.dispatch(
  86. MockRequest([
  87. {
  88. 'op': 'replace',
  89. 'path': 'mutate',
  90. 'value': 2,
  91. },
  92. {
  93. 'op': 'replace',
  94. 'path': 'mutate',
  95. 'value': 6,
  96. },
  97. {
  98. 'op': 'replace',
  99. 'path': 'error',
  100. 'value': 'invalid',
  101. },
  102. {
  103. 'op': 'replace',
  104. 'path': 'mutate',
  105. 'value': 7,
  106. },
  107. ]), MockObject(13)
  108. )
  109. self.assertEqual(response.status_code, 400)
  110. self.assertEqual(response.data['detail'], ["invalid data here!"])
  111. # op raised api validation error
  112. response = patch.dispatch(
  113. MockRequest([
  114. {
  115. 'op': 'replace',
  116. 'path': 'mutate',
  117. 'value': 2,
  118. },
  119. {
  120. 'op': 'replace',
  121. 'path': 'mutate',
  122. 'value': 6,
  123. },
  124. {
  125. 'op': 'replace',
  126. 'path': 'error',
  127. 'value': 'api_invalid',
  128. },
  129. {
  130. 'op': 'replace',
  131. 'path': 'mutate',
  132. 'value': 7,
  133. },
  134. ]), MockObject(13)
  135. )
  136. self.assertEqual(response.status_code, 400)
  137. self.assertEqual(response.data['detail'], ["invalid api data here!"])
  138. # action in dispatch raised perm denied
  139. response = patch.dispatch(
  140. MockRequest([
  141. {
  142. 'op': 'replace',
  143. 'path': 'mutate',
  144. 'value': 2,
  145. },
  146. {
  147. 'op': 'replace',
  148. 'path': 'mutate',
  149. 'value': 6,
  150. },
  151. {
  152. 'op': 'replace',
  153. 'path': 'mutate',
  154. 'value': 9,
  155. },
  156. {
  157. 'op': 'replace',
  158. 'path': 'error',
  159. 'value': 'perm',
  160. },
  161. ]), MockObject(13)
  162. )
  163. self.assertEqual(response.status_code, 403)
  164. self.assertEqual(response.data['detail'], "yo ain't doing that!")
  165. # action in dispatch raised 404
  166. response = patch.dispatch(
  167. MockRequest([
  168. {
  169. 'op': 'replace',
  170. 'path': 'mutate',
  171. 'value': 2,
  172. },
  173. {
  174. 'op': 'replace',
  175. 'path': 'error',
  176. 'value': '404',
  177. },
  178. {
  179. 'op': 'replace',
  180. 'path': 'mutate',
  181. 'value': 6,
  182. },
  183. {
  184. 'op': 'replace',
  185. 'path': 'mutate',
  186. 'value': 7,
  187. },
  188. ]), MockObject(13)
  189. )
  190. self.assertEqual(response.status_code, 404)
  191. self.assertEqual(response.data['detail'], "NOT FOUND")
  192. # action in dispatch raised 404 with message
  193. response = patch.dispatch(
  194. MockRequest([
  195. {
  196. 'op': 'replace',
  197. 'path': 'mutate',
  198. 'value': 2,
  199. },
  200. {
  201. 'op': 'replace',
  202. 'path': 'error',
  203. 'value': '404_reason',
  204. },
  205. {
  206. 'op': 'replace',
  207. 'path': 'mutate',
  208. 'value': 6,
  209. },
  210. {
  211. 'op': 'replace',
  212. 'path': 'mutate',
  213. 'value': 7,
  214. },
  215. ]), MockObject(13)
  216. )
  217. self.assertEqual(response.status_code, 404)
  218. self.assertEqual(response.data['detail'], "something was removed")