test_plugin.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. from __future__ import absolute_import
  2. import responses
  3. from six.moves.urllib.parse import urlparse, parse_qsl
  4. from exam import fixture
  5. from django.test import RequestFactory
  6. from sentry.testutils import PluginTestCase
  7. from sentry.utils import json
  8. from sentry_plugins.trello.plugin import TrelloPlugin
  9. class TrelloPluginTestBase(PluginTestCase):
  10. @fixture
  11. def plugin(self):
  12. return TrelloPlugin()
  13. @fixture
  14. def request(self):
  15. return RequestFactory()
  16. class TrelloPluginTest(TrelloPluginTestBase):
  17. def test_conf_key(self):
  18. assert self.plugin.conf_key == "trello"
  19. def test_entry_point(self):
  20. self.assertPluginInstalled("trello", self.plugin)
  21. def test_get_issue_label(self):
  22. group = self.create_group(message="Hello world", culprit="foo.bar")
  23. # test new and old format
  24. assert self.plugin.get_issue_label(group, "rPPDb") == "Trello-rPPDb"
  25. assert (
  26. self.plugin.get_issue_label(group, "5dafd/https://trello.com/c/rPPDb/75-title")
  27. == "Trello-5dafd"
  28. )
  29. def test_get_issue_url(self):
  30. group = self.create_group(message="Hello world", culprit="foo.bar")
  31. # test new and old format
  32. assert self.plugin.get_issue_url(group, "rPPDb") == "https://trello.com/c/rPPDb"
  33. assert self.plugin.get_issue_url(group, {"id": "rPPDb"}) == "https://trello.com/c/rPPDb"
  34. assert (
  35. self.plugin.get_issue_url(group, "5dafd/https://trello.com/c/rPPDb/75-title")
  36. == "https://trello.com/c/rPPDb/75-title"
  37. )
  38. def test_is_configured(self):
  39. assert self.plugin.is_configured(None, self.project) is False
  40. self.plugin.set_option("token", "7c8951d1", self.project)
  41. assert self.plugin.is_configured(None, self.project) is False
  42. self.plugin.set_option("key", "39g", self.project)
  43. assert self.plugin.is_configured(None, self.project) is True
  44. class TrelloPluginApiTests(TrelloPluginTestBase):
  45. def setUp(self):
  46. self.group = self.create_group(message="Hello world", culprit="foo.bar")
  47. self.plugin.set_option("token", "7c8951d1", self.project)
  48. self.plugin.set_option("key", "39g", self.project)
  49. self.plugin.set_option("organization", "f187", self.project)
  50. self.login_as(self.user)
  51. def test_get_config_no_org(self):
  52. self.plugin.unset_option("organization", self.project)
  53. out = self.plugin.get_config(self.project)
  54. assert out == [
  55. {
  56. "default": "39g",
  57. "required": True,
  58. "type": "text",
  59. "name": "key",
  60. "label": "Trello API Key",
  61. },
  62. {
  63. "name": "token",
  64. "default": None,
  65. "required": False,
  66. "label": "Trello API Token",
  67. "prefix": "7c895",
  68. "type": "secret",
  69. "has_saved_value": True,
  70. },
  71. ]
  72. @responses.activate
  73. def test_get_config_include_additional(self):
  74. self.plugin.unset_option("organization", self.project)
  75. responses.add(
  76. responses.GET,
  77. "https://api.trello.com/1/members/me/organizations",
  78. json=[{"name": "team 1", "id": "2d8e"}, {"name": "team 2", "id": "d0cc"}],
  79. )
  80. out = self.plugin.get_config(self.project, add_additial_fields=True)
  81. assert out == [
  82. {
  83. "default": "39g",
  84. "required": True,
  85. "type": "text",
  86. "name": "key",
  87. "label": "Trello API Key",
  88. },
  89. {
  90. "name": "token",
  91. "default": None,
  92. "required": False,
  93. "label": "Trello API Token",
  94. "prefix": "7c895",
  95. "type": "secret",
  96. "has_saved_value": True,
  97. },
  98. {
  99. "name": "organization",
  100. "default": None,
  101. "required": False,
  102. "choices": [("2d8e", "team 1"), ("d0cc", "team 2")],
  103. "label": "Trello Organization",
  104. "type": "select",
  105. },
  106. ]
  107. @responses.activate
  108. def test_create_issue(self):
  109. responses.add(responses.POST, "https://api.trello.com/1/cards", json={"shortLink": "rds43"})
  110. form_data = {
  111. "title": "Hello",
  112. "description": "Fix this.",
  113. "board": "ads23f",
  114. "list": "23tds",
  115. }
  116. request = self.make_request(user=self.user, method="POST")
  117. assert self.plugin.create_issue(request, self.group, form_data) == "rds43"
  118. request = responses.calls[0].request
  119. assert request.url == "https://api.trello.com/1/cards?token=7c8951d1&key=39g"
  120. payload = json.loads(request.body)
  121. assert payload == {"name": "Hello", "desc": "Fix this.", "idList": "23tds"}
  122. @responses.activate
  123. def test_link_issue(self):
  124. responses.add(
  125. responses.GET,
  126. "https://api.trello.com/1/cards/SstgnBIQ",
  127. json={"idShort": 2, "name": "MyTitle", "shortLink": "SstgnBIQ"},
  128. )
  129. responses.add(
  130. responses.POST, "https://api.trello.com/1/cards/SstgnBIQ/actions/comments", json={}
  131. )
  132. form_data = {"comment": "please fix this", "issue_id": "SstgnBIQ"}
  133. request = self.make_request(user=self.user, method="POST")
  134. assert self.plugin.link_issue(request, self.group, form_data) == {
  135. "title": "MyTitle",
  136. "id": "SstgnBIQ",
  137. }
  138. request = responses.calls[0].request
  139. assert (
  140. request.url
  141. == "https://api.trello.com/1/cards/SstgnBIQ?fields=name%2CshortLink%2CidShort&token=7c8951d1&key=39g"
  142. )
  143. request = responses.calls[1].request
  144. assert (
  145. request.url
  146. == "https://api.trello.com/1/cards/SstgnBIQ/actions/comments?text=please+fix+this&token=7c8951d1&key=39g"
  147. )
  148. @responses.activate
  149. def test_view_options(self):
  150. responses.add(
  151. responses.GET,
  152. "https://api.trello.com/1/boards/f34/lists",
  153. json=[{"id": "8f3", "name": "list 1"}, {"id": "j8f", "name": "list 2"}],
  154. )
  155. request = self.make_request(user=self.user, method="GET")
  156. request.GET["option_field"] = "list"
  157. request.GET["board"] = "f34"
  158. response = self.plugin.view_options(request, self.group)
  159. assert response.data == {"list": [("8f3", "list 1"), ("j8f", "list 2")]}
  160. request = responses.calls[0].request
  161. assert request.url == "https://api.trello.com/1/boards/f34/lists?token=7c8951d1&key=39g"
  162. @responses.activate
  163. def test_view_autocomplete(self):
  164. responses.add(
  165. responses.GET,
  166. "https://api.trello.com/1/search",
  167. json={
  168. "cards": [
  169. {"id": "4fsdafad", "name": "KeyError", "idShort": 1, "shortLink": "0lr"},
  170. {"id": "f4usdfa", "name": "Key Missing", "idShort": 3, "shortLink": "9lf"},
  171. ]
  172. },
  173. )
  174. request = self.make_request(user=self.user, method="GET")
  175. request.GET["autocomplete_field"] = "issue_id"
  176. request.GET["autocomplete_query"] = "Key"
  177. response = self.plugin.view_autocomplete(request, self.group)
  178. assert response.data == {
  179. "issue_id": [
  180. {"id": "0lr", "text": "(#1) KeyError"},
  181. {"id": "9lf", "text": "(#3) Key Missing"},
  182. ]
  183. }
  184. request = responses.calls[0].request
  185. url = urlparse(request.url)
  186. query = dict(parse_qsl(url.query))
  187. assert url.path == "/1/search"
  188. assert query == {
  189. "cards_limit": "100",
  190. "partial": "true",
  191. "modelTypes": "cards",
  192. "token": "7c8951d1",
  193. "card_fields": "name,shortLink,idShort",
  194. "key": "39g",
  195. "query": "Key",
  196. "idOrganizations": "f187",
  197. }
  198. @responses.activate
  199. def test_view_autocomplete_no_org(self):
  200. self.plugin.unset_option("organization", self.project)
  201. responses.add(
  202. responses.GET,
  203. "https://api.trello.com/1/search",
  204. json={
  205. "cards": [
  206. {"id": "4fsdafad", "name": "KeyError", "idShort": 1, "shortLink": "0lr"},
  207. {"id": "f4usdfa", "name": "Key Missing", "idShort": 3, "shortLink": "9lf"},
  208. ]
  209. },
  210. )
  211. request = self.make_request(user=self.user, method="GET")
  212. request.GET["autocomplete_field"] = "issue_id"
  213. request.GET["autocomplete_query"] = "Key"
  214. response = self.plugin.view_autocomplete(request, self.group)
  215. assert response.data == {
  216. "issue_id": [
  217. {"id": "0lr", "text": "(#1) KeyError"},
  218. {"id": "9lf", "text": "(#3) Key Missing"},
  219. ]
  220. }
  221. request = responses.calls[0].request
  222. url = urlparse(request.url)
  223. query = dict(parse_qsl(url.query))
  224. assert url.path == "/1/search"
  225. assert query == {
  226. "cards_limit": "100",
  227. "partial": "true",
  228. "modelTypes": "cards",
  229. "token": "7c8951d1",
  230. "card_fields": "name,shortLink,idShort",
  231. "key": "39g",
  232. "query": "Key",
  233. }