pagePerformanceTable.spec.tsx 6.0 KB

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