From 9985eaaeb57a21fcc95ddd113406f3552915fc4b 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 --- packages/react/src/errorboundary.tsx | 24 +++++++++++++--------- packages/react/test/errorboundary.test.tsx | 17 ++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) 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)); }); }); });