Add tests more tests to TeamConnector.test.tsx
This commit is contained in:
parent
9dd6994498
commit
289ea00de8
@ -1,16 +1,36 @@
|
|||||||
import * as Feature from './'
|
import * as Feature from './'
|
||||||
// export ReactDOM from 'react-dom'
|
// export ReactDOM from 'react-dom'
|
||||||
// import T from 'react-dom/test-utils'
|
import T from 'react-dom/test-utils'
|
||||||
import {HTTPClientMock, TestUtils/*, getError*/} from '../test-utils'
|
import {HTTPClientMock, TestUtils, getError} from '../test-utils'
|
||||||
import {IAPIDef, ITeam, IUserInTeam} from '@rondo/common'
|
import {IAPIDef, ITeam, IUserInTeam} from '@rondo/common'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import {MemoryRouter} from 'react-router-dom'
|
||||||
|
|
||||||
const test = new TestUtils()
|
const test = new TestUtils()
|
||||||
|
|
||||||
describe('TeamConnector', () => {
|
describe('TeamConnector', () => {
|
||||||
|
|
||||||
const http = new HTTPClientMock<IAPIDef>()
|
let teamActions!: Feature.TeamActions
|
||||||
const teamActions = new Feature.TeamActions(http)
|
let http: HTTPClientMock<IAPIDef>
|
||||||
|
beforeEach(() => {
|
||||||
|
http = new HTTPClientMock<IAPIDef>()
|
||||||
|
|
||||||
|
http.mockAdd({
|
||||||
|
method: 'get',
|
||||||
|
url: '/my/teams',
|
||||||
|
}, teams)
|
||||||
|
http.mockAdd({
|
||||||
|
method: 'get',
|
||||||
|
url: '/teams/:teamId/users',
|
||||||
|
params: {
|
||||||
|
teamId: 123,
|
||||||
|
},
|
||||||
|
}, users)
|
||||||
|
|
||||||
|
teamActions = new Feature.TeamActions(http)
|
||||||
|
})
|
||||||
|
|
||||||
|
const historyEntries = ['/teams']
|
||||||
|
|
||||||
const createTestProvider = () => test.withProvider({
|
const createTestProvider = () => test.withProvider({
|
||||||
reducers: {Team: Feature.Team},
|
reducers: {Team: Feature.Team},
|
||||||
@ -20,7 +40,11 @@ describe('TeamConnector', () => {
|
|||||||
new Feature
|
new Feature
|
||||||
.TeamConnector(teamActions)
|
.TeamConnector(teamActions)
|
||||||
.connect(select))
|
.connect(select))
|
||||||
.withJSX((Component, props) => <Component {...props} />)
|
.withJSX((Component, props) =>
|
||||||
|
<MemoryRouter initialEntries={historyEntries}>
|
||||||
|
<Component {...props} />
|
||||||
|
</MemoryRouter>,
|
||||||
|
)
|
||||||
|
|
||||||
const teams: ITeam[] = [{id: 100, name: 'my-team', userId: 1}]
|
const teams: ITeam[] = [{id: 100, name: 'my-team', userId: 1}]
|
||||||
|
|
||||||
@ -33,20 +57,52 @@ describe('TeamConnector', () => {
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
it('it fetches user teams on render', async () => {
|
it('it fetches user teams on render', async () => {
|
||||||
http.mockAdd({
|
const {node} = createTestProvider().render({})
|
||||||
method: 'get',
|
|
||||||
url: '/my/teams',
|
|
||||||
}, teams)
|
|
||||||
http.mockAdd({
|
|
||||||
method: 'get',
|
|
||||||
url: '/teams/:teamId/users',
|
|
||||||
params: {
|
|
||||||
teamId: 123,
|
|
||||||
},
|
|
||||||
}, users)
|
|
||||||
const {node} = createTestProvider().render({editTeamId123: 123})
|
|
||||||
await http.wait()
|
await http.wait()
|
||||||
expect(node.innerHTML).toContain('my-team')
|
expect(node.innerHTML).toContain('my-team')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('add team', () => {
|
||||||
|
it('sends a POST request to POST /teams', async () => {
|
||||||
|
const newTeam: Partial<ITeam> = {id: 101, name: 'new-team'}
|
||||||
|
http.mockAdd({
|
||||||
|
method: 'post',
|
||||||
|
url: '/teams',
|
||||||
|
data: {name: 'new-team'},
|
||||||
|
}, newTeam)
|
||||||
|
const {render, store} = createTestProvider()
|
||||||
|
const {node} = render({})
|
||||||
|
const addTeamForm = node.querySelector('.team-add') as HTMLFormElement
|
||||||
|
const nameInput = addTeamForm
|
||||||
|
.querySelector('input') as HTMLInputElement
|
||||||
|
T.Simulate.change(nameInput, {target: {value: newTeam.name}} as any)
|
||||||
|
T.Simulate.submit(addTeamForm)
|
||||||
|
await http.wait()
|
||||||
|
expect(nameInput.value).toEqual('')
|
||||||
|
const {Team} = store.getState()
|
||||||
|
expect(Team.teamIds).toEqual([100, 101])
|
||||||
|
expect(Team.teamsById[101]).toEqual(newTeam)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('displays an error', async () => {
|
||||||
|
const error = {error: 'An error'}
|
||||||
|
http.mockAdd({
|
||||||
|
method: 'post',
|
||||||
|
url: '/teams',
|
||||||
|
data: {name: 'test'},
|
||||||
|
}, error, 400)
|
||||||
|
const {render} = createTestProvider()
|
||||||
|
const {node} = render({})
|
||||||
|
const addTeamForm = node.querySelector('.team-add') as HTMLFormElement
|
||||||
|
const nameInput = addTeamForm
|
||||||
|
.querySelector('input') as HTMLInputElement
|
||||||
|
T.Simulate.change(nameInput, {target: {value: 'test'}} as any)
|
||||||
|
T.Simulate.submit(addTeamForm)
|
||||||
|
const error2 = await getError(http.wait())
|
||||||
|
expect(error2.message).toMatch(/HTTP Status: 400/)
|
||||||
|
expect(nameInput.value).toEqual('test')
|
||||||
|
expect(addTeamForm.innerHTML).toMatch(/HTTP Status: 400/)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Button, Control, Heading, Input} from 'bloomer'
|
import {Button, Control, Heading, Help, Input} from 'bloomer'
|
||||||
import {ITeam} from '@rondo/common'
|
import {ITeam} from '@rondo/common'
|
||||||
import {TeamActions} from './TeamActions'
|
import {TeamActions} from './TeamActions'
|
||||||
import {FaPlusSquare, FaCheck, FaEdit} from 'react-icons/fa'
|
import {FaPlusSquare, FaCheck, FaEdit} from 'react-icons/fa'
|
||||||
@ -14,6 +14,8 @@ export type ITeamEditorProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ITeamEditorState {
|
export interface ITeamEditorState {
|
||||||
|
// TODO use redux state for errors!
|
||||||
|
error: string
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,6 +24,7 @@ extends React.PureComponent<ITeamEditorProps, ITeamEditorState> {
|
|||||||
constructor(props: ITeamEditorProps) {
|
constructor(props: ITeamEditorProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
|
error: '',
|
||||||
name: props.type === 'update' ? this.getName(props.team) : '',
|
name: props.type === 'update' ? this.getName(props.team) : '',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,15 +48,22 @@ extends React.PureComponent<ITeamEditorProps, ITeamEditorState> {
|
|||||||
handleSubmit = async (event: React.FormEvent) => {
|
handleSubmit = async (event: React.FormEvent) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const {name} = this.state
|
const {name} = this.state
|
||||||
|
try {
|
||||||
if (this.props.type === 'update') {
|
if (this.props.type === 'update') {
|
||||||
const {team} = this.props
|
const {team} = this.props
|
||||||
await this.props.onUpdateTeam({id: team.id, name})
|
await this.props.onUpdateTeam({id: team.id, name}).payload
|
||||||
} else {
|
} else {
|
||||||
await this.props.onAddTeam({name})
|
await this.props.onAddTeam({name}).payload
|
||||||
}
|
}
|
||||||
this.setState({name: ''})
|
} catch (err) {
|
||||||
|
this.setState({error: err.message})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.setState({error: '', name: ''})
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
|
const {error} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
@ -72,6 +82,9 @@ extends React.PureComponent<ITeamEditorProps, ITeamEditorState> {
|
|||||||
<span className='icon is-left'>
|
<span className='icon is-left'>
|
||||||
{this.props.type === 'update' ? <FaEdit /> : <FaPlusSquare />}
|
{this.props.type === 'update' ? <FaEdit /> : <FaPlusSquare />}
|
||||||
</span>
|
</span>
|
||||||
|
{error && (
|
||||||
|
<Help isColor='danger'>{error}</Help>
|
||||||
|
)}
|
||||||
</Control>
|
</Control>
|
||||||
<div className='text-right mt-1'>
|
<div className='text-right mt-1'>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@ -128,7 +128,9 @@ export class HTTPClientMock<T extends IRoutes> extends HTTPClient<T> {
|
|||||||
const result: IReqRes = await new Promise((resolve, reject) => {
|
const result: IReqRes = await new Promise((resolve, reject) => {
|
||||||
this.waitPromise = {resolve, reject}
|
this.waitPromise = {resolve, reject}
|
||||||
})
|
})
|
||||||
await new Promise(resolve => setImmediate(resolve))
|
// TODO think of a better way to do this.
|
||||||
|
// We wait for all http request promise handlers to execute...
|
||||||
|
await new Promise(resolve => setTimeout(resolve))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user