SlideShare a Scribd company logo
The Many Ways to 

Test React
All Things Open 2016
#ATO2016
Van J. Wilson
@vanwilson
Who I Am
Who I Am
Who You Are?
Who You Are
• Know Javascript
• Already familiar with React
• Know a little bit about testing (vanilla Javascript,
another Javascript library/framework, or even in
another language)
• Want to write better software
How most devs actually test
(Look closely; she’s hitting CTRL-R over and over again.)
Why Write Automated Tests?
https://twitter.com/housecor/status/714430381680775168
Why Write Automated Tests?
https://twitter.com/jjafuller/status/714595373059166208
Benefits of Testing
Testing does …
➡ … help you focus on what’s important in the code
➡ … give you confidence that—if you change
something about the code—it still does the same
stuff it did before
Testing doesn’t …
➡ … prove that your code is “correct”
➡ … guarantee the absence of bugs.
Benefits of Testing
• Defensive driving doesn’t guarantee that you won’t
get in an accident.
• Wearing a seat belt doesn’t guarantee that you
won’t get hurt if you do have an accident.
That doesn’t mean you should not wear a seatbelt
or drive defensively.
“It is a profoundly erroneous truism, repeated
by all copy-books and by eminent people when
they are making speeches, that we should
cultivate the habit of thinking of what we are
doing. The precise opposite is the case.
Civilization advances by extending the number
of important operations which we can perform
without thinking about them. Operations of
thought are like cavalry charges in a battle —
they are strictly limited in number, they require
fresh horses, and must only be made at
decisive moments.”
–Alfred North Whitehead, An Introduction to Mathematics
Test-Driven Development
FAIL
PASSREFACTOR
1. Write Tests
2. Run Tests (TESTS FAIL)
3. Write Code to Make
Tests Pass
4. Run Tests (TESTS PASS)

5. Refactor (repeat until
you can’t think of
anything else to test)
Test-During Development
CODE
FAILPASS
1. Write Some Code

2. Write Some Tests
3. Run Tests (TESTS FAIL)
4. Write More Code
5. Run Tests (TESTS PASS)

6. Refactor (repeat until all
the features and tests
are done)
Kinds of automated testing
• Unit Testing
• Integration Testing
• Functional / Acceptance Testing
Kinds of automated testing
Unit
Integration
Functional
xUnit
Test Harness
Selenium
Kinds of automated testing
• Unit Testing
• Integration Testing
• Functional / Acceptance Testing
Why testing React is easy
React apps are meant to be
predictable,

and consequently they are eminently
testable.
React components == 

mathematical functions
y = mx +b
where
m is the slope of the line,
x is the x-coordinate,
b is the y-intercept
React Components
• Hierarchical
• Encourage one-way data flow
• Ultimately, just Javascript functions
Even JSX is just functions
JSX is functions
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
Library Fatigue
Required files
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "6.11.4",
"babel-loader": "^6.2.4",
"babel-polyfill": "^6.13.0",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.11.1",
"babel-register": "^6.14.0",
"chai": "^3.5.0",
"chai-enzyme": "^0.5.1",
"chalk": "1.1.3",
"enzyme": "^2.4.1",
"eslint": "3.1.1",
"eslint-loader": "1.4.1",
"expect": "^1.20.2",
"istanbul": "^0.4.5",
"istanbul-instrumenter-loader":
"^0.2.0",
"karma": "^1.2.0",
"karma-chai": "^0.1.0",
"karma-chai-plugins": "^0.7.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^1.0.0",
"karma-junit-reporter": "^1.1.0",
"karma-mocha": "^1.1.1",
"karma-mocha-reporter": "^2.1.0",
"karma-phantomjs-launcher": "^1.0.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.26",
"karma-webpack": "^1.8.0",
"mocha": "^3.0.2",
"nock": "^8.0.0",
"phantomjs-polyfill": "0.0.2",
"phantomjs-prebuilt": "^2.1.12",
"react-addons-test-utils": "^15.3.1",
"redux-mock-store": "^1.1.4",
"sass-loader": "^3.1.2",
"sinon": "^1.17.5",
"webpack": "1.13.1"
}
Just kidding!
The real minimum
requirements
• Test Framework
• A DOM
• A test utility library that “speaks React”
An aside: It’s still React,
though
So, we’re going to need a few basic building blocks
in order to:
• Compile JSX
• Transpile ES6 (if you want to use it)
• Bundle the libraries with your code
• Include React and ReactDOM (duh)
Bare-bones React setup
"dependencies": {
"react": "^15.3.1",
"react-dom": "^15.3.1"
},
"devDependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.13.0",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"live-server": "^1.1.0",
"npm-run-all": "^3.1.0",
"webpack": "^1.13.2"
}
Get it all at:
https://gist.github.com/vjwilson/a040c234c0d6683c1341331f57a81e77
Test Frameworks
Test Frameworks
• Jasmine - mature, built-in assertions and spies
• Jest - wrapper around Jasmine for React
• Tape - straightforward, traditional paradigm
• Ava - built-in ES2015, concurrent test running
• Mocha - modular, allows (requires) separate
assertion and spy libraries
How to decide? Just ask?
https://twitter.com/housecor/status/717759300886618112
Test Frameworks
• Jasmine - mature, built-in assertions and spies
• Jest
• Tape - straightforward, traditional paradigm
• Ava - built-in ES2015, concurrent test running
• Mocha
npm install —save-dev mocha #(or) jest
A little bait-and-switch
Mocha requires you to choose a separate assertion library
Assertion Libraries
• Assert - built into Node, just require/import
• Expect - basic BDD style, similar to Jasmine
• Should - uber BDD style, bleeding edge
• Chai - can mimic any of the three libraries
• Power-Assert - concentrates on “truthy” values
• UnitJS - similar to Chai
Assertion Libraries
• Assert - built into Node, just require/import
• Expect - basic BDD style, similar to Jasmine
• Should - uber BDD style, bleeding edge
• Chai
• Power-Assert - concentrates on “truthy” values
• UnitJS - similar to Chai
npm install —save-dev chai
Options for a test DOM
• A real browser (Chrome, Firefox, Safari etc)
• PhantomJS (a “headless” browser)
• JSDom
Real browsers or PhantomJS will require some “glue”
in the form of something like Karma.
Options for a test DOM
• A real browser (Chrome, Firefox, Safari etc)
• PhantomJS (a “headless” browser)
• JSDom
npm install —save-dev jsdom
Helper Libraries
• React Test Utils - from Facebook, bare-bones
• React Shallow Testutils - some helper wrappers
• Enzyme - like jQuery, but for tests
• Sinon - spies, mocks, and stubs
Helper Libraries
• React Test Utils
• React Shallow Testutils
• Enzyme
• Sinon
npm install —save-dev react-test-utils react-
shallow-testutils enzyme simon
One more thing… spies
Mocha doesn’t come with a mocking library, so to test
the behavior of functions thoroughly, you’ll need a
mocking library.
One more thing… spies
Sinon is the most popular mocking library for Mocha.
npm install —save-dev sinon
Where Do Tests Go?
In their own folder With the code they are testing
Enough setup…
Let’s run some tests!
The Example App
https://github.com/vjwilson/many-ways-to-test-react
The Example App
Ex1: ES5
• React.createClass (ES5) style components
• Webpack/Babel compiles JSX to a static bundle
• Live Server serves and auto-refreshes the page
• No tests yet (Test-During Development)
Ex1: The App component
var App = React.createClass({
getInitialState: function() {
return {
castMembers: this.props.initialCastMembers,
user: this.props.initialUser
};
},
loginAction: function() {
this.setState({ user: this.props.initialUser });;
},
logoutAction: function() {
this.setState({ user: null });;
},
ex1-react-es5/src/App.js (excerpt)
Ex1: App (cont.)
render: function() {
return (
<div className="container">
<Header user={this.state.user} login={this.loginAction}

logout={this.logoutAction} />
<Jumbotron />
<div className="panel panel-default">
<div className="panel-heading">
<h2 className="panel-title">Top-Billed Cast</h2>
</div>
<div className="panel-body">
<CastMemberList members = {this.state.castMembers} />
</div>
</div>
</div>
);
}
});
Ex2: Mocha and 

React Test Utils
• Mocha test framework
• JSDom
• React Test Utils (and a little Shallow Tests Utils)
• Chai’s expect function
• Sinon for function spies
Ex2: What changed in
the tooling
"scripts": {
// build stuff …
"test": "mocha --reporter spec test/helpers/testSetup.js 

"test/**/*.test.js"",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
// other dependencies …
"chai": "^3.5.0",
"jsdom": "^9.5.0",
"mocha": "^3.0.2",
"react-addons-test-utils": "15.0.2",
"react-shallow-testutils": "^2.0.0",
"sinon": "^1.17.6",
}
ex2-mocha-react-test-utils/package.json (excerpt)
Ex2: Test Setup
require(‘babel-register')();
var jsdom = require('jsdom').jsdom;
var exposedProperties = ['window', 'navigator', 'document'];
global.document = jsdom('');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
}
});
global.navigator = {
userAgent: 'node.js'
};
documentRef = document;
ex2-mocha-react-test-utils/test/helpers/testSetup.js (excerpt)
Ex2: Test Setup (cont.)
{
"presets": [
"react",
"es2015"
]
}
ex2-mocha-react-test-utils/.babelrc (excerpt)
Ex2: Components and Tests
!"" src
#   !"" App.js
#   !"" CastMember.js
#   !"" CastMemberList.js
#   !"" Header.js
#   !"" Jumbotron.js
#   $"" index.js
!"" test
#   !"" helpers
#   #   $"" testSetup.js
#   !"" App.test.js
#   !"" CastMember.test.js
#   !"" CastMemberList.test.js
#   !"" Header.test.js
#   $"" Jumbotron.test.js
React Test Utils
• Replaces ReactDOM
• Can renderIntoDocument() or “shallow render”
• Functions to find rendered nodes (e.g.):
• scryRenderedDOMComponentsWithClass()
• findRenderedDOMComponentWithClass()
• Simulate() to fire DOM events
• Function to test nodes (e.g.):
• isElementOfType()
• isCompositeComponentWithType()
Ex2: What a Test Looks Like
var chai = require('chai');
var React= require('react');
var TestUtils = require('react-addons-test-utils');
var CastMember = require('../src/CastMember');
const expect = chai.expect;
function setup(props) {
let renderer = TestUtils.createRenderer();
renderer.render(<CastMember {...props}/>);
let output = renderer.getRenderOutput();
return {
props,
output,
renderer
};
}
ex2-mocha-react-test-utils/test/CastMember.test.js (part 1 of 3)
Ex2: What a Test Looks Like
describe('CastMember component', () => {
let props = {
member: {
id: 3,
name: 'Testy McTestface',
imageUrl: 'test-image.jpg',
thumbnailUrl: 'test-image-small.jpg',
bio: 'This is a test.'
}
};
it('should render a div with correct class', () => {
const {output} = setup(props);
expect(output.type).to.equal('div');
expect(output.props.className).to.equal('media');
});
ex2-mocha-react-test-utils/test/CastMember.test.js (part 2 of 3)
Ex2: What a Test Looks Like
it('should contain two child divs with appropriate classes', () => {
const {output} = setup(props);
const firstChild = output.props.children[0];
const secondChild = output.props.children[1];
expect(firstChild.type).to.equal('div');
expect(firstChild.props.className).to.equal('media-left');
expect(secondChild.type).to.equal('div');
expect(secondChild.props.className).to.equal('media-body');
});
it('should contain a heading element', () => {
const output = TestUtils.renderIntoDocument(<CastMember

{...props} />);
const titleElement =

TestUtils.findRenderedDOMComponentWithClass(output, 'media-heading');
expect(TestUtils.isDOMComponent(titleElement)).to.be.true;
});
});
ex2-mocha-react-test-utils/test/CastMember.test.js (part 3 of 3)
99 Problems with React Test Utils
• Limited API
• Verbose function names
• Too subtle and obtuse
• What is scrying, anyway?
• Brittle and hard to pinpoint elements
• var loginBlock =

output.props.children.props.children[1]

.props.children[2].props.children;

// Wut?
Shallow Test Utils
// other imports…
var ShallowTestUtils = require('react-shallow-testutils');
var Header= require(‘../src/Header');
// other tests…
it('should render a nav with username and logout link if user

logged in', () => {
props.user = user;
var output = setup(props);
var navbarText = ShallowTestUtils.findWithClass(output, 

'navbar-text');
var navbarLink = ShallowTestUtils.findWithClass(output,

'navbar-link');
expect(navbarText.props.children).to.equal('Welcome,

' + user.username);
expect(navbarLink.props.children).to.equal('Logout');
});
ex2-mocha-react-test-utils/test/Header.test.js (excerpt)
The Many Ways to Test Your React App
Enzyme
• Extends React Test Utils
• Can render a React DOM, shallow-render in
element, or render the final HTML DOM
• Has a ton of jQuery-like selectors and helpers
• <renderedOutput>.find(selector)
• <renderedOutput>.findWhere(fn)
• <renderedOutput>.text()
• <renderedOutput>..prop(key)
• and many, many more…
• https://github.com/airbnb/enzyme
Ex3: Mocha and 

Enzyme
"scripts": {
// build stuff …
"test": "mocha --reporter spec test/helpers/testSetup.js 

"src/**/*.test.js"",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
// other dependencies …
"chai": “^3.5.0",
"enzyme": "^2.4.1",
"jsdom": "^9.5.0",
"mocha": "^3.0.2",
"react-addons-test-utils": "15.0.2",
"react-shallow-testutils": "^2.0.0",
"sinon": "^1.17.6",
}
ex3-mocha-react-test-utils/package.json (excerpt)
Ex3: Components with Tests
!"" src
#   !"" App
#   #   !"" App.js
#   #   $"" App.test.js
#   !"" Cast
#   #   !"" tests
#   #   !"" CastMember.js
#   #   $"" CastMemberList.js
#   !"" Header
#   #   !"" Header.js
#   #   $"" Header.test.js
#   !"" Jumbotron
#   #   !"" Jumbotron.js
#   #   $"" Jumbotron.test.js
#   $"" index.js
!"" test
#   $"" helpers
#   $"" testSetup.js
Ex3: What a Test Looks Like
import React from 'react';
import { expect } from 'chai';
import { shallow, mount, render } from 'enzyme';
import sinon from 'sinon';
import Header from './Header';
describe('Header component', function() {
let props;
beforeEach(function() {
props = {
user: null,
login: function() {},
logout: function() {}
};
});
ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 1 of 4)
Ex3: What a Test Looks Like
it('should render the static component', function() {
// sanity-check test
// does it "render without exploding"?
// see: https://gist.github.com/thevangelist/

e2002bc6b9834def92d46e4d92f15874
const shallowOutput = shallow(<Header user={props.user}

login={props.loginAction} logout={props.logoutAction} />);
expect(shallowOutput).to.have.length(1);
});
// more tests
ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 2 of 4)
Ex3: What a Test Looks Like
describe('calling the appropriate action props', function() {
let loginAction;
let logoutAction;
beforeEach(function() {
loginAction = sinon.spy();
logoutAction = sinon.spy();
props.loginAction = loginAction;
props.logoutAction = logoutAction;
});
ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 3 of 4)
Ex3: What a Test Looks Like
it('should call login function if no authenticated use', function() {
const shallowOutput = shallow(<Header user={props.user}
login={props.loginAction} logout={props.logoutAction} />);
const authLink = shallowOutput.find('.login-block .navbar-link');
authLink.simulate('click');
expect(loginAction.calledOnce).to.be.true;
});
it('should call logout function when there is an authenticated user',
function() {
props.user = {
id: 3,
username: 'gmtester'
};
const shallowOutput = shallow(<Header user={props.user}
login={props.loginAction} logout={props.logoutAction} />);
const authLink = shallowOutput.find('.login-block .navbar-link');
authLink.simulate('click')
expect(logoutAction.calledOnce).to.be.true;
});
});
ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 3 of 4)
Ex4: Mocha and 

Enzyme, but in ES6
module: {
loaders: [
{
test: /.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react']
}
},
]
}
ex1-react-es5/webpack.config.js (excerpt)
module: {
loaders: [
{
test: /.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015',
'react']
}
},
]
}
ex2-mocha-react-test-utils/webpack.config.js

(excerpt)
A digression — Jest
Remember this poll?
https://twitter.com/housecor/status/717759300886618112
9% usage?!?
Before / After 

Jest-pocalype
• Auto-mocking on by
default
• Optimized inside
Facebook, but not by
default in open source
setup
• Slow
< v15.0 v15.0+
• Auto-mocking off by
default
• New commitment to
community
• Snapshot testing (v14)
• Fast
Ex5: Mocha and 

Jest
• Jest test framework
• JSDom (included with Jest)
• expect function (included with Jasmine2, which is
included with Jest)
• Spies (that’s right, included with Jasmine2, which is
included with Jest)
Ex5: Tests in separate folder
!"" __tests__
#   !"" __snapshots__
#   #   !"" App.test.js.snap
#   #   !"" CastMember.test.js.snap
#   #   !"" CastMemberList.test.js.snap
#   #   !"" Header.test.js.snap
#   #   $"" Jumbotron.test.js.snap
#   !"" App.test.js
#   !"" CastMember.test.js
#   !"" CastMemberList.test.js
#   !"" Header.test.js
#   $"" Jumbotron.test.js
!"" src
#   !"" App
#   #   $"" App.js
#   !"" Cast
#   #   !"" CastMember.js
#   #   $"" CastMemberList.js
#   !"" Header
#   #   $"" Header.js
#   !"" Jumbotron
#   #   $"" Jumbotron.js
#   $"" index.js
Ex5: What a Test Looks Like
import React from 'react';
import renderer from 'react-test-renderer';
import CastMember from '../src/Cast/CastMember';
test('CastMember rendered static HTML', () => {
const props = {
member: {
id: 3,
name: 'Testy McTestFace',
imageUrl: 'test-image.jpg',
thumbnailUrl: 'test-image-small.jpg',
bio: 'This is a test.'
}
};
ex5-jest/__tests__/CastMember.test.js (part 1 of 2)
Ex5: What a Test Looks Like
const component = renderer.create(
<CastMember {...props} />
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
ex5-jest/__tests__/CastMember.test.js (part 2 of 2)
One big advantage for Jest
Jest comes set up when you create a
React app with
create-react-app,
Facebook’s React generator
Ex6: Mocha Enzyme, ES6,
and React-Router
• Mocha test framework
• JSDom
• Enzyme
• Chai’s expect function
• Sinon for function spies
• React-Router
Ex6: A Second Page!
Ex6: React-Router folder structure
!"" src
#   !"" App
#   !"" Cast
#   !"" Header
#   !"" Home
#   !"" Jumbotron
#   !"" Tickets
#   !"" castMemberData.js
#   !"" index.js
#   !"" initialUserData.js
#   !"" routes.js
#   !"" routes.test.js
#   $"" seatData.js
!"" test
#   !"" fixtures
#   $"" helpers
Ex6: What a Test Looks Like
import React from 'react';
import { expect } from 'chai';
import { shallow, mount } from 'enzyme';
import sinon from 'sinon';
import BuyTicketsPage from './BuyTicketsPage';
import SeatingChart from './Seating/SeatingChart';
import TicketForm from './TicketForm';
import mockSeatData from '../../test/fixtures/mockSeatData';
describe('BuyTicketsPage component', function() {
let routeObject;
beforeEach(function() {
routeObject = {
initialSeatData: []
};
});
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 1 of 6)
Ex6: What a Test Looks Like
describe('rendering', function() {
it('should render the component (smoke test)', function() {
const shallowOutput = shallow(<BuyTicketsPage 

route={routeObject} />);
expect(shallowOutput).to.have.length(1);
});
it('should render an element with correct classes', 

function() {
const shallowOutput = shallow(<BuyTicketsPage 

route={routeObject} />);
expect(shallowOutput.hasClass('text-center')).to.be.true;
});
});
//…
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 2 of 6)
Ex6: What a Test Looks Like
describe('BuyTicketsPage component actions', function() {
it('should handle a form submission from its TicketForm 

component (manual test)', function() {
routeObject.initialSeatData = 

JSON.parse(JSON.stringify(mockSeatData));
const buyTicketsPage = mount(<BuyTicketsPage 

route={routeObject} />);
// manually set the state of selected seats and the 

package to buy
let seatsToSelect = 

routeObject.initialSeatData[2].slice(0, 2);
seatsToSelect[0].selected = true;
seatsToSelect[1].selected = true;
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 3 of 6)
Ex6: What a Test Looks Like
buyTicketsPage.setState({
ticketPackage: {
seats: seatsToSelect
}
});
const ticketForm = buyTicketsPage.find('.ticket-form');
ticketForm.simulate('submit');
const seatArray = buyTicketsPage.state('seatData');
const ticketPackage = 

buyTicketsPage.state('ticketPackage');
expect(seatArray[2][0].sold).to.be.true;
expect(seatArray[2][1].sold).to.be.true;
expect(ticketPackage.seats).to.have.lengthOf(0);
});
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 4 of 6)
Ex6: What a Test Looks Like
it('should handle a form submission from its TicketForm
component (automatic test)', function() {
routeObject.initialSeatData =
JSON.parse(JSON.stringify(mockSeatData));
const buyTicketsPage = mount(<BuyTicketsPage
route={routeObject} />);
// automatically set the state of selected seats and the 

package to buy
const pageInstance = buyTicketsPage.instance();
pageInstance.updateSeatStatus('C1');
pageInstance.updateSeatStatus('C2');
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 5 of 6)
Ex6: What a Test Looks Like
const ticketForm = buyTicketsPage.find('.ticket-form');
ticketForm.simulate('submit');
const seatArray = buyTicketsPage.state('seatData');
const ticketPackage =
buyTicketsPage.state('ticketPackage');
expect(seatArray[2][0].sold).to.be.true;
expect(seatArray[2][1].sold).to.be.true;
expect(ticketPackage.seats).to.have.lengthOf(0);
});
ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 6 of 6)
Ex7: Mocha Enzyme, ES6,
React-Router, and Redux
• Mocha test framework
• JSDom
• Enzyme
• Chai’s expect function
• Sinon for function spies
• React-Router
• Redux
Ex7: Redux folder structure!"" src
#   !"" actions
#   #   !"" actionTypes.js
#   #   !"" castMemberActions.js
#   #   !"" seatActions.js
#   #   !"" seatActions.test.js
#   #   !"" userActions.js
#   #   $"" userActions.test.js
#   !"" components
#   !"" reducers
#   #   !"" castMembersReducer.js
#   #   !"" castMembersReducer.test.js
#   #   !"" index.js
#   #   !"" initialState.js
#   #   !"" initialState.test.js
#   #   !"" seatReducer.js
#   #   !"" seatReducer.test.js
#   #   !"" userReducer.js
#   #   $"" userReducer.test.js
#   !"" selectors
#   #   !"" selectors.js
#   #   $"" selectors.test.js
#   !"" store
#   #   $"" configureStore.js
!"" test
#   !"" fixtures
#   #   !"" mockCastMemberData.js
#   #   $"" mockSeatData.js
Ex7: What a Test Looks Like
import { expect } from 'chai';
import seatReducer from './seatReducer';
import * as actions from '../actions/seatActions';
import mockSeatData from '../../test/fixtures/mockSeatData';
import * as types from '../actions/actionTypes';
describe('Seat reducer', function() {
let seats;
beforeEach(function() {
seats = JSON.parse(JSON.stringify(mockSeatData));
});
it('should load seats', function() {
const initialState = [];
const action = actions.loadSeats(seats);
const newState = seatReducer(initialState, action);
const expectedSeats = JSON.parse(JSON.stringify(mockSeatData));
expect(newState).to.equal(seats);
});
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 1 of 3)
Ex7: What a Test Looks Like
it('should mark a seat as selected', function() {
const initialState = seats;
const seat = initialState[0][2]; // mock seat A3
const expectedState = 

JSON.parse(JSON.stringify(initialState));
expectedState[0][2].selected = true;
const action = actions.toggleSeatSelected(seat);
const newState = seatReducer(initialState, action);
// .eql instead of .equal,
// to compare the contents, instead of the reference
expect(newState).to.eql(expectedState);
});
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 2 of 3)
Ex7: What a Test Looks Like
it('should mark a seat as sold', function() {
const initialState = seats;
const seat = seats[0][2]; // mock seat A3
seat.selected = true;
const expectedState = JSON.parse(JSON.stringify(seats));
expectedState[0][2].sold = true;
expectedState[0][2].selected = false;
const action = actions.markSeatSold(seat);
const newState = seatReducer(initialState, action);
// .eql instead of .equal,
// to compare the contents, instead of the reference
expect(newState).to.eql(expectedState);
});
});
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 3 of 3)
Ex7: The Code Under Test
import * as types from '../actions/actionTypes';
import initialState from './initialState';
export default function seatReducer(state = initialState.seats,

action) {
let newState;
switch(action.type) {
case types.LOAD_SEATS:
return action.seats;
break;
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 1 of 3)
Ex7: The Code Under Test
case types.TOGGLE_SEAT_SELECTED:
newState = state.map((row) => {
return row.map((seat) => {
if (seat.seatNumber === action.seat.seatNumber) {
const updatedSeat = Object.assign({}, seat);
updatedSeat.selected = !updatedSeat.selected;
return updatedSeat;
} else {
return seat;
}
});
});
return newState;
break;
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 2 of 3)
Ex7: The Code Under Test
case types.MARK_SEAT_SOLD:
newState = state.map((row) => {
return row.map((seat) => {
if (seat.seatNumber === action.seat.seatNumber) {
const updatedSeat = Object.assign({}, seat);
updatedSeat.selected = false;
updatedSeat.sold = true;
return updatedSeat;
} else {
return seat;
}
});
});
return newState;
break;
default:
return state;
}
}
ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 3 of 3)
Resources
• https://facebook.github.io/react/docs/test-utils.html 🚫
• https://github.com/airbnb/enzyme
• https://semaphoreci.com/community/tutorials/testing-
react-components-with-enzyme-and-
mocha#comments
• https://facebook.github.io/jest/
• https://egghead.io/courses/react-testing-cookbook
Contact
• @vanwilson on Twitter
• van@vanwilson.info
• vanwilson.info (where I blog once or twice a year)
Questions?
Go forth, and test.
Ad

More Related Content

What's hot (20)

Building React app using Test-driven Development
Building React app using Test-driven DevelopmentBuilding React app using Test-driven Development
Building React app using Test-driven Development
Nik Sumeiko
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
Richard Paul
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for selenium
apoorvams
 
How to go about testing in React?
How to go about testing in React? How to go about testing in React?
How to go about testing in React?
Lisa Gagarina
 
Jenkins Introduction
Jenkins IntroductionJenkins Introduction
Jenkins Introduction
Pavan Gupta
 
Js: master prototypes
Js: master prototypesJs: master prototypes
Js: master prototypes
Barak Drechsler
 
Jmeter Performance Testing
Jmeter Performance TestingJmeter Performance Testing
Jmeter Performance Testing
Atul Pant
 
How to implement internationalization (i18n) in angular application(multiple ...
How to implement internationalization (i18n) in angular application(multiple ...How to implement internationalization (i18n) in angular application(multiple ...
How to implement internationalization (i18n) in angular application(multiple ...
Katy Slemon
 
Saving Time By Testing With Jest
Saving Time By Testing With JestSaving Time By Testing With Jest
Saving Time By Testing With Jest
Ben McCormick
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
Christoffer Noring
 
Selenium
SeleniumSelenium
Selenium
Vladimir Soghoyan
 
Jenkins tutorial for beginners
Jenkins tutorial for beginnersJenkins tutorial for beginners
Jenkins tutorial for beginners
BugRaptors
 
JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
priya_trivedi
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
Rafael Casuso Romate
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
nickokiss
 
Introduction to Selenium Web Driver
Introduction to Selenium Web DriverIntroduction to Selenium Web Driver
Introduction to Selenium Web Driver
Return on Intelligence
 
Test Automation Framework with BDD and Cucumber
Test Automation Framework with BDD and CucumberTest Automation Framework with BDD and Cucumber
Test Automation Framework with BDD and Cucumber
Rhoynar Software Consulting
 
Apache JMeter - A brief introduction
Apache JMeter - A brief introductionApache JMeter - A brief introduction
Apache JMeter - A brief introduction
silenceIT Inc.
 
Introduction to Swagger
Introduction to SwaggerIntroduction to Swagger
Introduction to Swagger
Knoldus Inc.
 
Use Node.js to create a REST API
Use Node.js to create a REST APIUse Node.js to create a REST API
Use Node.js to create a REST API
Fabien Vauchelles
 
Building React app using Test-driven Development
Building React app using Test-driven DevelopmentBuilding React app using Test-driven Development
Building React app using Test-driven Development
Nik Sumeiko
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
Richard Paul
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for selenium
apoorvams
 
How to go about testing in React?
How to go about testing in React? How to go about testing in React?
How to go about testing in React?
Lisa Gagarina
 
Jenkins Introduction
Jenkins IntroductionJenkins Introduction
Jenkins Introduction
Pavan Gupta
 
Jmeter Performance Testing
Jmeter Performance TestingJmeter Performance Testing
Jmeter Performance Testing
Atul Pant
 
How to implement internationalization (i18n) in angular application(multiple ...
How to implement internationalization (i18n) in angular application(multiple ...How to implement internationalization (i18n) in angular application(multiple ...
How to implement internationalization (i18n) in angular application(multiple ...
Katy Slemon
 
Saving Time By Testing With Jest
Saving Time By Testing With JestSaving Time By Testing With Jest
Saving Time By Testing With Jest
Ben McCormick
 
Jenkins tutorial for beginners
Jenkins tutorial for beginnersJenkins tutorial for beginners
Jenkins tutorial for beginners
BugRaptors
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
Rafael Casuso Romate
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
nickokiss
 
Apache JMeter - A brief introduction
Apache JMeter - A brief introductionApache JMeter - A brief introduction
Apache JMeter - A brief introduction
silenceIT Inc.
 
Introduction to Swagger
Introduction to SwaggerIntroduction to Swagger
Introduction to Swagger
Knoldus Inc.
 
Use Node.js to create a REST API
Use Node.js to create a REST APIUse Node.js to create a REST API
Use Node.js to create a REST API
Fabien Vauchelles
 

Viewers also liked (20)

Contribution & Confidence
Contribution & ConfidenceContribution & Confidence
Contribution & Confidence
All Things Open
 
Civic Hacking 201: Successful techniques for civic tech
Civic Hacking 201: Successful techniques for civic techCivic Hacking 201: Successful techniques for civic tech
Civic Hacking 201: Successful techniques for civic tech
All Things Open
 
Modern Container Orchestration (Without Breaking the Bank)
Modern Container Orchestration (Without Breaking the Bank)Modern Container Orchestration (Without Breaking the Bank)
Modern Container Orchestration (Without Breaking the Bank)
All Things Open
 
Scaling Your Logging Infrastructure With Syslog-NG
Scaling Your Logging Infrastructure With Syslog-NGScaling Your Logging Infrastructure With Syslog-NG
Scaling Your Logging Infrastructure With Syslog-NG
All Things Open
 
DevOps for Managers
DevOps for ManagersDevOps for Managers
DevOps for Managers
All Things Open
 
Data Encryption at Rest
Data Encryption at RestData Encryption at Rest
Data Encryption at Rest
All Things Open
 
React & Redux
React & ReduxReact & Redux
React & Redux
Federico Bond
 
Student Pipeline to Open Source Communities using HFOSS
Student Pipeline to Open Source Communities using HFOSSStudent Pipeline to Open Source Communities using HFOSS
Student Pipeline to Open Source Communities using HFOSS
All Things Open
 
Building the Right Platform Architecture for Hadoop
Building the Right Platform Architecture for HadoopBuilding the Right Platform Architecture for Hadoop
Building the Right Platform Architecture for Hadoop
All Things Open
 
BFFs: UX & SEO Partnering to Design Successful Products
BFFs: UX & SEO Partnering to Design Successful ProductsBFFs: UX & SEO Partnering to Design Successful Products
BFFs: UX & SEO Partnering to Design Successful Products
All Things Open
 
Building a Distributed & Automated Open Source Program at Netflix
Building a Distributed & Automated Open Source Program at NetflixBuilding a Distributed & Automated Open Source Program at Netflix
Building a Distributed & Automated Open Source Program at Netflix
All Things Open
 
Marketing is not all fluff; engineering is not all math
Marketing is not all fluff; engineering is not all mathMarketing is not all fluff; engineering is not all math
Marketing is not all fluff; engineering is not all math
All Things Open
 
CSS Grid Layout
CSS Grid LayoutCSS Grid Layout
CSS Grid Layout
All Things Open
 
The Datacenter Network You Wish You Had: It's yours for the taking.
The Datacenter Network You Wish You Had: It's yours for the taking.The Datacenter Network You Wish You Had: It's yours for the taking.
The Datacenter Network You Wish You Had: It's yours for the taking.
All Things Open
 
Leveraging Open Source for Database Development: Database Version Control wit...
Leveraging Open Source for Database Development: Database Version Control wit...Leveraging Open Source for Database Development: Database Version Control wit...
Leveraging Open Source for Database Development: Database Version Control wit...
All Things Open
 
Develop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
Develop and Deploy Cloud-Native Apps as Resilient Microservice ArchitecturesDevelop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
Develop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
All Things Open
 
Netflix and Containers: Not Stranger Things
Netflix and Containers: Not Stranger ThingsNetflix and Containers: Not Stranger Things
Netflix and Containers: Not Stranger Things
All Things Open
 
Cross-platform Mobile Development on Open Source
Cross-platform Mobile Development on Open SourceCross-platform Mobile Development on Open Source
Cross-platform Mobile Development on Open Source
All Things Open
 
Tools & tricks for testing React applications
Tools & tricks for testing React applications Tools & tricks for testing React applications
Tools & tricks for testing React applications
React London Community
 
War of Attrition: AWS vs. Google, IBM and Microsoft Azure
War of Attrition: AWS vs. Google, IBM and Microsoft AzureWar of Attrition: AWS vs. Google, IBM and Microsoft Azure
War of Attrition: AWS vs. Google, IBM and Microsoft Azure
IT Brand Pulse
 
Contribution & Confidence
Contribution & ConfidenceContribution & Confidence
Contribution & Confidence
All Things Open
 
Civic Hacking 201: Successful techniques for civic tech
Civic Hacking 201: Successful techniques for civic techCivic Hacking 201: Successful techniques for civic tech
Civic Hacking 201: Successful techniques for civic tech
All Things Open
 
Modern Container Orchestration (Without Breaking the Bank)
Modern Container Orchestration (Without Breaking the Bank)Modern Container Orchestration (Without Breaking the Bank)
Modern Container Orchestration (Without Breaking the Bank)
All Things Open
 
Scaling Your Logging Infrastructure With Syslog-NG
Scaling Your Logging Infrastructure With Syslog-NGScaling Your Logging Infrastructure With Syslog-NG
Scaling Your Logging Infrastructure With Syslog-NG
All Things Open
 
Student Pipeline to Open Source Communities using HFOSS
Student Pipeline to Open Source Communities using HFOSSStudent Pipeline to Open Source Communities using HFOSS
Student Pipeline to Open Source Communities using HFOSS
All Things Open
 
Building the Right Platform Architecture for Hadoop
Building the Right Platform Architecture for HadoopBuilding the Right Platform Architecture for Hadoop
Building the Right Platform Architecture for Hadoop
All Things Open
 
BFFs: UX & SEO Partnering to Design Successful Products
BFFs: UX & SEO Partnering to Design Successful ProductsBFFs: UX & SEO Partnering to Design Successful Products
BFFs: UX & SEO Partnering to Design Successful Products
All Things Open
 
Building a Distributed & Automated Open Source Program at Netflix
Building a Distributed & Automated Open Source Program at NetflixBuilding a Distributed & Automated Open Source Program at Netflix
Building a Distributed & Automated Open Source Program at Netflix
All Things Open
 
Marketing is not all fluff; engineering is not all math
Marketing is not all fluff; engineering is not all mathMarketing is not all fluff; engineering is not all math
Marketing is not all fluff; engineering is not all math
All Things Open
 
The Datacenter Network You Wish You Had: It's yours for the taking.
The Datacenter Network You Wish You Had: It's yours for the taking.The Datacenter Network You Wish You Had: It's yours for the taking.
The Datacenter Network You Wish You Had: It's yours for the taking.
All Things Open
 
Leveraging Open Source for Database Development: Database Version Control wit...
Leveraging Open Source for Database Development: Database Version Control wit...Leveraging Open Source for Database Development: Database Version Control wit...
Leveraging Open Source for Database Development: Database Version Control wit...
All Things Open
 
Develop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
Develop and Deploy Cloud-Native Apps as Resilient Microservice ArchitecturesDevelop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
Develop and Deploy Cloud-Native Apps as Resilient Microservice Architectures
All Things Open
 
Netflix and Containers: Not Stranger Things
Netflix and Containers: Not Stranger ThingsNetflix and Containers: Not Stranger Things
Netflix and Containers: Not Stranger Things
All Things Open
 
Cross-platform Mobile Development on Open Source
Cross-platform Mobile Development on Open SourceCross-platform Mobile Development on Open Source
Cross-platform Mobile Development on Open Source
All Things Open
 
Tools & tricks for testing React applications
Tools & tricks for testing React applications Tools & tricks for testing React applications
Tools & tricks for testing React applications
React London Community
 
War of Attrition: AWS vs. Google, IBM and Microsoft Azure
War of Attrition: AWS vs. Google, IBM and Microsoft AzureWar of Attrition: AWS vs. Google, IBM and Microsoft Azure
War of Attrition: AWS vs. Google, IBM and Microsoft Azure
IT Brand Pulse
 
Ad

Similar to The Many Ways to Test Your React App (20)

TDD super mondays-june-2014
TDD super mondays-june-2014TDD super mondays-june-2014
TDD super mondays-june-2014
Alex Kavanagh
 
Testing sync engine
Testing sync engineTesting sync engine
Testing sync engine
Ilya Puchka
 
Automating JavaScript testing with Jasmine and Perl
Automating JavaScript testing with Jasmine and PerlAutomating JavaScript testing with Jasmine and Perl
Automating JavaScript testing with Jasmine and Perl
nohuhu
 
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
seleniumconf
 
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWJest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Holger Grosse-Plankermann
 
Writing Well Abstracted Automation on Foundations of Jello
Writing Well Abstracted Automation on Foundations of JelloWriting Well Abstracted Automation on Foundations of Jello
Writing Well Abstracted Automation on Foundations of Jello
Dan Cuellar
 
How to use selenium successfully
How to use selenium successfullyHow to use selenium successfully
How to use selenium successfully
TEST Huddle
 
Getting Started with Selenium
Getting Started with SeleniumGetting Started with Selenium
Getting Started with Selenium
Dave Haeffner
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
Mats Bryntse
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!
Ortus Solutions, Corp
 
Browser Automated Testing Frameworks - Nightwatch.js
Browser Automated Testing Frameworks - Nightwatch.jsBrowser Automated Testing Frameworks - Nightwatch.js
Browser Automated Testing Frameworks - Nightwatch.js
Luís Bastião Silva
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testing
Mats Bryntse
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
Lilia Sfaxi
 
33rd degree
33rd degree33rd degree
33rd degree
Dariusz Kordonski
 
unit test in node js - test cases in node
unit test in node js - test cases in nodeunit test in node js - test cases in node
unit test in node js - test cases in node
Goa App
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
Eugene Dvorkin
 
An Introduction to unit testing
An Introduction to unit testingAn Introduction to unit testing
An Introduction to unit testing
Steven Casey
 
jQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & TricksjQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & Tricks
Addy Osmani
 
Automated Testing but like for PowerShell (April 2012)
Automated Testing but like for PowerShell (April 2012)Automated Testing but like for PowerShell (April 2012)
Automated Testing but like for PowerShell (April 2012)
Rob Reynolds
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
All Things Open
 
TDD super mondays-june-2014
TDD super mondays-june-2014TDD super mondays-june-2014
TDD super mondays-june-2014
Alex Kavanagh
 
Testing sync engine
Testing sync engineTesting sync engine
Testing sync engine
Ilya Puchka
 
Automating JavaScript testing with Jasmine and Perl
Automating JavaScript testing with Jasmine and PerlAutomating JavaScript testing with Jasmine and Perl
Automating JavaScript testing with Jasmine and Perl
nohuhu
 
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
seleniumconf
 
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRWJest: Frontend Testing richtig gemacht @WebworkerNRW
Jest: Frontend Testing richtig gemacht @WebworkerNRW
Holger Grosse-Plankermann
 
Writing Well Abstracted Automation on Foundations of Jello
Writing Well Abstracted Automation on Foundations of JelloWriting Well Abstracted Automation on Foundations of Jello
Writing Well Abstracted Automation on Foundations of Jello
Dan Cuellar
 
How to use selenium successfully
How to use selenium successfullyHow to use selenium successfully
How to use selenium successfully
TEST Huddle
 
Getting Started with Selenium
Getting Started with SeleniumGetting Started with Selenium
Getting Started with Selenium
Dave Haeffner
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
Mats Bryntse
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!
Ortus Solutions, Corp
 
Browser Automated Testing Frameworks - Nightwatch.js
Browser Automated Testing Frameworks - Nightwatch.jsBrowser Automated Testing Frameworks - Nightwatch.js
Browser Automated Testing Frameworks - Nightwatch.js
Luís Bastião Silva
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testing
Mats Bryntse
 
unit test in node js - test cases in node
unit test in node js - test cases in nodeunit test in node js - test cases in node
unit test in node js - test cases in node
Goa App
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
Eugene Dvorkin
 
An Introduction to unit testing
An Introduction to unit testingAn Introduction to unit testing
An Introduction to unit testing
Steven Casey
 
jQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & TricksjQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & Tricks
Addy Osmani
 
Automated Testing but like for PowerShell (April 2012)
Automated Testing but like for PowerShell (April 2012)Automated Testing but like for PowerShell (April 2012)
Automated Testing but like for PowerShell (April 2012)
Rob Reynolds
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
All Things Open
 
Ad

More from All Things Open (20)

Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
Let's Create a GitHub Copilot Extension! - Nick Taylor, PomeriumLet's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
All Things Open
 
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
All Things Open
 
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
All Things Open
 
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
All Things Open
 
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
All Things Open
 
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
All Things Open
 
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
All Things Open
 
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
All Things Open
 
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
Don't just talk to AI, do more with AI: how to improve productivity with AI a...Don't just talk to AI, do more with AI: how to improve productivity with AI a...
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
All Things Open
 
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
All Things Open
 
The Death of the Browser - Rachel-Lee Nabors, AgentQL
The Death of the Browser - Rachel-Lee Nabors, AgentQLThe Death of the Browser - Rachel-Lee Nabors, AgentQL
The Death of the Browser - Rachel-Lee Nabors, AgentQL
All Things Open
 
Making Operating System updates fast, easy, and safe
Making Operating System updates fast, easy, and safeMaking Operating System updates fast, easy, and safe
Making Operating System updates fast, easy, and safe
All Things Open
 
Reshaping the landscape of belonging to transform community
Reshaping the landscape of belonging to transform communityReshaping the landscape of belonging to transform community
Reshaping the landscape of belonging to transform community
All Things Open
 
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
All Things Open
 
Integrating Diversity, Equity, and Inclusion into Product Design
Integrating Diversity, Equity, and Inclusion into Product DesignIntegrating Diversity, Equity, and Inclusion into Product Design
Integrating Diversity, Equity, and Inclusion into Product Design
All Things Open
 
The Open Source Ecosystem for eBPF in Kubernetes
The Open Source Ecosystem for eBPF in KubernetesThe Open Source Ecosystem for eBPF in Kubernetes
The Open Source Ecosystem for eBPF in Kubernetes
All Things Open
 
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon PitmanOpen Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
All Things Open
 
Open-Source Low-Code - Craig St. Jean, Xebia
Open-Source Low-Code - Craig St. Jean, XebiaOpen-Source Low-Code - Craig St. Jean, Xebia
Open-Source Low-Code - Craig St. Jean, Xebia
All Things Open
 
How I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
How I Learned to Stop Worrying about my Infrastructure and Love [Open]TofuHow I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
How I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
All Things Open
 
The Developers' Framework for Content Creation
The Developers' Framework for Content CreationThe Developers' Framework for Content Creation
The Developers' Framework for Content Creation
All Things Open
 
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
Let's Create a GitHub Copilot Extension! - Nick Taylor, PomeriumLet's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
All Things Open
 
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
All Things Open
 
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
All Things Open
 
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
All Things Open
 
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
All Things Open
 
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
All Things Open
 
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
All Things Open
 
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
All Things Open
 
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
Don't just talk to AI, do more with AI: how to improve productivity with AI a...Don't just talk to AI, do more with AI: how to improve productivity with AI a...
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
All Things Open
 
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
All Things Open
 
The Death of the Browser - Rachel-Lee Nabors, AgentQL
The Death of the Browser - Rachel-Lee Nabors, AgentQLThe Death of the Browser - Rachel-Lee Nabors, AgentQL
The Death of the Browser - Rachel-Lee Nabors, AgentQL
All Things Open
 
Making Operating System updates fast, easy, and safe
Making Operating System updates fast, easy, and safeMaking Operating System updates fast, easy, and safe
Making Operating System updates fast, easy, and safe
All Things Open
 
Reshaping the landscape of belonging to transform community
Reshaping the landscape of belonging to transform communityReshaping the landscape of belonging to transform community
Reshaping the landscape of belonging to transform community
All Things Open
 
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
All Things Open
 
Integrating Diversity, Equity, and Inclusion into Product Design
Integrating Diversity, Equity, and Inclusion into Product DesignIntegrating Diversity, Equity, and Inclusion into Product Design
Integrating Diversity, Equity, and Inclusion into Product Design
All Things Open
 
The Open Source Ecosystem for eBPF in Kubernetes
The Open Source Ecosystem for eBPF in KubernetesThe Open Source Ecosystem for eBPF in Kubernetes
The Open Source Ecosystem for eBPF in Kubernetes
All Things Open
 
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon PitmanOpen Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
All Things Open
 
Open-Source Low-Code - Craig St. Jean, Xebia
Open-Source Low-Code - Craig St. Jean, XebiaOpen-Source Low-Code - Craig St. Jean, Xebia
Open-Source Low-Code - Craig St. Jean, Xebia
All Things Open
 
How I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
How I Learned to Stop Worrying about my Infrastructure and Love [Open]TofuHow I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
How I Learned to Stop Worrying about my Infrastructure and Love [Open]Tofu
All Things Open
 
The Developers' Framework for Content Creation
The Developers' Framework for Content CreationThe Developers' Framework for Content Creation
The Developers' Framework for Content Creation
All Things Open
 

Recently uploaded (20)

TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 

The Many Ways to Test Your React App

  • 1. The Many Ways to 
 Test React All Things Open 2016 #ATO2016 Van J. Wilson @vanwilson
  • 5. Who You Are • Know Javascript • Already familiar with React • Know a little bit about testing (vanilla Javascript, another Javascript library/framework, or even in another language) • Want to write better software
  • 6. How most devs actually test (Look closely; she’s hitting CTRL-R over and over again.)
  • 7. Why Write Automated Tests? https://twitter.com/housecor/status/714430381680775168
  • 8. Why Write Automated Tests? https://twitter.com/jjafuller/status/714595373059166208
  • 9. Benefits of Testing Testing does … ➡ … help you focus on what’s important in the code ➡ … give you confidence that—if you change something about the code—it still does the same stuff it did before Testing doesn’t … ➡ … prove that your code is “correct” ➡ … guarantee the absence of bugs.
  • 10. Benefits of Testing • Defensive driving doesn’t guarantee that you won’t get in an accident. • Wearing a seat belt doesn’t guarantee that you won’t get hurt if you do have an accident. That doesn’t mean you should not wear a seatbelt or drive defensively.
  • 11. “It is a profoundly erroneous truism, repeated by all copy-books and by eminent people when they are making speeches, that we should cultivate the habit of thinking of what we are doing. The precise opposite is the case. Civilization advances by extending the number of important operations which we can perform without thinking about them. Operations of thought are like cavalry charges in a battle — they are strictly limited in number, they require fresh horses, and must only be made at decisive moments.” –Alfred North Whitehead, An Introduction to Mathematics
  • 12. Test-Driven Development FAIL PASSREFACTOR 1. Write Tests 2. Run Tests (TESTS FAIL) 3. Write Code to Make Tests Pass 4. Run Tests (TESTS PASS)
 5. Refactor (repeat until you can’t think of anything else to test)
  • 13. Test-During Development CODE FAILPASS 1. Write Some Code
 2. Write Some Tests 3. Run Tests (TESTS FAIL) 4. Write More Code 5. Run Tests (TESTS PASS)
 6. Refactor (repeat until all the features and tests are done)
  • 14. Kinds of automated testing • Unit Testing • Integration Testing • Functional / Acceptance Testing
  • 15. Kinds of automated testing Unit Integration Functional xUnit Test Harness Selenium
  • 16. Kinds of automated testing • Unit Testing • Integration Testing • Functional / Acceptance Testing
  • 17. Why testing React is easy React apps are meant to be predictable,
 and consequently they are eminently testable.
  • 18. React components == 
 mathematical functions y = mx +b where m is the slope of the line, x is the x-coordinate, b is the y-intercept
  • 19. React Components • Hierarchical • Encourage one-way data flow • Ultimately, just Javascript functions
  • 20. Even JSX is just functions
  • 21. JSX is functions const element = ( <h1 className="greeting"> Hello, world! </h1> ); const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' );
  • 23. Required files "devDependencies": { "babel": "^6.5.2", "babel-core": "6.11.4", "babel-loader": "^6.2.4", "babel-polyfill": "^6.13.0", "babel-preset-es2015": "6.9.0", "babel-preset-react": "6.11.1", "babel-register": "^6.14.0", "chai": "^3.5.0", "chai-enzyme": "^0.5.1", "chalk": "1.1.3", "enzyme": "^2.4.1", "eslint": "3.1.1", "eslint-loader": "1.4.1", "expect": "^1.20.2", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^0.2.0", "karma": "^1.2.0", "karma-chai": "^0.1.0", "karma-chai-plugins": "^0.7.0", "karma-chrome-launcher": "^2.0.0", "karma-cli": "^1.0.1", "karma-coverage": "^1.1.1", "karma-firefox-launcher": "^1.0.0", "karma-junit-reporter": "^1.1.0", "karma-mocha": "^1.1.1", "karma-mocha-reporter": "^2.1.0", "karma-phantomjs-launcher": "^1.0.1", "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "0.0.26", "karma-webpack": "^1.8.0", "mocha": "^3.0.2", "nock": "^8.0.0", "phantomjs-polyfill": "0.0.2", "phantomjs-prebuilt": "^2.1.12", "react-addons-test-utils": "^15.3.1", "redux-mock-store": "^1.1.4", "sass-loader": "^3.1.2", "sinon": "^1.17.5", "webpack": "1.13.1" }
  • 25. The real minimum requirements • Test Framework • A DOM • A test utility library that “speaks React”
  • 26. An aside: It’s still React, though So, we’re going to need a few basic building blocks in order to: • Compile JSX • Transpile ES6 (if you want to use it) • Bundle the libraries with your code • Include React and ReactDOM (duh)
  • 27. Bare-bones React setup "dependencies": { "react": "^15.3.1", "react-dom": "^15.3.1" }, "devDependencies": { "babel-core": "^6.14.0", "babel-loader": "^6.2.5", "babel-polyfill": "^6.13.0", "babel-preset-es2015": "^6.14.0", "babel-preset-react": "^6.11.1", "live-server": "^1.1.0", "npm-run-all": "^3.1.0", "webpack": "^1.13.2" } Get it all at: https://gist.github.com/vjwilson/a040c234c0d6683c1341331f57a81e77
  • 29. Test Frameworks • Jasmine - mature, built-in assertions and spies • Jest - wrapper around Jasmine for React • Tape - straightforward, traditional paradigm • Ava - built-in ES2015, concurrent test running • Mocha - modular, allows (requires) separate assertion and spy libraries
  • 30. How to decide? Just ask? https://twitter.com/housecor/status/717759300886618112
  • 31. Test Frameworks • Jasmine - mature, built-in assertions and spies • Jest • Tape - straightforward, traditional paradigm • Ava - built-in ES2015, concurrent test running • Mocha npm install —save-dev mocha #(or) jest
  • 32. A little bait-and-switch Mocha requires you to choose a separate assertion library
  • 33. Assertion Libraries • Assert - built into Node, just require/import • Expect - basic BDD style, similar to Jasmine • Should - uber BDD style, bleeding edge • Chai - can mimic any of the three libraries • Power-Assert - concentrates on “truthy” values • UnitJS - similar to Chai
  • 34. Assertion Libraries • Assert - built into Node, just require/import • Expect - basic BDD style, similar to Jasmine • Should - uber BDD style, bleeding edge • Chai • Power-Assert - concentrates on “truthy” values • UnitJS - similar to Chai npm install —save-dev chai
  • 35. Options for a test DOM • A real browser (Chrome, Firefox, Safari etc) • PhantomJS (a “headless” browser) • JSDom Real browsers or PhantomJS will require some “glue” in the form of something like Karma.
  • 36. Options for a test DOM • A real browser (Chrome, Firefox, Safari etc) • PhantomJS (a “headless” browser) • JSDom npm install —save-dev jsdom
  • 37. Helper Libraries • React Test Utils - from Facebook, bare-bones • React Shallow Testutils - some helper wrappers • Enzyme - like jQuery, but for tests • Sinon - spies, mocks, and stubs
  • 38. Helper Libraries • React Test Utils • React Shallow Testutils • Enzyme • Sinon npm install —save-dev react-test-utils react- shallow-testutils enzyme simon
  • 39. One more thing… spies Mocha doesn’t come with a mocking library, so to test the behavior of functions thoroughly, you’ll need a mocking library.
  • 40. One more thing… spies Sinon is the most popular mocking library for Mocha. npm install —save-dev sinon
  • 41. Where Do Tests Go? In their own folder With the code they are testing
  • 45. Ex1: ES5 • React.createClass (ES5) style components • Webpack/Babel compiles JSX to a static bundle • Live Server serves and auto-refreshes the page • No tests yet (Test-During Development)
  • 46. Ex1: The App component var App = React.createClass({ getInitialState: function() { return { castMembers: this.props.initialCastMembers, user: this.props.initialUser }; }, loginAction: function() { this.setState({ user: this.props.initialUser });; }, logoutAction: function() { this.setState({ user: null });; }, ex1-react-es5/src/App.js (excerpt)
  • 47. Ex1: App (cont.) render: function() { return ( <div className="container"> <Header user={this.state.user} login={this.loginAction}
 logout={this.logoutAction} /> <Jumbotron /> <div className="panel panel-default"> <div className="panel-heading"> <h2 className="panel-title">Top-Billed Cast</h2> </div> <div className="panel-body"> <CastMemberList members = {this.state.castMembers} /> </div> </div> </div> ); } });
  • 48. Ex2: Mocha and 
 React Test Utils • Mocha test framework • JSDom • React Test Utils (and a little Shallow Tests Utils) • Chai’s expect function • Sinon for function spies
  • 49. Ex2: What changed in the tooling "scripts": { // build stuff … "test": "mocha --reporter spec test/helpers/testSetup.js 
 "test/**/*.test.js"", "test:watch": "npm run test -- --watch" }, "devDependencies": { // other dependencies … "chai": "^3.5.0", "jsdom": "^9.5.0", "mocha": "^3.0.2", "react-addons-test-utils": "15.0.2", "react-shallow-testutils": "^2.0.0", "sinon": "^1.17.6", } ex2-mocha-react-test-utils/package.json (excerpt)
  • 50. Ex2: Test Setup require(‘babel-register')(); var jsdom = require('jsdom').jsdom; var exposedProperties = ['window', 'navigator', 'document']; global.document = jsdom(''); global.window = document.defaultView; Object.keys(document.defaultView).forEach((property) => { if (typeof global[property] === 'undefined') { exposedProperties.push(property); global[property] = document.defaultView[property]; } }); global.navigator = { userAgent: 'node.js' }; documentRef = document; ex2-mocha-react-test-utils/test/helpers/testSetup.js (excerpt)
  • 51. Ex2: Test Setup (cont.) { "presets": [ "react", "es2015" ] } ex2-mocha-react-test-utils/.babelrc (excerpt)
  • 52. Ex2: Components and Tests !"" src #   !"" App.js #   !"" CastMember.js #   !"" CastMemberList.js #   !"" Header.js #   !"" Jumbotron.js #   $"" index.js !"" test #   !"" helpers #   #   $"" testSetup.js #   !"" App.test.js #   !"" CastMember.test.js #   !"" CastMemberList.test.js #   !"" Header.test.js #   $"" Jumbotron.test.js
  • 53. React Test Utils • Replaces ReactDOM • Can renderIntoDocument() or “shallow render” • Functions to find rendered nodes (e.g.): • scryRenderedDOMComponentsWithClass() • findRenderedDOMComponentWithClass() • Simulate() to fire DOM events • Function to test nodes (e.g.): • isElementOfType() • isCompositeComponentWithType()
  • 54. Ex2: What a Test Looks Like var chai = require('chai'); var React= require('react'); var TestUtils = require('react-addons-test-utils'); var CastMember = require('../src/CastMember'); const expect = chai.expect; function setup(props) { let renderer = TestUtils.createRenderer(); renderer.render(<CastMember {...props}/>); let output = renderer.getRenderOutput(); return { props, output, renderer }; } ex2-mocha-react-test-utils/test/CastMember.test.js (part 1 of 3)
  • 55. Ex2: What a Test Looks Like describe('CastMember component', () => { let props = { member: { id: 3, name: 'Testy McTestface', imageUrl: 'test-image.jpg', thumbnailUrl: 'test-image-small.jpg', bio: 'This is a test.' } }; it('should render a div with correct class', () => { const {output} = setup(props); expect(output.type).to.equal('div'); expect(output.props.className).to.equal('media'); }); ex2-mocha-react-test-utils/test/CastMember.test.js (part 2 of 3)
  • 56. Ex2: What a Test Looks Like it('should contain two child divs with appropriate classes', () => { const {output} = setup(props); const firstChild = output.props.children[0]; const secondChild = output.props.children[1]; expect(firstChild.type).to.equal('div'); expect(firstChild.props.className).to.equal('media-left'); expect(secondChild.type).to.equal('div'); expect(secondChild.props.className).to.equal('media-body'); }); it('should contain a heading element', () => { const output = TestUtils.renderIntoDocument(<CastMember
 {...props} />); const titleElement =
 TestUtils.findRenderedDOMComponentWithClass(output, 'media-heading'); expect(TestUtils.isDOMComponent(titleElement)).to.be.true; }); }); ex2-mocha-react-test-utils/test/CastMember.test.js (part 3 of 3)
  • 57. 99 Problems with React Test Utils • Limited API • Verbose function names • Too subtle and obtuse • What is scrying, anyway? • Brittle and hard to pinpoint elements • var loginBlock =
 output.props.children.props.children[1]
 .props.children[2].props.children;
 // Wut?
  • 58. Shallow Test Utils // other imports… var ShallowTestUtils = require('react-shallow-testutils'); var Header= require(‘../src/Header'); // other tests… it('should render a nav with username and logout link if user
 logged in', () => { props.user = user; var output = setup(props); var navbarText = ShallowTestUtils.findWithClass(output, 
 'navbar-text'); var navbarLink = ShallowTestUtils.findWithClass(output,
 'navbar-link'); expect(navbarText.props.children).to.equal('Welcome,
 ' + user.username); expect(navbarLink.props.children).to.equal('Logout'); }); ex2-mocha-react-test-utils/test/Header.test.js (excerpt)
  • 60. Enzyme • Extends React Test Utils • Can render a React DOM, shallow-render in element, or render the final HTML DOM • Has a ton of jQuery-like selectors and helpers • <renderedOutput>.find(selector) • <renderedOutput>.findWhere(fn) • <renderedOutput>.text() • <renderedOutput>..prop(key) • and many, many more… • https://github.com/airbnb/enzyme
  • 61. Ex3: Mocha and 
 Enzyme "scripts": { // build stuff … "test": "mocha --reporter spec test/helpers/testSetup.js 
 "src/**/*.test.js"", "test:watch": "npm run test -- --watch" }, "devDependencies": { // other dependencies … "chai": “^3.5.0", "enzyme": "^2.4.1", "jsdom": "^9.5.0", "mocha": "^3.0.2", "react-addons-test-utils": "15.0.2", "react-shallow-testutils": "^2.0.0", "sinon": "^1.17.6", } ex3-mocha-react-test-utils/package.json (excerpt)
  • 62. Ex3: Components with Tests !"" src #   !"" App #   #   !"" App.js #   #   $"" App.test.js #   !"" Cast #   #   !"" tests #   #   !"" CastMember.js #   #   $"" CastMemberList.js #   !"" Header #   #   !"" Header.js #   #   $"" Header.test.js #   !"" Jumbotron #   #   !"" Jumbotron.js #   #   $"" Jumbotron.test.js #   $"" index.js !"" test #   $"" helpers #   $"" testSetup.js
  • 63. Ex3: What a Test Looks Like import React from 'react'; import { expect } from 'chai'; import { shallow, mount, render } from 'enzyme'; import sinon from 'sinon'; import Header from './Header'; describe('Header component', function() { let props; beforeEach(function() { props = { user: null, login: function() {}, logout: function() {} }; }); ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 1 of 4)
  • 64. Ex3: What a Test Looks Like it('should render the static component', function() { // sanity-check test // does it "render without exploding"? // see: https://gist.github.com/thevangelist/
 e2002bc6b9834def92d46e4d92f15874 const shallowOutput = shallow(<Header user={props.user}
 login={props.loginAction} logout={props.logoutAction} />); expect(shallowOutput).to.have.length(1); }); // more tests ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 2 of 4)
  • 65. Ex3: What a Test Looks Like describe('calling the appropriate action props', function() { let loginAction; let logoutAction; beforeEach(function() { loginAction = sinon.spy(); logoutAction = sinon.spy(); props.loginAction = loginAction; props.logoutAction = logoutAction; }); ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 3 of 4)
  • 66. Ex3: What a Test Looks Like it('should call login function if no authenticated use', function() { const shallowOutput = shallow(<Header user={props.user} login={props.loginAction} logout={props.logoutAction} />); const authLink = shallowOutput.find('.login-block .navbar-link'); authLink.simulate('click'); expect(loginAction.calledOnce).to.be.true; }); it('should call logout function when there is an authenticated user', function() { props.user = { id: 3, username: 'gmtester' }; const shallowOutput = shallow(<Header user={props.user} login={props.loginAction} logout={props.logoutAction} />); const authLink = shallowOutput.find('.login-block .navbar-link'); authLink.simulate('click') expect(logoutAction.calledOnce).to.be.true; }); }); ex3-mocha-enzyme/src/Header/Header.test.js (excerpts, 3 of 4)
  • 67. Ex4: Mocha and 
 Enzyme, but in ES6 module: { loaders: [ { test: /.js$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['react'] } }, ] } ex1-react-es5/webpack.config.js (excerpt) module: { loaders: [ { test: /.js$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['es2015', 'react'] } }, ] } ex2-mocha-react-test-utils/webpack.config.js
 (excerpt)
  • 70. Before / After 
 Jest-pocalype • Auto-mocking on by default • Optimized inside Facebook, but not by default in open source setup • Slow < v15.0 v15.0+ • Auto-mocking off by default • New commitment to community • Snapshot testing (v14) • Fast
  • 71. Ex5: Mocha and 
 Jest • Jest test framework • JSDom (included with Jest) • expect function (included with Jasmine2, which is included with Jest) • Spies (that’s right, included with Jasmine2, which is included with Jest)
  • 72. Ex5: Tests in separate folder !"" __tests__ #   !"" __snapshots__ #   #   !"" App.test.js.snap #   #   !"" CastMember.test.js.snap #   #   !"" CastMemberList.test.js.snap #   #   !"" Header.test.js.snap #   #   $"" Jumbotron.test.js.snap #   !"" App.test.js #   !"" CastMember.test.js #   !"" CastMemberList.test.js #   !"" Header.test.js #   $"" Jumbotron.test.js !"" src #   !"" App #   #   $"" App.js #   !"" Cast #   #   !"" CastMember.js #   #   $"" CastMemberList.js #   !"" Header #   #   $"" Header.js #   !"" Jumbotron #   #   $"" Jumbotron.js #   $"" index.js
  • 73. Ex5: What a Test Looks Like import React from 'react'; import renderer from 'react-test-renderer'; import CastMember from '../src/Cast/CastMember'; test('CastMember rendered static HTML', () => { const props = { member: { id: 3, name: 'Testy McTestFace', imageUrl: 'test-image.jpg', thumbnailUrl: 'test-image-small.jpg', bio: 'This is a test.' } }; ex5-jest/__tests__/CastMember.test.js (part 1 of 2)
  • 74. Ex5: What a Test Looks Like const component = renderer.create( <CastMember {...props} /> ); let tree = component.toJSON(); expect(tree).toMatchSnapshot(); }); ex5-jest/__tests__/CastMember.test.js (part 2 of 2)
  • 75. One big advantage for Jest Jest comes set up when you create a React app with create-react-app, Facebook’s React generator
  • 76. Ex6: Mocha Enzyme, ES6, and React-Router • Mocha test framework • JSDom • Enzyme • Chai’s expect function • Sinon for function spies • React-Router
  • 77. Ex6: A Second Page!
  • 78. Ex6: React-Router folder structure !"" src #   !"" App #   !"" Cast #   !"" Header #   !"" Home #   !"" Jumbotron #   !"" Tickets #   !"" castMemberData.js #   !"" index.js #   !"" initialUserData.js #   !"" routes.js #   !"" routes.test.js #   $"" seatData.js !"" test #   !"" fixtures #   $"" helpers
  • 79. Ex6: What a Test Looks Like import React from 'react'; import { expect } from 'chai'; import { shallow, mount } from 'enzyme'; import sinon from 'sinon'; import BuyTicketsPage from './BuyTicketsPage'; import SeatingChart from './Seating/SeatingChart'; import TicketForm from './TicketForm'; import mockSeatData from '../../test/fixtures/mockSeatData'; describe('BuyTicketsPage component', function() { let routeObject; beforeEach(function() { routeObject = { initialSeatData: [] }; }); ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 1 of 6)
  • 80. Ex6: What a Test Looks Like describe('rendering', function() { it('should render the component (smoke test)', function() { const shallowOutput = shallow(<BuyTicketsPage 
 route={routeObject} />); expect(shallowOutput).to.have.length(1); }); it('should render an element with correct classes', 
 function() { const shallowOutput = shallow(<BuyTicketsPage 
 route={routeObject} />); expect(shallowOutput.hasClass('text-center')).to.be.true; }); }); //… ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 2 of 6)
  • 81. Ex6: What a Test Looks Like describe('BuyTicketsPage component actions', function() { it('should handle a form submission from its TicketForm 
 component (manual test)', function() { routeObject.initialSeatData = 
 JSON.parse(JSON.stringify(mockSeatData)); const buyTicketsPage = mount(<BuyTicketsPage 
 route={routeObject} />); // manually set the state of selected seats and the 
 package to buy let seatsToSelect = 
 routeObject.initialSeatData[2].slice(0, 2); seatsToSelect[0].selected = true; seatsToSelect[1].selected = true; ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 3 of 6)
  • 82. Ex6: What a Test Looks Like buyTicketsPage.setState({ ticketPackage: { seats: seatsToSelect } }); const ticketForm = buyTicketsPage.find('.ticket-form'); ticketForm.simulate('submit'); const seatArray = buyTicketsPage.state('seatData'); const ticketPackage = 
 buyTicketsPage.state('ticketPackage'); expect(seatArray[2][0].sold).to.be.true; expect(seatArray[2][1].sold).to.be.true; expect(ticketPackage.seats).to.have.lengthOf(0); }); ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 4 of 6)
  • 83. Ex6: What a Test Looks Like it('should handle a form submission from its TicketForm component (automatic test)', function() { routeObject.initialSeatData = JSON.parse(JSON.stringify(mockSeatData)); const buyTicketsPage = mount(<BuyTicketsPage route={routeObject} />); // automatically set the state of selected seats and the 
 package to buy const pageInstance = buyTicketsPage.instance(); pageInstance.updateSeatStatus('C1'); pageInstance.updateSeatStatus('C2'); ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 5 of 6)
  • 84. Ex6: What a Test Looks Like const ticketForm = buyTicketsPage.find('.ticket-form'); ticketForm.simulate('submit'); const seatArray = buyTicketsPage.state('seatData'); const ticketPackage = buyTicketsPage.state('ticketPackage'); expect(seatArray[2][0].sold).to.be.true; expect(seatArray[2][1].sold).to.be.true; expect(ticketPackage.seats).to.have.lengthOf(0); }); ex6-mocha-enzyme-es6-react-router/src/Tickets/BuyTicketsPage.test.js (excerpts, 6 of 6)
  • 85. Ex7: Mocha Enzyme, ES6, React-Router, and Redux • Mocha test framework • JSDom • Enzyme • Chai’s expect function • Sinon for function spies • React-Router • Redux
  • 86. Ex7: Redux folder structure!"" src #   !"" actions #   #   !"" actionTypes.js #   #   !"" castMemberActions.js #   #   !"" seatActions.js #   #   !"" seatActions.test.js #   #   !"" userActions.js #   #   $"" userActions.test.js #   !"" components #   !"" reducers #   #   !"" castMembersReducer.js #   #   !"" castMembersReducer.test.js #   #   !"" index.js #   #   !"" initialState.js #   #   !"" initialState.test.js #   #   !"" seatReducer.js #   #   !"" seatReducer.test.js #   #   !"" userReducer.js #   #   $"" userReducer.test.js #   !"" selectors #   #   !"" selectors.js #   #   $"" selectors.test.js #   !"" store #   #   $"" configureStore.js !"" test #   !"" fixtures #   #   !"" mockCastMemberData.js #   #   $"" mockSeatData.js
  • 87. Ex7: What a Test Looks Like import { expect } from 'chai'; import seatReducer from './seatReducer'; import * as actions from '../actions/seatActions'; import mockSeatData from '../../test/fixtures/mockSeatData'; import * as types from '../actions/actionTypes'; describe('Seat reducer', function() { let seats; beforeEach(function() { seats = JSON.parse(JSON.stringify(mockSeatData)); }); it('should load seats', function() { const initialState = []; const action = actions.loadSeats(seats); const newState = seatReducer(initialState, action); const expectedSeats = JSON.parse(JSON.stringify(mockSeatData)); expect(newState).to.equal(seats); }); ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 1 of 3)
  • 88. Ex7: What a Test Looks Like it('should mark a seat as selected', function() { const initialState = seats; const seat = initialState[0][2]; // mock seat A3 const expectedState = 
 JSON.parse(JSON.stringify(initialState)); expectedState[0][2].selected = true; const action = actions.toggleSeatSelected(seat); const newState = seatReducer(initialState, action); // .eql instead of .equal, // to compare the contents, instead of the reference expect(newState).to.eql(expectedState); }); ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 2 of 3)
  • 89. Ex7: What a Test Looks Like it('should mark a seat as sold', function() { const initialState = seats; const seat = seats[0][2]; // mock seat A3 seat.selected = true; const expectedState = JSON.parse(JSON.stringify(seats)); expectedState[0][2].sold = true; expectedState[0][2].selected = false; const action = actions.markSeatSold(seat); const newState = seatReducer(initialState, action); // .eql instead of .equal, // to compare the contents, instead of the reference expect(newState).to.eql(expectedState); }); }); ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.test.js (part 3 of 3)
  • 90. Ex7: The Code Under Test import * as types from '../actions/actionTypes'; import initialState from './initialState'; export default function seatReducer(state = initialState.seats,
 action) { let newState; switch(action.type) { case types.LOAD_SEATS: return action.seats; break; ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 1 of 3)
  • 91. Ex7: The Code Under Test case types.TOGGLE_SEAT_SELECTED: newState = state.map((row) => { return row.map((seat) => { if (seat.seatNumber === action.seat.seatNumber) { const updatedSeat = Object.assign({}, seat); updatedSeat.selected = !updatedSeat.selected; return updatedSeat; } else { return seat; } }); }); return newState; break; ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 2 of 3)
  • 92. Ex7: The Code Under Test case types.MARK_SEAT_SOLD: newState = state.map((row) => { return row.map((seat) => { if (seat.seatNumber === action.seat.seatNumber) { const updatedSeat = Object.assign({}, seat); updatedSeat.selected = false; updatedSeat.sold = true; return updatedSeat; } else { return seat; } }); }); return newState; break; default: return state; } } ex7-mocha-enzyme-es6-react-router-redux/src/reducers/seatReducer.js (part 3 of 3)
  • 93. Resources • https://facebook.github.io/react/docs/test-utils.html 🚫 • https://github.com/airbnb/enzyme • https://semaphoreci.com/community/tutorials/testing- react-components-with-enzyme-and- mocha#comments • https://facebook.github.io/jest/ • https://egghead.io/courses/react-testing-cookbook
  • 94. Contact • @vanwilson on Twitter • [email protected] • vanwilson.info (where I blog once or twice a year)
  • 96. Go forth, and test.