Test stack in CM project
MSD.js
and what we learned
Comparator modelling in July 2016
- React.js + alt.js
- No single unit test
- Antipatters (this.props.items.push(...))
- Requests being made inside stores
- Constantly failing robot tests as a result
- Unstable project after just 1/2 year of development

Building unit tests - questions
- What to test? Where to start?
- Stack ready to use vs. custom stack on top of current one?
Our test stack
-
Mocha
- our choice for test framework
-
Sinon
- library for mocking API requests, action calls, time etc.
-
Chai.js
- assertion library with fabulous grammar
-
Enzyme
- Utility to help with React.js components
-
Karma
- test runner because several components are depending heavily on browser environment
Sinon - what we learned
- version 1.x doesn't work well with webpack
import sinon from 'sinon'
// undefined' is not an object (evaluating 'modules[moduleId].call')// webpack configuration
resolve: {
alias: {
// it's necessary to import dist instead of sinon module
// exported by default and this hides this ugly fact from us
sinon: 'sinon/pkg/sinon.js'
}
}Sinon
// some tested code
callAsync = (cb) => {
doStuff();
setTimeout(cb, 300);
};
// test
const fakedClocks = sinon.useFakeTimers();
const spy = sinon.spy();
callAsync(spy);
fakedClocks.tick(310);
expect(spy).to.have.been.calledOnce;
fakedClocks.restore();
Chai.js
- Really rich grammar + lot of useful plugins:
it('shows table header', function () {
const headerContent = tableHeaderWrapper.find('.header-content');
expect(headerContent).to.be.present();
expect(headerContent).to.contain.text('Author name');
});
it('does not show filter popup by default', function () {
expect(tableHeaderWrapper.find('FilterContainer')).to.not.be.present();
});Enzyme
render, shallow, mount - what to use?
-
render
-
when you are interested only in html
-
-
shallow
- interactions - clicks, mouse events etc.
-
mount
- when you need DOM or lifecycle methods
Enzyme
Component displayName is important
const Loading = (props) => {
const msg = props.message || 'Loading...';
return (
<div className='loading__wrap'>
<div className='loading__inner'>
<img
src={loading}
className='loading__spinner'
alt='loading'
/>
<p>{msg}</p>
</div>
</div>
);
};
// won't work without it:
// expect(parentComponent.find('Loading')).to.be.present();
Loading.displayName = 'Loading';
export default Loading;What we learned?
- Building stack is harsh
- There are ready-to-use solutions
- Don't plan unit testing, just start
test-stack-msd
By Jaroslav Kubíček
test-stack-msd
- 236