ErrorMatcher.test.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { render, screen } from '@testing-library/react'
  2. import { beforeEach, describe, expect, it, vi } from 'vitest'
  3. import { ErrorMatcher } from './ErrorMatcher'
  4. import { ConnectionTimeoutError } from '@/types/api-errors'
  5. import { ResponseError } from '@/types/base'
  6. vi.mock('@/lib/telemetry/track', () => ({ useTrack: () => vi.fn() }))
  7. vi.mock('@/state/ai-assistant-state', () => ({
  8. useAiAssistantStateSnapshot: () => ({ newChat: vi.fn() }),
  9. }))
  10. vi.mock('@/state/sidebar-manager-state', () => ({
  11. useSidebarManagerSnapshot: () => ({ openSidebar: vi.fn() }),
  12. }))
  13. vi.mock('@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider', () => ({
  14. SIDEBAR_KEYS: { AI_ASSISTANT: 'ai-assistant' },
  15. }))
  16. vi.mock('./RestartProjectDialog', () => ({
  17. RestartProjectDialog: () => null,
  18. }))
  19. describe('ErrorMatcher', () => {
  20. beforeEach(() => vi.clearAllMocks())
  21. it('renders the provided title and error message', () => {
  22. render(
  23. <ErrorMatcher
  24. title="Failed to load tables"
  25. error="ERROR: FAILED TO RUN SQL QUERY: CONNECTION TERMINATED DUE TO CONNECTION TIMEOUT."
  26. supportFormParams={{}}
  27. />
  28. )
  29. expect(screen.getByText('Failed to load tables')).toBeInTheDocument()
  30. expect(
  31. screen.getByText(
  32. 'ERROR: FAILED TO RUN SQL QUERY: CONNECTION TERMINATED DUE TO CONNECTION TIMEOUT.'
  33. )
  34. ).toBeInTheDocument()
  35. })
  36. it('renders troubleshooting steps for classified errors', () => {
  37. const error = new ConnectionTimeoutError('CONNECTION TERMINATED DUE TO CONNECTION TIMEOUT')
  38. render(<ErrorMatcher title="Failed to load tables" error={error} supportFormParams={{}} />)
  39. expect(screen.getByText('Try restarting your project')).toBeInTheDocument()
  40. expect(screen.getByText('Try our troubleshooting guide')).toBeInTheDocument()
  41. expect(screen.getByText('Debug with AI')).toBeInTheDocument()
  42. })
  43. it('renders fallback for plain ResponseError (not a classified subclass)', () => {
  44. render(
  45. <ErrorMatcher
  46. title="Failed to load tables"
  47. error={new ResponseError('CONNECTION TERMINATED DUE TO CONNECTION TIMEOUT')}
  48. supportFormParams={{}}
  49. />
  50. )
  51. expect(screen.getByText('Failed to load tables')).toBeInTheDocument()
  52. expect(screen.queryByText('Try restarting your project')).not.toBeInTheDocument()
  53. })
  54. it('renders fallback with provided title for unmatched errors', () => {
  55. render(
  56. <ErrorMatcher title="Failed to load tables" error="UNKNOWN ERROR" supportFormParams={{}} />
  57. )
  58. expect(screen.getByText('Failed to load tables')).toBeInTheDocument()
  59. expect(screen.getByText('UNKNOWN ERROR')).toBeInTheDocument()
  60. })
  61. it('accepts error as object with message property', () => {
  62. render(
  63. <ErrorMatcher
  64. title="Failed to load tables"
  65. error={{ message: 'UNKNOWN ERROR' }}
  66. supportFormParams={{}}
  67. />
  68. )
  69. expect(screen.getByText('UNKNOWN ERROR')).toBeInTheDocument()
  70. })
  71. it('builds support link with projectRef param', () => {
  72. render(
  73. <ErrorMatcher
  74. title="Failed to load tables"
  75. error="UNKNOWN ERROR"
  76. supportFormParams={{ projectRef: 'my-project' }}
  77. />
  78. )
  79. expect(screen.getByRole('link', { name: /contact support/i })).toHaveAttribute(
  80. 'href',
  81. '/support/new?projectRef=my-project'
  82. )
  83. })
  84. it('builds support link with no params when supportFormParams is omitted', () => {
  85. render(<ErrorMatcher title="Failed to load tables" error="UNKNOWN ERROR" />)
  86. expect(screen.getByRole('link', { name: /contact support/i })).toHaveAttribute(
  87. 'href',
  88. '/support/new'
  89. )
  90. })
  91. })