feat(error-handling): introduce unified and configurable error handling (#7761)
Refs #7778
This commit is contained in:
@@ -179,7 +179,7 @@ describe("auth plugin - actions", () => {
|
||||
|
||||
describe("tokenRequest", function () {
|
||||
it("should send the code verifier when set", () => {
|
||||
const testCodeVerifierForAuthorizationCodeFlows = (flowAction) => {
|
||||
const testCodeVerifierForAuthorizationCodeFlows = (flowAction) => {
|
||||
const data = {
|
||||
auth: {
|
||||
schema: {
|
||||
|
||||
253
test/unit/core/plugins/safe-render/index.jsx
Normal file
253
test/unit/core/plugins/safe-render/index.jsx
Normal file
@@ -0,0 +1,253 @@
|
||||
import React from "react"
|
||||
import { mount } from "enzyme"
|
||||
import sinon from "sinon"
|
||||
import { Provider } from "react-redux"
|
||||
import noop from "lodash/noop"
|
||||
|
||||
import System from "core/system"
|
||||
import ViewPlugin from "core/plugins/view"
|
||||
import SafeRenderPlugin from "core/plugins/safe-render"
|
||||
|
||||
describe("safe-render", function() {
|
||||
const DisableComponentDidCatchPlugin = () => ({
|
||||
fn: {
|
||||
componentDidCatch: noop,
|
||||
}
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of React Component class render method", function() {
|
||||
class BrokenComponent extends React.Component {
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<SafeBrokenComponent />)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of PureComponent class render method", function() {
|
||||
class BrokenComponent extends React.PureComponent {
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<SafeBrokenComponent />)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of function component", function() {
|
||||
const BrokenComponent = () => null
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<SafeBrokenComponent />)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of container created from React Component class", function() {
|
||||
class BrokenComponent extends React.Component {
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent", true)
|
||||
const wrapper = mount(
|
||||
<Provider store={system.getStore()}>
|
||||
<SafeBrokenComponent />
|
||||
</Provider>
|
||||
)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of container created from function component", function() {
|
||||
const BrokenComponent = () => null
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent", true)
|
||||
const wrapper = mount(
|
||||
<Provider store={system.getStore()}>
|
||||
<SafeBrokenComponent />
|
||||
</Provider>
|
||||
)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should render custom Fallback component", function() {
|
||||
const BrokenComponent = () => null
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
const FallbackPlugin = () => ({
|
||||
components: {
|
||||
Fallback: () => "fallback component",
|
||||
},
|
||||
})
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
FallbackPlugin,
|
||||
DisableComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<SafeBrokenComponent />)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(wrapper.text()).toEqual("fallback component")
|
||||
})
|
||||
|
||||
it("should call custom componentDidCatch hook", function() {
|
||||
const BrokenComponent = () => null
|
||||
const componentDidCatch = sinon.spy()
|
||||
|
||||
const BrokenComponentPlugin = () => {
|
||||
return {
|
||||
components: {
|
||||
BrokenComponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
const ComponentDidCatchPlugin = () => ({
|
||||
fn: {
|
||||
componentDidCatch,
|
||||
},
|
||||
})
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
BrokenComponentPlugin,
|
||||
SafeRenderPlugin({
|
||||
fullOverride: true,
|
||||
componentList: ["BrokenComponent"],
|
||||
}),
|
||||
ComponentDidCatchPlugin,
|
||||
]
|
||||
})
|
||||
|
||||
const SafeBrokenComponent = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<SafeBrokenComponent />)
|
||||
wrapper.find(BrokenComponent).simulateError(new Error("error"))
|
||||
|
||||
expect(componentDidCatch.calledOnce).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -911,142 +911,5 @@ describe("bound system", function(){
|
||||
|
||||
expect(system.getSystem().throwSelectors.func).not.toThrow()
|
||||
})
|
||||
|
||||
describe("components", function() {
|
||||
it("should catch errors thrown inside of React Component Class render methods", function() {
|
||||
// Given
|
||||
class BrokenComponent extends React.Component {
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
let Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const renderedComponent = render(<Component />)
|
||||
|
||||
// Then
|
||||
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of pure component", function() {
|
||||
// Given
|
||||
class BrokenComponent extends PureComponent {
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
let Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<Component />)
|
||||
|
||||
// Then
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of stateless component function", function() {
|
||||
// Given
|
||||
// eslint-disable-next-line react/require-render-return
|
||||
const BrokenComponent = () => { throw new Error("This component is broken") }
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
const Component = system.getSystem().getComponent("BrokenComponent")
|
||||
const wrapper = mount(<Component />)
|
||||
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of container created from class component", function() {
|
||||
// Given
|
||||
class BrokenComponent extends React.Component {
|
||||
render() {
|
||||
throw new Error("This component is broken")
|
||||
}
|
||||
}
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
const Component = system.getSystem().getComponent("BrokenComponent", true)
|
||||
const wrapper = render(
|
||||
<Provider store={system.getStore()}>
|
||||
<Component />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
|
||||
it("should catch errors thrown inside of container created from stateless component function", function() {
|
||||
// Given
|
||||
const BrokenComponent = () => { throw new Error("This component is broken") }
|
||||
|
||||
const system = new System({
|
||||
plugins: [
|
||||
ViewPlugin,
|
||||
{
|
||||
components: {
|
||||
BrokenComponent
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
const Component = system.getSystem().getComponent("BrokenComponent", true)
|
||||
const wrapper = mount(
|
||||
<Provider store={system.getStore()}>
|
||||
<Component />
|
||||
</Provider>
|
||||
)
|
||||
|
||||
// Then
|
||||
expect(wrapper.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user