Created
August 21, 2016 13:52
React UnitTest Practice
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"presets": [ | |
"es2015", | |
"react" | |
], | |
"env": { | |
"development": { | |
"presets": [ | |
"power-assert" | |
] | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### https://raw.github.com/github/gitignore/ef8772f1346e95272f6ee2fa76ce502c88444a7b/Node.gitignore | |
# Logs | |
logs | |
*.log | |
npm-debug.log* | |
# Runtime data | |
pids | |
*.pid | |
*.seed | |
*.pid.lock | |
# Directory for instrumented libs generated by jscoverage/JSCover | |
lib-cov | |
# Coverage directory used by tools like istanbul | |
coverage | |
# nyc test coverage | |
.nyc_output | |
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | |
.grunt | |
# node-waf configuration | |
.lock-wscript | |
# Compiled binary addons (http://nodejs.org/api/addons.html) | |
build/Release | |
# Dependency directories | |
node_modules | |
jspm_packages | |
# Optional npm cache directory | |
.npm | |
# Optional REPL history | |
.node_repl_history | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
export class BeerListContainer extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
beers: [] | |
} | |
this.addItem = this.addItem.bind(this); | |
} | |
render() { | |
return ( | |
<div> | |
<InputArea onSubmit={this.addItem} /> | |
<BeerList items={this.state.beers} /> | |
</div> | |
); | |
} | |
addItem(name) { | |
this.setState({ | |
beers: [].concat(this.state.beers).concat([name]) | |
}); | |
} | |
} | |
export class InputArea extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
text: '' | |
}; | |
this.setText = this.setText.bind(this); | |
this.handleClick = this.handleClick.bind(this); | |
} | |
render() { | |
return ( | |
<div> | |
<input value={this.state.text} onChange={this.setText} /> | |
<button onClick={this.handleClick}>Add</button> | |
</div> | |
); | |
} | |
handleClick() { | |
this.props.onSubmit(this.state.text); | |
} | |
setText(event) { | |
this.setState({ | |
text: event.target.value | |
}); | |
} | |
} | |
InputArea.propTypes = { | |
onSubmit: React.PropTypes.func.isRequired | |
}; | |
export class BeerList extends Component { | |
render() { | |
return this.props.items ? ( | |
<ul> | |
{this.props.items.map((item, index) => ( | |
<li key={index}>{item}</li> | |
))} | |
</ul> | |
) : null; | |
} | |
} | |
BeerList.propTypes = { | |
items: React.PropTypes.array.isRequired | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const assert = require('assert'); | |
import { spy } from 'sinon'; | |
import React from 'react'; | |
import { shallow, mount } from 'enzyme'; | |
import { BeerListContainer, InputArea, BeerList } from './components'; | |
describe('BeerListContainer', () => { | |
it('should render InputArea and BeerList', () => { | |
const wrapper = shallow(<BeerListContainer />); | |
assert.ok(wrapper.containsAllMatchingElements([ | |
<InputArea />, | |
<BeerList /> | |
])); | |
}); | |
it('should start with an empty list', () => { | |
const wrapper = shallow(<BeerListContainer />); | |
const beers = wrapper.state('beers'); | |
assert.ok(Array.isArray(beers)); | |
assert(beers.length === 0); | |
}); | |
it('adds items to the list', () => { | |
const wrapper = shallow(<BeerListContainer />); | |
wrapper.instance().addItem('Sam Adams'); | |
assert(wrapper.state('beers')[0] === 'Sam Adams'); | |
}); | |
it('passes addItem to InputArea', () => { | |
const wrapper = shallow(<BeerListContainer />); | |
const inputArea = wrapper.find(InputArea); | |
const addItem = wrapper.instance().addItem; | |
assert(inputArea.prop('onSubmit') === addItem); | |
}); | |
it('passes a bound addItem function to InputArea', () => { | |
const wrapper = shallow(<BeerListContainer />); | |
const inputArea = wrapper.find(InputArea); | |
inputArea.prop('onSubmit')('Sam Adams'); | |
assert(wrapper.state('beers')[0] === 'Sam Adams'); | |
}); | |
}); | |
describe('InputArea', () => { | |
it('should contain an input and a button', () => { | |
const wrapper = shallow(<InputArea />); | |
// assertのなかでcontainsAllMatchingElementsするとパースエラーになる | |
const result = wrapper.containsAllMatchingElements([ | |
<input/>, | |
<button>Add</button> | |
]); | |
assert.ok(result); | |
}); | |
it('should accept input', () => { | |
const wrapper = mount(<InputArea />); | |
const input = wrapper.find('input'); | |
input.simulate('change', { target: { value: 'Resin' } }); | |
assert(wrapper.state('text') === 'Resin'); | |
assert(input.prop('value') === 'Resin'); | |
}); | |
it('should call onSubmit when Add is clicked', () => { | |
const addItemSpy = spy(); | |
const wrapper = shallow(<InputArea onSubmit={addItemSpy} />); | |
wrapper.setState({ text: 'Octoberfest' }); | |
const addButton = wrapper.find('button'); | |
addButton.simulate('click'); | |
assert.ok(addItemSpy.calledOnce); | |
assert.ok(addItemSpy.calledWith('Octoberfest')); | |
}); | |
}); | |
describe('BeerList', () => { | |
it('should render zero items', () => { | |
const wrapper = shallow(<BeerList items={[]} />); | |
assert(wrapper.find('li').length === 0); | |
}); | |
it('should render undefined items', () => { | |
const wrapper = shallow(<BeerList items={undefined} />); | |
assert(wrapper.find('li').length === 0); | |
}); | |
it('should render some items', () => { | |
const items = ['Sam Adams', 'Resin', 'Octoberfest']; | |
const wrapper = shallow(<BeerList items={items} />); | |
assert(wrapper.find('li').length === 3); | |
}); | |
it('should render the items', () => { | |
const wrapper = mount(<BeerListContainer />); | |
wrapper.instance().addItem('Sam Adams'); | |
wrapper.instance().addItem('Resin'); | |
assert(wrapper.find('li').length === 2); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "react-test", | |
"version": "0.1.0", | |
"description": "React Unit Test", | |
"main": "components.js", | |
"scripts": { | |
"test": "mocha --require setup.js *.spec.js" | |
}, | |
"author": "", | |
"license": "ISC", | |
"devDependencies": { | |
"babel-preset-es2015": "^6.13.2", | |
"babel-preset-power-assert": "^1.0.0", | |
"babel-preset-react": "^6.11.1", | |
"babel-register": "^6.11.6", | |
"enzyme": "^2.4.1", | |
"eslint": "^3.3.1", | |
"jsdom": "^9.4.2", | |
"mocha": "^3.0.2", | |
"power-assert": "^1.4.1", | |
"react": "^15.3.0", | |
"react-addons-test-utils": "^15.3.0", | |
"react-dom": "^15.3.0", | |
"sinon": "^1.17.5" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment