0
votes

Im struggling to find a solution when testing a redux-form component. The problem is that only when I test simply if the component is rendering it gives me an error: "TypeError: handleSubmit is not a function", but the app is working fine, as expected.

I've tried to solve it just to make handleSubmit a function and not taking it from props, but then the app doesn't work. When the submit form is correct it must navigate to /landing page, but instead just re-render the login component.

The component:

import React, { Component } from 'react'
//import { Link } from 'react-router-dom'
import { Field, reduxForm } from 'redux-form'
import '../../style/style.css'

export class Login extends Component {

    renderField(field) {

        const { meta: { touched, error} } = field;
        const className = `form-group ${touched && error ? 'has-danger' : ''}`; 

        return (
            <div className={className}>
                
                <input className="form-control" id="username_field" placeholder={field.label} type="text" {...field.input} />
                
                <div className="text-help"> 
                    { field.meta.touched ? field.meta.error : '' }
                </div>
            </div>
        )
    }

    renderPasswordField(field) {

        const { meta: { touched, error} } = field;
        const className = `form-group ${touched && error ? 'has-danger' : ''}`; 

        return (
            <div className={className}>
                
                <input className="form-control" id="password_field" placeholder={field.label} type="password" {...field.input} />
                
                <div className="text-help"> 
                { field.meta.touched ? field.meta.error : '' }
                </div>
            </div>
        )
    }

    onSubmit(values) {
       
        this.props.history.push('/landing')

    }

    // DOESN'T WORK!!! 
    //  handleSubmit(formValues){
    //   //console.log(formValues);
    // }



    render() {

        const { handleSubmit } = this.props

        return (

            <div>
                <div className="login-form">
                    <form onSubmit={ /*this.*/handleSubmit(this.onSubmit.bind(this))}>

                        <h2 className="text-center">TQI Log in</h2>
                        <div className="form-group">

                            <Field id="username" name="username" label="username" component={this.renderField} />
                        </div>
                        <div className="form-group">
                            <Field id="password" name="password" label="password" component={this.renderPasswordField} />

                        </div>
                        <div className="form-group">
                            
                            <button id="login_button" type="submit" className="btn btn-primary btn-block">Login </button>

                        </div>
                    </form>
                </div>
            </div>
        );
    }
}

function validate(values) {
    const errors = {}

    const dummyData = {
        username: 'admin',
        password: '123'
    }

    // Validate the inputs from values 
    if(!values.username) {
        errors.username = "Enter a username"
    } else if(values.username !== dummyData.username){
        errors.username = "Wrong username"
    }

    if(!values.password) {
        errors.password = "Enter a password"
    } else if( values.username === dummyData.username && values.password !== dummyData.password){
        errors.password = "Wrong password"
    }

    // if errors is empty, the form is fine to submit
    // If errors has *any* properties, redux forms assumes form is invalid
    return errors
}

export default reduxForm({
    validate,
    form: 'LoginForm'
})(Login)

The testing file:

import React from 'react'
import { shallow } from 'enzyme'
import { Login } from './login'


describe('<Login />', () => {

	it('render the <Login /> component without crashing', () => {
		const wrapper = shallow(<Login />)
		expect(wrapper.length).toEqual(1)
	})

	// it('navigate to /landing page when the form is submit correctly', () => {
		
	// })

 })
3

3 Answers

0
votes

You are consuming a prop function from your HOC reduxForm on your render method. But on the test file, you are importing the component without the HOC on top of it, which means that prop/function is not available. You have to provide Login with a mock handleSubmit prop function.

Try:

import React from 'react'
import { shallow } from 'enzyme'
import { Login } from './login'

describe('<Login />', () => {
    it('render the <Login /> component without crashing', () => {
        const wrapper = shallow(<Login handleSubmit={() => {}}  />)
        expect(wrapper.length).toEqual(1)
    })
 })
0
votes

you need pass onSubmit on initialization:

export default reduxForm({
    validate,
    form: 'LoginForm',
    onSubmit: this.onSubmit // here
})(Login)

or in props:

<Component>
    <Login onSubmit={this.onSubmit}/>
</Component>
0
votes

First export the redux-form decorated class

    export const DecoratedLogin = reduxForm({
      validate,
      form: 'LoginForm'
    })(Login);

Then use it instead of the plain class.

import { DecoratedLogin } from './login'

and you should be able to access the props from redux-form.