pagePerformanceTable.spec.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {
  4. render,
  5. screen,
  6. waitFor,
  7. waitForElementToBeRemoved,
  8. } from 'sentry-test/reactTestingLibrary';
  9. import {useLocation} from 'sentry/utils/useLocation';
  10. import usePageFilters from 'sentry/utils/usePageFilters';
  11. import useProjects from 'sentry/utils/useProjects';
  12. import {PagePerformanceTable} from 'sentry/views/insights/browser/webVitals/components/tables/pagePerformanceTable';
  13. jest.mock('sentry/utils/useLocation');
  14. jest.mock('sentry/utils/useProjects');
  15. jest.mock('sentry/utils/usePageFilters');
  16. describe('PagePerformanceTable', function () {
  17. const organization = OrganizationFixture();
  18. let eventsMock;
  19. beforeEach(function () {
  20. jest.mocked(useLocation).mockReturnValue({
  21. pathname: '',
  22. search: '',
  23. query: {},
  24. hash: '',
  25. state: undefined,
  26. action: 'PUSH',
  27. key: '',
  28. });
  29. jest.mocked(usePageFilters).mockReturnValue({
  30. isReady: true,
  31. desyncedFilters: new Set(),
  32. pinnedFilters: new Set(),
  33. shouldPersist: true,
  34. selection: {
  35. datetime: {
  36. period: '10d',
  37. start: null,
  38. end: null,
  39. utc: false,
  40. },
  41. environments: [],
  42. projects: [],
  43. },
  44. });
  45. jest.mocked(useProjects).mockReturnValue({
  46. projects: [
  47. ProjectFixture({
  48. id: '11276',
  49. name: 'frontend',
  50. slug: 'frontend',
  51. platform: 'python',
  52. }),
  53. ],
  54. onSearch: jest.fn(),
  55. reloadProjects: jest.fn(),
  56. placeholders: [],
  57. fetching: false,
  58. hasMore: null,
  59. fetchError: null,
  60. initiallyLoaded: false,
  61. });
  62. MockApiClient.addMockResponse({
  63. url: `/organizations/${organization.slug}/projects/`,
  64. body: [ProjectFixture({id: '11276', name: 'frontend', slug: 'frontend'})],
  65. });
  66. eventsMock = MockApiClient.addMockResponse({
  67. url: `/organizations/${organization.slug}/events/`,
  68. body: {
  69. data: [
  70. {
  71. 'project.id': 11276,
  72. project: 'frontend',
  73. transaction: '/insights/browser/',
  74. 'count()': 492,
  75. 'count_scores(measurements.score.inp)': 985,
  76. 'count_scores(measurements.score.total)': 985,
  77. 'avg(measurements.score.total)': 0.847767385770207,
  78. 'total_opportunity_score()': 6.956683571915815e-5,
  79. 'opportunity_score(measurements.score.total)': 179.76662400002692,
  80. 'p75(measurements.inp)': 144.0,
  81. 'p75(measurements.ttfb)': 783.125,
  82. 'p75(measurements.lcp)': 700.2999782562256,
  83. 'p75(measurements.cls)': 0.17772871140057198,
  84. 'p75(measurements.fcp)': 563.2752180099487,
  85. 'count_scores(measurements.score.cls)': 311,
  86. 'count_scores(measurements.score.fcp)': 414,
  87. 'count_scores(measurements.score.ttfb)': 477,
  88. 'count_scores(measurements.score.lcp)': 391,
  89. },
  90. ],
  91. meta: {
  92. fields: {
  93. transaction: 'string',
  94. 'project.id': 'number',
  95. project: 'string',
  96. },
  97. },
  98. },
  99. });
  100. });
  101. afterEach(function () {
  102. jest.clearAllMocks();
  103. });
  104. it('escapes user input search filter', async () => {
  105. jest.mocked(useLocation).mockReturnValue({
  106. pathname: '',
  107. search: '',
  108. query: {query: '/issues/*'},
  109. hash: '',
  110. state: undefined,
  111. action: 'PUSH',
  112. key: '',
  113. });
  114. render(<PagePerformanceTable />, {organization});
  115. await waitFor(() => {
  116. expect(eventsMock).toHaveBeenCalledTimes(1);
  117. expect(eventsMock).toHaveBeenLastCalledWith(
  118. '/organizations/org-slug/events/',
  119. expect.objectContaining({
  120. query: expect.objectContaining({
  121. query: expect.stringContaining('transaction:"*/issues/\\**"'),
  122. }),
  123. })
  124. );
  125. });
  126. });
  127. it('renders a list of pages', async function () {
  128. render(<PagePerformanceTable />, {organization});
  129. await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
  130. expect(screen.getByRole('table', {name: 'Pages'})).toBeInTheDocument();
  131. expect(screen.getByRole('columnheader', {name: 'Pages'})).toBeInTheDocument();
  132. expect(screen.getByRole('columnheader', {name: 'Project'})).toBeInTheDocument();
  133. expect(screen.getByRole('columnheader', {name: 'Pageloads'})).toBeInTheDocument();
  134. expect(screen.getByRole('columnheader', {name: 'LCP'})).toBeInTheDocument();
  135. expect(screen.getByRole('columnheader', {name: 'LCP'})).toBeInTheDocument();
  136. expect(screen.getByRole('columnheader', {name: 'INP'})).toBeInTheDocument();
  137. expect(screen.getByRole('columnheader', {name: 'CLS'})).toBeInTheDocument();
  138. expect(screen.getByRole('columnheader', {name: 'TTFB'})).toBeInTheDocument();
  139. expect(screen.getByRole('columnheader', {name: 'Perf Score'})).toBeInTheDocument();
  140. expect(screen.getByRole('columnheader', {name: 'Opportunity'})).toBeInTheDocument();
  141. expect(screen.getByRole('cell', {name: '/insights/browser/'})).toBeInTheDocument();
  142. expect(screen.getByRole('link', {name: '/insights/browser/'})).toHaveAttribute(
  143. 'href',
  144. 'overview/?project=11276&transaction=%2Finsights%2Fbrowser%2F'
  145. );
  146. expect(screen.getByRole('cell', {name: 'frontend'})).toBeInTheDocument();
  147. expect(screen.getByRole('link', {name: 'frontend'})).toHaveAttribute(
  148. 'href',
  149. '/organizations/org-slug/projects/frontend/?project=11276'
  150. );
  151. expect(screen.getByRole('cell', {name: '492'})).toBeInTheDocument();
  152. expect(screen.getByRole('cell', {name: '700ms'})).toBeInTheDocument();
  153. expect(screen.getByRole('cell', {name: '563ms'})).toBeInTheDocument();
  154. expect(screen.getByRole('cell', {name: '144ms'})).toBeInTheDocument();
  155. expect(screen.getByRole('cell', {name: '0.18'})).toBeInTheDocument();
  156. expect(screen.getByRole('cell', {name: '783ms'})).toBeInTheDocument();
  157. expect(screen.getByRole('cell', {name: 'Meh 85'})).toBeInTheDocument();
  158. expect(screen.getByRole('cell', {name: '0.01'})).toBeInTheDocument();
  159. });
  160. });