diff --git a/frontend/src/components/LandingPage.tsx b/frontend/src/components/LandingPage.tsx index ed79de4a..4d8316b7 100644 --- a/frontend/src/components/LandingPage.tsx +++ b/frontend/src/components/LandingPage.tsx @@ -215,6 +215,13 @@ export const LandingPage: React.FC = ({ className }) => {

Platform Statistics

Unable to load statistics at this time. Please try again later.

+
}> diff --git a/frontend/src/components/__tests__/LandingPage.error-boundary.test.tsx b/frontend/src/components/__tests__/LandingPage.error-boundary.test.tsx index 0418ad5b..299c854a 100644 --- a/frontend/src/components/__tests__/LandingPage.error-boundary.test.tsx +++ b/frontend/src/components/__tests__/LandingPage.error-boundary.test.tsx @@ -38,6 +38,7 @@ describe('LandingPage with ErrorBoundary', () => { render(); expect(screen.getByText('Unable to load statistics at this time. Please try again later.')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /retry loading statistics/i })).toBeInTheDocument(); }); it('should display error message with role alert', () => { diff --git a/frontend/src/components/__tests__/Statistics.test.tsx b/frontend/src/components/__tests__/Statistics.test.tsx index f3b424da..100e976a 100644 --- a/frontend/src/components/__tests__/Statistics.test.tsx +++ b/frontend/src/components/__tests__/Statistics.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import { Statistics } from '../Statistics'; +import { ErrorBoundary } from '../ErrorBoundary'; import { api } from '../../lib/api/client'; // Mock the API @@ -86,4 +87,91 @@ describe('Statistics', () => { expect(screen.getByRole('region', { name: /platform statistics/i })).toBeInTheDocument(); }); -}); \ No newline at end of file +}); + +// Component that unconditionally throws to simulate a rendering exception in Statistics +const ThrowingStatistics: React.FC = () => { + throw new Error('Statistics rendering exception'); +}; + +describe('Statistics wrapped in ErrorBoundary', () => { + beforeEach(() => { + jest.clearAllMocks(); + // Suppress console.error for expected error boundary output + jest.spyOn(console, 'error').mockImplementation(() => {}); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('catches a rendering exception thrown inside Statistics and renders the fallback', () => { + const fallback = ( +
+

Platform Statistics

+
+

Unable to load statistics at this time. Please try again later.

+ +
+
+ ); + + render( + + + + ); + + // Fallback heading and message should be visible + expect(screen.getByRole('heading', { name: /platform statistics/i })).toBeInTheDocument(); + expect(screen.getByRole('alert')).toBeInTheDocument(); + expect(screen.getByText(/unable to load statistics at this time/i)).toBeInTheDocument(); + }); + + it('renders a retry button in the fallback when Statistics throws', () => { + const fallback = ( +
+

Platform Statistics

+
+

Unable to load statistics at this time. Please try again later.

+ +
+
+ ); + + render( + + + + ); + + expect(screen.getByRole('button', { name: /retry loading statistics/i })).toBeInTheDocument(); + }); + + it('does not render the Statistics content when an error is thrown', () => { + const fallback = ( +
+

Unable to load statistics at this time. Please try again later.

+ +
+ ); + + render( + + + + ); + + // Normal statistics content should not be present + expect(screen.queryByText('Total Markets')).not.toBeInTheDocument(); + expect(screen.queryByText('Total Volume')).not.toBeInTheDocument(); + expect(screen.queryByText('Active Users')).not.toBeInTheDocument(); + + // Fallback should be visible instead + expect(screen.getByRole('alert')).toBeInTheDocument(); + }); +});