Skip to content

Commit 33a5926

Browse files
authored
Merge pull request #9 from brunolm/routes
Add routes, component and tests
2 parents 1ab330f + a679160 commit 33a5926

File tree

7 files changed

+239
-10
lines changed

7 files changed

+239
-10
lines changed

package-lock.json

Lines changed: 89 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"dependencies": {
66
"react": "^16.1.1",
77
"react-dom": "^16.1.1",
8+
"react-router": "^4.2.0",
9+
"react-router-dom": "^4.2.2",
810
"react-scripts-ts": "2.8.0"
911
},
1012
"scripts": {
@@ -29,6 +31,8 @@
2931
"@types/node": "^8.0.53",
3032
"@types/react": "^16.0.25",
3133
"@types/react-dom": "^16.0.3",
34+
"@types/react-router": "^4.0.17",
35+
"@types/react-router-dom": "^4.2.1",
3236
"coveralls": "^3.0.0",
3337
"enzyme": "^3.2.0",
3438
"enzyme-adapter-react-16": "^1.1.0",

src/App.tsx

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,41 @@
11
import * as React from 'react';
22
import './App.css';
33

4-
const logo = require('./logo.svg');
4+
import { createBrowserHistory } from 'history';
5+
import { Link, Route, Router, Switch } from 'react-router-dom';
6+
7+
import Home from './components/home';
8+
9+
const history = createBrowserHistory();
510

611
class App extends React.Component {
712
render() {
813
return (
9-
<div className="App">
10-
<div className="App-header">
11-
<img src={logo} className="App-logo" alt="logo" />
12-
<h2>Welcome to React</h2>
13-
</div>
14-
<p className="App-intro">
15-
To get started, edit <code>src/App.tsx</code> and save to reload.
16-
</p>
14+
<div>
15+
<Router history={history}>
16+
<div>
17+
<header>
18+
<h2>React / TS</h2>
19+
</header>
20+
<main>
21+
<ul>
22+
<li>
23+
<Link to="/">/</Link>
24+
</li>
25+
<li>
26+
<Link to="/home/brunolm">Home</Link>
27+
</li>
28+
</ul>
29+
30+
<hr />
31+
32+
<Switch>
33+
<Route exact={true} path="/" component={Home} />
34+
<Route path="/home/:name" component={Home} />
35+
</Switch>
36+
</main>
37+
</div>
38+
</Router>
1739
</div>
1840
);
1941
}

src/components/home/index.css

Whitespace-only changes.

src/components/home/index.spec.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Home, { Props, PropsWithRoute, State } from './';
2+
3+
import { shallow, ShallowWrapper } from '../../specHelper';
4+
5+
describe('Home', () => {
6+
let component: ShallowWrapper<Props & PropsWithRoute, State>;
7+
8+
beforeEach(() => {
9+
const routerProps = {
10+
match: {
11+
params: {
12+
name: 'brunolm',
13+
},
14+
},
15+
};
16+
17+
component = shallow(Home, { props: routerProps });
18+
});
19+
20+
it('renders without crashing', () => {
21+
expect(component).toBeTruthy();
22+
});
23+
24+
it('toggles status on button click', () => {
25+
const toggleStatusButton = component.find('.toggle-status');
26+
27+
expect(component.state().loading).toBeFalsy();
28+
29+
toggleStatusButton.simulate('click');
30+
31+
expect(component.state().loading).toBeTruthy();
32+
});
33+
34+
it('displays name value from url param', () => {
35+
const nameTitle = component.find('h3.name-title');
36+
37+
expect(nameTitle.text()).toBe('Hello brunolm');
38+
});
39+
40+
describe('', () => {
41+
beforeEach(() => {
42+
const routerProps = {
43+
match: {
44+
params: {
45+
name: undefined,
46+
},
47+
},
48+
};
49+
50+
component = shallow(Home, { props: routerProps });
51+
});
52+
53+
it('displays "no name" when there are no values from url param', () => {
54+
const nameTitle = component.find('h3.name-title');
55+
56+
expect(nameTitle.text()).toBe('Hello no name');
57+
});
58+
});
59+
});

src/components/home/index.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import './index.css';
2+
3+
import * as React from 'react';
4+
5+
export interface Props {
6+
something?: string;
7+
}
8+
export interface PropsWithRoute {
9+
match: {
10+
params: {
11+
name: string;
12+
};
13+
};
14+
}
15+
16+
export interface State {
17+
loading: boolean;
18+
}
19+
20+
export default class Home extends React.Component<Props & PropsWithRoute, State> {
21+
constructor(props) {
22+
super(props);
23+
24+
this.state = {
25+
loading: false,
26+
};
27+
}
28+
29+
toggleStatus = () => {
30+
const { loading } = this.state;
31+
32+
this.setState({ loading: !loading });
33+
}
34+
35+
render() {
36+
const { params } = this.props.match;
37+
const { loading } = this.state;
38+
39+
const name = params.name || 'no name';
40+
41+
return (
42+
<div>
43+
<h3 className="name-title">Hello {name}</h3>
44+
<button className="toggle-status" onClick={this.toggleStatus}>Toggle Status</button>
45+
46+
{loading &&
47+
<span>Loading...</span>
48+
}
49+
{!loading &&
50+
<span>Done.</span>
51+
}
52+
</div>
53+
);
54+
}
55+
}

src/specHelper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ export function shallow(Component, { store, props }: any) {
99
return Enzyme.shallow(<Component {...props} />);
1010
}
1111

12-
export type ShallowWrapper = Enzyme.ShallowWrapper<any, any>;
12+
export type ShallowWrapper<TProps, TState> = Enzyme.ShallowWrapper<TProps, TState>;

0 commit comments

Comments
 (0)