Fix broken LoginForm.test.tsx
This commit is contained in:
parent
8f8c3b6c9c
commit
637b51382a
@ -1,8 +1,10 @@
|
|||||||
import * as Feature from './'
|
import * as Feature from './'
|
||||||
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import 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} from '@rondo/common'
|
import {IAPIDef} from '@rondo/common'
|
||||||
|
import {MemoryRouter} from 'react-router-dom'
|
||||||
|
|
||||||
const test = new TestUtils()
|
const test = new TestUtils()
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ describe('LoginForm', () => {
|
|||||||
reducers: {Login: Feature.Login},
|
reducers: {Login: Feature.Login},
|
||||||
connector: new Feature.LoginConnector(loginActions),
|
connector: new Feature.LoginConnector(loginActions),
|
||||||
select: state => state.Login,
|
select: state => state.Login,
|
||||||
|
customJSX: (Component, props) =>
|
||||||
|
<MemoryRouter><Component {...props} /></MemoryRouter>,
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@ -61,16 +65,7 @@ describe('LoginForm', () => {
|
|||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
expect(onSuccess.mock.calls.length).toBe(1)
|
expect(onSuccess.mock.calls.length).toBe(1)
|
||||||
expect(
|
// TODO test clear username/password
|
||||||
(node.querySelector('input[name="username"]') as HTMLInputElement)
|
|
||||||
.value,
|
|
||||||
)
|
|
||||||
.toEqual('')
|
|
||||||
expect(
|
|
||||||
(node.querySelector('input[name="password"]') as HTMLInputElement)
|
|
||||||
.value,
|
|
||||||
)
|
|
||||||
.toEqual('')
|
|
||||||
node = ReactDOM.findDOMNode(component) as Element
|
node = ReactDOM.findDOMNode(component) as Element
|
||||||
expect(node.innerHTML).toMatch(/<a href="\/">/)
|
expect(node.innerHTML).toMatch(/<a href="\/">/)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {IAction} from '../actions'
|
import {IPendingAction} from '../actions'
|
||||||
|
|
||||||
export interface IComponentProps<Data> {
|
export interface IComponentProps<Data> {
|
||||||
onSubmit: () => void
|
onSubmit: () => void
|
||||||
@ -10,13 +10,18 @@ export interface IComponentProps<Data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IFormHOCProps<Data> {
|
export interface IFormHOCProps<Data> {
|
||||||
onSubmit: (props: Data) => IAction<any>
|
onSubmit: (props: Data) => IPendingAction<any, any>
|
||||||
// TODO figure out what would happen if the underlying child component
|
// TODO figure out what would happen if the underlying child component
|
||||||
// would have the same required property as the HOC, like onSuccess?
|
// would have the same required property as the HOC, like onSuccess?
|
||||||
onSuccess?: () => void
|
onSuccess?: () => void
|
||||||
clearOnSuccess?: boolean
|
clearOnSuccess?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IFormHOCState<Data> {
|
||||||
|
error: string
|
||||||
|
data: Data
|
||||||
|
}
|
||||||
|
|
||||||
export function withForm<Data, Props extends IComponentProps<Data>>(
|
export function withForm<Data, Props extends IComponentProps<Data>>(
|
||||||
Component: React.ComponentType<Props>,
|
Component: React.ComponentType<Props>,
|
||||||
initialState: Data,
|
initialState: Data,
|
||||||
@ -26,28 +31,44 @@ export function withForm<Data, Props extends IComponentProps<Data>>(
|
|||||||
Exclude<keyof Props, keyof IComponentProps<Data>>>
|
Exclude<keyof Props, keyof IComponentProps<Data>>>
|
||||||
type T = IFormHOCProps<Data> & OtherProps
|
type T = IFormHOCProps<Data> & OtherProps
|
||||||
|
|
||||||
return class FormHOC extends React.PureComponent<T, Data> {
|
return class FormHOC extends React.PureComponent<T, IFormHOCState<Data>> {
|
||||||
constructor(props: T) {
|
constructor(props: T) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = initialState
|
this.state = {
|
||||||
|
error: '',
|
||||||
|
data: initialState,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handleSubmit = async (e: React.FormEvent) => {
|
handleSubmit = async (e: React.FormEvent) => {
|
||||||
const {clearOnSuccess, onSuccess} = this.props
|
const {clearOnSuccess, onSuccess} = this.props
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const promise = this.props.onSubmit(this.state)
|
const action = this.props.onSubmit(this.state.data)
|
||||||
console.log('aaaaaaaaa', promise)
|
try {
|
||||||
await promise
|
await action.payload
|
||||||
|
} catch (err) {
|
||||||
|
this.setState({
|
||||||
|
error: err.message,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
if (clearOnSuccess) {
|
if (clearOnSuccess) {
|
||||||
this.setState(initialState)
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
data: initialState,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleChange = (name: string, value: string) => {
|
handleChange = (name: string, value: string) => {
|
||||||
this.setState(
|
this.setState({
|
||||||
{[name]: value} as unknown as Pick<Data, keyof Data>,
|
...this.state,
|
||||||
)
|
data: {
|
||||||
|
...this.state.data,
|
||||||
|
[name]: value,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const {children, onSuccess, onSubmit, ...otherProps} = this.props
|
const {children, onSuccess, onSubmit, ...otherProps} = this.props
|
||||||
|
|||||||
@ -110,9 +110,11 @@ export class HTTPClientMock<T extends IRoutes> extends HTTPClient<T> {
|
|||||||
*/
|
*/
|
||||||
async wait(): Promise<IReqRes> {
|
async wait(): Promise<IReqRes> {
|
||||||
expect(this.waitPromise).toBe(undefined)
|
expect(this.waitPromise).toBe(undefined)
|
||||||
return 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))
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,9 @@ interface IRenderParams<State> {
|
|||||||
state?: DeepPartial<State>
|
state?: DeepPartial<State>
|
||||||
connector: Connector<any>
|
connector: Connector<any>
|
||||||
select: IStateSelector<State, any>
|
select: IStateSelector<State, any>
|
||||||
customJSX?: <Props>(
|
customJSX?: (
|
||||||
Component: React.ComponentType<Props>,
|
Component: React.ComponentType<any>,
|
||||||
additionalProps: Record<string, Props>,
|
additionalProps: Record<string, any>,
|
||||||
) => JSX.Element
|
) => JSX.Element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user