Skip to content

Commit 504d092

Browse files
committed
Exercise for testing react component
1 parent 003aa1b commit 504d092

File tree

16 files changed

+1335
-65
lines changed

16 files changed

+1335
-65
lines changed

exercises/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["env", "react", "stage-1"]
3+
}

exercises/package.json

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,33 @@
1010
"react-helmet": "^5.2.0",
1111
"react-router-dom": "^4.2.2",
1212
"react-scripts": "1.1.0",
13-
"styled-components": "^3.2.5"
13+
"styled-components": "^3.2.5",
14+
"classnames": "^2.2.5",
15+
"prop-types": "^15.6.1",
16+
"react-redux": "^5.0.7",
17+
"redux": "^3.7.2"
18+
},
19+
"devDependencies": {
20+
"babel-core": "^6.26.0",
21+
"babel-jest": "^22.4.3",
22+
"babel-loader": "^7.1.4",
23+
"babel-polyfill": "^6.26.0",
24+
"babel-preset-env": "^1.6.1",
25+
"babel-preset-react": "^6.24.1",
26+
"babel-preset-stage-1": "^6.22.0",
27+
"enzyme": "^3.3.0",
28+
"enzyme-adapter-react-16": "^1.1.1",
29+
"jest": "^22.4.3",
30+
"react-test-renderer": "^16.2.0"
1431
},
15-
"devDependencies": {},
1632
"scripts": {
1733
"start": "react-scripts start",
1834
"build": "react-scripts build",
19-
"test": "react-scripts test --env=jsdom",
35+
"test": "jest --watch",
2036
"eject": "react-scripts eject"
37+
},
38+
"jest": {
39+
"setupFiles": ["<rootDir>/tests/setup.js"],
40+
"testEnvironment": "node"
2141
}
2242
}

exercises/src/App.js

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,40 @@ import React, { Component } from "react";
22
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
33
import PerformanceOptimizations from "./performance-optimizations";
44
import ErrorBoundaries from "./error-boundaries";
5+
import { Provider } from 'react-redux'
6+
import { createStore } from "redux";
7+
8+
import reducer from ".testing-react-component/components/CounterStore/reducer";
9+
10+
const store = createStore(reducer)
511

612
class App extends Component {
713
render() {
814
return (
9-
<Router>
10-
<div className="container">
11-
<div className="sidebar">
12-
<ul>
13-
<li>
14-
<Link to="/">Refs</Link>
15-
</li>
16-
<li>
17-
<Link to="/performance-optimizations">perfromance optimizations</Link>
18-
</li>
19-
<li>
20-
<Link to="/error-boundaries">Error Boundaries</Link>
21-
</li>
22-
</ul>
23-
</div>
24-
<div className="content">
25-
<Route exact path="/" component={PerformanceOptimizations} />
26-
<Route path="/performance-optimizations" component={PerformanceOptimizations} />
27-
<Route path="/error-boundaries" component={ErrorBoundaries} />
15+
<Provider store={store}>
16+
<Router>
17+
<div className="container">
18+
<div className="sidebar">
19+
<ul>
20+
<li>
21+
<Link to="/">Refs</Link>
22+
</li>
23+
<li>
24+
<Link to="/performance-optimizations">perfromance optimizations</Link>
25+
</li>
26+
<li>
27+
<Link to="/error-boundaries">Error Boundaries</Link>
28+
</li>
29+
</ul>
30+
</div>
31+
<div className="content">
32+
<Route exact path="/" component={PerformanceOptimizations} />
33+
<Route path="/performance-optimizations" component={PerformanceOptimizations} />
34+
<Route path="/error-boundaries" component={ErrorBoundaries} />
35+
</div>
2836
</div>
29-
</div>
30-
</Router>
37+
</Router>
38+
</Provider>
3139
);
3240
}
3341
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Testing React Component
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React from "react";
2+
import { shallow } from "enzyme";
3+
import renderer from "react-test-renderer";
4+
import Button from ".";
5+
6+
// Exasice #1
7+
describe("Rendering", () => {
8+
// A sample test.
9+
it("Should render a button", () => {
10+
const wrapper = shallow(<Button />);
11+
expect(wrapper.find('button').length).toEqual(1);
12+
});
13+
14+
it("Should render defaults", () => {
15+
// Write test here for default button
16+
// ...
17+
});
18+
19+
describe("Render based on size", () => {
20+
it("Small Button", () => {
21+
// Write test here for 'small' button.
22+
// ...
23+
});
24+
25+
it("Medium Button", () => {
26+
// Write test here for 'medium' button.
27+
// ...
28+
});
29+
30+
it("Large Button", () => {
31+
// Write test here for 'large' button.
32+
// ...
33+
});
34+
});
35+
36+
describe("Button disabled based on props", () => {
37+
it("Button should have disabled attribute", () => {
38+
const wrapper = shallow(<Button disabled={true}/>);
39+
// Expect a button with disabled props
40+
// ...
41+
});
42+
43+
it("Button should not have disabled attribute", () => {
44+
const wrapper = shallow(<Button disabled={false}/>);
45+
// Expect a button without disabled props
46+
// ...
47+
});
48+
49+
it("Button should be disabled class", () => {
50+
const wrapper = shallow(<Button disabled={true}/>);
51+
// Expect a button with disabled class
52+
// ...
53+
});
54+
55+
it("Button should be disabled class", () => {
56+
const wrapper = shallow(<Button disabled={false}/>);
57+
// Expect a button without disabled class
58+
// ...
59+
});
60+
});
61+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from "react";
2+
import { shallow } from "enzyme";
3+
import Button from ".";
4+
5+
// Exasice #2
6+
describe("Interaction", () => {
7+
it("Callback props onClick", () => {
8+
// Write test for button click. Tips: Use a mock (spy) function.
9+
const spyFunc = jest.fn()
10+
// ...
11+
})
12+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from "react";
2+
import PropTypes from "prop-types";
3+
import classnames from "classnames";
4+
5+
const Button = (props) => {
6+
const btnClasses = classnames(props.className, "btn", {
7+
"btn-sm": props.size === "small",
8+
"btn-md": props.size === "medium",
9+
"btn-lg": props.size === "large",
10+
"disabled": props.disabled === true
11+
});
12+
13+
return (
14+
<button className={ btnClasses } onClick={props.onClick} disabled={props.disabled}>
15+
{ props.children }
16+
</button>
17+
);
18+
}
19+
20+
Button.propTypes = {
21+
disabled: PropTypes.bool,
22+
children: PropTypes.string,
23+
size: PropTypes.oneOf(["small", "medium", "large"]),
24+
onClick: PropTypes.func
25+
};
26+
27+
Button.defaultProps = {
28+
disabled: false,
29+
children: "Button",
30+
size: "medium",
31+
onClick: () => {}
32+
};
33+
34+
export default Button;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from "react";
2+
import { shallow } from "enzyme";
3+
import Counter from ".";
4+
5+
// Exasice #3
6+
describe("Initial state of the counter", () => {
7+
8+
// A Sample bad test
9+
it("initial state in bad way", () => {
10+
const wrapper = shallow(<Counter />);
11+
expect(wrapper.state().count).toEqual(0);
12+
});
13+
14+
it("initial state should be 0", () => {
15+
// We should write test from the user prospective.
16+
// ...
17+
});
18+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from "react";
2+
import { shallow } from "enzyme";
3+
import Counter from ".";
4+
5+
// Exasice #4
6+
describe("User interactions on counter", () => {
7+
8+
it("increment the count when the increment button is clicked", () => {
9+
const wrapper = shallow(<Counter />);
10+
// ...
11+
wrapper.find('Button.increment').simulate('click');
12+
expect(wrapper.find(".count").text()).toEqual("1");
13+
});
14+
15+
it("decrement the count when the decrement button is clicked", () => {
16+
const wrapper = shallow(<Counter />);
17+
// ...
18+
wrapper.find('Button.decrement').simulate('click');
19+
expect(wrapper.find(".count").text()).toEqual("-1");
20+
});
21+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React, { Component } from "react";
2+
3+
import Button from "../Button";
4+
5+
class Counter extends Component {
6+
constructor(props) {
7+
super(props);
8+
this.state = {
9+
count: 0
10+
}
11+
12+
this.increment = this.increment.bind(this);
13+
this.decrement = this.decrement.bind(this);
14+
}
15+
16+
increment() {
17+
this.setState(prevState => ({ count: prevState.count + 1 }));
18+
};
19+
20+
decrement() {
21+
this.setState(prevState => ({ count: prevState.count - 1 }));
22+
};
23+
24+
render() {
25+
return (
26+
<div className="counter-card">
27+
<h2 className="count">{this.state.count}</h2>
28+
<Button
29+
className="increment"
30+
onClick={this.increment}
31+
>
32+
Increment
33+
</Button>
34+
<Button
35+
className="decrement"
36+
onClick={this.decrement}
37+
>
38+
Decrement
39+
</Button>
40+
</div>
41+
);
42+
}
43+
}
44+
45+
export default Counter;
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 { shallow } from 'enzyme'
3+
import { counterIncrement, counterDecrement } from './actions'
4+
5+
import { Counter } from './index'
6+
7+
describe('Counter component connected with redux store', () => {
8+
9+
// A sample test
10+
it('should renders the count', () => {
11+
const props = {
12+
dispatch: jest.fn(),
13+
count: 1
14+
}
15+
16+
const wrapper = shallow(<Counter {...props} />)
17+
expect(wrapper.find('.count').text()).toEqual('1')
18+
})
19+
20+
it('dispatches the right action for incrementing', () => {
21+
const props = {
22+
dispatch: jest.fn(),
23+
count: 3
24+
}
25+
26+
// Write the test here
27+
// ...
28+
})
29+
30+
it('dispatches the right action for decrementing', () => {
31+
const props = {
32+
dispatch: jest.fn(),
33+
count: 3
34+
}
35+
36+
// Write the test here
37+
// ...
38+
})
39+
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const COUNTER_INCREMENT = '@@Counter/COUNTER_INCREMENT';
2+
export const COUNTER_DECREMENT = '@@Counter/COUNTER_DECREMENT';
3+
4+
export const counterIncrement = () => ({
5+
type: COUNTER_INCREMENT
6+
});
7+
8+
export const counterDecrement = () => ({
9+
type: COUNTER_DECREMENT
10+
});

0 commit comments

Comments
 (0)