From 0add2110723fbcd13a30edeebd0a6a5d7bc29493 Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Tue, 28 Jun 2022 17:42:33 -0500 Subject: [PATCH 1/6] Call WP action hook that allow other consuming code to set a custom additional error reporting logic for Error Boundaries --- .../customize-widgets/src/components/error-boundary/index.js | 3 +++ .../edit-navigation/src/components/error-boundary/index.js | 3 +++ packages/edit-site/src/components/error-boundary/index.js | 5 +++++ packages/edit-widgets/src/components/error-boundary/index.js | 3 +++ packages/editor/src/components/error-boundary/index.js | 3 +++ 5 files changed, 17 insertions(+) diff --git a/packages/customize-widgets/src/components/error-boundary/index.js b/packages/customize-widgets/src/components/error-boundary/index.js index 17047e7f546ea0..d2a057ec254ae2 100644 --- a/packages/customize-widgets/src/components/error-boundary/index.js +++ b/packages/customize-widgets/src/components/error-boundary/index.js @@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { Warning } from '@wordpress/block-editor'; import { useCopyToClipboard } from '@wordpress/compose'; +import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); @@ -26,6 +27,8 @@ export default class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); + + doAction( 'gb.reportErrorBoundaryException', error ); } render() { diff --git a/packages/edit-navigation/src/components/error-boundary/index.js b/packages/edit-navigation/src/components/error-boundary/index.js index bea03d909c380d..75c253161f8536 100644 --- a/packages/edit-navigation/src/components/error-boundary/index.js +++ b/packages/edit-navigation/src/components/error-boundary/index.js @@ -5,6 +5,7 @@ import { Component } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { Warning } from '@wordpress/block-editor'; +import { doAction } from '@wordpress/hooks'; class ErrorBoundary extends Component { constructor() { @@ -19,6 +20,8 @@ class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); + + doAction( 'gb.reportErrorBoundaryException', error ); } reboot() { diff --git a/packages/edit-site/src/components/error-boundary/index.js b/packages/edit-site/src/components/error-boundary/index.js index 35387fe5399c1b..82c28452516b2a 100644 --- a/packages/edit-site/src/components/error-boundary/index.js +++ b/packages/edit-site/src/components/error-boundary/index.js @@ -3,6 +3,7 @@ */ import { Component } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; +import { doAction } from '@wordpress/hooks'; /** * Internal dependencies @@ -20,6 +21,10 @@ export default class ErrorBoundary extends Component { }; } + componentDidCatch( error ) { + doAction( 'gb.reportErrorBoundaryException', error ); + } + static getDerivedStateFromError( error ) { return { error }; } diff --git a/packages/edit-widgets/src/components/error-boundary/index.js b/packages/edit-widgets/src/components/error-boundary/index.js index cf2098a30844d9..1399a85cd9cd6e 100644 --- a/packages/edit-widgets/src/components/error-boundary/index.js +++ b/packages/edit-widgets/src/components/error-boundary/index.js @@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { Warning } from '@wordpress/block-editor'; import { useCopyToClipboard } from '@wordpress/compose'; +import { doAction } from '@wordpress/hooks'; function CopyButton( { text, children } ) { const ref = useCopyToClipboard( text ); @@ -29,6 +30,8 @@ export default class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); + + doAction( 'gb.reportErrorBoundaryException', error ); } reboot() { diff --git a/packages/editor/src/components/error-boundary/index.js b/packages/editor/src/components/error-boundary/index.js index c7d0824a3dee21..85bd6abbacb0a2 100644 --- a/packages/editor/src/components/error-boundary/index.js +++ b/packages/editor/src/components/error-boundary/index.js @@ -7,6 +7,7 @@ import { Button } from '@wordpress/components'; import { select } from '@wordpress/data'; import { Warning } from '@wordpress/block-editor'; import { useCopyToClipboard } from '@wordpress/compose'; +import { doAction } from '@wordpress/hooks'; /** * Internal dependencies @@ -36,6 +37,8 @@ class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); + + doAction( 'gb.reportErrorBoundaryException', error ); } reboot() { From f8e14dcf5c26748fd432920009fc032bfbd8ee4f Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Fri, 1 Jul 2022 18:29:24 -0500 Subject: [PATCH 2/6] Remove doAction from edit navigation error boundary Separate navigation editor screen development is on hold. --- .../edit-navigation/src/components/error-boundary/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/edit-navigation/src/components/error-boundary/index.js b/packages/edit-navigation/src/components/error-boundary/index.js index 75c253161f8536..bea03d909c380d 100644 --- a/packages/edit-navigation/src/components/error-boundary/index.js +++ b/packages/edit-navigation/src/components/error-boundary/index.js @@ -5,7 +5,6 @@ import { Component } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { Warning } from '@wordpress/block-editor'; -import { doAction } from '@wordpress/hooks'; class ErrorBoundary extends Component { constructor() { @@ -20,8 +19,6 @@ class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); - - doAction( 'gb.reportErrorBoundaryException', error ); } reboot() { From ee5398a2f890f609b846ee0551ccdbb343fbb7ed Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Fri, 8 Jul 2022 16:22:12 -0500 Subject: [PATCH 3/6] Rename action --- .../customize-widgets/src/components/error-boundary/index.js | 2 +- packages/edit-site/src/components/error-boundary/index.js | 2 +- packages/edit-widgets/src/components/error-boundary/index.js | 2 +- packages/editor/src/components/error-boundary/index.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/customize-widgets/src/components/error-boundary/index.js b/packages/customize-widgets/src/components/error-boundary/index.js index d2a057ec254ae2..d1aece49b91736 100644 --- a/packages/customize-widgets/src/components/error-boundary/index.js +++ b/packages/customize-widgets/src/components/error-boundary/index.js @@ -28,7 +28,7 @@ export default class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); - doAction( 'gb.reportErrorBoundaryException', error ); + doAction( 'editor.ErrorBoundary.errorLogged', error ); } render() { diff --git a/packages/edit-site/src/components/error-boundary/index.js b/packages/edit-site/src/components/error-boundary/index.js index 82c28452516b2a..9e07afafd04a4e 100644 --- a/packages/edit-site/src/components/error-boundary/index.js +++ b/packages/edit-site/src/components/error-boundary/index.js @@ -22,7 +22,7 @@ export default class ErrorBoundary extends Component { } componentDidCatch( error ) { - doAction( 'gb.reportErrorBoundaryException', error ); + doAction( 'editor.ErrorBoundary.errorLogged', error ); } static getDerivedStateFromError( error ) { diff --git a/packages/edit-widgets/src/components/error-boundary/index.js b/packages/edit-widgets/src/components/error-boundary/index.js index 1399a85cd9cd6e..8b941630b347c0 100644 --- a/packages/edit-widgets/src/components/error-boundary/index.js +++ b/packages/edit-widgets/src/components/error-boundary/index.js @@ -31,7 +31,7 @@ export default class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); - doAction( 'gb.reportErrorBoundaryException', error ); + doAction( 'editor.ErrorBoundary.errorLogged', error ); } reboot() { diff --git a/packages/editor/src/components/error-boundary/index.js b/packages/editor/src/components/error-boundary/index.js index 85bd6abbacb0a2..72e6a7680421f3 100644 --- a/packages/editor/src/components/error-boundary/index.js +++ b/packages/editor/src/components/error-boundary/index.js @@ -38,7 +38,7 @@ class ErrorBoundary extends Component { componentDidCatch( error ) { this.setState( { error } ); - doAction( 'gb.reportErrorBoundaryException', error ); + doAction( 'editor.ErrorBoundary.errorLogged', error ); } reboot() { From 32671b5db224d1568d5225d099992980e1d5111f Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Fri, 8 Jul 2022 17:34:49 -0500 Subject: [PATCH 4/6] Add unit tests --- .../src/components/test/error-boundary.js | 38 +++++++++++++++++++ .../src/components/test/error-boundary.js | 38 +++++++++++++++++++ .../src/components/test/error-boundary.js | 38 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 packages/customize-widgets/src/components/test/error-boundary.js create mode 100644 packages/edit-site/src/components/test/error-boundary.js create mode 100644 packages/edit-widgets/src/components/test/error-boundary.js diff --git a/packages/customize-widgets/src/components/test/error-boundary.js b/packages/customize-widgets/src/components/test/error-boundary.js new file mode 100644 index 00000000000000..7b9977e10f1315 --- /dev/null +++ b/packages/customize-widgets/src/components/test/error-boundary.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import * as wpHooks from '@wordpress/hooks'; +/** + * Internal dependencies + */ +import ErrorBoundary from '../error-boundary'; +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + +const theError = new Error( 'Kaboom' ); + +const ChildComponent = () => { + throw theError; +}; + +describe( 'Error Boundary', () => { + describe( 'when error is thrown from a Child component', () => { + it( 'calls the `editor.ErrorBoundary.errorLogged` hook action with the error object', () => { + const doAction = jest.spyOn( wpHooks, 'doAction' ); + + render( + + + + ); + + expect( doAction ).toHaveBeenCalledWith( + 'editor.ErrorBoundary.errorLogged', + theError + ); + expect( console ).toHaveErrored(); + } ); + } ); +} ); diff --git a/packages/edit-site/src/components/test/error-boundary.js b/packages/edit-site/src/components/test/error-boundary.js new file mode 100644 index 00000000000000..7b9977e10f1315 --- /dev/null +++ b/packages/edit-site/src/components/test/error-boundary.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import * as wpHooks from '@wordpress/hooks'; +/** + * Internal dependencies + */ +import ErrorBoundary from '../error-boundary'; +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + +const theError = new Error( 'Kaboom' ); + +const ChildComponent = () => { + throw theError; +}; + +describe( 'Error Boundary', () => { + describe( 'when error is thrown from a Child component', () => { + it( 'calls the `editor.ErrorBoundary.errorLogged` hook action with the error object', () => { + const doAction = jest.spyOn( wpHooks, 'doAction' ); + + render( + + + + ); + + expect( doAction ).toHaveBeenCalledWith( + 'editor.ErrorBoundary.errorLogged', + theError + ); + expect( console ).toHaveErrored(); + } ); + } ); +} ); diff --git a/packages/edit-widgets/src/components/test/error-boundary.js b/packages/edit-widgets/src/components/test/error-boundary.js new file mode 100644 index 00000000000000..7b9977e10f1315 --- /dev/null +++ b/packages/edit-widgets/src/components/test/error-boundary.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import * as wpHooks from '@wordpress/hooks'; +/** + * Internal dependencies + */ +import ErrorBoundary from '../error-boundary'; +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + +const theError = new Error( 'Kaboom' ); + +const ChildComponent = () => { + throw theError; +}; + +describe( 'Error Boundary', () => { + describe( 'when error is thrown from a Child component', () => { + it( 'calls the `editor.ErrorBoundary.errorLogged` hook action with the error object', () => { + const doAction = jest.spyOn( wpHooks, 'doAction' ); + + render( + + + + ); + + expect( doAction ).toHaveBeenCalledWith( + 'editor.ErrorBoundary.errorLogged', + theError + ); + expect( console ).toHaveErrored(); + } ); + } ); +} ); From 6159e86627813605759dd684def8376060ec2ec8 Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Fri, 8 Jul 2022 17:53:46 -0500 Subject: [PATCH 5/6] Document the new action --- .../actions/editor-actions.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/reference-guides/actions/editor-actions.md diff --git a/docs/reference-guides/actions/editor-actions.md b/docs/reference-guides/actions/editor-actions.md new file mode 100644 index 00000000000000..2bf33f9a07a8a1 --- /dev/null +++ b/docs/reference-guides/actions/editor-actions.md @@ -0,0 +1,24 @@ +# Editor Actions + +To help you hook into the editor lifecycle and extend it, the following Actions are exposed: + +### Error Boundaries + +#### `editor.ErrorBoundary.errorLogged` + +Allows you to hook into the editor Error Boundaries' `componentDidCatch` and gives you access to the error object. + +You can use If you want to get hold of the error object that's handled by the boundaries, i.e to send them to an external error tracking tool. + +_Example_: + +```js +addAction( + 'editor.ErrorBoundary.errorLogged', + 'mu-plugin/error-capture-setup', + ( error ) => { + // error is the exception's error object + ErrorCaptureTool.captureError( error ); + } +); +``` From 8f2a522f86fb3144657afc278775759528aa9879 Mon Sep 17 00:00:00 2001 From: Marcelo Serpa <81248+fullofcaffeine@users.noreply.github.com> Date: Mon, 11 Jul 2022 13:29:45 -0500 Subject: [PATCH 6/6] Update editor-actions.md --- docs/reference-guides/actions/editor-actions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-guides/actions/editor-actions.md b/docs/reference-guides/actions/editor-actions.md index 2bf33f9a07a8a1..d5e37744036ee2 100644 --- a/docs/reference-guides/actions/editor-actions.md +++ b/docs/reference-guides/actions/editor-actions.md @@ -8,7 +8,7 @@ To help you hook into the editor lifecycle and extend it, the following Actions Allows you to hook into the editor Error Boundaries' `componentDidCatch` and gives you access to the error object. -You can use If you want to get hold of the error object that's handled by the boundaries, i.e to send them to an external error tracking tool. +You can use if you want to get hold of the error object that's handled by the boundaries, i.e to send them to an external error tracking tool. _Example_: