Skip to content

Commit 853a310

Browse files
authored
Merge pull request #6 from simpletut/testingActions
tests for actions
2 parents 3149d8e + 9744756 commit 853a310

File tree

11 files changed

+289
-2
lines changed

11 files changed

+289
-2
lines changed

Utils/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import checkPropTypes from 'check-prop-types';
2+
import { applyMiddleware, createStore } from 'redux';
3+
import rootReducer from './../src/reducers';
4+
import { middlewares } from './../src/createStore';
25

36
export const findByTestAtrr = (component, attr) => {
47
const wrapper = component.find(`[data-test='${attr}']`);
@@ -8,4 +11,9 @@ export const findByTestAtrr = (component, attr) => {
811
export const checkProps = (component, expectedProps) => {
912
const propsErr = checkPropTypes(component.propTypes, expectedProps, 'props', component.name);
1013
return propsErr;
14+
};
15+
16+
export const testStore = (initialState) => {
17+
const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore);
18+
return createStoreWithMiddleware(rootReducer, initialState);
1119
};

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"axios": "^0.18.0",
67
"node-sass": "^4.11.0",
78
"prop-types": "^15.6.2",
89
"react": "^16.7.0",
@@ -32,6 +33,7 @@
3233
"enzyme": "^3.8.0",
3334
"enzyme-adapter-react-16": "^1.7.1",
3435
"jest": "^23.6.0",
35-
"jest-enzyme": "^7.0.1"
36+
"jest-enzyme": "^7.0.1",
37+
"moxios": "^0.4.0"
3638
}
3739
}

src/App.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import React, { Component } from 'react';
22
import Header from './component/header';
33
import Headline from './component/headline';
4+
import SharedButton from './component/button';
5+
import ListItem from './component/listItem';
6+
import { connect } from 'react-redux';
7+
import { fetchPosts } from './actions';
48
import './app.scss';
59

610
/* This const is not used within our app.
@@ -15,16 +19,54 @@ const tempArr = [{
1519
}];
1620

1721
class App extends Component {
22+
23+
constructor(props){
24+
super(props);
25+
this.fetch = this.fetch.bind(this);
26+
}
27+
28+
fetch(){
29+
this.props.fetchPosts();
30+
}
31+
1832
render() {
33+
const { posts } = this.props;
34+
35+
const configButton = {
36+
buttonText: 'Get posts',
37+
emitEvent: this.fetch
38+
}
39+
1940
return (
2041
<div className="App">
2142
<Header />
2243
<section className="main">
2344
<Headline header="Posts" desc="Click the button to render posts!" tempArr={tempArr} />
45+
<SharedButton {...configButton} />
46+
{posts.length > 0 &&
47+
<div>
48+
{posts.map((post, index) => {
49+
const { title, body } = post;
50+
const configListItem = {
51+
title,
52+
desc: body
53+
};
54+
return (
55+
<ListItem key={index} {...configListItem} />
56+
)
57+
})}
58+
</div>
59+
}
2460
</section>
2561
</div>
2662
);
2763
}
2864
}
2965

30-
export default App;
66+
const mapStateToProps = state => {
67+
return {
68+
posts: state.posts
69+
}
70+
}
71+
72+
export default connect(mapStateToProps, {fetchPosts})(App);

src/_integrationTests/spec.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import moxios from 'moxios';
2+
import { testStore } from './../../Utils';
3+
import { fetchPosts } from './../actions';
4+
5+
describe('fetchPosts action', () => {
6+
7+
beforeEach(() => {
8+
moxios.install();
9+
});
10+
11+
afterEach(() => {
12+
moxios.uninstall();
13+
});
14+
15+
test('Store is updated correctly', () => {
16+
17+
const expectedState = [{
18+
title: 'Example title 1',
19+
body: 'Some Text'
20+
},{
21+
title: 'Example title 2',
22+
body: 'Some Text'
23+
},{
24+
title: 'Example title 3',
25+
body: 'Some Text'
26+
}];
27+
const store = testStore();
28+
29+
moxios.wait(() => {
30+
const request = moxios.requests.mostRecent();
31+
request.respondWith({
32+
status: 200,
33+
response: expectedState
34+
})
35+
});
36+
37+
return store.dispatch(fetchPosts())
38+
.then(() => {
39+
const newState = store.getState();
40+
expect(newState.posts).toBe(expectedState);
41+
})
42+
43+
});
44+
45+
});

src/actions/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { types } from './types';
2+
import axios from 'axios';
3+
4+
export const fetchPosts = () => async (dispatch) => {
5+
await axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
6+
.then(res => {
7+
dispatch({
8+
type: types.GET_POSTS,
9+
payload: res.data
10+
})
11+
})
12+
.catch(err => {
13+
// console.log(err);
14+
})
15+
};

src/component/button/index.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
class SharedButton extends Component {
5+
6+
submitEvent(){
7+
if(this.props.emitEvent){
8+
this.props.emitEvent();
9+
}
10+
}
11+
12+
render(){
13+
const { buttonText } = this.props;
14+
15+
return(
16+
<button onClick={() => this.submitEvent()} data-test="buttonComponent">
17+
{buttonText}
18+
</button>
19+
);
20+
}
21+
}
22+
23+
SharedButton.propTypes = {
24+
buttonText: PropTypes.string,
25+
emitEvent: PropTypes.func
26+
};
27+
28+
export default SharedButton;

src/component/button/spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import { findByTestAtrr, checkProps } from './../../../Utils';
4+
import SharedButton from './index';
5+
6+
describe('SharedButton Component', () => {
7+
8+
describe('Checking PropTypes', () => {
9+
10+
it('Should NOT throw a warning', () => {
11+
const expectedProps = {
12+
buttonText: 'Example Button Text',
13+
emitEvent: () => {
14+
15+
}
16+
};
17+
const propsError = checkProps(SharedButton, expectedProps);
18+
expect(propsError).toBeUndefined();
19+
});
20+
21+
});
22+
23+
describe('Renders', () => {
24+
25+
let wrapper;
26+
beforeEach(() => {
27+
const props = {
28+
buttonText: 'Example Button Text',
29+
emitEvent: () => {
30+
31+
}
32+
};
33+
wrapper = shallow(<SharedButton {...props} />);
34+
});
35+
36+
it('Should Render a button', () => {
37+
const button = findByTestAtrr(wrapper, 'buttonComponent');
38+
expect(button.length).toBe(1);
39+
});
40+
41+
42+
});
43+
44+
45+
46+
47+
});

src/component/button/styles.scss

Whitespace-only changes.

src/component/listItem/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
class ListItem extends Component {
5+
6+
render() {
7+
const { title, desc } = this.props;
8+
9+
if(!title){
10+
return null;
11+
}
12+
13+
return(
14+
<div data-test="listItemComponent">
15+
<h2 data-test="componentTitle">{title}</h2>
16+
<div data-test="componentDesc">
17+
{desc}
18+
</div>
19+
</div>
20+
);
21+
}
22+
23+
}
24+
25+
ListItem.propTypes = {
26+
title: PropTypes.string,
27+
desc: PropTypes.string
28+
}
29+
30+
export default ListItem;

src/component/listItem/spec.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import { findByTestAtrr, checkProps } from './../../../Utils';
4+
import ListItem from './index';
5+
6+
describe('ListItem Component', () => {
7+
8+
describe('Checking PropTypes', () => {
9+
10+
it('Should NOT throw a warning', () => {
11+
const expectedProps = {
12+
title: 'Example Title',
13+
desc: 'Some text'
14+
};
15+
const propsError = checkProps(ListItem, expectedProps);
16+
expect(propsError).toBeUndefined();
17+
});
18+
19+
});
20+
21+
describe('Component Renders', () => {
22+
23+
let wrapper;
24+
beforeEach(() => {
25+
const props = {
26+
title: 'Example Title',
27+
desc: 'Some text'
28+
};
29+
wrapper = shallow(<ListItem {...props} />);
30+
});
31+
32+
it('Should renders without error', () => {
33+
const component = findByTestAtrr(wrapper, 'listItemComponent');
34+
expect(component.length).toBe(1);
35+
});
36+
37+
it('Should render a title', () => {
38+
const title = findByTestAtrr(wrapper, 'componentTitle');
39+
expect(title.length).toBe(1);
40+
});
41+
42+
it('Should render a desc', () => {
43+
const desc = findByTestAtrr(wrapper, 'componentDesc');
44+
expect(desc.length).toBe(1);
45+
});
46+
47+
48+
});
49+
50+
51+
describe('Should NOT render', () => {
52+
53+
let wrapper;
54+
beforeEach(() => {
55+
const props = {
56+
desc: 'Some text'
57+
};
58+
wrapper = shallow(<ListItem {...props} />);
59+
});
60+
61+
it('Component is not rendered', () => {
62+
const component = findByTestAtrr(wrapper, 'listItemComponent');
63+
expect(component.length).toBe(0);
64+
});
65+
66+
});
67+
68+
69+
});
70+

0 commit comments

Comments
 (0)