Skip to content

Commit

Permalink
Added TestErrorBoundary component
Browse files Browse the repository at this point in the history
  • Loading branch information
viktor-podzigun committed Jun 26, 2023
1 parent 3052bb6 commit 247cadf
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 5 deletions.
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,24 @@ npm i --save-dev react-assert

### Usage

Imports:

```javascript
import React from "react";
import TestRenderer from "react-test-renderer";
import assert from "node:assert/strict";
import mockFunction from "mock-fn";

import {
assertComponents,
mockComponent,
TestErrorBoundary,
} from "react-assert";
```

// 1. import
import { assertComponents, mockComponent } from "react-assert";
Components:

```javascript
function SubComponent() {
return <p className="sub">Sub</p>;
}
Expand All @@ -43,7 +54,11 @@ function MyComponent(props) {
}
MyComponent.displayName = "MyComponent";
MyComponent.SubComp = SubComponent;
```

Tests:

```javascript
describe("MyComponent", () => {
it("should render nested components", () => {
//given
Expand All @@ -53,7 +68,7 @@ describe("MyComponent", () => {
const result = TestRenderer.create(<MyComponent text={text} />).root;

//then
// 2. call assertComponents to check expected components tree
// call assertComponents to check expected components tree
assertComponents(
result.children,
<div>
Expand All @@ -65,7 +80,7 @@ describe("MyComponent", () => {

it("should render mock components", () => {
//given
// 3. use mockComponent to mock nested components
// use mockComponent to mock nested components
MyComponent.SubComp = mockComponent(SubComponent);
const { SubComp } = MyComponent;
const text = "Hello";
Expand All @@ -82,5 +97,33 @@ describe("MyComponent", () => {
</div>
);
});

it("should render error details if error during render", () => {
//given
// suppress intended error
// see: https://github.com/facebook/react/issues/11098#issuecomment-412682721
const savedConsoleError = console.error;
const consoleErrorMock = mockFunction(() => {
console.error = savedConsoleError;
});
console.error = consoleErrorMock;

const ErrorComp = () => {
throw Error("test error");
return <>{"Not rendered"}</>;
};

//when
const result = TestRenderer.create(
<TestErrorBoundary>
<ErrorComp />
<TestErrorBoundary/>
).root;

//then
assert.deepEqual(consoleErrorMock.times, 1);
assert.deepEqual(console.error, savedConsoleError);
assertComponents(result.children, <div>{"Error: test error"}</div>);
});
});
```
8 changes: 7 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { Component } from "react";
import TestRenderer from "react-test-renderer";

export function assertComponent(
Expand All @@ -14,3 +14,9 @@ export function assertComponents(
export function mockComponent<
T = React.FunctionComponent<any> | React.ComponentClass<any>
>(comp: T, name?: string): T;

interface State {
error?: object;
}

export class TestErrorBoundary extends Component<any, State> {}
1 change: 1 addition & 0 deletions index.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as assertComponent } from "./src/assertComponent.mjs";
export { default as assertComponents } from "./src/assertComponents.mjs";
export { default as mockComponent } from "./src/mockComponent.mjs";
export { default as TestErrorBoundary } from "./src/TestErrorBoundary.mjs";
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/react": "^17.0.1",
"@types/react-test-renderer": "^17.0.1",
"c8": "^7.13.0",
"mock-fn": "^1.0.0",
"prettier": "^2.8.8",
"react": "^17.0.1",
"react-test-renderer": "^17.0.1",
Expand Down
42 changes: 42 additions & 0 deletions src/TestErrorBoundary.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { Component } from "react";

const h = React.createElement;

/**
* @typedef State
* @prop {object} [error]
*/

/**
* @extends Component<any, State>
*/
class TestErrorBoundary extends Component {
/** @type {State} */
state = {
error: undefined,
};

/**
* @param {any} props
*/
constructor(props) {
super(props);
}

/**
* @param {object} [error]
*/
componentDidCatch(error) {
this.setState({
error,
});
}

render() {
const error = this.state.error;
return error ? h("div", null, `${error}`) : this.props.children;
}
}
TestErrorBoundary.displayName = "TestErrorBoundary";

export default TestErrorBoundary;
52 changes: 52 additions & 0 deletions test/TestErrorBoundary.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import assert from "node:assert/strict";
import mockFunction from "mock-fn";
import { assertComponents, TestErrorBoundary } from "../index.mjs";

const h = React.createElement;

const { describe, it } = await (async () => {
// @ts-ignore
return process.isBun // @ts-ignore
? Promise.resolve({ describe: (_, fn) => fn(), it: test })
: import("node:test");
})();

describe("TestErrorBoundary.test.mjs", () => {
it("should render children if no errors", () => {
//when
const result = TestRenderer.create(
h(TestErrorBoundary, null, "some child")
).root;

//then
assertComponents(result.children, "some child");
});

it("should render error details if error during render", () => {
//given
// suppress intended error
// see: https://github.com/facebook/react/issues/11098#issuecomment-412682721
const savedConsoleError = console.error;
const consoleErrorMock = mockFunction(() => {
console.error = savedConsoleError;
});
console.error = consoleErrorMock;

const ErrorComp = () => {
throw Error("test error");
return h(React.Fragment);
};

//when
const result = TestRenderer.create(
h(TestErrorBoundary, null, h(ErrorComp))
).root;

//then
assert.deepEqual(consoleErrorMock.times, 1);
assert.deepEqual(console.error, savedConsoleError);
assertComponents(result.children, h("div", null, "Error: test error"));
});
});
1 change: 1 addition & 0 deletions test/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ await import("./testRenderer.test.mjs");
await import("./assertComponent.test.mjs");
await import("./assertComponents.test.mjs");
await import("./mockComponent.test.mjs");
await import("./TestErrorBoundary.test.mjs");

0 comments on commit 247cadf

Please sign in to comment.