test_discover_saved_query_detail.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. import pytest
  2. from django.urls import NoReverseMatch, reverse
  3. from sentry.discover.models import DiscoverSavedQuery, DiscoverSavedQueryProject
  4. from sentry.testutils import APITestCase, SnubaTestCase
  5. from sentry.testutils.silo import region_silo_test
  6. class DiscoverSavedQueryDetailTest(APITestCase, SnubaTestCase):
  7. feature_name = "organizations:discover"
  8. def setUp(self):
  9. super().setUp()
  10. self.login_as(user=self.user)
  11. self.org = self.create_organization(owner=self.user)
  12. self.org_without_access = self.create_organization()
  13. self.project_ids = [
  14. self.create_project(organization=self.org).id,
  15. self.create_project(organization=self.org).id,
  16. ]
  17. query = {"fields": ["test"], "conditions": [], "limit": 10}
  18. model = DiscoverSavedQuery.objects.create(
  19. organization=self.org, created_by=self.user, name="Test query", query=query
  20. )
  21. model.set_projects(self.project_ids)
  22. self.query_id = model.id
  23. invalid = DiscoverSavedQuery.objects.create(
  24. organization=self.org_without_access, name="Query without access", query=query
  25. )
  26. invalid.set_projects(self.project_ids)
  27. self.query_id_without_access = invalid.id
  28. def test_invalid_id(self):
  29. with pytest.raises(NoReverseMatch):
  30. reverse("sentry-api-0-discover-saved-query-detail", args=[self.org.slug, "not-an-id"])
  31. def test_get(self):
  32. with self.feature(self.feature_name):
  33. url = reverse(
  34. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  35. )
  36. response = self.client.get(url)
  37. assert response.status_code == 200, response.content
  38. assert response.data["id"] == str(self.query_id)
  39. assert set(response.data["projects"]) == set(self.project_ids)
  40. assert response.data["fields"] == ["test"]
  41. assert response.data["conditions"] == []
  42. assert response.data["limit"] == 10
  43. def test_get_discover_query_flag(self):
  44. with self.feature("organizations:discover-query"):
  45. url = reverse(
  46. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  47. )
  48. response = self.client.get(url)
  49. assert response.status_code == 200, response.content
  50. assert response.data["id"] == str(self.query_id)
  51. assert set(response.data["projects"]) == set(self.project_ids)
  52. assert response.data["fields"] == ["test"]
  53. assert response.data["conditions"] == []
  54. assert response.data["limit"] == 10
  55. def test_get_version(self):
  56. query = {"fields": ["event_id"], "query": "event.type:error", "limit": 10, "version": 2}
  57. model = DiscoverSavedQuery.objects.create(
  58. organization=self.org, created_by=self.user, name="v2 query", query=query
  59. )
  60. model.set_projects(self.project_ids)
  61. with self.feature(self.feature_name):
  62. url = reverse(
  63. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, model.id]
  64. )
  65. response = self.client.get(url)
  66. assert response.status_code == 200, response.content
  67. assert response.data["id"] == str(model.id)
  68. assert set(response.data["projects"]) == set(self.project_ids)
  69. assert response.data["fields"] == ["event_id"]
  70. assert response.data["query"] == "event.type:error"
  71. assert response.data["limit"] == 10
  72. assert response.data["version"] == 2
  73. def test_get_org_without_access(self):
  74. with self.feature(self.feature_name):
  75. url = reverse(
  76. "sentry-api-0-discover-saved-query-detail",
  77. args=[self.org_without_access.slug, self.query_id],
  78. )
  79. response = self.client.get(url)
  80. assert response.status_code == 403, response.content
  81. def test_get_homepage_query(self):
  82. query = {"fields": ["event_id"], "query": "event.type:error", "limit": 10, "version": 2}
  83. model = DiscoverSavedQuery.objects.create(
  84. organization=self.org,
  85. created_by=self.user,
  86. name="v2 query",
  87. query=query,
  88. is_homepage=True,
  89. )
  90. model.set_projects(self.project_ids)
  91. with self.feature(self.feature_name):
  92. url = reverse(
  93. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, model.id]
  94. )
  95. response = self.client.get(url)
  96. assert response.status_code == 404, response.content
  97. def test_put(self):
  98. with self.feature(self.feature_name):
  99. url = reverse(
  100. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  101. )
  102. response = self.client.put(
  103. url,
  104. {
  105. "name": "New query",
  106. "projects": self.project_ids,
  107. "fields": [],
  108. "range": "24h",
  109. "limit": 20,
  110. "conditions": [],
  111. "aggregations": [],
  112. "orderby": "-time",
  113. },
  114. )
  115. assert response.status_code == 200, response.content
  116. assert response.data["id"] == str(self.query_id)
  117. assert set(response.data["projects"]) == set(self.project_ids)
  118. assert response.data["fields"] == []
  119. assert response.data["conditions"] == []
  120. assert response.data["limit"] == 20
  121. def test_put_with_interval(self):
  122. with self.feature(self.feature_name):
  123. url = reverse(
  124. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  125. )
  126. response = self.client.put(
  127. url,
  128. {
  129. "name": "New query",
  130. "projects": self.project_ids,
  131. "fields": ["transaction", "count()"],
  132. "range": "24h",
  133. "interval": "10m",
  134. "version": 2,
  135. "orderby": "-count",
  136. },
  137. )
  138. assert response.status_code == 200, response.content
  139. assert response.data["fields"] == ["transaction", "count()"]
  140. assert response.data["interval"] == "10m"
  141. def test_put_query_without_access(self):
  142. with self.feature(self.feature_name):
  143. url = reverse(
  144. "sentry-api-0-discover-saved-query-detail",
  145. args=[self.org.slug, self.query_id_without_access],
  146. )
  147. response = self.client.put(
  148. url, {"name": "New query", "projects": self.project_ids, "range": "24h"}
  149. )
  150. assert response.status_code == 404
  151. def test_put_query_with_team(self):
  152. team = self.create_team(organization=self.org, members=[self.user])
  153. project = self.create_project(organization=self.org, teams=[team])
  154. query = DiscoverSavedQuery.objects.create(
  155. organization=self.org,
  156. created_by=self.user,
  157. name="Test query",
  158. query={"fields": ["test"], "conditions": [], "limit": 10},
  159. )
  160. query.set_projects([project.id])
  161. with self.feature(self.feature_name):
  162. url = reverse(
  163. "sentry-api-0-discover-saved-query-detail",
  164. args=[self.org.slug, query.id],
  165. )
  166. response = self.client.put(url, {"name": "New query", "projects": [], "range": "24h"})
  167. assert response.status_code == 200
  168. def test_put_query_without_team(self):
  169. team = self.create_team(organization=self.org, members=[])
  170. project = self.create_project(organization=self.org, teams=[team])
  171. query = DiscoverSavedQuery.objects.create(
  172. organization=self.org,
  173. created_by=self.user,
  174. name="Test query",
  175. query={"fields": ["test"], "conditions": [], "limit": 10},
  176. )
  177. query.set_projects([project.id])
  178. with self.feature(self.feature_name):
  179. url = reverse(
  180. "sentry-api-0-discover-saved-query-detail",
  181. args=[self.org.slug, query.id],
  182. )
  183. response = self.client.put(url, {"name": "New query", "projects": [], "range": "24h"})
  184. assert response.status_code == 400
  185. assert "No Projects found, join a Team" == response.data["detail"]
  186. def test_put_homepage_query(self):
  187. query = {"fields": ["event_id"], "query": "event.type:error", "limit": 10, "version": 2}
  188. model = DiscoverSavedQuery.objects.create(
  189. organization=self.org,
  190. created_by=self.user,
  191. name="v2 query",
  192. query=query,
  193. is_homepage=True,
  194. )
  195. model.set_projects(self.project_ids)
  196. with self.feature(self.feature_name):
  197. url = reverse(
  198. "sentry-api-0-discover-saved-query-detail",
  199. args=[self.org.slug, model.id],
  200. )
  201. response = self.client.put(
  202. url, {"name": "New query", "projects": [], "range": "24h", "fields": []}
  203. )
  204. assert response.status_code == 404, response.content
  205. def test_put_org_without_access(self):
  206. with self.feature(self.feature_name):
  207. url = reverse(
  208. "sentry-api-0-discover-saved-query-detail",
  209. args=[self.org_without_access.slug, self.query_id],
  210. )
  211. response = self.client.put(
  212. url, {"name": "New query", "projects": self.project_ids, "range": "24h"}
  213. )
  214. assert response.status_code == 403, response.content
  215. def test_delete(self):
  216. with self.feature(self.feature_name):
  217. url = reverse(
  218. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  219. )
  220. response = self.client.delete(url)
  221. assert response.status_code == 204
  222. assert self.client.get(url).status_code == 404
  223. def test_delete_removes_projects(self):
  224. with self.feature(self.feature_name):
  225. url = reverse(
  226. "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, self.query_id]
  227. )
  228. self.client.delete(url)
  229. projects = list(
  230. DiscoverSavedQueryProject.objects.filter(discover_saved_query=self.query_id)
  231. )
  232. assert projects == []
  233. def test_delete_query_without_access(self):
  234. with self.feature(self.feature_name):
  235. url = reverse(
  236. "sentry-api-0-discover-saved-query-detail",
  237. args=[self.org.slug, self.query_id_without_access],
  238. )
  239. response = self.client.delete(url)
  240. assert response.status_code == 404
  241. def test_delete_org_without_access(self):
  242. with self.feature(self.feature_name):
  243. url = reverse(
  244. "sentry-api-0-discover-saved-query-detail",
  245. args=[self.org_without_access.slug, self.query_id],
  246. )
  247. response = self.client.delete(url)
  248. assert response.status_code == 403, response.content
  249. def test_delete_homepage_query(self):
  250. query = {"fields": ["event_id"], "query": "event.type:error", "limit": 10, "version": 2}
  251. model = DiscoverSavedQuery.objects.create(
  252. organization=self.org,
  253. created_by=self.user,
  254. name="v2 query",
  255. query=query,
  256. is_homepage=True,
  257. )
  258. model.set_projects(self.project_ids)
  259. with self.feature(self.feature_name):
  260. url = reverse(
  261. "sentry-api-0-discover-saved-query-detail",
  262. args=[self.org.slug, model.id],
  263. )
  264. response = self.client.delete(url)
  265. assert response.status_code == 404, response.content
  266. @region_silo_test
  267. class OrganizationDiscoverQueryVisitTest(APITestCase, SnubaTestCase):
  268. def setUp(self):
  269. super().setUp()
  270. self.login_as(user=self.user)
  271. self.org = self.create_organization(owner=self.user)
  272. self.org_without_access = self.create_organization()
  273. self.project_ids = [
  274. self.create_project(organization=self.org).id,
  275. self.create_project(organization=self.org).id,
  276. ]
  277. q = {"fields": ["test"], "conditions": [], "limit": 10}
  278. self.query = DiscoverSavedQuery.objects.create(
  279. organization=self.org, created_by=self.user, name="Test query", query=q
  280. )
  281. self.query.set_projects(self.project_ids)
  282. def url(self, query_id):
  283. return reverse(
  284. "sentry-api-0-discover-saved-query-visit",
  285. kwargs={"organization_slug": self.org.slug, "query_id": query_id},
  286. )
  287. def test_visit_query(self):
  288. last_visited = self.query.last_visited
  289. assert self.query.visits == 1
  290. with self.feature("organizations:discover-query"):
  291. response = self.client.post(self.url(self.query.id))
  292. assert response.status_code == 204
  293. query = DiscoverSavedQuery.objects.get(id=self.query.id)
  294. assert query.visits == 2
  295. assert query.last_visited > last_visited
  296. def test_visit_query_no_access(self):
  297. last_visited = self.query.last_visited
  298. assert self.query.visits == 1
  299. with self.feature({"organizations:discover-query": False}):
  300. response = self.client.post(self.url(self.query.id))
  301. assert response.status_code == 404
  302. query = DiscoverSavedQuery.objects.get(id=self.query.id)
  303. assert query.visits == 1
  304. assert query.last_visited == last_visited