test_plugin.py 9.2 KB

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