Skip to content

Commit 695f62b

Browse files
committed
chore: add js test with mocha and chai
This commit adds a JS unit testing framework with mocha and chai. Sample unit tests are provided for Comment and CommentList.
1 parent 98894c7 commit 695f62b

File tree

8 files changed

+163
-8
lines changed

8 files changed

+163
-8
lines changed

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ module.exports = {
183183
// And update this
184184
styleLoader: 'style-loader!css-loader!sass-loader?imagePath=/assets/images&includePaths[]=' + bourbonPaths,
185185
```
186-
- `@import 'bourbon';` Import bourbon from your [scss file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss)
186+
- `@import 'bourbon';` Import bourbon from your [scss file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss)
187187

188188
# Notes on Rails assets
189189
## Rails Asset Pipeline Magic
@@ -260,11 +260,31 @@ git push heroku master
260260
```
261261

262262
# Running Tests
263-
*Default rake task runs tests and linting*
263+
*Default rake task runs feature specs, mocha tests and linting*
264264

265-
We have feature tests in /spec/features
265+
We have;
266+
267+
* feature tests in /spec/features
268+
* component unit tests in /client/test/
269+
* javascript linting with ESLint
270+
271+
From the root of the project, you can run all specs+tests+linter with
272+
273+
npm run test
274+
275+
Run the feature specs individually with `rspec`.
276+
277+
Run the React unit tests (all .js and .jsx files) from the `client` dir with;
278+
279+
cd client
280+
npm run test --silent
281+
282+
In lieu of having `mocha --watch` working properly (pull request welcome!), you can have your js tests continually running with `watch`
283+
284+
npm install -g watch
285+
cd client
286+
watch 'npm run test --silent' test/ app/
266287

267-
Run the tests with `rspec`.
268288

269289
## CI configuration
270290
Add those lines to your CI scripts after `bundle install`

client/.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ plugins:
99
env:
1010
browser: true
1111
node: true
12+
mocha: true
1213

1314
rules:
1415
indent: [1, 2, { SwitchCase: 1, VariableDeclarator: 2 }]

client/app/components/Comment.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Comment = React.createClass({
1717
<h2 className="comment-author">
1818
{author}
1919
</h2>
20-
<span dangerouslySetInnerHTML={{__html: rawMarkup}}/>
20+
<span dangerouslySetInnerHTML={{__html: rawMarkup}} className="comment-text"/>
2121
</div>
2222
);
2323
},

client/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
},
2525
"homepage": "https://github.com/shakacode/react-webpack-rails-tutorial",
2626
"scripts": {
27-
"test": "echo \"Error: no test specified\" && exit 1",
27+
"test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js 'test/**/*.@(js|jsx)'",
28+
"test:debug": "npm run test -- --debug-brk",
2829
"start": "node server.js",
2930
"build:client": "NODE_ENV=production webpack --config webpack.client.rails.config.js",
3031
"build:server": "NODE_ENV=production webpack --config webpack.server.rails.config.js",
@@ -63,6 +64,8 @@
6364
"babel-plugin-react-transform": "^1.1.1",
6465
"bootstrap-sass": "^3.3.5",
6566
"bootstrap-sass-loader": "^1.0.9",
67+
"chai": "^3.4.0",
68+
"chai-immutable": "^1.4.0",
6669
"css-loader": "^0.19.0",
6770
"eslint": "^1.6.0",
6871
"eslint-config-airbnb": "0.1.0",
@@ -72,7 +75,9 @@
7275
"file-loader": "^0.8.4",
7376
"jade": "^1.11.0",
7477
"jscs": "^2.3.0",
78+
"mocha": "^2.3.3",
7579
"node-sass": "^3.3.3",
80+
"react-addons-test-utils": "^0.14.1",
7681
"react-transform-hmr": "^1.0.1",
7782
"sass-loader": "^3.0.0",
7883
"style-loader": "^0.12.4",
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { React, expect, TestUtils } from '../test_helper';
2+
import { List, Map } from 'immutable';
3+
import CommentList from '../../app/components/CommentList';
4+
import Comment from '../../app/components/Comment';
5+
6+
const {
7+
renderIntoDocument,
8+
findRenderedDOMComponentWithTag,
9+
scryRenderedComponentsWithType,
10+
} = TestUtils;
11+
12+
describe('CommentList', () => {
13+
const comments = List.of(
14+
new Map({
15+
author: 'Frank',
16+
text: 'hi',
17+
}),
18+
new Map({
19+
author: 'Furter',
20+
text: 'ho',
21+
}),
22+
);
23+
24+
it('renders a list of Comments in reverse order', () => {
25+
const component = renderIntoDocument(
26+
<CommentList $$comments={comments}/>
27+
);
28+
const list = scryRenderedComponentsWithType(component, Comment);
29+
expect(list.length).to.equal(2);
30+
expect(list[0].props.author).to.equal('Furter');
31+
expect(list[1].props.author).to.equal('Frank');
32+
});
33+
34+
it('renders an alert if errors', () => {
35+
const component = renderIntoDocument(
36+
<CommentList $$comments={comments} error="zomg" />
37+
);
38+
39+
const alert = findRenderedDOMComponentWithTag(component, 'strong');
40+
expect(alert.textContent).to.equal('Comments could not be retrieved. ');
41+
});
42+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { React, expect, TestUtils } from '../test_helper';
2+
import Comment from '../../app/components/Comment';
3+
4+
const {
5+
renderIntoDocument,
6+
findRenderedDOMComponentWithClass,
7+
findRenderedDOMComponentWithTag,
8+
} = TestUtils;
9+
10+
describe('Comment', () => {
11+
it('renders an author and comment with proper css classes', () => {
12+
const component = renderIntoDocument(
13+
<Comment author="Frank" text="Hi!"/>
14+
);
15+
16+
const comment = findRenderedDOMComponentWithTag(component, 'div');
17+
expect(comment.className).to.equal('comment');
18+
const author = findRenderedDOMComponentWithTag(component, 'h2');
19+
expect(author.className).to.equal('comment-author');
20+
const text = findRenderedDOMComponentWithTag(component, 'span');
21+
expect(text.className).to.equal('comment-text');
22+
});
23+
24+
it('shows the author', () => {
25+
const component = renderIntoDocument(
26+
<Comment author="Frank" text="Hi!"/>
27+
);
28+
29+
const author = findRenderedDOMComponentWithClass(component, 'comment-author');
30+
expect(author.textContent).to.equal('Frank');
31+
});
32+
33+
it('shows the comment text in markdown', () => {
34+
const component = renderIntoDocument(
35+
<Comment author="Frank" text="Hi!"/>
36+
);
37+
38+
const comment = findRenderedDOMComponentWithClass(component, 'comment-text');
39+
expect(comment.textContent).to.equal('Hi!\n');
40+
});
41+
});

client/test/test_helper.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import TestUtils from 'react-addons-test-utils';
3+
import jsdom from 'jsdom';
4+
import chai from 'chai';
5+
import chaiImmutable from 'chai-immutable';
6+
7+
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>');
8+
const win = doc.defaultView;
9+
10+
global.document = doc;
11+
global.window = win;
12+
13+
// from mocha-jsdom https://github.com/rstacruz/mocha-jsdom/blob/master/index.js#L80
14+
function propagateToGlobal(window) {
15+
for (const key in window) {
16+
if (!window.hasOwnProperty(key)) continue;
17+
if (key in global) continue;
18+
19+
global[key] = window[key];
20+
}
21+
}
22+
// take all properties of the window object and also attach it to the
23+
// mocha global object
24+
propagateToGlobal(win);
25+
26+
// everything we need for our tests
27+
const {
28+
assert, expect,
29+
} = chai;
30+
31+
chai.use(chaiImmutable);
32+
33+
export {
34+
React,
35+
chai,
36+
assert,
37+
expect,
38+
TestUtils,
39+
};

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
},
1010
"scripts": {
1111
"postinstall": "cd client && npm install",
12-
"test": "rspec && (cd client && npm run lint)"
12+
"test": "rspec && npm run test:client",
13+
"test:client": "(cd client && npm run test --silent && npm run eslint --silent)"
1314
},
1415
"repository": {
1516
"type": "git",
@@ -27,5 +28,11 @@
2728
"url": "https://github.com/shakacode/react-webpack-rails-tutorial/issues"
2829
},
2930
"homepage": "https://github.com/shakacode/react-webpack-rails-tutorial",
30-
"dependencies": {}
31+
"dependencies": {},
32+
"devDependencies": {
33+
"chai": "^3.4.0",
34+
"chai-immutable": "^1.4.0",
35+
"jsdom": "^7.0.2",
36+
"mocha": "^2.3.3"
37+
}
3138
}

0 commit comments

Comments
 (0)