useQueryInsightsIssues.utils.test.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { safeSql } from '@supabase/pg-meta'
  2. import { describe, expect, it, vi } from 'vitest'
  3. import { hasIndexRecommendations } from '../../QueryPerformance/IndexAdvisor/index-advisor.utils'
  4. import type { QueryPerformanceRow } from '../../QueryPerformance/QueryPerformance.types'
  5. import { classifyQuery } from './useQueryInsightsIssues.utils'
  6. vi.mock('../../QueryPerformance/IndexAdvisor/index-advisor.utils', () => ({
  7. hasIndexRecommendations: vi.fn(),
  8. }))
  9. const baseRow: QueryPerformanceRow = {
  10. query: safeSql`SELECT * FROM users`,
  11. calls: 10,
  12. mean_time: 50,
  13. min_time: 10,
  14. max_time: 200,
  15. total_time: 500,
  16. prop_total_time: 5,
  17. rows_read: 100,
  18. cache_hit_rate: 1,
  19. rolname: 'postgres',
  20. application_name: 'test',
  21. index_advisor_result: null,
  22. _total_cache_hits: 0,
  23. _total_cache_misses: 0,
  24. }
  25. describe('classifyQuery', () => {
  26. it('returns error when index_advisor_result has errors', () => {
  27. const row = {
  28. ...baseRow,
  29. index_advisor_result: {
  30. errors: ['some error'],
  31. index_statements: [],
  32. startup_cost_before: 0,
  33. startup_cost_after: 0,
  34. total_cost_before: 0,
  35. total_cost_after: 0,
  36. },
  37. }
  38. const result = classifyQuery(row)
  39. expect(result.issueType).toBe('error')
  40. expect(result.hint).toBe('some error')
  41. })
  42. it('returns index when hasIndexRecommendations is true', () => {
  43. vi.mocked(hasIndexRecommendations).mockReturnValue(true)
  44. const row = {
  45. ...baseRow,
  46. index_advisor_result: {
  47. errors: [],
  48. index_statements: [safeSql`CREATE INDEX ...`],
  49. startup_cost_before: 0,
  50. startup_cost_after: 0,
  51. total_cost_before: 0,
  52. total_cost_after: 0,
  53. },
  54. }
  55. const result = classifyQuery(row)
  56. expect(result.issueType).toBe('index')
  57. expect(result.hint).toContain('Missing index')
  58. vi.mocked(hasIndexRecommendations).mockReset()
  59. })
  60. it('returns slow when mean_time exceeds threshold', () => {
  61. vi.mocked(hasIndexRecommendations).mockReturnValue(false)
  62. const row = { ...baseRow, mean_time: 300 }
  63. const result = classifyQuery(row)
  64. expect(result.issueType).toBe('slow')
  65. expect(result.hint).toBe('Abnormally slow query detected')
  66. vi.mocked(hasIndexRecommendations).mockReset()
  67. })
  68. it('returns null issue for healthy queries', () => {
  69. vi.mocked(hasIndexRecommendations).mockReturnValue(false)
  70. const row = { ...baseRow, mean_time: 50 }
  71. const result = classifyQuery(row)
  72. expect(result.issueType).toBeNull()
  73. expect(result.hint).toBe('')
  74. vi.mocked(hasIndexRecommendations).mockReset()
  75. })
  76. it('errors take priority over index recommendations', () => {
  77. vi.mocked(hasIndexRecommendations).mockReturnValue(true)
  78. const row = {
  79. ...baseRow,
  80. index_advisor_result: {
  81. errors: ['critical error'],
  82. index_statements: [safeSql`CREATE INDEX ...`],
  83. startup_cost_before: 0,
  84. startup_cost_after: 0,
  85. total_cost_before: 0,
  86. total_cost_after: 0,
  87. },
  88. }
  89. const result = classifyQuery(row)
  90. expect(result.issueType).toBe('error')
  91. vi.mocked(hasIndexRecommendations).mockReset()
  92. })
  93. })