From 2eb61e1adc36b6ddc9769a03163bd953135a26de Mon Sep 17 00:00:00 2001 From: arsam Date: Fri, 18 Sep 2026 23:14:02 +0330 Subject: [PATCH] Import source: cshare-app/src/components/ErrorBoundary Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality. --- cshare-app/src/components/ErrorBoundary.jsx | 79 +++++++++++++++++++ .../src/components/ErrorBoundary.test.jsx | 52 ++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 cshare-app/src/components/ErrorBoundary.jsx create mode 100644 cshare-app/src/components/ErrorBoundary.test.jsx diff --git a/cshare-app/src/components/ErrorBoundary.jsx b/cshare-app/src/components/ErrorBoundary.jsx new file mode 100644 index 0000000..449ce32 --- /dev/null +++ b/cshare-app/src/components/ErrorBoundary.jsx @@ -0,0 +1,79 @@ +import { Component } from 'react'; + +export class ErrorBoundary extends Component { + constructor(props) { + super(props); + this.state = { error: null }; + } + + static getDerivedStateFromError(error) { + return { error }; + } + + componentDidCatch(error, info) { + console.error('[ErrorBoundary]', error, info.componentStack); + } + + reset() { + this.setState({ error: null }); + } + + render() { + if (this.state.error) { + if (this.props.fallback) { + return this.props.fallback(this.state.error, () => this.reset()); + } + + return ( +
+
+
+ ⚠ +
+

+ Something went wrong +

+

+ {this.state.error?.message || 'An unexpected error occurred.'} +

+ +
+
+ ); + } + + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/cshare-app/src/components/ErrorBoundary.test.jsx b/cshare-app/src/components/ErrorBoundary.test.jsx new file mode 100644 index 0000000..12e2e2b --- /dev/null +++ b/cshare-app/src/components/ErrorBoundary.test.jsx @@ -0,0 +1,52 @@ +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import ErrorBoundary from './ErrorBoundary'; + +// Suppress console.error noise during error boundary tests +const originalError = console.error; +beforeEach(() => { console.error = vi.fn(); }); +afterEach(() => { console.error = originalError; }); + +function Bomb({ shouldThrow }) { + if (shouldThrow) throw new Error('Test error'); + return
OK
; +} + +describe('ErrorBoundary', () => { + it('renders children when no error', () => { + render( + + + , + ); + expect(screen.getByText('OK')).toBeInTheDocument(); + }); + + it('renders fallback UI on error', () => { + render( + + + , + ); + expect(screen.getByText('Something went wrong')).toBeInTheDocument(); + expect(screen.getByText(/Test error/)).toBeInTheDocument(); + }); + + it('renders custom fallback when provided', () => { + render( +
Custom: {err.message}
}> + +
, + ); + expect(screen.getByText('Custom: Test error')).toBeInTheDocument(); + }); + + it('shows a go-home button on default fallback', () => { + render( + + + , + ); + expect(screen.getByRole('button', { name: /go home/i })).toBeInTheDocument(); + }); +});