Tests for Member.jsx

This commit is contained in:
Rodrigo Pedroso 2019-07-17 00:14:21 -04:00
commit f2303fb70c
15 changed files with 4428 additions and 10535 deletions

1
.eslintignore Normal file
View file

@ -0,0 +1 @@
node_modules/**

15
.eslintrc Normal file
View 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
View 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
}

6118
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,21 +4,22 @@
"private": true,
"dependencies": {
"axios": "^0.19.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"node-sass": "^4.12.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"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": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "react-scripts test --env=jsdom --verbose --silent",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
@ -30,5 +31,11 @@
"last 1 firefox 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"
}
}

View file

@ -7,5 +7,5 @@ export default function App() {
<div className='app'>
<Router />
</div>
);
)
}

View file

@ -4,6 +4,7 @@ import history from '../history.js'
import Home from '../views/Home'
import Team from '../views/Team'
import Member from '../views/Member'
import config from '../config.json'
history.listen(location => {
window.scrollTo(0,0)
@ -13,7 +14,7 @@ export default function Router(props) {
let [team, setTeam] = useState([])
let [allTeams, setAllTeams] = useState([])
let [users, setUsers] = useState([])
let [userId, setUserId] = useState([])
let [memberProps, setMemberProps] = useState({})
let teamCallback = (el) => {
setTeam(el)
@ -24,7 +25,10 @@ export default function Router(props) {
}
let userIdCallback = (el) => {
setUserId(el)
setMemberProps({
url: config.api + '/user/' + el,
teams: allTeams
})
}
let allTeamsCallback = (el) => {
@ -44,7 +48,7 @@ export default function Router(props) {
/>
<Route
exact path='/member'
render={(props) => <Member userId={userId} teams={allTeams} {...props} />}
render={(props) => <Member props={memberProps} />}
/>
</Switch>
</ReactRouter>

4
src/setupTests.js Normal file
View 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
View 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)
})

View file

@ -31,14 +31,12 @@ export default function Home(props) {
}
catch(err) {
setLoading(false)
console.log('Fetch data error: ' + err)
}
}
fetchData()
}, [])
// MARK: - Load users
useEffect(() => {
let fetchData = async() => {
@ -52,7 +50,6 @@ export default function Home(props) {
}
catch(err) {
setLoadingUsers(false)
console.log('Fetch data error: ' + err)
}
}

View file

@ -2,23 +2,20 @@
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import history from '../history.js'
import config from '../config.json'
// import config from '../config.json'
import './Member.scss'
// teamProps, usersProps, userIdCallback
export default function Member(props) {
export default function Member({ props }) {
// MARK: State
let [loading, setLoading] = useState(true)
let [user, setUser] = useState([])
let [user, setUser] = useState(null)
let [teamNames, setTeamNames] = useState([])
// MARK: Effects
// MARK: - Load user info from Tempo backend on initialization
useEffect(() => {
let fetchData = async() => {
setLoading(true)
try {
let result = await axios(config.api + '/user/' + props.userId)
let result = await axios.get(props.url)
if (result.data) {
setUser(result.data)
@ -29,11 +26,8 @@ export default function Member(props) {
return null
})
}
setLoading(false)
}
catch(err) {
setLoading(false)
console.log('Fetch data error: ' + err)
history.push('/')
}
}
@ -41,22 +35,20 @@ export default function Member(props) {
fetchData()
}, [props])
// MARK: Helpers
let navBack = () => {
history.push('/team')
}
// MARK: Return
return (
<div className='member'>
{loading ? (<div>Loading...</div>) : (
{user === null ? (<div data-testid='loading'>Loading...</div>) : (
user !== undefined &&
<div>
<div className='header'>
<h1>Member {user.name}</h1>
<span data-testid='resolved'><h1>Member {user.name}</h1></span>
</div>
<div className='back'>

31
src/views/Member.test.js Normal file
View 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)
})

View file

@ -0,0 +1,3 @@
export default {
get: jest.fn().mockResolvedValue({ data: {} })
}

21
src/views/utils.js Normal file
View 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;
}

8634
yarn.lock

File diff suppressed because it is too large Load diff