index.spec.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen, waitForElementToBeRemoved} from 'sentry-test/reactTestingLibrary';
  3. import type {DetailedOrganization} from 'sentry/types';
  4. import {useLocation} from 'sentry/utils/useLocation';
  5. import useOrganization from 'sentry/utils/useOrganization';
  6. import usePageFilters from 'sentry/utils/usePageFilters';
  7. import ResourcesLandingPage from 'sentry/views/performance/browser/resources';
  8. import {SpanFunction, SpanMetricsField} from 'sentry/views/starfish/types';
  9. const {
  10. SPAN_SELF_TIME,
  11. SPAN_GROUP,
  12. HTTP_RESPONSE_CONTENT_LENGTH,
  13. SPAN_DOMAIN,
  14. SPAN_DESCRIPTION,
  15. PROJECT_ID,
  16. RESOURCE_RENDER_BLOCKING_STATUS,
  17. SPAN_OP,
  18. } = SpanMetricsField;
  19. const {SPM, TIME_SPENT_PERCENTAGE} = SpanFunction;
  20. jest.mock('sentry/utils/useLocation');
  21. jest.mock('sentry/utils/usePageFilters');
  22. jest.mock('sentry/utils/useOrganization');
  23. const requestMocks: Record<string, jest.Mock> = {};
  24. describe('ResourcesLandingPage', function () {
  25. const organization = OrganizationFixture({
  26. features: ['spans-first-ui', 'starfish-view'],
  27. });
  28. beforeEach(() => {
  29. setupMocks(organization);
  30. setupMockRequests(organization);
  31. });
  32. afterEach(function () {
  33. jest.resetAllMocks();
  34. });
  35. it('renders a list of resources', async () => {
  36. render(<ResourcesLandingPage />);
  37. await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
  38. expect(
  39. screen.getByRole('cell', {name: 'https://*.sentry-cdn.com/123.js'})
  40. ).toBeInTheDocument();
  41. expect(
  42. screen.getByRole('cell', {name: 'https://*.sentry-cdn.com/456.js'})
  43. ).toBeInTheDocument();
  44. });
  45. it('contains correct query in charts', async () => {
  46. render(<ResourcesLandingPage />);
  47. await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
  48. expect(requestMocks.mainTable.mock.calls).toMatchInlineSnapshot(`
  49. [
  50. [
  51. "/organizations/org-slug/events/",
  52. {
  53. "error": [Function],
  54. "method": "GET",
  55. "query": {
  56. "dataset": "spansMetrics",
  57. "environment": [],
  58. "field": [
  59. "span.description",
  60. "span.op",
  61. "count()",
  62. "avg(span.self_time)",
  63. "spm()",
  64. "span.group",
  65. "avg(http.response_content_length)",
  66. "project.id",
  67. "time_spent_percentage()",
  68. "sum(span.self_time)",
  69. ],
  70. "per_page": 100,
  71. "project": [],
  72. "query": "!span.description:"browser-extension://*" ( span.op:resource.script OR file_extension:css OR file_extension:[woff,woff2,ttf,otf,eot] OR file_extension:[jpg,jpeg,png,gif,svg,webp,apng,avif] OR span.op:resource.img ) ",
  73. "referrer": "api.performance.browser.resources.main-table",
  74. "sort": "-time_spent_percentage()",
  75. "statsPeriod": "10d",
  76. },
  77. "skipAbort": undefined,
  78. "success": [Function],
  79. },
  80. ],
  81. ]
  82. `);
  83. });
  84. });
  85. const setupMocks = (organization: DetailedOrganization) => {
  86. jest.mocked(usePageFilters).mockReturnValue({
  87. isReady: true,
  88. desyncedFilters: new Set(),
  89. pinnedFilters: new Set(),
  90. shouldPersist: true,
  91. selection: {
  92. datetime: {
  93. period: '10d',
  94. start: null,
  95. end: null,
  96. utc: false,
  97. },
  98. environments: [],
  99. projects: [],
  100. },
  101. });
  102. jest.mocked(useLocation).mockReturnValue({
  103. pathname: '',
  104. search: '',
  105. query: {statsPeriod: '10d'},
  106. hash: '',
  107. state: undefined,
  108. action: 'PUSH',
  109. key: '',
  110. });
  111. jest.mocked(useOrganization).mockReturnValue(organization);
  112. };
  113. const setupMockRequests = (organization: DetailedOrganization) => {
  114. requestMocks.mainTable = MockApiClient.addMockResponse({
  115. url: `/organizations/${organization.slug}/events/`,
  116. method: 'GET',
  117. match: [
  118. MockApiClient.matchQuery({
  119. referrer: 'api.performance.browser.resources.main-table',
  120. }),
  121. ],
  122. body: {
  123. data: [
  124. {
  125. [`avg(${HTTP_RESPONSE_CONTENT_LENGTH})`]: 123,
  126. [`avg(${SPAN_SELF_TIME})`]: 123,
  127. [RESOURCE_RENDER_BLOCKING_STATUS]: 123,
  128. [SPAN_DESCRIPTION]: 'https://*.sentry-cdn.com/123.js',
  129. [SPAN_DOMAIN]: ['https://*.sentry-cdn.com'],
  130. [PROJECT_ID]: 123,
  131. [SPAN_OP]: 'resource.script',
  132. [SPAN_GROUP]: 'group123',
  133. [`${SPM}()`]: 123,
  134. [`${TIME_SPENT_PERCENTAGE}()`]: 0.5,
  135. [`sum(${SPAN_SELF_TIME})`]: 123,
  136. 'count()': 123,
  137. },
  138. {
  139. [`avg(${HTTP_RESPONSE_CONTENT_LENGTH})`]: 123,
  140. [`avg(${SPAN_SELF_TIME})`]: 123,
  141. [RESOURCE_RENDER_BLOCKING_STATUS]: 123,
  142. [SPAN_DESCRIPTION]: 'https://*.sentry-cdn.com/456.js',
  143. [SPAN_DOMAIN]: ['https://*.sentry-cdn.com'],
  144. [PROJECT_ID]: 123,
  145. [SPAN_OP]: 'resource.script',
  146. [SPAN_GROUP]: 'group123',
  147. [`${SPM}()`]: 123,
  148. [`${TIME_SPENT_PERCENTAGE}()`]: 0.5,
  149. [`sum(${SPAN_SELF_TIME})`]: 123,
  150. 'count()': 123,
  151. },
  152. ],
  153. },
  154. });
  155. MockApiClient.addMockResponse({
  156. url: `/organizations/${organization.slug}/events/`,
  157. method: 'GET',
  158. match: [
  159. MockApiClient.matchQuery({
  160. referrer: 'api.performance.browser.resources.page-selector',
  161. }),
  162. ],
  163. body: {
  164. data: [{transaction: '/page/123/', 'count()': 1}],
  165. },
  166. });
  167. MockApiClient.addMockResponse({
  168. url: `/organizations/${organization.slug}/events/`,
  169. method: 'GET',
  170. match: [MockApiClient.matchQuery({referrer: 'api.starfish.get-span-domains'})],
  171. body: {
  172. data: [{'span.domain': ['*.sentry-cdn.com'], count: 1}],
  173. },
  174. });
  175. MockApiClient.addMockResponse({
  176. url: `/organizations/${organization.slug}/events-stats/`,
  177. method: 'GET',
  178. match: [MockApiClient.matchQuery({referrer: 'api.starfish.span-time-charts'})],
  179. body: {
  180. [`${SPM}()`]: {
  181. data: [
  182. [1699907700, [{count: 7810.2}]],
  183. [1699908000, [{count: 1216.8}]],
  184. ],
  185. },
  186. [`avg(${SPAN_SELF_TIME})`]: {
  187. data: [
  188. [1699907700, [{count: 1111.2}]],
  189. [1699908000, [{count: 2222.8}]],
  190. ],
  191. },
  192. },
  193. });
  194. };