httpDomainSummaryPage.spec.tsx 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen, waitForElementToBeRemoved} from 'sentry-test/reactTestingLibrary';
  3. import {useLocation} from 'sentry/utils/useLocation';
  4. import usePageFilters from 'sentry/utils/usePageFilters';
  5. import {HTTPDomainSummaryPage} from 'sentry/views/insights/http/views/httpDomainSummaryPage';
  6. jest.mock('sentry/utils/useLocation');
  7. jest.mock('sentry/utils/usePageFilters');
  8. describe('HTTPSummaryPage', function () {
  9. const organization = OrganizationFixture();
  10. let domainChartsRequestMock, domainTransactionsListRequestMock, spanFieldTagsMock;
  11. jest.mocked(usePageFilters).mockReturnValue({
  12. isReady: true,
  13. desyncedFilters: new Set(),
  14. pinnedFilters: new Set(),
  15. shouldPersist: true,
  16. selection: {
  17. datetime: {
  18. period: '10d',
  19. start: null,
  20. end: null,
  21. utc: false,
  22. },
  23. environments: [],
  24. projects: [],
  25. },
  26. });
  27. jest.mocked(useLocation).mockReturnValue({
  28. pathname: '',
  29. search: '',
  30. query: {domain: '*.sentry.dev', statsPeriod: '10d', transactionsCursor: '0:20:0'},
  31. hash: '',
  32. state: undefined,
  33. action: 'PUSH',
  34. key: '',
  35. });
  36. beforeEach(function () {
  37. jest.clearAllMocks();
  38. domainTransactionsListRequestMock = MockApiClient.addMockResponse({
  39. url: `/organizations/${organization.slug}/events/`,
  40. method: 'GET',
  41. body: {
  42. data: [],
  43. },
  44. });
  45. domainChartsRequestMock = MockApiClient.addMockResponse({
  46. url: `/organizations/${organization.slug}/events-stats/`,
  47. method: 'GET',
  48. body: {
  49. 'spm()': {
  50. data: [
  51. [1699907700, [{count: 7810.2}]],
  52. [1699908000, [{count: 1216.8}]],
  53. ],
  54. },
  55. },
  56. });
  57. spanFieldTagsMock = MockApiClient.addMockResponse({
  58. url: `/organizations/${organization.slug}/spans/fields/`,
  59. method: 'GET',
  60. body: [
  61. {
  62. key: 'api_key',
  63. name: 'Api Key',
  64. },
  65. {
  66. key: 'bytes.size',
  67. name: 'Bytes.Size',
  68. },
  69. ],
  70. });
  71. });
  72. afterAll(function () {
  73. jest.resetAllMocks();
  74. });
  75. it('fetches module data', async function () {
  76. render(<HTTPDomainSummaryPage />, {organization});
  77. expect(domainChartsRequestMock).toHaveBeenNthCalledWith(
  78. 1,
  79. `/organizations/${organization.slug}/events-stats/`,
  80. expect.objectContaining({
  81. method: 'GET',
  82. query: {
  83. cursor: undefined,
  84. dataset: 'spansMetrics',
  85. environment: [],
  86. excludeOther: 0,
  87. field: [],
  88. interval: '30m',
  89. orderby: undefined,
  90. partial: 1,
  91. per_page: 50,
  92. project: [],
  93. query: 'span.module:http span.op:http.client span.domain:"\\*.sentry.dev"',
  94. referrer: 'api.performance.http.domain-summary-throughput-chart',
  95. statsPeriod: '10d',
  96. topEvents: undefined,
  97. yAxis: 'spm()',
  98. },
  99. })
  100. );
  101. expect(domainChartsRequestMock).toHaveBeenNthCalledWith(
  102. 2,
  103. `/organizations/${organization.slug}/events-stats/`,
  104. expect.objectContaining({
  105. method: 'GET',
  106. query: {
  107. cursor: undefined,
  108. dataset: 'spansMetrics',
  109. environment: [],
  110. excludeOther: 0,
  111. field: [],
  112. interval: '30m',
  113. orderby: undefined,
  114. partial: 1,
  115. per_page: 50,
  116. project: [],
  117. query: 'span.module:http span.op:http.client span.domain:"\\*.sentry.dev"',
  118. referrer: 'api.performance.http.domain-summary-duration-chart',
  119. statsPeriod: '10d',
  120. topEvents: undefined,
  121. yAxis: 'avg(span.self_time)',
  122. },
  123. })
  124. );
  125. expect(domainChartsRequestMock).toHaveBeenNthCalledWith(
  126. 3,
  127. `/organizations/${organization.slug}/events-stats/`,
  128. expect.objectContaining({
  129. method: 'GET',
  130. query: {
  131. cursor: undefined,
  132. dataset: 'spansMetrics',
  133. environment: [],
  134. excludeOther: 0,
  135. field: [],
  136. interval: '30m',
  137. orderby: undefined,
  138. partial: 1,
  139. per_page: 50,
  140. project: [],
  141. query: 'span.module:http span.op:http.client span.domain:"\\*.sentry.dev"',
  142. referrer: 'api.performance.http.domain-summary-response-code-chart',
  143. statsPeriod: '10d',
  144. topEvents: undefined,
  145. yAxis: [
  146. 'http_response_rate(3)',
  147. 'http_response_rate(4)',
  148. 'http_response_rate(5)',
  149. ],
  150. },
  151. })
  152. );
  153. expect(domainTransactionsListRequestMock).toHaveBeenNthCalledWith(
  154. 1,
  155. `/organizations/${organization.slug}/events/`,
  156. expect.objectContaining({
  157. method: 'GET',
  158. query: {
  159. dataset: 'spansMetrics',
  160. environment: [],
  161. field: [
  162. 'spm()',
  163. 'avg(span.self_time)',
  164. 'sum(span.self_time)',
  165. 'http_response_rate(3)',
  166. 'http_response_rate(4)',
  167. 'http_response_rate(5)',
  168. 'time_spent_percentage()',
  169. ],
  170. per_page: 50,
  171. project: [],
  172. query: 'span.module:http span.op:http.client span.domain:"\\*.sentry.dev"',
  173. referrer: 'api.performance.http.domain-summary-metrics-ribbon',
  174. statsPeriod: '10d',
  175. },
  176. })
  177. );
  178. expect(domainTransactionsListRequestMock).toHaveBeenNthCalledWith(
  179. 2,
  180. `/organizations/${organization.slug}/events/`,
  181. expect.objectContaining({
  182. method: 'GET',
  183. query: {
  184. dataset: 'spansMetrics',
  185. environment: [],
  186. field: [
  187. 'project.id',
  188. 'transaction',
  189. 'transaction.method',
  190. 'spm()',
  191. 'http_response_rate(3)',
  192. 'http_response_rate(4)',
  193. 'http_response_rate(5)',
  194. 'avg(span.self_time)',
  195. 'sum(span.self_time)',
  196. 'time_spent_percentage()',
  197. ],
  198. per_page: 20,
  199. project: [],
  200. cursor: '0:20:0',
  201. query: 'span.module:http span.op:http.client span.domain:"\\*.sentry.dev"',
  202. sort: '-time_spent_percentage()',
  203. referrer: 'api.performance.http.domain-summary-transactions-list',
  204. statsPeriod: '10d',
  205. },
  206. })
  207. );
  208. expect(spanFieldTagsMock).toHaveBeenNthCalledWith(
  209. 1,
  210. `/organizations/${organization.slug}/spans/fields/`,
  211. expect.objectContaining({
  212. method: 'GET',
  213. query: {
  214. project: [],
  215. environment: [],
  216. statsPeriod: '1h',
  217. },
  218. })
  219. );
  220. await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
  221. });
  222. it('renders a list of queries', async function () {
  223. MockApiClient.addMockResponse({
  224. url: `/organizations/${organization.slug}/events/`,
  225. method: 'GET',
  226. match: [
  227. MockApiClient.matchQuery({
  228. referrer: 'api.performance.http.domain-summary-transactions-list',
  229. }),
  230. ],
  231. body: {
  232. data: [
  233. {
  234. 'project.id': 8,
  235. transaction: '/api/users',
  236. 'transaction.method': 'GET',
  237. 'spm()': 17.88,
  238. 'http_response_rate(3)': 0.97,
  239. 'http_response_rate(4)': 0.025,
  240. 'http_response_rate(5)': 0.005,
  241. 'avg(span.self_time)': 204.5,
  242. 'sum(span.self_time)': 177238,
  243. },
  244. ],
  245. meta: {
  246. fields: {
  247. 'spm()': 'rate',
  248. 'avg(span.self_time)': 'duration',
  249. 'http_response_rate(3)': 'percentage',
  250. 'http_response_rate(4)': 'percentage',
  251. 'http_response_rate(5)': 'percentage',
  252. 'sum(span.self_time)': 'duration',
  253. },
  254. },
  255. },
  256. });
  257. render(<HTTPDomainSummaryPage />, {organization});
  258. await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
  259. expect(screen.getByRole('table', {name: 'Transactions'})).toBeInTheDocument();
  260. expect(screen.getByRole('columnheader', {name: 'Found In'})).toBeInTheDocument();
  261. expect(
  262. screen.getByRole('columnheader', {name: 'Requests Per Minute'})
  263. ).toBeInTheDocument();
  264. expect(screen.getByRole('columnheader', {name: '3XXs'})).toBeInTheDocument();
  265. expect(screen.getByRole('columnheader', {name: '4XXs'})).toBeInTheDocument();
  266. expect(screen.getByRole('columnheader', {name: '5XXs'})).toBeInTheDocument();
  267. expect(screen.getByRole('columnheader', {name: 'Avg Duration'})).toBeInTheDocument();
  268. expect(screen.getByRole('columnheader', {name: 'Time Spent'})).toBeInTheDocument();
  269. expect(screen.getByRole('cell', {name: 'GET /api/users'})).toBeInTheDocument();
  270. expect(screen.getByRole('link', {name: 'GET /api/users'})).toHaveAttribute(
  271. 'href',
  272. '/organizations/org-slug/insights/http/domains/?domain=%2A.sentry.dev&project=8&statsPeriod=10d&transaction=%2Fapi%2Fusers&transactionMethod=GET&transactionsCursor=0%3A20%3A0'
  273. );
  274. expect(screen.getByRole('cell', {name: '17.9/s'})).toBeInTheDocument();
  275. expect(screen.getByRole('cell', {name: '97%'})).toBeInTheDocument();
  276. expect(screen.getByRole('cell', {name: '2.5%'})).toBeInTheDocument();
  277. expect(screen.getByRole('cell', {name: '0.5%'})).toBeInTheDocument();
  278. expect(screen.getByRole('cell', {name: '204.50ms'})).toBeInTheDocument();
  279. expect(screen.getByRole('cell', {name: '2.95min'})).toBeInTheDocument();
  280. });
  281. });