issueUptimeCheckTimeline.spec.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 {render, screen, within} from 'sentry-test/reactTestingLibrary';
  6. import {useTimeWindowConfig} from 'sentry/components/checkInTimeline/hooks/useTimeWindowConfig';
  7. import {getConfigFromTimeRange} from 'sentry/components/checkInTimeline/utils/getConfigFromTimeRange';
  8. import GroupStore from 'sentry/stores/groupStore';
  9. import ProjectsStore from 'sentry/stores/projectsStore';
  10. import {IssueCategory, IssueType} from 'sentry/types/group';
  11. import {CheckStatus} from 'sentry/views/alerts/rules/uptime/types';
  12. import {statusToText} from 'sentry/views/insights/uptime/timelineConfig';
  13. import {IssueUptimeCheckTimeline} from 'sentry/views/issueDetails/streamline/issueUptimeCheckTimeline';
  14. const startTime = new Date('2025-01-01T11:00:00Z');
  15. jest.mock('sentry/components/checkInTimeline/hooks/useTimeWindowConfig');
  16. jest
  17. .mocked(useTimeWindowConfig)
  18. .mockReturnValue(
  19. getConfigFromTimeRange(
  20. startTime,
  21. new Date(startTime.getTime() + 1000 * 60 * 60),
  22. 1000
  23. )
  24. );
  25. describe('IssueUptimeCheckTimeline', () => {
  26. const uptimeRuleId = '123';
  27. const organization = OrganizationFixture();
  28. const project = ProjectFixture({
  29. environments: ['production'],
  30. });
  31. const group = GroupFixture({
  32. issueCategory: IssueCategory.UPTIME,
  33. issueType: IssueType.UPTIME_DOMAIN_FAILURE,
  34. });
  35. const event = EventFixture({
  36. tags: [
  37. {
  38. key: 'uptime_rule',
  39. value: uptimeRuleId,
  40. },
  41. ],
  42. });
  43. beforeEach(() => {
  44. GroupStore.init();
  45. GroupStore.add([group]);
  46. ProjectsStore.init();
  47. ProjectsStore.loadInitialData([project]);
  48. MockApiClient.clearMockResponses();
  49. MockApiClient.addMockResponse({
  50. url: `/organizations/${organization.slug}/issues/${group.id}/`,
  51. body: group,
  52. });
  53. MockApiClient.addMockResponse({
  54. url: `/organizations/${organization.slug}/issues/${group.id}/events/recommended/`,
  55. body: event,
  56. });
  57. });
  58. it('renders the uptime check timeline with a legend and data', async function () {
  59. MockApiClient.addMockResponse({
  60. url: `/organizations/${organization.slug}/uptime-stats/`,
  61. query: {
  62. projectUptimeSubscriptionId: [uptimeRuleId],
  63. },
  64. body: {
  65. [uptimeRuleId]: [
  66. [
  67. new Date('2025-01-01T11:00:00Z').getTime() / 1000,
  68. {
  69. [CheckStatus.SUCCESS]: 1,
  70. [CheckStatus.MISSED_WINDOW]: 1,
  71. [CheckStatus.FAILURE]: 1,
  72. },
  73. ],
  74. ],
  75. },
  76. });
  77. render(<IssueUptimeCheckTimeline group={group} />, {organization});
  78. expect(await screen.findByTestId('check-in-placeholder')).not.toBeInTheDocument();
  79. const legend = screen.getByRole('caption');
  80. expect(
  81. within(legend).getByText(statusToText[CheckStatus.SUCCESS])
  82. ).toBeInTheDocument();
  83. expect(
  84. within(legend).getByText(statusToText[CheckStatus.MISSED_WINDOW])
  85. ).toBeInTheDocument();
  86. expect(
  87. within(legend).getByText(statusToText[CheckStatus.FAILURE])
  88. ).toBeInTheDocument();
  89. expect(screen.getByRole('figure')).toBeInTheDocument();
  90. const gridlineLabels = [
  91. 'Jan 1, 2025 11:00 AM UTC',
  92. '11:10 AM',
  93. '11:20 AM',
  94. '11:30 AM',
  95. '11:40 AM',
  96. '11:50 AM',
  97. ];
  98. gridlineLabels.forEach(label => {
  99. expect(screen.getByText(label)).toBeInTheDocument();
  100. });
  101. });
  102. it('hides missed status from legend if not present in data', async function () {
  103. MockApiClient.addMockResponse({
  104. url: `/organizations/${organization.slug}/uptime-stats/`,
  105. query: {
  106. projectUptimeSubscriptionId: [uptimeRuleId],
  107. },
  108. body: {
  109. [uptimeRuleId]: [
  110. [
  111. startTime.getTime() / 1000,
  112. {
  113. [CheckStatus.SUCCESS]: 1,
  114. [CheckStatus.FAILURE]: 1,
  115. },
  116. ],
  117. ],
  118. },
  119. });
  120. render(<IssueUptimeCheckTimeline group={group} />, {organization});
  121. expect(await screen.findByTestId('check-in-placeholder')).not.toBeInTheDocument();
  122. const legend = screen.getByRole('caption');
  123. expect(
  124. within(legend).getByText(statusToText[CheckStatus.SUCCESS])
  125. ).toBeInTheDocument();
  126. expect(
  127. within(legend).queryByText(statusToText[CheckStatus.MISSED_WINDOW])
  128. ).not.toBeInTheDocument();
  129. expect(
  130. within(legend).getByText(statusToText[CheckStatus.FAILURE])
  131. ).toBeInTheDocument();
  132. });
  133. });