From 378ec5ff011ff4fb47451becb6365a81c35a7c7b Mon Sep 17 00:00:00 2001 From: Sebastiaan ten Pas Date: Mon, 29 Jun 2020 16:05:19 +0100 Subject: [PATCH] feat(react): Expose eventId on React ErrorBoundary --- CHANGELOG.md | 1 + packages/react/src/errorboundary.tsx | 24 +++++++++++++--------- packages/react/test/errorboundary.test.tsx | 17 ++++++++------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1fc05cef6e..cb203f9addf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott - [tracing] fix: Add manual Location typing (#2700) +- [react] feat: Expose eventId on ErrorBoundary component ## 5.18.1 diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 4d50395025d4..ec05ad73dd43 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -8,6 +8,7 @@ export type FallbackRender = (fallback: { error: Error | null; componentStack: string | null; resetError(): void; + eventId: string | null; }) => React.ReactNode; export type ErrorBoundaryProps = { @@ -30,23 +31,25 @@ export type ErrorBoundaryProps = { fallback?: React.ReactNode | FallbackRender; // tslint:enable no-null-undefined-union /** Called with the error boundary encounters an error */ - onError?(error: Error, componentStack: string): void; + onError?(error: Error, componentStack: string, eventId: string): void; /** Called on componentDidMount() */ onMount?(): void; /** Called if resetError() is called from the fallback render props function */ - onReset?(error: Error | null, componentStack: string | null): void; + onReset?(error: Error | null, componentStack: string | null, eventId: string | null): void; /** Called on componentWillUnmount() */ - onUnmount?(error: Error | null, componentStack: string | null): void; + onUnmount?(error: Error | null, componentStack: string | null, eventId: string | null): void; }; type ErrorBoundaryState = { componentStack: string | null; error: Error | null; + eventId: string | null; }; const INITIAL_STATE = { componentStack: null, error: null, + eventId: null, }; /** @@ -60,7 +63,7 @@ class ErrorBoundary extends React.Component { const { onReset } = this.props; + const { error, componentStack, eventId } = this.state; if (onReset) { - onReset(this.state.error, this.state.componentStack); + onReset(error, componentStack, eventId); } this.setState(INITIAL_STATE); }; public render(): React.ReactNode { const { fallback } = this.props; - const { error, componentStack } = this.state; + const { error, componentStack, eventId } = this.state; if (error) { if (React.isValidElement(fallback)) { return fallback; } if (typeof fallback === 'function') { - return fallback({ error, componentStack, resetError: this.resetErrorBoundary }) as FallbackRender; + return fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId }) as FallbackRender; } // Fail gracefully if no fallback provided diff --git a/packages/react/test/errorboundary.test.tsx b/packages/react/test/errorboundary.test.tsx index 9e4e5de11344..e522841636e8 100644 --- a/packages/react/test/errorboundary.test.tsx +++ b/packages/react/test/errorboundary.test.tsx @@ -22,10 +22,10 @@ const TestApp: React.FC = ({ children, ...props }) => { return ( { + onReset={(...args) => { setError(false); if (props.onReset) { - props.onReset(err, stack); + props.onReset(...args); } }} > @@ -107,7 +107,7 @@ describe('ErrorBoundary', () => { expect(mockOnUnmount).toHaveBeenCalledTimes(0); unmount(); expect(mockOnUnmount).toHaveBeenCalledTimes(1); - expect(mockOnUnmount).toHaveBeenCalledWith(null, null); + expect(mockOnUnmount).toHaveBeenCalledWith(null, null, null); }); it('renders children correctly when there is no error', () => { @@ -140,12 +140,14 @@ describe('ErrorBoundary', () => { it('renders a render props component', async () => { let errorString = ''; let compStack = ''; + let eventIdString = ''; const { container } = render( { - if (error && componentStack) { + fallback={({ error, componentStack, eventId }) => { + if (error && componentStack && eventId) { errorString = error.toString(); compStack = componentStack; + eventIdString = eventId; } return
Fallback here
; }} @@ -167,6 +169,7 @@ describe('ErrorBoundary', () => { in Bam (created by TestApp) in ErrorBoundary (created by TestApp) in TestApp`); + expect(eventIdString).toBe(EVENT_ID); }); }); @@ -186,7 +189,7 @@ describe('ErrorBoundary', () => { fireEvent.click(btn); expect(mockOnError).toHaveBeenCalledTimes(1); - expect(mockOnError).toHaveBeenCalledWith(expect.any(Error), expect.any(String)); + expect(mockOnError).toHaveBeenCalledWith(expect.any(Error), expect.any(String), expect.any(String)); expect(mockCaptureException).toHaveBeenCalledTimes(1); expect(mockCaptureException).toHaveBeenCalledWith(expect.any(Error), { @@ -249,7 +252,7 @@ describe('ErrorBoundary', () => { fireEvent.click(reset); expect(mockOnReset).toHaveBeenCalledTimes(1); - expect(mockOnReset).toHaveBeenCalledWith(expect.any(Error), expect.any(String)); + expect(mockOnReset).toHaveBeenCalledWith(expect.any(Error), expect.any(String), expect.any(String)); }); }); });