From 44bd85a5bb2faeed3e137d068f45329db47c30be Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 17 Nov 2017 18:26:07 -0800 Subject: [PATCH] Wrap container components in render protection --- src/core/plugins/view/root-injects.js | 2 +- test/core/system/system.js | 110 ++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/core/plugins/view/root-injects.js b/src/core/plugins/view/root-injects.js index 04d0131a..d977400d 100644 --- a/src/core/plugins/view/root-injects.js +++ b/src/core/plugins/view/root-injects.js @@ -120,5 +120,5 @@ export const getComponent = (getSystem, getStore, getComponents, componentName, return makeContainer(getSystem, component, getStore()) // container == truthy - return makeContainer(getSystem, component) + return makeContainer(getSystem, wrapRender(component)) } diff --git a/test/core/system/system.js b/test/core/system/system.js index 3abd02d9..073390fa 100644 --- a/test/core/system/system.js +++ b/test/core/system/system.js @@ -571,6 +571,116 @@ describe("bound system", function(){ // Then expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props") }) + + it("should catch errors thrown inside of React Component Class render methods", function() { + // Given + // eslint-disable-next-line react/require-render-return + class BrokenComponent extends React.Component { + render() { + throw new Error("This component is broken") + } + } + const system = new System({ + plugins: [ + ViewPlugin, + { + components: { + BrokenComponent + } + } + ] + }) + + // When + var Component = system.getSystem().getComponent("BrokenComponent") + const renderedComponent = render() + + // Then + expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.") + }) + + it("should catch errors thrown inside of pure component render methods", function() { + // Given + // eslint-disable-next-line react/require-render-return + class BrokenComponent extends PureComponent { + render() { + throw new Error("This component is broken") + } + } + + const system = new System({ + plugins: [ + ViewPlugin, + { + components: { + BrokenComponent + } + } + ] + }) + + // When + var Component = system.getSystem().getComponent("BrokenComponent") + const renderedComponent = render() + + // Then + expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.") + }) + + it("should catch errors thrown inside of stateless component functions", function() { + // Given + // eslint-disable-next-line react/require-render-return + let BrokenComponent = function BrokenComponent() { throw new Error("This component is broken") } + const system = new System({ + plugins: [ + ViewPlugin, + { + components: { + BrokenComponent + } + } + ] + }) + + // When + var Component = system.getSystem().getComponent("BrokenComponent") + const renderedComponent = render() + + // Then + expect(renderedComponent.text().startsWith("😱 Could not render")).toEqual(true) + }) + + it("should catch errors thrown inside of container components", function() { + // Given + // eslint-disable-next-line react/require-render-return + class BrokenComponent extends React.Component { + render() { + throw new Error("This component is broken") + } + } + + const system = new System({ + plugins: [ + ViewPlugin, + { + components: { + BrokenComponent + } + } + ] + }) + + // When + var Component = system.getSystem().getComponent("BrokenComponent", true) + const renderedComponent = render( + + + + ) + + // Then + expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.") + }) }) })