React / Redux Study via real examples: Testing
Welcome back to the React / Redux Learning series through practical examples , in the previous lesson, we completed the project setup and wrote the first React components. In this lesson, I will guide you through the setup to test React components. I will teach you basic testing without going too far into mastering testing!
For testing purposes, we will use mocha , a test framework, bottle custom libraries used for comparison, and jsdom a library gives us access to the DOM feature on the node.
Setting
From the root directory of the project, you install it as follows.
1 | npm install --save-dev mocha jsdom bottle |
Next we need a setup file to contain the config. From the root directory you create the test setup file as follows.
1 2 3 | mkdir test cd test touch setup.js |
Open the setup.js
file and start installing the test environment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import React from 'react'; import {expect} from 'bottle'; import jsdom from 'jsdom'; const document = jsdom.jsdom ('<! doctype html> <html> <body> </body> </html>'); const window = document.defaultView; global.document = document; global.window = window; Object.keys (window) .forEach ((key) => { if (! (key in global)) { global [key] = window [key]; } }); global.React = React; global.expect = expect; |
Basically, we expose a generated jsdom document and a window object to the global scope, these will be used by React during the test. In addition, we also need to expose all properties of the window object so that they can be used later. Last but not least it is to allow React objects as well as expect to be accessed at global scope. This helps us not to have to import them every time we want to test.
In the package.json
file we will add a new script to run the test, this script will use mocha as test framework, use the test/setup.js
file to install the environment and browse all the files with the extension *.spec.js
in the src
directory as test files.
1 2 3 4 5 6 | ... "scripts": { ... "test": "mocha --compilers js: babel-core / register --require ./test/setup.js 'src / ** / * spec.js'" }, ... |
In addition, we need some more neat libraries to help us test React components. Enzyme is a support library that simulates the state at the time of React component test. Let's install it!
1 | npm install --save-dev react-addons-test-utils enzyme |
Now what are you waiting for, start writing our first React component test file.
Put your hand on the keyboard to write test case!
In src/components
directory create TrackList.spec.js
file to test component TrackList
. Write the test case for the component in this file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import TrackList from './TrackList'; import {shallow} from 'enzyme'; describe ('TrackList', () => { it ('shows two tracks', () => { const props = { tracks: [{id: 1, title: 'foo'}, {id: 2, title: 'bar'}] }; const element = Shallow (<TrackList {... props} />); expect (element.find ('div')). to.have.length (2); }); }); |
This is test case I write to test component TrackList
. As we know, when this component will render the div
containing the title of the song, here I pass into the props
is a list of two songs so it will render two div
containing the song title. When running the test, it will have to pass.
Run the test with the npm test
command and see what results.
Wait, something is not right!
Eh, something seems to be wrong, the test runs fail, let's double check again, test case we give is to transfer the list of two songs to render
two div
, why is it wrong?
Looking back on the TrackList
component, well, it was wrapped by an external div
. Instead of finding the div
, we must find the div
of the div
. So the test case will be corrected as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import TrackList from './TrackList'; import {shallow} from 'enzyme'; describe ('TrackList', () => { it ('shows two tracks', () => { const props = { tracks: [{id: 1, title: 'foo'}, {id: 2, title: 'bar'}] }; const element = Shallow (<TrackList {... props} />); expect (element.find ('div> div')). to.have.length (2); }); }); |
Let's run the test again.
Great, pass test. Actually, I deliberately wrote a test fail to show you how the test fail face looks like, not a bad code, haha.
Get the momentum to write more test cases, this time we will test whether the component render
the song name correctly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import TrackList from './TrackList'; import {shallow} from 'enzyme'; describe ('TrackList', () => { ... it ('shows track title', () => { const props = { tracks: [{id: 1, title: 'foo'}] } const element = Shallow (<TrackList {... props} />); expect (element.contains ('foo')). to.be.true; }) }); |
Let's run the test, this time how to pass, I calculated it all.
In addition, we can add the script to package.json
to watch during the development process locally, any edits make the test fail we can see.
1 2 3 4 5 6 | ... "scripts": { ... "test: watch": "npm run test - --watch" }, ... |
To run, simply enter the npm run test:watch
command npm run test:watch
.
Source code in the lesson you can find at https://github.com/codeaholicguy/react-redux-tutorial/tree/master/testing-setup
Today is enough, I won't write any more test cases. Feel free to create more test cases, boring to wait for the next lesson, the next lesson will touch Redux
! Any comment, don't forget to leave me below the post, goodbye!
ITZone via codealohicguy