index.spec.tsx 6.1 KB

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