0

This is my form:

import { useState } from "react"
import { Form, Button, Row, Col } from "react-bootstrap"
import { actions as parametersActions } from "../../actions/ParametersActions"
import { connect } from "react-redux"

export const Parameters = props => {

    const [birthdate, setBirthdate] = useState("")
    const [height, setHeight] = useState("")

    const handleForm = (e) => {
        if (e.target.id === 'birthdate') {
            setBirthdate(e.target.value)
        }
        if (e.target.id === 'height') {
            setHeight(e.target.value)
        }
    }

    const handleSubmit = (e) => {
        e.preventDefault()
        const payload = {
            birthdate: birthdate,
            height: height
        }
        props.post(payload)
    }

    return (
        <Row className="justify-content-md-center">
            <Col xs lg="4">
                <Form>
                    <Form.Group controlId="birthdate">
                        <Form.Label>Data di nascita</Form.Label>
                        <Form.Control type="text" placeholder="Inserisci data di nascita" value={birthdate} onChange={handleForm} />
                    </Form.Group>
                    <Form.Group controlId="height">
                        <Form.Label>Altezza</Form.Label>
                        <Form.Control type="text" placeholder="Altezza" value={height} onChange={handleForm} />
                    </Form.Group>
                    <div className="d-grid gap-2">
                        <Button variant="primary" onClick={handleSubmit}>
                            Salva
                        </Button>
                    </div>
                </Form>
            </Col>
        </Row>
        
    )
}

export const mapStateToProps = (state) => {
    return {
        isLoading: state.parameters.isLoading
    }
}

export const mapDispatchToProps = (dispatch) => {
    return {
        post: (data) => dispatch(parametersActions.post(data))
    }
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Parameters)

And this is my test:

import { render, screen, fireEvent } from '@testing-library/react'
import thunk from 'redux-thunk'
import configureMockStore from 'redux-mock-store'
import Parameters from '../../../presentationals/forms/Parameters'
import { action as parametersActions } from '../../../actions/ParametersActions'


describe('Parameters form', () => {

    it('Can store new parameters', async () => {

        const middlewares = [thunk]
        const mockStore = configureMockStore(middlewares)
      
        const initialState = {
            parameters: {
                isLoading: false,
            },
            post: (data) => dispatch(parametersActions.post(data))
        }
        const store = mockStore(initialState)

        render(<Parameters store={store} />)
        const birthdate = screen.getByText(/nascita/i)
        expect(birthdate).toBeInTheDocument()
      
        const height = screen.getByText(/altezza/i)
        expect(height).toBeInTheDocument()
      
        fireEvent.change(screen.getByLabelText(/nascita/i), {
            target: {value: '1990-12-31'},
        })
      
        fireEvent.change(screen.getByLabelText(/altezza/i), {
            target: {value: '170'},
        })

        fireEvent.click(screen.getByText(/salva/i))
        // how can I test here?
        
    })

})

I want to test that

  1. handleSubmit is called
  2. props.post() is called

How can I add that test?

2
  • 1
    You don't want to test 1., that's an implementation detail. Commented Oct 8, 2021 at 19:15
  • 1
    toHaveBeenCalled Commented Oct 8, 2021 at 19:17

2 Answers 2

1

When using React-Testing-Library don't test internal implementation details, but rather the API of the component, in this case, the post prop callback function.

  1. Import and test the unconnected component, you can easily mock the prop values redux would provide
  2. Mock a post prop function
  3. Interact with the UI
  4. Assert the post prop function was called (toHaveBeenCalled)

Code:

import { render, screen, fireEvent } from '@testing-library/react';
import { Parameters } from '../../../presentationals/forms/Parameters'
import { action as parametersActions } from '../../../actions/ParametersActions';


describe('Parameters form', () => {
  it('Can store new parameters', async () => {
    const postMock = jest.fn();             // <-- create mock callback

    render(<Parameters post={postMock} />); // <-- pass mock as prop

    ...

    fireEvent.click(screen.getByText(/salva/i));
    expect(postMock).toHaveBeenCalled();    // <-- assert mock was called
  });
});

If required you can use toHaveBeenCalledWith to assert specific values were passed to the callback.

expect(postMock).toHaveBeenCalledWith({
  birthdate: '1990-12-31',
  height: '170',
});
Sign up to request clarification or add additional context in comments.

Comments

0

Instead of testing if the handleSubmit has been called, you should test the result of triggering the submit event. Which in this case could mean verifying that the dispatch is made.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.