LogsPreviewer.test.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import { screen, waitFor } from '@testing-library/react'
  2. import userEvent from '@testing-library/user-event'
  3. import dayjs from 'dayjs'
  4. import utc from 'dayjs/plugin/utc'
  5. import { beforeEach, describe, expect, test, vi } from 'vitest'
  6. import { LOGS_API_MOCKS } from './logs.mocks'
  7. import { LogsTableName } from '@/components/interfaces/Settings/Logs/Logs.constants'
  8. import {
  9. calculateBarClickTimeRange,
  10. LogsPreviewer,
  11. } from '@/components/interfaces/Settings/Logs/LogsPreviewer'
  12. import useLogsPreview from '@/hooks/analytics/useLogsPreview'
  13. import { customRender, customRenderHook } from '@/tests/lib/custom-render'
  14. import { addAPIMock } from '@/tests/lib/msw'
  15. vi.mock('@/components/interfaces/Settings/Logs/LogTable', () => ({
  16. LogTable: ({ data }: { data: any[] }) => (
  17. <div data-testid="log-table-mock">
  18. {data.map((row) => (
  19. <div key={row.id} data-testid="log-row">
  20. {row.event_message}
  21. </div>
  22. ))}
  23. </div>
  24. ),
  25. }))
  26. dayjs.extend(utc)
  27. vi.mock('common', async (importOriginal) => {
  28. const actual = await importOriginal()
  29. return {
  30. useParams: vi.fn().mockReturnValue({}),
  31. useIsLoggedIn: vi.fn(),
  32. isBrowser: false,
  33. LOCAL_STORAGE_KEYS: (actual as any).LOCAL_STORAGE_KEYS,
  34. ...(actual as any),
  35. }
  36. })
  37. vi.mock('@/lib/gotrue', async (importOriginal) => ({
  38. ...(await importOriginal()),
  39. auth: { onAuthStateChange: vi.fn() },
  40. }))
  41. beforeEach(() => {
  42. addAPIMock({
  43. method: 'get',
  44. path: '/platform/projects/:ref/analytics/endpoints/logs.all',
  45. response: LOGS_API_MOCKS,
  46. })
  47. })
  48. test('search loads with whatever is on the URL', async () => {
  49. customRender(
  50. <LogsPreviewer queryType="api" projectRef="default" tableName={LogsTableName.EDGE} />,
  51. {
  52. nuqs: {
  53. searchParams: {
  54. s: 'test-search-box-value',
  55. },
  56. },
  57. }
  58. )
  59. await waitFor(() => {
  60. expect(screen.getByRole('textbox')).toHaveValue('test-search-box-value')
  61. })
  62. await waitFor(() => {
  63. expect(screen.getByRole('textbox')).not.toHaveValue('WRONGVALUE!🪿')
  64. })
  65. })
  66. test('useLogsPreview returns data from MSW', async () => {
  67. const { result } = customRenderHook(() =>
  68. useLogsPreview({
  69. projectRef: 'default',
  70. table: LogsTableName.EDGE,
  71. })
  72. )
  73. await waitFor(() => {
  74. expect(result.current.isLoading).toBe(false)
  75. })
  76. await waitFor(() => {
  77. expect(result.current.logData.length).toBeGreaterThan(0)
  78. })
  79. expect(result.current.logData).toEqual(LOGS_API_MOCKS.result)
  80. })
  81. test('LogsPreviewer passes API data to LogTable', async () => {
  82. customRender(
  83. <LogsPreviewer queryType="api" projectRef="default" tableName={LogsTableName.EDGE} />
  84. )
  85. const firstLogEventMessage = LOGS_API_MOCKS.result[0].event_message
  86. await waitFor(() => {
  87. expect(screen.getAllByText(firstLogEventMessage)[0]).toBeInTheDocument()
  88. })
  89. })
  90. test('can toggle log event chart', async () => {
  91. customRender(
  92. <LogsPreviewer queryType="api" projectRef="default" tableName={LogsTableName.EDGE} />
  93. )
  94. expect(screen.getByRole('button', { name: /Chart/i })).toBeInTheDocument()
  95. await waitFor(() => {
  96. expect(screen.getByTestId('logs-bar-chart')).toBeInTheDocument()
  97. })
  98. await userEvent.click(screen.getByRole('button', { name: /Chart/i }))
  99. await waitFor(() => {
  100. expect(screen.queryByTestId('logs-bar-chart')).not.toBeInTheDocument()
  101. })
  102. })
  103. test('can click load older', async () => {
  104. customRender(
  105. <LogsPreviewer queryType="api" projectRef="default" tableName={LogsTableName.EDGE} />
  106. )
  107. const loadOlder = await waitFor(
  108. async () => await screen.findByRole('button', { name: /Load older/i }),
  109. { timeout: 10000 }
  110. )
  111. const handleClick = vi.fn()
  112. loadOlder.addEventListener('click', handleClick)
  113. await userEvent.click(loadOlder)
  114. expect(handleClick).toHaveBeenCalled()
  115. })
  116. describe('calculateBarClickTimeRange', () => {
  117. const clickedTime = '2024-01-15T12:30:00.000Z'
  118. test('uses 15-second range for time ranges less than 2 minutes', () => {
  119. const rangeStart = '2024-01-15T12:00:00.000Z'
  120. const rangeEnd = '2024-01-15T12:01:30.000Z' // 1.5 minutes
  121. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  122. expect(result.start).toBe('2024-01-15T12:29:52.500Z') // 7.5 seconds before
  123. expect(result.end).toBe('2024-01-15T12:30:07.500Z') // 7.5 seconds after
  124. })
  125. test('uses 2-minute range for time ranges between 2 minutes and 1 hour', () => {
  126. const rangeStart = '2024-01-15T12:00:00.000Z'
  127. const rangeEnd = '2024-01-15T12:30:00.000Z' // 30 minutes
  128. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  129. expect(result.start).toBe('2024-01-15T12:29:00.000Z') // 1 minute before
  130. expect(result.end).toBe('2024-01-15T12:31:00.000Z') // 1 minute after
  131. })
  132. test('uses 5-minute range for time ranges between 1 and 12 hours', () => {
  133. const rangeStart = '2024-01-15T10:00:00.000Z'
  134. const rangeEnd = '2024-01-15T14:00:00.000Z' // 4 hours
  135. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  136. expect(result.start).toBe('2024-01-15T12:27:30.000Z') // 2.5 minutes before
  137. expect(result.end).toBe('2024-01-15T12:32:30.000Z') // 2.5 minutes after
  138. })
  139. test('uses 1-hour range for time ranges 12 hours or more', () => {
  140. const rangeStart = '2024-01-15T00:00:00.000Z'
  141. const rangeEnd = '2024-01-15T24:00:00.000Z' // 24 hours
  142. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  143. expect(result.start).toBe('2024-01-15T12:00:00.000Z') // 30 minutes before
  144. expect(result.end).toBe('2024-01-15T13:00:00.000Z') // 30 minutes after
  145. })
  146. test('handles edge case of exactly 2 minutes range', () => {
  147. const rangeStart = '2024-01-15T12:00:00.000Z'
  148. const rangeEnd = '2024-01-15T12:02:00.000Z' // exactly 2 minutes
  149. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  150. expect(result.start).toBe('2024-01-15T12:29:00.000Z') // 1 minute before
  151. expect(result.end).toBe('2024-01-15T12:31:00.000Z') // 1 minute after
  152. })
  153. test('handles edge case of exactly 1 hour range', () => {
  154. const rangeStart = '2024-01-15T12:00:00.000Z'
  155. const rangeEnd = '2024-01-15T13:00:00.000Z' // exactly 1 hour
  156. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  157. expect(result.start).toBe('2024-01-15T12:27:30.000Z') // 2.5 minutes before
  158. expect(result.end).toBe('2024-01-15T12:32:30.000Z') // 2.5 minutes after
  159. })
  160. test('handles edge case of exactly 12 hours range', () => {
  161. const rangeStart = '2024-01-15T00:00:00.000Z'
  162. const rangeEnd = '2024-01-15T12:00:00.000Z' // exactly 12 hours
  163. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, clickedTime)
  164. expect(result.start).toBe('2024-01-15T12:00:00.000Z') // 30 minutes before
  165. expect(result.end).toBe('2024-01-15T13:00:00.000Z') // 30 minutes after
  166. })
  167. test('handles different clicked timestamps correctly', () => {
  168. const rangeStart = '2024-01-15T00:00:00.000Z'
  169. const rangeEnd = '2024-01-15T24:00:00.000Z' // 24 hours
  170. const differentClickedTime = '2024-01-15T06:15:30.000Z'
  171. const result = calculateBarClickTimeRange(rangeStart, rangeEnd, differentClickedTime)
  172. expect(result.start).toBe('2024-01-15T05:45:30.000Z') // 30 minutes before
  173. expect(result.end).toBe('2024-01-15T06:45:30.000Z') // 30 minutes after
  174. })
  175. })