Tests for Member.jsx
This commit is contained in:
parent
cc1c3285b0
commit
f2303fb70c
15 changed files with 4428 additions and 10535 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node_modules/**
|
15
.eslintrc
Normal file
15
.eslintrc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"parser": "babel-eslint", // https://github.com/babel/babel-eslint
|
||||||
|
"env": { // http://eslint.org/docs/user-guide/configuring.html#specifying-environments
|
||||||
|
"node": true, // Node.js global variables and Node.js-specific rules
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6
|
||||||
|
},
|
||||||
|
"plugins": ["prettier"],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"no-unused-vars": 1
|
||||||
|
}
|
||||||
|
}
|
15
.prettierrc
Normal file
15
.prettierrc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"insertPragma": false,
|
||||||
|
"jsxBracketSameLine": true,
|
||||||
|
"parser": "babylon",
|
||||||
|
"printWidth": 120,
|
||||||
|
"proseWrap": "preserve",
|
||||||
|
"requirePragma": false,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"useTabs": false
|
||||||
|
}
|
8940
package-lock.json
generated
8940
package-lock.json
generated
File diff suppressed because it is too large
Load diff
17
package.json
17
package.json
|
@ -4,21 +4,22 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
|
"enzyme": "^3.10.0",
|
||||||
|
"enzyme-adapter-react-16": "^1.14.0",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.12.0",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
"react-router-dom": "^5.0.1",
|
"react-router-dom": "^5.0.1",
|
||||||
"react-scripts": "3.0.1"
|
"react-scripts": "3.0.1",
|
||||||
|
"react-test-renderer": "^16.8.6",
|
||||||
|
"typescript": "^3.5.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test --env=jsdom --verbose --silent",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
|
||||||
"extends": "react-app"
|
|
||||||
},
|
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.2%",
|
">0.2%",
|
||||||
|
@ -30,5 +31,11 @@
|
||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@testing-library/jest-dom": "^4.0.0",
|
||||||
|
"@testing-library/react": "^8.0.4",
|
||||||
|
"eslint-plugin-prettier": "^3.1.0",
|
||||||
|
"prettier": "1.18.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,5 @@ export default function App() {
|
||||||
<div className='app'>
|
<div className='app'>
|
||||||
<Router />
|
<Router />
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import history from '../history.js'
|
||||||
import Home from '../views/Home'
|
import Home from '../views/Home'
|
||||||
import Team from '../views/Team'
|
import Team from '../views/Team'
|
||||||
import Member from '../views/Member'
|
import Member from '../views/Member'
|
||||||
|
import config from '../config.json'
|
||||||
|
|
||||||
history.listen(location => {
|
history.listen(location => {
|
||||||
window.scrollTo(0,0)
|
window.scrollTo(0,0)
|
||||||
|
@ -13,7 +14,7 @@ export default function Router(props) {
|
||||||
let [team, setTeam] = useState([])
|
let [team, setTeam] = useState([])
|
||||||
let [allTeams, setAllTeams] = useState([])
|
let [allTeams, setAllTeams] = useState([])
|
||||||
let [users, setUsers] = useState([])
|
let [users, setUsers] = useState([])
|
||||||
let [userId, setUserId] = useState([])
|
let [memberProps, setMemberProps] = useState({})
|
||||||
|
|
||||||
let teamCallback = (el) => {
|
let teamCallback = (el) => {
|
||||||
setTeam(el)
|
setTeam(el)
|
||||||
|
@ -24,7 +25,10 @@ export default function Router(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let userIdCallback = (el) => {
|
let userIdCallback = (el) => {
|
||||||
setUserId(el)
|
setMemberProps({
|
||||||
|
url: config.api + '/user/' + el,
|
||||||
|
teams: allTeams
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let allTeamsCallback = (el) => {
|
let allTeamsCallback = (el) => {
|
||||||
|
@ -44,7 +48,7 @@ export default function Router(props) {
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact path='/member'
|
exact path='/member'
|
||||||
render={(props) => <Member userId={userId} teams={allTeams} {...props} />}
|
render={(props) => <Member props={memberProps} />}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</ReactRouter>
|
</ReactRouter>
|
||||||
|
|
4
src/setupTests.js
Normal file
4
src/setupTests.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { configure } from 'enzyme'
|
||||||
|
import Adapter from 'enzyme-adapter-react-16'
|
||||||
|
|
||||||
|
configure({ adapter: new Adapter() })
|
69
src/views/Attempt.js
Normal file
69
src/views/Attempt.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import React from 'react'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import Member from './Member.jsx'
|
||||||
|
|
||||||
|
jest.mock('axios')
|
||||||
|
|
||||||
|
// test('should fetch users', () => {
|
||||||
|
// const userMock = {
|
||||||
|
// "username": "goodpanda",
|
||||||
|
// "member_teams": [
|
||||||
|
// 3
|
||||||
|
// ],
|
||||||
|
// "lead_teams": [],
|
||||||
|
// "id": 15,
|
||||||
|
// "name": "Charlotte Amsterdan"
|
||||||
|
// }
|
||||||
|
// const resp = {data: userMock}
|
||||||
|
// axios.get.mockResolvedValue(resp)
|
||||||
|
|
||||||
|
// // or you could use the following depending on your use case:
|
||||||
|
// // axios.get.mockImplementation(() => Promise.resolve(resp))
|
||||||
|
|
||||||
|
// return Users.then(data => expect(data).toEqual(userMock))
|
||||||
|
// })
|
||||||
|
|
||||||
|
jest.mock("services/dataService", () => ({
|
||||||
|
getData: jest.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
let getDataPromise
|
||||||
|
|
||||||
|
getData.mockImplementation(() => {
|
||||||
|
getDataPromise = new MockPromise()
|
||||||
|
|
||||||
|
return getDataPromise
|
||||||
|
})
|
||||||
|
|
||||||
|
it('When fetching succeed', async () => {
|
||||||
|
const wrapper = mount(<Member />)
|
||||||
|
let loadingNode = wrapper.find('[data-test-id="loading"]')
|
||||||
|
let dataNoode = wrapper.find('[data-test-id="user"]')
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
"username": "goodpanda",
|
||||||
|
"member_teams": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"lead_teams": [],
|
||||||
|
"id": 15,
|
||||||
|
"name": "Charlotte Amsterdan"
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(loadingNode).toHaveLength(1)
|
||||||
|
expect(loadingNode.text()).toBe("Loading...")
|
||||||
|
expect(dataNode).toHaveLength(0)
|
||||||
|
|
||||||
|
await getDataPromise.resolve(data)
|
||||||
|
|
||||||
|
wrapper.update()
|
||||||
|
|
||||||
|
loadingNode = wrapper.find('[data-test-id="loading"]')
|
||||||
|
dataNode = wrapper.find('[data-test-id="user"]')
|
||||||
|
|
||||||
|
expect(loadingNode).toHaveLength(0)
|
||||||
|
|
||||||
|
expect(dataNode).toHaveLength(1)
|
||||||
|
expect(dataNode.text()).toBe(data)
|
||||||
|
})
|
|
@ -31,14 +31,12 @@ export default function Home(props) {
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
console.log('Fetch data error: ' + err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData()
|
fetchData()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Load users
|
// MARK: - Load users
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let fetchData = async() => {
|
let fetchData = async() => {
|
||||||
|
@ -52,7 +50,6 @@ export default function Home(props) {
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
setLoadingUsers(false)
|
setLoadingUsers(false)
|
||||||
console.log('Fetch data error: ' + err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,20 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import history from '../history.js'
|
import history from '../history.js'
|
||||||
import config from '../config.json'
|
// import config from '../config.json'
|
||||||
import './Member.scss'
|
import './Member.scss'
|
||||||
|
|
||||||
// teamProps, usersProps, userIdCallback
|
export default function Member({ props }) {
|
||||||
export default function Member(props) {
|
|
||||||
// MARK: State
|
// MARK: State
|
||||||
let [loading, setLoading] = useState(true)
|
let [user, setUser] = useState(null)
|
||||||
let [user, setUser] = useState([])
|
|
||||||
let [teamNames, setTeamNames] = useState([])
|
let [teamNames, setTeamNames] = useState([])
|
||||||
|
|
||||||
// MARK: Effects
|
// MARK: Effects
|
||||||
// MARK: - Load user info from Tempo backend on initialization
|
// MARK: - Load user info from Tempo backend on initialization
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let fetchData = async() => {
|
let fetchData = async() => {
|
||||||
setLoading(true)
|
|
||||||
try {
|
try {
|
||||||
let result = await axios(config.api + '/user/' + props.userId)
|
let result = await axios.get(props.url)
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
setUser(result.data)
|
setUser(result.data)
|
||||||
|
|
||||||
|
@ -29,11 +26,8 @@ export default function Member(props) {
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
setLoading(false)
|
|
||||||
console.log('Fetch data error: ' + err)
|
|
||||||
history.push('/')
|
history.push('/')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,22 +35,20 @@ export default function Member(props) {
|
||||||
fetchData()
|
fetchData()
|
||||||
}, [props])
|
}, [props])
|
||||||
|
|
||||||
|
|
||||||
// MARK: Helpers
|
// MARK: Helpers
|
||||||
let navBack = () => {
|
let navBack = () => {
|
||||||
history.push('/team')
|
history.push('/team')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Return
|
// MARK: Return
|
||||||
return (
|
return (
|
||||||
<div className='member'>
|
<div className='member'>
|
||||||
|
|
||||||
{loading ? (<div>Loading...</div>) : (
|
{user === null ? (<div data-testid='loading'>Loading...</div>) : (
|
||||||
user !== undefined &&
|
user !== undefined &&
|
||||||
<div>
|
<div>
|
||||||
<div className='header'>
|
<div className='header'>
|
||||||
<h1>Member {user.name}</h1>
|
<span data-testid='resolved'><h1>Member {user.name}</h1></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='back'>
|
<div className='back'>
|
||||||
|
|
31
src/views/Member.test.js
Normal file
31
src/views/Member.test.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { render, waitForElement } from '@testing-library/react'
|
||||||
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
import '@testing-library/react/cleanup-after-each'
|
||||||
|
import axiosMock from 'axios'
|
||||||
|
import Member from './Member'
|
||||||
|
|
||||||
|
it('Renders without crashing', () => {
|
||||||
|
const { getByTestId } = render(<Member />)
|
||||||
|
expect(getByTestId('loading')).toHaveTextContent('Loading...')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Fetches and displays data', async () => {
|
||||||
|
const callData = {
|
||||||
|
username: 'goodpanda',
|
||||||
|
member_teams: [3],
|
||||||
|
lead_teams: [],
|
||||||
|
id: 15,
|
||||||
|
name: 'Charlotte Amsterdan'
|
||||||
|
}
|
||||||
|
|
||||||
|
axiosMock.get.mockResolvedValueOnce({ data: callData })
|
||||||
|
|
||||||
|
const address = { url: '/user15' }
|
||||||
|
const { getByTestId } = render(<Member props={address} />)
|
||||||
|
const resolvedSpan = await waitForElement(() => getByTestId('resolved'))
|
||||||
|
|
||||||
|
expect(resolvedSpan).toHaveTextContent('Member ' + callData.name)
|
||||||
|
expect(axiosMock.get).toHaveBeenCalledTimes(1)
|
||||||
|
expect(axiosMock.get).toHaveBeenCalledWith(address.url)
|
||||||
|
})
|
3
src/views/__mocks__/axios.js
Normal file
3
src/views/__mocks__/axios.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default {
|
||||||
|
get: jest.fn().mockResolvedValue({ data: {} })
|
||||||
|
}
|
21
src/views/utils.js
Normal file
21
src/views/utils.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { act as reactAct } from 'react-dom/test-utils';
|
||||||
|
|
||||||
|
const SUPPRESSED_PREFIXES = [
|
||||||
|
"Warning: Do not await the result of calling ReactTestUtils.act(...)",
|
||||||
|
"Warning: An update to %s inside a test was not wrapped in act(...)",
|
||||||
|
];
|
||||||
|
|
||||||
|
function isSuppressedErrorMessage(message: string): boolean {
|
||||||
|
return SUPPRESSED_PREFIXES.some(sp => message.startsWith(sp));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function act(f: () => void): Promise<void> {
|
||||||
|
const oldError = window.console.error;
|
||||||
|
window.console.error = (...args: any[]) => {
|
||||||
|
if (!isSuppressedErrorMessage(args[0])) {
|
||||||
|
oldError(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await Promise.race([reactAct(f), new Promise(res => setTimeout(res))]);
|
||||||
|
window.console.error = oldError;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue