Skip to content

Commit 27ea659

Browse files
committed
feat(test): add ava test runner with some tests
1 parent 5fa605d commit 27ea659

20 files changed

+558
-223
lines changed

.eslintrc

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
{
2-
"extends": "airbnb",
2+
"extends": [
3+
"airbnb",
4+
"plugin:ava/recommended"
5+
],
36
"parser": "babel-eslint",
7+
"plugins": [
8+
"ava"
9+
],
410
"env": {
511
"browser": true,
612
"node": true,
@@ -18,7 +24,11 @@
1824
"arrow-body-style": [0],
1925
"react/jsx-no-bind": [0]
2026
},
21-
"globals": {
22-
"webpackIsomorphicTools": true
27+
"settings": {
28+
"import/resolver": {
29+
"webpack": {
30+
"config": "./webpack.config.dev.js"
31+
}
32+
}
2333
}
2434
}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ dump.rdb
66
.vscode/
77
public/*
88
dist
9+
coverage/
10+
.nyc_output/

client/modules/App/App.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Footer from './components/Footer/Footer';
1313
// Import Actions
1414
import { toggleAddPost } from './AppActions';
1515

16-
class App extends Component {
16+
export class App extends Component {
1717
constructor(props) {
1818
super(props);
1919
this.state = { isMounted: false };
@@ -30,7 +30,7 @@ class App extends Component {
3030
render() {
3131
return (
3232
<div>
33-
{this.state.isMounted && !window.devToolsExtension && <DevTools />}
33+
{this.state.isMounted && !window.devToolsExtension && process.env.NODE_ENV === 'development' && <DevTools />}
3434
<div>
3535
<Helmet
3636
title="MERN Starter - Blog App"
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from 'react';
2+
import test from 'ava';
3+
import sinon from 'sinon';
4+
import { shallow, mount } from 'enzyme';
5+
import { App } from '../App';
6+
import styles from '../App.css';
7+
import { toggleAddPost } from '../AppActions';
8+
9+
const children = <h1>Test</h1>;
10+
const dispatch = sinon.spy();
11+
const props = {
12+
children,
13+
dispatch,
14+
};
15+
16+
test('renders properly', t => {
17+
const wrapper = shallow(
18+
<App {...props} />
19+
);
20+
21+
// t.is(wrapper.find('Helmet').length, 1);
22+
t.is(wrapper.find('Header').length, 1);
23+
t.is(wrapper.find('Footer').length, 1);
24+
t.is(wrapper.find('Header').prop('toggleAddPost'), wrapper.instance().toggleAddPostSection);
25+
t.truthy(wrapper.find('Header + div').hasClass(styles.container));
26+
t.truthy(wrapper.find('Header + div').children(), children);
27+
});
28+
29+
test('calls componentDidMount', t => {
30+
sinon.spy(App.prototype, 'componentDidMount');
31+
mount(
32+
<App {...props} />,
33+
{
34+
context: {
35+
router: {
36+
isActive: sinon.stub().returns(true),
37+
push: sinon.stub(),
38+
replace: sinon.stub(),
39+
go: sinon.stub(),
40+
goBack: sinon.stub(),
41+
goForward: sinon.stub(),
42+
setRouteLeaveHook: sinon.stub(),
43+
createHref: sinon.stub(),
44+
},
45+
},
46+
childContextTypes: {
47+
router: React.PropTypes.object,
48+
},
49+
},
50+
);
51+
52+
t.truthy(App.prototype.componentDidMount.calledOnce);
53+
App.prototype.componentDidMount.restore();
54+
});
55+
56+
test('calling toggleAddPostSection dispatches toggleAddPost', t => {
57+
const wrapper = shallow(
58+
<App {...props} />
59+
);
60+
61+
wrapper.instance().toggleAddPostSection();
62+
t.truthy(dispatch.calledOnce);
63+
t.truthy(dispatch.calledWith(toggleAddPost()));
64+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import test from 'ava';
2+
import { actionTest } from 'redux-ava';
3+
import { TOGGLE_ADD_POST, toggleAddPost } from '../AppActions';
4+
5+
test('should return the correct type for toggleAddPost', actionTest(toggleAddPost, null, { type: TOGGLE_ADD_POST }));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import test from 'ava';
2+
import { reducerTest } from 'redux-ava';
3+
import appReducer from '../AppReducer';
4+
import { toggleAddPost } from '../AppActions';
5+
6+
test('action for TOGGLE_ADD_POST is working', reducerTest(
7+
appReducer,
8+
{ showAddPost: false },
9+
toggleAddPost(),
10+
{ showAddPost: true },
11+
));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
import test from 'ava';
3+
import { shallow } from 'enzyme';
4+
import Footer from '../../components/Footer/Footer';
5+
6+
test('renders the footer properly', t => {
7+
const wrapper = shallow(
8+
<Footer />
9+
);
10+
11+
t.is(wrapper.find('p').length, 2);
12+
t.is(wrapper.find('p').first().text(), '© 2016 · Hashnode · LinearBytes Inc.');
13+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React from 'react';
2+
import test from 'ava';
3+
import sinon from 'sinon';
4+
import { shallow } from 'enzyme';
5+
import Header from '../../components/Header/Header';
6+
7+
test('renders the header properly', t => {
8+
const router = {
9+
isActive: sinon.stub().returns(true),
10+
};
11+
const wrapper = shallow(
12+
<Header toggleAddPost={() => {}} />,
13+
{
14+
context: {
15+
router,
16+
},
17+
}
18+
);
19+
20+
t.regex(wrapper.find('Link').first().html(), /MERN Starter Blog/);
21+
t.is(wrapper.find('a').length, 1);
22+
});
23+
24+
test('doesn\'t add post in pages other than home', t => {
25+
const router = {
26+
isActive: sinon.stub().returns(false),
27+
};
28+
const wrapper = shallow(
29+
<Header toggleAddPost={() => {}} />,
30+
{
31+
context: {
32+
router,
33+
},
34+
}
35+
);
36+
37+
t.is(wrapper.find('a').length, 0);
38+
});
39+
40+
test('toggleAddPost called properly', t => {
41+
const router = {
42+
isActive: sinon.stub().returns(true),
43+
};
44+
const toggleAddPost = sinon.spy();
45+
const wrapper = shallow(
46+
<Header toggleAddPost={toggleAddPost} />,
47+
{
48+
context: {
49+
router,
50+
},
51+
}
52+
);
53+
54+
wrapper.find('a').first().simulate('click');
55+
t.truthy(toggleAddPost.calledOnce);
56+
});

client/modules/Post/PostActions.js

-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ const baseURL = typeof window === 'undefined' ? process.env.BASE_URL || (`http:/
55

66
// Export Constants
77
export const ADD_POST = 'ADD_POST';
8-
export const CHANGE_SELECTED_POST = 'CHANGE_SELECTED_POST';
9-
export const ADD_POST_REQUEST = 'ADD_POST_REQUEST';
108
export const ADD_POSTS = 'ADD_POSTS';
119
export const ADD_SELECTED_POST = 'ADD_SELECTED_POST';
1210
export const DELETE_POST = 'DELETE_POST';

client/modules/Post/PostReducer.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ADD_POST, CHANGE_SELECTED_POST, ADD_POSTS, ADD_SELECTED_POST, DELETE_POST } from './PostActions';
1+
import { ADD_POST, ADD_POSTS, ADD_SELECTED_POST, DELETE_POST } from './PostActions';
22

33
const initialState = { posts: [], post: null };
44

@@ -16,12 +16,6 @@ const PostReducer = (state = initialState, action) => {
1616
}, ...state.posts],
1717
post: state.post };
1818

19-
case CHANGE_SELECTED_POST :
20-
return {
21-
posts: state.posts,
22-
post: action.slug,
23-
};
24-
2519
case ADD_POSTS :
2620
return {
2721
posts: action.posts,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import test from 'ava';
2+
import { actionTest } from 'redux-ava';
3+
import {
4+
ADD_POST,
5+
ADD_SELECTED_POST,
6+
DELETE_POST,
7+
ADD_POSTS,
8+
addPost,
9+
addSelectedPost,
10+
deletePost,
11+
addPosts,
12+
} from '../PostActions';
13+
14+
const post = { name: 'Prashant', title: 'Hello Mern', cuid: 'f34gb2bh24b24b2', content: "All cats meow 'mern!'", slug: 'hello-mern', _id: 1 };
15+
16+
test('should return the correct type for addPost', actionTest(addPost, post, {
17+
type: ADD_POST,
18+
name: post.name,
19+
title: post.title,
20+
content: post.content,
21+
slug: post.slug,
22+
cuid: post.cuid,
23+
_id: post._id,
24+
}));
25+
26+
test('should return the correct type for addSelectedPost', actionTest(deletePost, post, { type: DELETE_POST, post }));
27+
28+
test('should return the correct type for deletePost', actionTest(addSelectedPost, post, { type: ADD_SELECTED_POST, post }));
29+
30+
test('should return the correct type for addPosts', actionTest(addPosts, [post], {
31+
type: ADD_POSTS,
32+
posts: [post],
33+
}));

0 commit comments

Comments
 (0)