简体   繁体   中英

simulate("click") in test of ejected react-create-app project doesn't cause rerender

I find myself in a very unique situation because every blog I have been to says that I should not be having the issue with enzyme + jest that I am having. I am using react 16.8.5 to put together a small application. In that application I have the following code of a functional component that uses hooks

const allDaSums = (props) => {
    const [inputStateVal, setInputStateVal] = useState("");
    const [inputNumArray, setInputNumArray] = useState([0]);
    const [exception, setException] = useState("")
    const [result, setResult ] = useState(null);

    const createNumArray = () => {

        //code generating zeroArray and also positiveNumberArray
        //more code that also sets exception using SetException from above

        const positiveNumberArray = numberOnlyArray.filter(n => n  > 0)
        setInputNumArray([...positiveNumberArray, ...zeroArray]);
    }

    const evaluateSum = () => {
        // code doing math things and produce result
        setResult(reduceResult);
    }

    const styleResult = () => {
        return <span id={"resultElement"} className={classes.Result}>{result}</span>;
    }

    return(
        <React.Fragment>
            <div className={classes.CalculatorUIContainer}>
                <input 
                    className={exception.length ? classes.CalculatorInputException : classes.CalculatorInput}
                    value={inputStateVal} 
                    onChange={(e) => setInputStateVal(e.target.value)} 
                    onBlur={createNumArray}
                    id={"inputVals"}
                    placeholder={placeHolderText ? placeHolderText : "Input comma separated numbers"} />
                <Button 
                    id={"calculateButton"}
                    type={"button"} 
                    btnType={"Success"} 
                    clicked={evaluateSum} 
                >Calculate</Button>
            </div>

            {result !== null && !exception.length ? 
                <div id={"resultDiv"} className={classes.ResultAnnouncement}>The sum of the values is: {styleResult()}</div>
                :
                null
            }
            {exception.length ? 
                <div id={"exceptionElement"} className={classes.Exception}>{exception}</div>
                :
                null
            }
        </React.Fragment>
    )
}

the above is a condensed version of my functional component. Then in my app, created using create-react-app script and ejected, I have a folder called test and inside I have my test file with the following breaking test

import React from 'react';
import { shallow, mount} from 'enzyme'
import  AllDaSums from '../../src/containers/AllDaSums/AllDaSums';

describe("Inputing values", () => {
    it('values are entered into the input field and state updates', () => {
        const wrapper = shallow(<AllDaSums />);

        // wrapper.find("input").simulate('change', { target: { value: '1,2' } });
        wrapper.find("input").prop('onChange')({
            target: {
                value: '1,2'
            }
        });

        wrapper.find(Button).simulate("click");

        wrapper.update();

        expect(wrapper.find('#resultDiv')).toHaveLength(1)

        console.log(wrapper.debug())

    });
});

current my test fails with the following error

  ● Inputing values › values are entered into the input field and state updates

    expect(received).toHaveLength(expected)

    Expected length: 1
    Received length: 0
    Received object: {}

and the console.log shows the following

  console.log test/StringCalculator.test.js:38
    <Fragment>
      <div className={[undefined]}>
        <input className={[undefined]} type="text" value="1,2" onChange={[Function: onChange]} onBlur={[Function: createNumArray]} id="inputVals" />
        <button id="calculateButton"clicked={[Function: evaluateSum]}>
          Calculate
        </button>
      </div>
    </Fragment>

what I can't seem to figure out is why the simulated click is not causing a new render thus updating the result variable and thus rendering the jsx that shows the result.

Here are my devDependencies

  "devDependencies": {
    "babel-preset-env": "^1.7.0",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.2",
    "babel-preset-react-app": "^7.0.0"
  }

and I have a test folder with my test file in it as well as a jest.config.js file with the following:

module.exports = {
    setupFiles: [
        '<rootDir>/test/setupTests.js',
    ],
    moduleNameMapper: {
        '\\.(css|less)$': '<rootDir>/test/styleMock.js',
    }
};

So might anyone know what I am doing wrong or what is causing my test to fail when it, I think, obviously shouldn't?

PS I have also tried the react-testing-library endorsed by THE Kent C. Dodds but that also doesn't cause a rerender thus the result dependent jsx doesn't show up on the page when I search for it.

PSS Using mount instead of shallow gives me this error

  ● Inputing values › values are entered into the input field and state updates

    TypeError: Cannot read property 'current' of undefined

I think I found a solution but maybe not the most ideal solution. So if anyone can think of a cleaner one, please don't be shy.

My new working test now looks like this

    it('values are entered into the input field, button is clicked, and result is shown', () => {
        const wrapper = shallow(<StringCalculator />);

        wrapper.find("input").simulate('change', { target: { value: '1,2' } });

        wrapper.find("#inputVals").props().onBlur();

        wrapper.find(Button).props().clicked();

        expect(wrapper.find('#resultDiv').exists()).toEqual(true)

        expect(wrapper.find('#resultElement').text()).toEqual('3')

    });
});

I think this should work perfectly fine with @testing-library/react

Note : testing-library is by default configured to pick your elements by data-testid so you need to use data-testid instead of just id . However you can configure this to refer id as well.

import React from "react";
import { render, fireEvent } from "@testing-library/react";
// import AllDaSums -- your component

it("render test", () => {
  const { getByTestId } = render(<AllDaSums />);
  fireEvent.change(getByTestId("inputVals"), { target: { value: "1,2" } });
  fireEvent.click(getByTestId("calculateButton"));
  expect(getByTestId("resultDiv").textContent).toBe(
    "The sum of the values is: 3"
  );
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM