groupUptimeChecks.spec.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import {EventFixture} from 'sentry-fixture/event';
  2. import {GroupFixture} from 'sentry-fixture/group';
  3. import {OrganizationFixture} from 'sentry-fixture/organization';
  4. import {ProjectFixture} from 'sentry-fixture/project';
  5. import {RouterFixture} from 'sentry-fixture/routerFixture';
  6. import {UptimeCheckFixture} from 'sentry-fixture/uptimeCheck';
  7. import {UptimeRuleFixture} from 'sentry-fixture/uptimeRule';
  8. import {render, screen} from 'sentry-test/reactTestingLibrary';
  9. import GroupStore from 'sentry/stores/groupStore';
  10. import PageFiltersStore from 'sentry/stores/pageFiltersStore';
  11. import ProjectsStore from 'sentry/stores/projectsStore';
  12. import {IssueCategory, IssueType} from 'sentry/types/group';
  13. import {getShortEventId} from 'sentry/utils/events';
  14. import {statusToText} from 'sentry/views/insights/uptime/timelineConfig';
  15. import GroupUptimeChecks from 'sentry/views/issueDetails/groupUptimeChecks';
  16. describe('GroupUptimeChecks', () => {
  17. const uptimeRuleId = '123';
  18. const event = EventFixture({
  19. tags: [
  20. {
  21. key: 'uptime_rule',
  22. value: uptimeRuleId,
  23. },
  24. ],
  25. });
  26. const group = GroupFixture({
  27. issueCategory: IssueCategory.UPTIME,
  28. issueType: IssueType.UPTIME_DOMAIN_FAILURE,
  29. });
  30. const organization = OrganizationFixture();
  31. const project = ProjectFixture();
  32. const router = RouterFixture({
  33. params: {groupId: group.id},
  34. });
  35. beforeEach(() => {
  36. GroupStore.init();
  37. GroupStore.add([group]);
  38. ProjectsStore.init();
  39. ProjectsStore.loadInitialData([project]);
  40. MockApiClient.clearMockResponses();
  41. MockApiClient.addMockResponse({
  42. url: `/organizations/${organization.slug}/issues/${group.id}/`,
  43. body: group,
  44. });
  45. MockApiClient.addMockResponse({
  46. url: `/organizations/${organization.slug}/issues/${group.id}/events/recommended/`,
  47. body: event,
  48. });
  49. MockApiClient.addMockResponse({
  50. url: `/projects/org-slug/project-slug/uptime/123/`,
  51. body: UptimeRuleFixture(),
  52. });
  53. PageFiltersStore.onInitializeUrlState(
  54. {
  55. projects: [Number(project.id)],
  56. environments: [],
  57. datetime: {period: '24h', start: null, end: null, utc: null},
  58. },
  59. new Set()
  60. );
  61. });
  62. it('renders the empty uptime check table', async () => {
  63. MockApiClient.addMockResponse({
  64. url: `/projects/${organization.slug}/${project.slug}/uptime/${uptimeRuleId}/checks/`,
  65. body: [],
  66. });
  67. render(<GroupUptimeChecks />, {organization, router});
  68. expect(await screen.findByText('All Uptime Checks')).toBeInTheDocument();
  69. for (const column of ['Timestamp', 'Status', 'Duration', 'Trace', 'Region']) {
  70. expect(screen.getByText(column)).toBeInTheDocument();
  71. }
  72. expect(screen.getByText('No matching uptime checks found')).toBeInTheDocument();
  73. });
  74. it('renders the uptime check table with data', async () => {
  75. const uptimeCheck = UptimeCheckFixture();
  76. MockApiClient.addMockResponse({
  77. url: `/projects/${organization.slug}/${project.slug}/uptime/${uptimeRuleId}/checks/`,
  78. body: [uptimeCheck],
  79. });
  80. MockApiClient.addMockResponse({
  81. url: `/organizations/${organization.slug}/events/`,
  82. method: 'GET',
  83. body: {
  84. data: [],
  85. },
  86. match: [MockApiClient.matchQuery({referrer: 'api.uptime-checks-grid'})],
  87. });
  88. render(<GroupUptimeChecks />, {organization, router});
  89. expect(await screen.findByText('All Uptime Checks')).toBeInTheDocument();
  90. expect(screen.queryByText('No matching uptime checks found')).not.toBeInTheDocument();
  91. expect(screen.getByText('Showing 1-1 matching uptime checks')).toBeInTheDocument();
  92. expect(screen.getByRole('button', {name: 'Previous Page'})).toBeInTheDocument();
  93. expect(screen.getByRole('button', {name: 'Next Page'})).toBeInTheDocument();
  94. expect(screen.getByRole('time')).toHaveTextContent(/Jan 1, 2025/);
  95. expect(screen.getByText(statusToText[uptimeCheck.checkStatus])).toBeInTheDocument();
  96. expect(screen.getByText(`${uptimeCheck.durationMs}ms`)).toBeInTheDocument();
  97. expect(screen.getByText(getShortEventId(uptimeCheck.traceId))).toBeInTheDocument();
  98. expect(screen.getByText(uptimeCheck.regionName)).toBeInTheDocument();
  99. // Span counts also need to load
  100. expect(await screen.findByText('0 spans')).toBeInTheDocument();
  101. });
  102. it('indicates when there are spans in a trace', async () => {
  103. const uptimeCheck = UptimeCheckFixture();
  104. MockApiClient.addMockResponse({
  105. url: `/projects/${organization.slug}/${project.slug}/uptime/${uptimeRuleId}/checks/`,
  106. body: [uptimeCheck],
  107. });
  108. MockApiClient.addMockResponse({
  109. url: `/organizations/${organization.slug}/events/`,
  110. method: 'GET',
  111. body: {
  112. data: [{trace: uptimeCheck.traceId, 'count()': 10}],
  113. },
  114. match: [MockApiClient.matchQuery({referrer: 'api.uptime-checks-grid'})],
  115. });
  116. render(<GroupUptimeChecks />, {organization, router});
  117. expect(await screen.findByText('All Uptime Checks')).toBeInTheDocument();
  118. const traceId = getShortEventId(uptimeCheck.traceId);
  119. // TraceID is a not link until we know there are spans
  120. expect(screen.getByText(traceId)).toBeInTheDocument();
  121. expect(screen.queryByRole('link', {name: traceId})).not.toBeInTheDocument();
  122. // Once the span count has loaded it will be a link
  123. expect(await screen.findByText('10 spans')).toBeInTheDocument();
  124. expect(screen.getByRole('link', {name: traceId})).toBeInTheDocument();
  125. });
  126. });