| | import React from 'react'; |
| | import { render, screen, fireEvent } from '@testing-library/react'; |
| | import { ErrorDisplay } from '../ErrorDisplay'; |
| |
|
| | |
| | Object.defineProperty(window, 'matchMedia', { |
| | writable: true, |
| | value: jest.fn().mockImplementation((query) => ({ |
| | matches: false, |
| | media: query, |
| | onchange: null, |
| | addListener: jest.fn(), |
| | removeListener: jest.fn(), |
| | addEventListener: jest.fn(), |
| | removeEventListener: jest.fn(), |
| | dispatchEvent: jest.fn(), |
| | })), |
| | }); |
| |
|
| | |
| | const mockLocalize = jest.fn((key: string, options?: any) => { |
| | const translations: Record<string, string> = { |
| | com_agents_error_title: 'Something went wrong', |
| | com_agents_error_generic: 'We encountered an issue while loading the content.', |
| | com_agents_error_suggestion_generic: 'Please try refreshing the page or try again later.', |
| | com_agents_error_network_title: 'Connection Problem', |
| | com_agents_error_network_message: 'Unable to connect to the server.', |
| | com_agents_error_network_suggestion: 'Check your internet connection and try again.', |
| | com_agents_error_not_found_title: 'Not Found', |
| | com_agents_error_not_found_message: 'The requested content could not be found.', |
| | com_agents_error_not_found_suggestion: |
| | 'Try browsing other options or go back to the marketplace.', |
| | com_agents_error_invalid_request: 'Invalid Request', |
| | com_agents_error_bad_request_message: 'The request could not be processed.', |
| | com_agents_error_bad_request_suggestion: 'Please check your input and try again.', |
| | com_agents_error_server_title: 'Server Error', |
| | com_agents_error_server_message: 'The server is temporarily unavailable.', |
| | com_agents_error_server_suggestion: 'Please try again in a few moments.', |
| | com_agents_error_search_title: 'Search Error', |
| | com_agents_error_category_title: 'Category Error', |
| | com_agents_error_timeout_title: 'Connection Timeout', |
| | com_agents_error_timeout_message: 'The request took too long to complete.', |
| | com_agents_error_timeout_suggestion: 'Please check your internet connection and try again.', |
| | com_agents_search_no_results: `No agents found for "${options?.query}"`, |
| | com_agents_category_empty: `No agents found in the ${options?.category} category`, |
| | com_agents_error_retry: 'Try Again', |
| | }; |
| |
|
| | return translations[key] || key; |
| | }); |
| |
|
| | jest.mock('~/hooks/useLocalize', () => () => mockLocalize); |
| |
|
| | describe('ErrorDisplay', () => { |
| | beforeEach(() => { |
| | mockLocalize.mockClear(); |
| | }); |
| |
|
| | describe('Backend error responses', () => { |
| | it('displays user-friendly message from backend response', () => { |
| | const error = { |
| | response: { |
| | data: { |
| | userMessage: 'Unable to load agents. Please try refreshing the page.', |
| | suggestion: 'Try refreshing the page or check your network connection', |
| | }, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.getByText('Something went wrong')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('Unable to load agents. Please try refreshing the page.'), |
| | ).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('💡 Try refreshing the page or check your network connection'), |
| | ).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles search context with backend response', () => { |
| | const error = { |
| | response: { |
| | data: { |
| | userMessage: 'Search is temporarily unavailable. Please try again.', |
| | suggestion: 'Try a different search term or check your network connection', |
| | }, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} context={{ searchQuery: 'test query' }} />); |
| |
|
| | expect(screen.getByText('Search Error')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('Search is temporarily unavailable. Please try again.'), |
| | ).toBeInTheDocument(); |
| | }); |
| | }); |
| |
|
| | describe('Network errors', () => { |
| | it('displays network error message', () => { |
| | const error = { |
| | code: 'NETWORK_ERROR', |
| | message: 'Network Error', |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.getByText('Connection Problem')).toBeInTheDocument(); |
| | expect(screen.getByText('Unable to connect to the server.')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('💡 Check your internet connection and try again.'), |
| | ).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles timeout errors', () => { |
| | const error = { |
| | code: 'ECONNABORTED', |
| | message: 'timeout of 5000ms exceeded', |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_timeout_title'); |
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_timeout_message'); |
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_timeout_suggestion'); |
| | }); |
| | }); |
| |
|
| | describe('HTTP status codes', () => { |
| | it('handles 404 errors with search context', () => { |
| | const error = { |
| | response: { |
| | status: 404, |
| | data: {}, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} context={{ searchQuery: 'nonexistent agent' }} />); |
| |
|
| | expect(screen.getByText('Not Found')).toBeInTheDocument(); |
| | expect(screen.getByText('No agents found for "nonexistent agent"')).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles 404 errors with category context', () => { |
| | const error = { |
| | response: { |
| | status: 404, |
| | data: {}, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} context={{ category: 'productivity' }} />); |
| |
|
| | expect(screen.getByText('Not Found')).toBeInTheDocument(); |
| | expect(screen.getByText('No agents found in the productivity category')).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles 400 bad request errors', () => { |
| | const error = { |
| | response: { |
| | status: 400, |
| | data: { |
| | error: 'Search query is required', |
| | userMessage: 'Please enter a search term to find agents', |
| | suggestion: 'Enter a search term to find agents by name or description', |
| | }, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.getByText('Invalid Request')).toBeInTheDocument(); |
| | expect(screen.getByText('Please enter a search term to find agents')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('💡 Enter a search term to find agents by name or description'), |
| | ).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles 500 server errors', () => { |
| | const error = { |
| | response: { |
| | status: 500, |
| | data: {}, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.getByText('Server Error')).toBeInTheDocument(); |
| | expect(screen.getByText('The server is temporarily unavailable.')).toBeInTheDocument(); |
| | expect(screen.getByText('💡 Please try again in a few moments.')).toBeInTheDocument(); |
| | }); |
| | }); |
| |
|
| | describe('Retry functionality', () => { |
| | it('displays retry button when onRetry is provided', () => { |
| | const mockRetry = jest.fn(); |
| | const error = { |
| | response: { |
| | data: { |
| | userMessage: 'Unable to load agents. Please try refreshing the page.', |
| | }, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} onRetry={mockRetry} />); |
| |
|
| | const retryButton = screen.getByText('Try Again'); |
| | expect(retryButton).toBeInTheDocument(); |
| |
|
| | fireEvent.click(retryButton); |
| | expect(mockRetry).toHaveBeenCalledTimes(1); |
| | }); |
| |
|
| | it('does not display retry button when onRetry is not provided', () => { |
| | const error = { |
| | response: { |
| | data: { |
| | userMessage: 'Unable to load agents. Please try refreshing the page.', |
| | }, |
| | }, |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.queryByText('Try Again')).not.toBeInTheDocument(); |
| | }); |
| | }); |
| |
|
| | describe('Context-aware titles', () => { |
| | it('shows search error title for search context', () => { |
| | const error = { message: 'Some error' }; |
| |
|
| | render(<ErrorDisplay error={error} context={{ searchQuery: 'test' }} />); |
| |
|
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_search_title'); |
| | }); |
| |
|
| | it('shows category error title for category context', () => { |
| | const error = { message: 'Some error' }; |
| |
|
| | render(<ErrorDisplay error={error} context={{ category: 'productivity' }} />); |
| |
|
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_category_title'); |
| | }); |
| |
|
| | it('shows generic error title when no context', () => { |
| | const error = { message: 'Some error' }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(mockLocalize).toHaveBeenCalledWith('com_agents_error_title'); |
| | }); |
| | }); |
| |
|
| | describe('Fallback error handling', () => { |
| | it('handles unknown errors gracefully', () => { |
| | const error = { |
| | message: 'Unknown error occurred', |
| | }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | expect(screen.getByText('Something went wrong')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('We encountered an issue while loading the content.'), |
| | ).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('💡 Please try refreshing the page or try again later.'), |
| | ).toBeInTheDocument(); |
| | }); |
| |
|
| | it('handles null/undefined errors', () => { |
| | render(<ErrorDisplay error={null} />); |
| |
|
| | expect(screen.getByText('Something went wrong')).toBeInTheDocument(); |
| | expect( |
| | screen.getByText('We encountered an issue while loading the content.'), |
| | ).toBeInTheDocument(); |
| | }); |
| | }); |
| |
|
| | describe('Accessibility', () => { |
| | it('renders error icon with proper accessibility', () => { |
| | const error = { message: 'Test error' }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | const errorIcon = screen.getByRole('img', { hidden: true }); |
| | expect(errorIcon).toBeInTheDocument(); |
| | }); |
| |
|
| | it('has proper heading structure', () => { |
| | const error = { message: 'Test error' }; |
| |
|
| | render(<ErrorDisplay error={error} />); |
| |
|
| | const heading = screen.getByRole('heading', { level: 3 }); |
| | expect(heading).toHaveTextContent('Something went wrong'); |
| | }); |
| | }); |
| | }); |
| |
|