Skip to content

Component State doesn't update on simulating input change event #1283

@iiison

Description

@iiison

Hello, I am new to Jest. I am testing a login page and I am simulating text change in my form. I am setting a value to the input and then I am triggering the change event. Everything works fine, the expected function is being called, the input box holds the value but the state of the component is not being updated. Here is part of related code:

Container:

export class LoginContainer extends Component {
  constructor() {
    super()

    this.state = {
      userName : '',
      password : ''
    }
  }

  /**
  * Set value of state in order to show in the input box
  *
  * @param {String} value    value to be set in the field
  * @param {String} propName field name
  */
  handleInputChange = (value, propName) => {
    this.setState({
      ...this.state,
      [propName] : value
    })
  }

  /**
   * Initialte login call on form submit
   *
   * @param {Object} event Event object
   */
  handleLogin = (event) => {
    event.preventDefault()
    const {userName, password} = this.state

    this.props.userLogin({
      userName,
      password
    })
      .then(() => {
        this.props.history.push('/')
      })
  }

  // ... some other class functions..

  render() {
    const { userName, password } = this.state
    const { isFetching, error } = this.props

    return (
      <Login 
        error={error}
        userName={userName}
        password={password}
        isFetching={isFetching}
        onFormSubmit={this.handleLogin}
        onInputChange={this.handleInputChange}
      />
    )
  }
}
... connecting the component with react-redux connect...

Component:

<form className={`center ${styles['login-form']}`}>
  <div className={styles['input-container']}>
    <input 
      type='text' 
      value={userName}
      placeholder='Enter Email' 
      onChange={(event) => onInputChange(event.target.value, 'userName')}
    />
  </div>
  <div className={styles['input-container']}>
    <input 
      type='password'
      value={password} 
      placeholder='Enter Password'
      onChange={(event) => onInputChange(event.target.value, 'password')}
    />
  </div>
  <div>
    <button
      type='submit'
      onClick={onFormSubmit}
      disabled={isFetching}
      className={`button ${styles.submit} ${isFetching && styles.disabled}`}
    >{isFetching ? 'Loading...' : 'Login'}</button>
  </div>
</form>

Test:

describe('>>> Login Container -- Shallow Rendering', () => {
  const initialState = userActionCreators.initialState
  let mountedScreen
  const loginScreen = (customState = {}) => {
    if (!mountedScreen) {
      const updatedState = {
        ...initialState,
        ...customState
      }

      mountedScreen = mount(<LoginContainer {...updatedState} />)
    }

    return mountedScreen
  }

  beforeEach(() => {
    mountedScreen = undefined
  })

  it('Simulates text change in input box', () => {
      const tree = loginScreen()
      const instance = tree.instance()
      const handleInputChangeSpy = jest.spyOn(instance, 'handleInputChange')
      const input = tree
        .find('input')
        .first()

      instance.forceUpdate()
      input.value = 'test'
      input.simulate('change', input)

      console.log('&&&&&&&&&&&&&&&&&&&&&')
      console.log(instance.state) // userName and password are empty here
      console.log('&&&&&&&&&&&&&&&&&&&&&')

      expect(handleInputChangeSpy).toHaveBeenCalledWith('test', 'userName')
    })
})

Console Error:

● >>> Login Container -- Shallow Rendering › Simulates text change in input box

    expect(jest.fn()).toHaveBeenCalledWith(expected)

    Expected mock function to have been called with:
      "test" as argument 1, but it was called with "".

Let me know if you need anything else.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions