diff --git a/.eslintrc b/.eslintrc index 34819c3..57fca55 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,12 +1,13 @@ { "extends": "airbnb", + "env": { "mocha": true }, + "rules": { "semi": [2, "never"], "no-param-reassign": 0, - "prefer-rest-params": 0, "react/prefer-es6-class": 0, "react/prefer-stateless-function": 0, "react/no-multi-comp": 0 diff --git a/README.md b/README.md index 7518639..e043793 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,9 @@ # react-poop -react-poop wraps your stateless functions and the render method of your components -into a try/catch block and renders a 💩 when something goes wrong. +`react-poop` wraps your stateless functions and the render method of your components into a try/catch block. + +When something goes wrong, it shows a 💩 (or the custom handler you provided) so that the tree can still be rendered. ## Installation @@ -18,7 +19,15 @@ import React from 'react' import { render } from 'react-dom' import poop from 'react-poop' -const App = poop(() =>
Hello react-poop
) +// default + +const App = poop()(() =>
Hello react-poop
) + +// or +// with a custom handler + +const Handler = ({ message }) =>
{message}
+const App = poop(Handler)(() =>
Hello react-poop
) render(, document.getElementById('app')) ``` diff --git a/package.json b/package.json index f2f2cf0..e28a2ab 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "react-poop", - "version": "0.2.0", + "version": "1.0.0", "description": "The ultimate error handler for React", "main": "dist/index.js", "files": [ "dist" ], "scripts": { - "test": "mocha --compilers js:babel-register --reporter=emoji-reporter ./src/**/*.spec.js", + "test": "mocha --compilers js:babel-register --reporter emoji-reporter", "build": "babel ./src --out-dir ./dist --ignore *.spec.js", "prepublish": "npm run build" }, @@ -37,6 +37,7 @@ "eslint-plugin-import": "^1.9.2", "eslint-plugin-jsx-a11y": "^1.5.3", "eslint-plugin-react": "^5.2.2", + "jsdom": "^9.6.0", "mocha": "^2.5.3", "react": "^15.1.0", "react-addons-test-utils": "^15.1.0", diff --git a/src/poop.js b/src/poop.js index 6e84876..488bfb7 100644 --- a/src/poop.js +++ b/src/poop.js @@ -1,6 +1,6 @@ import React from 'react' -const isStateless = component => !(component.prototype && component.prototype.isReactComponent) +const isStateless = Component => !(Component.prototype && Component.prototype.isReactComponent) const createClass = component => React.createClass({ render() { @@ -8,10 +8,10 @@ const createClass = component => React.createClass({ }, }) -const wrap = (Target, Handler) => { - const originalRender = Target.prototype.render +const wrap = (Component, Handler) => { + const originalRender = Component.prototype.render - Target.prototype.render = function render(...args) { + Component.prototype.render = function render(...args) { try { return originalRender.apply(this, args) } catch (error) { @@ -19,13 +19,13 @@ const wrap = (Target, Handler) => { } } - return Target + return Component } -export default handler => component => { - const Component = isStateless(component) ? createClass(component) : component - const Poop = error =>
💩
- const Handler = handler || Poop +const Poop = error =>
💩
- return wrap(Component, Handler) +export default Handler => Component => { + const Target = isStateless(Component) ? createClass(Component) : Component + + return wrap(Target, Handler || Poop) } diff --git a/src/poop.spec.js b/src/poop.spec.js deleted file mode 100644 index c1b8ad4..0000000 --- a/src/poop.spec.js +++ /dev/null @@ -1,65 +0,0 @@ -import assert from 'assert' -import { shallow } from 'enzyme' -import React from 'react' - -import poop from './poop' - -const ErrorComponent = React.createClass({ - render() { - return
An error occurred
- }, -}) - -describe('poop', () => { - describe('class', () => { - it('renders the component when everything is fine', () => { - const Dummy = poop()(React.createClass({ - render() { - return
Dummy
- }, - })) - const wrapper = shallow() - assert(wrapper.contains('Dummy')) - }) - - it('renders the error component when something goes wrong', () => { - const Dummy = poop(ErrorComponent)(React.createClass({ - render() { - return
{this.does.not.exist}
- }, - })) - const wrapper = shallow() - assert(wrapper.find(ErrorComponent)) - }) - - it('renders the poop when something goes wrong and no errorComponent was provided', () => { - const Dummy = poop()(React.createClass({ - render() { - return
{this.does.not.exist}
- }, - })) - const wrapper = shallow() - assert(wrapper.find('Poop')) - }) - }) - - describe('stateless', () => { - it('renders the component when everything is fine', () => { - const Dummy = poop()(() =>
Dummy
) - const wrapper = shallow() - assert(wrapper.contains('Dummy')) - }) - - it('renders the error component when something goes wrong', () => { - const Dummy = poop(ErrorComponent)(() =>
{this.does.not.exist}
) - const wrapper = shallow() - assert(wrapper.find(ErrorComponent)) - }) - - it('renders the poop when something goes wrong and no errorComponent was provided', () => { - const Dummy = poop()(() =>
{this.does.not.exist}
) - const wrapper = shallow() - assert(wrapper.find('Poop')) - }) - }) -}) diff --git a/test/poop.spec.js b/test/poop.spec.js new file mode 100644 index 0000000..c09352b --- /dev/null +++ b/test/poop.spec.js @@ -0,0 +1,81 @@ +import assert from 'assert' +import { shallow, mount } from 'enzyme' +import React from 'react' + +import poop from '../src' + +describe('poop', () => { + const Handler = () =>
Handler
+ + describe('class', () => { + let NiceClass + let EvilClass + + beforeEach(() => { + NiceClass = React.createClass({ + render() { + return
Dummy
+ }, + }) + + EvilClass = React.createClass({ + render() { + return
{this.does.not.exist}
+ }, + }) + }) + + it('renders the component when everything is fine', () => { + const Dummy = poop()(NiceClass) + const wrapper = shallow() + + assert(wrapper.contains('Dummy')) + }) + + it('renders the handler when something goes wrong', () => { + const Dummy = poop(Handler)(EvilClass) + const wrapper = mount() + + assert.equal(wrapper.find('Handler').length, 1) + }) + + it('renders the poop when something goes wrong', () => { + const Dummy = poop()(EvilClass) + const wrapper = mount() + + assert.equal(wrapper.find('Poop').length, 1) + }) + }) + + describe('stateless', () => { + let NiceStateless + let EvilStateless + + beforeEach(() => { + NiceStateless = () =>
Dummy
+ + EvilStateless = () =>
{this.does.not.exist}
+ }) + + it('renders the component when everything is fine', () => { + const Dummy = poop()(NiceStateless) + const wrapper = shallow() + + assert(wrapper.contains('Dummy')) + }) + + it('renders the handler when something goes wrong', () => { + const Dummy = poop(Handler)(EvilStateless) + const wrapper = mount() + + assert.equal(wrapper.find('Handler').length, 1) + }) + + it('renders the poop when something goes wrong', () => { + const Dummy = poop()(EvilStateless) + const wrapper = mount() + + assert.equal(wrapper.find('Poop').length, 1) + }) + }) +}) diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 0000000..076b9db --- /dev/null +++ b/test/setup.js @@ -0,0 +1,13 @@ +import { jsdom } from 'jsdom' + +global.document = jsdom('') +global.window = document.defaultView +Object.keys(document.defaultView).forEach((property) => { + if (typeof global[property] === 'undefined') { + global[property] = document.defaultView[property] + } +}) + +global.navigator = { + userAgent: 'node.js', +}