Skip to content

Testing Hooks with mount: onChange not called #1996

@ekaradon

Description

@ekaradon

Current behavior

When simulating some changes on input with components using hooks, depending of the component, it looks like the onChange is not called.

Expected behavior

Whatever the component, when simulating changes on input, the onChange method must be called.

Your environment

API

mount

Version

library version
enzyme 3.4.1
react 16.8.0-alpha.1
react-dom 16.8.0-alpha.1
react-test-renderer 15.6.2
adapter (below) 1.3.0

Adapter

enzyme-adapter-react-16

import React, { useState, useEffect } from 'react';
import sinon from 'sinon';
import Adapter from 'enzyme-adapter-react-16';
import { mount, configure } from 'enzyme';

configure({ adapter: new Adapter() });

function useFormInput(initial_value = '') {
    const [value, setValue] = useState(initial_value);

    function handle_change(e) {
        setValue(e.target.value);
    }

    return {
        value
        , onChange: handle_change
    };
}

function Input(props) {
    return (
        <div>
            <input {...props} />
        </div>
    );
}

function ControlledInputWithEnhancedInput({ searchSomething }) {
    const search = useFormInput();

    useEffect(
        () => { searchSomething(search.value); }
        , [search.value]
    );

    return (
        <Input {...search} />
    );
}

function ControlledInputWithNativeInput({ searchSomething }) {
    const search = useFormInput();

    useEffect(
        () => { searchSomething(search.value); }
        , [search.value]
    );

    return (
        <input {...search} />
    );
}

it('does not succeed', () => {
    jest.useFakeTimers();

    const spy = sinon.spy();
    const component = mount(<ControlledInputWithEnhancedInput searchSomething={spy} />);

    component.simulate('change', { target: { value: 'foo' } });
    jest.runAllTimers();

    expect(spy.withArgs('foo').calledOnce).toBe(true);
});

it('does succeed', () => {
    jest.useFakeTimers();

    const spy = sinon.spy();
    const component = mount(<ControlledInputWithNativeInput searchSomething={spy} />);

    component.simulate('change', { target: { value: 'foo' } });
    jest.runAllTimers();

    expect(spy.withArgs('foo').calledOnce).toBe(true);
});

The single fact to wrap the input with a div is hurting the test. Really Weird. Is there anyone having an idea about this?

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