React, Enzyme, and Barbies... Oh my!
Valerie Kraucunas

(almost)

What i'll be covering
- Brief Intro to Enzyme
- React Testing Best Practices
- Discuss Additional Testing Tools
- Intro Fran's Barbie Dream Database
Please ask questions as they come to you.
If you have a better answer than I do, please contribute.
and how the dream didn't make it to the party

INTRO TO ENZYME
Started by Airbnb engineer Leland Richardson, since open sourced
Enzyme is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse your React Components' output.

INTRO TO ENZYME
Benefits of using Enzyme
- Unopinionated
- jQuery style DOM traversal
- Mocking out components to test is clean
Enzyme makes asking questions about the rendered output of your React components easy and intuitive
INTRO TO ENZYME
So uh... what am I supposed to be testing?
- Is it the component even rendering?
- Is everything rendering that you're expecting?
- Checking props
- Simulating events, such as a click
INTRO TO ENZYME
Example of basic test
import React from 'react';
import { shallow } from 'enzyme';
import ToDoList from '../components/ToDoList';
import ToDoItem from '../components/ToDoItem';
describe('<ToDoList />', () => {
it('renders the entire list of items', () => {
const items = [mockItem(), mockItem() /*, ... */];
const wrapper = shallow(<ToDoList items={items} />);
expect(wrapper.find(ToDoList)).to.have.length(items.length);
});
});INTRO TO ENZYME
Example of complex test
import React from 'react';
import { shallow } from 'enzyme';
import chai, {expect} from 'chai';
import { stub } from 'sinon';
import sinonChai from 'sinon-chai';
chai.use(sinonChai);
const FBButton4 = ({ likePage }) => {
const onClick = () => {
if (FB.like()) {
likePage();
}
};
return <button onClick={onClick}>Like this on Fakebook!</button>;
};
describe('<FBButton4 />', () => {
it('will call our action because FB.like returns `true`', () => {
const likePage = stub();
const wrapper = shallow(<FBButton4 likePage={likePage} />);
stub(FB, 'like').returns(true);
wrapper.find('button').simulate('click');
expect(likePage).to.have.been.called;
FB.like.restore(); // This is important!
});
});Rendering methods
Shallow
Mount
Render

Rendering methods
Shallow
Purest unit testing option
No children rendered, to ensure that your tests aren't indirectly asserting on behavior of child components.
Fastest rendering method, works best on stateless components

Rendering methods
Mount

Full DOM rendering, including children
If you do not want to run your tests inside of a browser, the recommended approach to using mount is to depend on a library called jsdom which is essentially a headless browser implemented completely in JS.
Includes the most lifecycle testing
Rendering methods
Render
Renders static html, including children, fewest lifecycle methods covered
Uses Cheerio
Render is useful when you just want to assert on the DOM your component(s) render, lets you skip incorporating jsdom

New Development
React v16
The environment is in a time of transition
npm i --save-dev enzyme-adapter-react-16Best practices
TEST EARLY AND TEST OFTEN
Best practices
- Start with .shallow()
- Always refresh your wrapper variable between tests
- Only pass wrappers the required props
- If it is hard to test, re-write the component
- Pick an assertion syntax and stick to it
Best practices
- Explicit setup() instead of beforeEach()
const setup = propOverrides => {
const props = Object.assign({
activeCount: 0,
onClearCompleted: sinon.spy(),
}, propOverrides)
const wrapper = shallow(<Footer {...props} />)
return {
props,
wrapper,
clear: wrapper.find('.clear-completed'),
count: wrapper.find('.todo-count'),
}
}
describe('count', () => {
test('when active count 0', () => {
const { count } = setup({ activeCount: 0 })
expect(count.text()).toEqual('No items left')
})
});Best practices
Test double library!
npm i --save-dev sinonAllows you to replace the difficult parts of your tests with something simple.
Best practices
Test double library!
- Spies, which offer information about function calls, without affecting their behavior
- Stubs, which are like spies, but completely replace the function. This makes it possible to make a stubbed function do whatever you like — throw an exception, return a specific value, etc
- Mocks, which make replacing whole objects easier by combining both spies and stubs
Best practices
Sinon.js
describe('onBoundsChanged called for the first time', function() {
const center = {lat: 37.7696044, lng: -122.41115960000001}
before(function() {
this.callback = sinon.spy();
this.onCenterChanged = sinon.stub()
this.wrapper = shallow(
<DispensaryMapComponent
dispensaries={dispensaries}
location={{retrieved: true, coords: {lat: 37.71412, lng: -122.4734}}}
onCenterChanged={this.onCenterChanged}
/>
).dive()
this.component = this.wrapper.instance()
sinon.stub(this.component, 'refreshClusters')
this.component.onBoundsChanged({center: center, zoom: 16, bounds: boundsTest})
})Best practices
Husky
"Git hooks made easy"
npm install husky --save-dev
// package.json
{
"scripts": {
"precommit": "npm test",
"prepush": "npm test",
"...": "..."
}
}npm uninstall huskyfran's barbie dream database
Why?

fran's barbie dream database
Tools && Libraries
- React & Redux
- react-router-dom, redux-thunk
- material-ui (ui kit)
- axios
fran's barbie dream database
My Approach
- MVP
- Phase I
- Phase II

fran's barbie dream database
When the Wheels Fell Off For Me
- Did not adhere to Testing Best Practice #1
- I did not ask enough questions this year
- Set up took a while
- redux-thunk
- material-ui
- create-react-app vs enzyme
fran's barbie dream database
React & Enzyme
React v16 and Enzyme v3 were released on September 26th.
Future of enzyme
- Improve event simulation across all rendering methods
- React Native testing improvements

Future of Fran's Barbie Dream Database
- Batch adding
- Uploading Images to AWS s3
- Transform to a React Native application to utilize phone camera

Thank you!
Valerie Kraucunas
valeriekraucunas@gmail.com
vkraucunas


RESOURCES
React, Enzyme & Barbies
By Valerie Kraucunas
React, Enzyme & Barbies
"Untested code is broken code." Enzyme, the testing utility for React, is flexible, intuitive, and compatible with most test runners. When matched with a test double library like Sinon.js, Enzyme becomes capable of unit testing both components and reducers. Together we'll cover the tradeoffs of the different rendering methods provided from Enzyme, best practices for writing test files, and upcoming features of Enzyme. (ReactJS 2/2017)
- 976