Skip to content

Commit c696164

Browse files
author
Antoine Lelaisant
committed
feat: step 5 - added tests
1 parent f730084 commit c696164

21 files changed

+462
-12
lines changed

.eslintrc.js

+2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ module.exports = {
44
'node': true,
55
'es6': true,
66
'browser': true,
7+
'jest/globals': true,
78
},
89
'plugins': [
910
'react',
1011
'react-hooks',
12+
'jest',
1113
],
1214
'parser': 'babel-eslint',
1315
'extends': [

jsconfig.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
],
88
"paths": {
99
"assets": ["./assets/*"],
10-
"components": ["./components/*"]
11-
"modules": ["./modules/*"]
10+
"components": ["./components/*"],
11+
"modules": ["./modules/*"],
12+
"utils": ["./utils/*"]
1213
}
1314
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@testing-library/user-event": "^12.6.3",
4646
"babel-eslint": "^10.1.0",
4747
"eslint": "^7.21.0",
48+
"eslint-plugin-jest": "^24.2.1",
4849
"eslint-plugin-react": "^7.22.0",
4950
"eslint-plugin-react-hooks": "^4.2.0"
5051
}

src/components/Game/Game.test.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react'
2+
import { Game } from './Game'
3+
import { Provider } from 'react-redux'
4+
import { MemoryRouter as Router } from 'react-router-dom'
5+
import { render, screen, waitFor } from '@testing-library/react'
6+
import configureStore from '../../configureStore'
7+
8+
describe('Game', () => {
9+
it('it renders correctly', async () => {
10+
const initialState = {
11+
game: {
12+
lines: 6,
13+
linesPerMillisecond: 2,
14+
skills: {}
15+
}
16+
}
17+
18+
render(
19+
<Provider store={configureStore(initialState)}>
20+
<Router>
21+
<Game />
22+
</Router>
23+
</Provider>
24+
)
25+
26+
expect(screen.getByText(/6 lines/)).toBeInTheDocument()
27+
expect(screen.getByText(/per second: 20/)).toBeInTheDocument()
28+
expect(screen.getByText(/Skills/)).toBeInTheDocument()
29+
expect(screen.getByText(/Store/)).toBeInTheDocument()
30+
31+
await waitFor(
32+
() => expect(screen.getByText(/8 lines/)).toBeInTheDocument(),
33+
{ timeout: 150 }
34+
)
35+
await waitFor(
36+
() => expect(screen.getByText(/10 lines/)).toBeInTheDocument(),
37+
{ timeout: 150 }
38+
)
39+
})
40+
})

src/components/Gitcoin/Gitcoin.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const Gitcoin = () => {
1313
<button
1414
className="gitcoin"
1515
onClick={handleClick}
16+
aria-label="Gitcoin"
1617
>
1718
<img src={githubIcon} alt="Gitcoin" />
1819
</button>
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react'
2+
import { Gitcoin } from './Gitcoin'
3+
import { render, screen, fireEvent } from '@testing-library/react'
4+
import { click } from 'modules/game'
5+
import configureStore from '../../configureStore'
6+
7+
jest.mock('react-redux', () => {
8+
const dispatch = jest.fn()
9+
10+
return {
11+
...jest.requireActual('react-redux'),
12+
useDispatch: () => dispatch
13+
}
14+
})
15+
import { Provider, useDispatch } from 'react-redux'
16+
17+
describe('Gitcoin', () => {
18+
it('Allows to click', () => {
19+
const initialState = {
20+
game: { lines: 6, linesPerMillisecond: 2 }
21+
}
22+
23+
render(
24+
<Provider store={configureStore(initialState)}>
25+
<Gitcoin />
26+
</Provider>
27+
)
28+
29+
expect(screen.getByAltText(/Gitcoin/i)).toBeInTheDocument()
30+
31+
const dispatch = useDispatch()
32+
33+
fireEvent.click(screen.getByLabelText(/Gitcoin/))
34+
expect(dispatch).toHaveBeenCalledWith(click())
35+
})
36+
})

src/components/Home.test.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react'
2+
import { Home } from './Home'
3+
import { MemoryRouter as Router } from 'react-router-dom'
4+
import { render, screen } from '@testing-library/react'
5+
6+
describe('Home', () => {
7+
it('renders correctly', () => {
8+
render(
9+
<Router>
10+
<Home />
11+
</Router>
12+
)
13+
14+
expect(screen.getByText(/Dogs have boundless enthusiasm/i)).toBeInTheDocument()
15+
expect(screen.getByText(/Play/i)).toBeInTheDocument()
16+
})
17+
})

src/components/Score.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react'
22
import { useSelector } from 'react-redux'
3+
import numberFormat from 'utils/numberFormat'
34

45
export const Score = () => {
5-
const lines = useSelector(state => parseInt(state.game.lines))
6-
const linesPerSecond = useSelector(state => parseInt(state.game.linesPerMillisecond * 10))
6+
const lines = useSelector(state => numberFormat(state.game.lines))
7+
const linesPerSecond = useSelector(state => numberFormat(state.game.linesPerMillisecond * 10))
78

89
return (
910
<>

src/components/Score.test.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react'
2+
import { Score } from './Score'
3+
import { Provider } from 'react-redux'
4+
import { render, screen } from '@testing-library/react'
5+
import configureStore from '../configureStore'
6+
7+
describe('Score', () => {
8+
it('should displays the number of lines', () => {
9+
const initialState = {
10+
game: { lines: 6, linesPerMillisecond: 2 }
11+
}
12+
13+
render(
14+
<Provider store={configureStore(initialState)}>
15+
<Score />
16+
</Provider>
17+
)
18+
19+
expect(screen.getByText(/6 lines/i)).toBeInTheDocument()
20+
expect(screen.getByText(/per second: 20/i)).toBeInTheDocument()
21+
})
22+
})

src/components/Skills/Section.test.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react'
2+
import { render, screen } from '@testing-library/react'
3+
import { Section } from './Section'
4+
5+
describe('Section', () => {
6+
it('Displays the owned skills', () => {
7+
render(<Section itemName="Bash" number={3} />)
8+
9+
expect(screen.getByText('Bash')).toBeInTheDocument()
10+
expect(screen.getAllByAltText('Bash')).toHaveLength(3)
11+
})
12+
})
13+

src/components/Skills/Skills.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react'
2+
import { Provider } from 'react-redux'
3+
import { render, screen } from '@testing-library/react'
4+
import { Skills } from './Skills'
5+
import configureStore from '../../configureStore'
6+
7+
8+
describe('Store', () => {
9+
it('Renders correctly', () => {
10+
const initialState = {
11+
game: {
12+
skills: { 'Bash': 2, 'Git': 3, 'Javascript': 4 }
13+
}
14+
}
15+
16+
render(
17+
<Provider store={configureStore(initialState)}>
18+
<Skills />
19+
</Provider>
20+
)
21+
22+
expect(screen.getByText(/Bash/i)).toBeInTheDocument()
23+
expect(screen.getByText(/Git/i)).toBeInTheDocument()
24+
expect(screen.getByText(/Javascript/i)).toBeInTheDocument()
25+
})
26+
})
27+

src/components/Store/Item.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react'
22
import PropTypes from 'prop-types'
33
import Button from '@material-ui/core/Button'
44
import Typography from '@material-ui/core/Typography'
5+
import numberFormat from 'utils/numberFormat'
56
import './Item.css'
67

78
export const Item = ({ item, lines, onBuy }) => {
@@ -20,15 +21,16 @@ export const Item = ({ item, lines, onBuy }) => {
2021
<img src={item.icon} alt={item.name} />
2122
<div>
2223
<Typography variant="subtitle1">{item.name}</Typography>
23-
<small>{linePerSecond} lines per second</small>
24+
<small>{numberFormat(linePerSecond)} lines per second</small>
2425
</div>
2526
</div>
2627
<Button
28+
name="buy"
2729
variant="contained"
2830
color="secondary"
2931
disabled={!canBuy(item)}
3032
>
31-
{item.price}
33+
{numberFormat(item.price)}
3234
</Button>
3335
</div>
3436
)

src/components/Store/Item.test.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React from 'react'
2+
import BashIcon from 'devicon/icons/bash/bash-original.svg'
3+
import { render, screen, fireEvent } from '@testing-library/react'
4+
import { Item } from './Item'
5+
6+
describe('Item', () => {
7+
it('Renders a buyable item', () => {
8+
const item = {
9+
name: 'Bash',
10+
price: 10,
11+
multiplier: 0.1,
12+
icon: BashIcon
13+
}
14+
15+
const onBuy = jest.fn()
16+
17+
render(
18+
<Item
19+
item={item}
20+
lines={150}
21+
onBuy={onBuy}
22+
/>
23+
)
24+
25+
expect(screen.getByText(/Bash/i)).toBeInTheDocument()
26+
expect(screen.getByText(/1 lines per second/i)).toBeInTheDocument()
27+
expect(screen.getByRole('button')).not.toBeDisabled()
28+
29+
fireEvent.click(screen.getByRole('button'))
30+
31+
expect(onBuy).toHaveBeenCalledWith(item)
32+
})
33+
34+
it('Renders a non buyable item', () => {
35+
const item = {
36+
name: 'Bash',
37+
price: 10,
38+
multiplier: 0.1,
39+
icon: BashIcon
40+
}
41+
42+
const onBuy = jest.fn()
43+
44+
render(
45+
<Item
46+
item={item}
47+
lines={0}
48+
onBuy={onBuy}
49+
/>
50+
)
51+
52+
expect(screen.getByText(/Bash/i)).toBeInTheDocument()
53+
expect(screen.getByText(/1 lines per second/i)).toBeInTheDocument()
54+
expect(screen.getByRole(/button/i)).toBeDisabled()
55+
56+
fireEvent.click(screen.getByRole('button'))
57+
58+
expect(onBuy).not.toHaveBeenCalledWith(item)
59+
})
60+
})
61+

src/components/Store/Store.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react'
2+
import { Provider } from 'react-redux'
3+
import { render, screen } from '@testing-library/react'
4+
import { Store } from './Store'
5+
import configureStore from '../../configureStore'
6+
7+
8+
describe('Store', () => {
9+
it('Renders correctly', () => {
10+
const initialState = {
11+
game: { lines: 6 }
12+
}
13+
14+
render(
15+
<Provider store={configureStore(initialState)}>
16+
<Store />
17+
</Provider>
18+
)
19+
20+
expect(screen.getByText(/Bash/i)).toBeInTheDocument()
21+
expect(screen.getByText(/Git/i)).toBeInTheDocument()
22+
expect(screen.getByText(/Javascript/i)).toBeInTheDocument()
23+
expect(screen.getByText(/React/i)).toBeInTheDocument()
24+
expect(screen.getByText(/Vim/i)).toBeInTheDocument()
25+
})
26+
})

src/configureStore.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createStore } from 'redux'
22
import { rootReducer } from './modules'
33

4-
export default () => {
5-
const store = createStore(rootReducer)
4+
export default (initialState = {}) => {
5+
const store = createStore(rootReducer, initialState)
66

77
return store
88
}

src/modules/game.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Actions
2-
const CLICK = 'game::CLICK'
3-
const BUY_ITEM = 'game::BUY_ITEM'
4-
const LOOP = 'game::LOOP'
2+
export const CLICK = 'game::CLICK'
3+
export const BUY_ITEM = 'game::BUY_ITEM'
4+
export const LOOP = 'game::LOOP'
55

66
// Action creators
77
export const click = () => ({
@@ -20,7 +20,7 @@ export const loop = () => ({
2020
const INITIAL_STATE = {
2121
lines: 0,
2222
linesPerMillisecond: 0,
23-
skills: []
23+
skills: {}
2424
}
2525

2626
export const reducer = (state = INITIAL_STATE, action) => {

0 commit comments

Comments
 (0)