Home > Software engineering >  How to assert that method is called
How to assert that method is called

Time:10-09

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?

CodePudding user response:

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.

CodePudding user response:

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',
});
  • Related