Redux Form and Typescript testing with React Testing Library

Issue: write unit tests for Redux Form with Typescript.

Redux Form is an HOC (Higher-Order Component) that gives us a convenient way of managing the state of forms using Redux.

TL;DR

Unit tests for Redux Form usually consist of testing the correct r…


This content originally appeared on DEV Community and was authored by DEV Community

Issue: write unit tests for Redux Form with Typescript.

Redux Form is an HOC (Higher-Order Component) that gives us a convenient way of managing the state of forms using Redux.

TL;DR

Unit tests for Redux Form usually consist of testing the correct rendering of the form and the correct interaction with the form.

Tests for rendering include rendering without initial values, rendering with initial values and rendering with some presetted values.

Interacting with a form changes its behaviour. It could be disabling fields, disabling buttons or adding something to the form.

For testing Redux Form we should first create a store. There are two ways to do it. The first is creating a mock store. It allows us to test a form with initial values and any other functionality, except submitting the form. To test submitting the form, we should use a real store.

Creating a mock store (source code of example):

import thunkMiddleware from 'redux-thunk'
import configureStore from 'redux-mock-store'
import { IStore } from '../store'

export const mockStoreFactory = (initialState: Partial<IStore>) =>
  configureStore([thunkMiddleware])({ ...initialState })

Here IStore is the interface for our real store:

export interface IStore {
  form: FormStateMap
}

The best and most convenient way for testing Redux Form is to import an unconnected form component and wrap it in reduxForm HOC:

const ReduxFormComponent = reduxForm<IFormData, IOwnProps>({
  form: 'LoginForm'
})(UnconnectedLoginForm)

Where types are:

export interface IFormData {
  username: string
  password: string
}

export interface IOwnProps {
  isLoading?: boolean
}

export type LoginFormProps = IOwnProps & InjectedFormProps<IFormData, IOwnProps>

Now we can do our first test for correct form rendering:

  it('should render username and password fields and buttons', () => {
    render(
      <Provider store={mockStoreFactory({})}>
        <ReduxFormComponent />
      </Provider>
    )

    expect(screen.getByText('Username')).toBeInTheDocument()
    expect(screen.getByText('Password')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('Username')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('Password')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'Sign Up' })).toBeInTheDocument()
    expect(
      screen.getByRole('button', { name: 'Clear Values' })
    ).toBeInTheDocument()
  })

For testing preset values, we can use the function we created for producing a mock store:

  it('should render preseted initial values', () => {
    const onSubmit = jest.fn()

    const mockStore = mockStoreFactory({
      form: {
        LoginForm: { values: { username: 'Cartman', password: '1234' } }
      }
    } as unknown as IStore)

    render(
      <Provider store={mockStore}>
        <ReduxFormComponent onSubmit={onSubmit} />
      </Provider>
    )

    expect(screen.getByPlaceholderText(/username/i)).toHaveValue('Cartman')
    expect(screen.getByPlaceholderText(/password/i)).toHaveValue('1234')
  })

For testing a submitting form, we should use a real store:

  it('should call submit ones with setted values', () => {
    const onSubmit = jest.fn()

    // For test submit event we should use real store
    render(
      <Provider store={store}>
        <ReduxFormComponent onSubmit={onSubmit} />
      </Provider>
    )

    userEvent.type(screen.getByPlaceholderText(/username/i), 'Cartman')
    userEvent.type(screen.getByPlaceholderText(/password/i), '1234')
    userEvent.click(screen.getByRole('button', { name: 'Sign Up' }))

    expect(onSubmit).toHaveBeenCalledTimes(1)
    expect(onSubmit.mock.calls[0][0]).toEqual({
      username: 'Cartman',
      password: '1234'
    })
  })

We can create a store like this:

import { createStore, applyMiddleware, compose, combineReducers } from 'redux'
import { reducer as reduxFormReducer } from 'redux-form'
import { FormStateMap } from 'redux-form'

declare global {
  interface Window {
    __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose
  }
}

export interface IStore {
  form: FormStateMap
}

const reducer = combineReducers({
  form: reduxFormReducer
})

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

export const store = createStore(reducer, composeEnhancers(applyMiddleware()))

export default store

Summary:

For testing Redux Form with Typescript we should wrap an unconnected form in the types we use:

const ReduxFormComponent = reduxForm<IFormData, IOwnProps>({
  form: 'LoginForm'
})(UnconnectedLoginForm)

And after this we can render ReduxFormComponent wrapped into Provider like this:

  render(
    <Provider
      store={mockStoreFactory({
        form: {
          LoginForm: { values: { username: 'Cartman', password: '1234' } }
        }
      } as unknown as IStore)}
    >
      <ReduxFormComponent />
    </Provider>
  )

And test the UI like any other component:

    expect(screen.getByText('Username')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'Sign Up' })).toBeInTheDocument()
    userEvent.click(screen.getByRole('button', { name: 'Sign Up' }))

You can find the source code of this example on my Github page: https://github.com/ip4422/redux-form-typescript-testing-rtl


This content originally appeared on DEV Community and was authored by DEV Community


Print Share Comment Cite Upload Translate Updates
APA

DEV Community | Sciencx (2022-02-23T10:55:34+00:00) Redux Form and Typescript testing with React Testing Library. Retrieved from https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/

MLA
" » Redux Form and Typescript testing with React Testing Library." DEV Community | Sciencx - Wednesday February 23, 2022, https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/
HARVARD
DEV Community | Sciencx Wednesday February 23, 2022 » Redux Form and Typescript testing with React Testing Library., viewed ,<https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/>
VANCOUVER
DEV Community | Sciencx - » Redux Form and Typescript testing with React Testing Library. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/
CHICAGO
" » Redux Form and Typescript testing with React Testing Library." DEV Community | Sciencx - Accessed . https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/
IEEE
" » Redux Form and Typescript testing with React Testing Library." DEV Community | Sciencx [Online]. Available: https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/. [Accessed: ]
rf:citation
» Redux Form and Typescript testing with React Testing Library | DEV Community | Sciencx | https://www.scien.cx/2022/02/23/redux-form-and-typescript-testing-with-react-testing-library/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.