Add captcha to main site, fix tests of styled-components

This commit is contained in:
Jerko Steiner 2019-11-04 11:07:46 -04:00
parent 262ba2c2af
commit c27e66a8e2
11 changed files with 43 additions and 11 deletions

View File

@ -13,5 +13,6 @@ module.exports = {
'jsx',
],
setupFiles: ['<rootDir>/jest.setup.js'],
setupFilesAfterEnv: ['<rootDir>/src/jest.env.ts'],
verbose: false,
}

View File

@ -0,0 +1,3 @@
import { TestUtils } from '@rondo.dev/react-test'
import { theme } from './theme'
TestUtils.defaultTheme = theme

View File

@ -36,7 +36,7 @@ export class LoginActions {
)
}
register = (profile: NewUser) => {
register = (profile: NewUser & { captcha: string }) => {
return createPendingAction(
this.http.post('/auth/register', profile),
'LOGIN_REGISTER',

View File

@ -5,12 +5,14 @@ import { Link } from 'react-router-dom'
import { Input } from '../components/Input'
import { Redirect } from '../components/Redirect'
import { Button } from '../components'
import { Captcha } from '@rondo.dev/react-captcha'
export interface RegisterFormProps {
baseUrl: string
error?: string
onSubmit: () => void
onChange: (name: string, value: string) => void
data: NewUser
data: NewUser & { captcha: string }
user?: UserProfile
redirectTo: string
}
@ -74,6 +76,19 @@ export class RegisterForm extends React.PureComponent<RegisterFormProps> {
value={this.props.data.lastName}
placeholder='Last name'
/>
<Captcha
imageUrl={this.props.baseUrl + '/api/auth/captcha.svg'}
audioUrl={this.props.baseUrl + '/api/auth/captcha.wav'}
/>
<Input
Icon={undefined}
label='Captcha'
name='captcha'
type='text'
onChange={this.props.onChange}
value={this.props.data.captcha}
placeholder='Captcha'
/>
<div className='text-center'>
<Button name='submit' type='submit'>
Register

View File

@ -20,7 +20,7 @@ describe('configureRegister', () => {
select: state => state.Login,
})
.withComponent(
select => configureRegister(select, loginActions),
select => configureRegister(select, loginActions, '/app'),
)
.withJSX((Component, props) =>
<MemoryRouter><Component {...props} /></MemoryRouter>,
@ -41,6 +41,7 @@ describe('configureRegister', () => {
password: 'pass',
firstName: '',
lastName: '',
captcha: '',
}
const onSuccess = jest.fn()
let node: Element

View File

@ -6,16 +6,18 @@ import { LoginState } from './LoginReducer'
import { RegisterForm } from './RegisterForm'
import { withForm } from './withForm'
const defaultCredentials: NewUser = {
const defaultCredentials: NewUser & { captcha: string }= {
username: '',
password: '',
firstName: '',
lastName: '',
captcha: '',
}
export function configureRegister<State>(
getLocalState: SelectState<State, LoginState>,
loginActions: LoginActions,
baseUrl: string,
) {
return pack(
getLocalState,
@ -25,6 +27,7 @@ export function configureRegister<State>(
redirectTo: state.redirectTo,
}),
dispatch => ({
baseUrl,
onSubmit: bindActionCreators(loginActions.register, dispatch),
clearOnSuccess: true,
}),

View File

@ -10,7 +10,7 @@ export interface APIDef {
}
'/auth/register': {
'post': {
body: NewUser
body: NewUser & { captcha: string }
response: UserProfile
}
}

View File

@ -13,9 +13,6 @@ export interface CaptchaState {
}
export class Captcha extends React.PureComponent<CaptchaProps, CaptchaState> {
static defaultProps = {
name: 'captcha',
}
state: CaptchaState = {
type: 'image',
attempt: 1,
@ -46,7 +43,7 @@ export class Captcha extends React.PureComponent<CaptchaProps, CaptchaState> {
</a>
{this.props.audioUrl && (
<a className='action-audio' onClick={this.changeToAudio}>
Click here for image version
Click here for audio version
</a>
)}
</>
@ -58,7 +55,7 @@ export class Captcha extends React.PureComponent<CaptchaProps, CaptchaState> {
Refresh
</a>
<a className='action-image' onClick={this.changeToImage}>
Click here for audio version
Click here for image version
</a>
</>
)}

View File

@ -2,8 +2,10 @@
import { createStore, SelectState, WaitMiddleware } from '@rondo.dev/redux'
import React from 'react'
import ReactDOM from 'react-dom'
import T from 'react-dom/test-utils'
import { Provider } from 'react-redux'
import { Action, AnyAction, combineReducers, Reducer, ReducersMapObject } from 'redux'
import { ThemeProvider, DefaultTheme } from 'styled-components'
interface RenderParams<State, LocalState> {
reducers: ReducersMapObject<State, any>
@ -18,15 +20,24 @@ export class TestContainer extends React.Component<{}> {
}
export class TestUtils {
static defaultTheme?: DefaultTheme
/**
* Create a redux store
*/
readonly createStore = createStore
readonly Utils = T
render(jsx: JSX.Element) {
const $div = document.createElement('div')
const component = ReactDOM.render(
<TestContainer>{jsx}</TestContainer>, $div) as unknown as TestContainer
<TestContainer>
<ThemeProvider theme={TestUtils.defaultTheme}>
{jsx}
</ThemeProvider>
</TestContainer>,
$div,
) as unknown as TestContainer
const node = component.ref.current!.children[0]
return {
component,

View File

@ -13,4 +13,5 @@ module.exports = {
'jsx',
],
setupFiles: ['<rootDir>/jest.setup.js'],
setupFilesAfterEnv: ['<rootDir>/src/jest.env.ts'],
}