Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for promise in Jest React test?

I want to test a React component with Jest and Enzyme. This component is a login form and when the user clicks on the login button, I want to check that depending the result, the object model is well updated accordingly.

Here is the part of the code that is called when the user clicks on on the submit button.

// Login.jsx
handleSubmit(e) {

  var that = this;

  this.setState({stateResult: "", errorLabel: ""});

  if(e) {
    e.preventDefault();
    e.stopPropagation();
  }

  MyService.login(this.state.email, this.state.password).then(function(account) {
    that.setState({stateResult: "login-ok", errorLabel: ""});
  }).catch(function(err) {
    that.setState({stateResult: "login-error", errorLabel: err.data.message});
  });
};

I wrote a Jest test. Here is the code:

// Login-test.js
test('that when the signin fails, the stateResult model is updated with login-error', () => {

    const wrapper = shallow(<Landing />);
    wrapper.find('a#landingjsx-signin').simulate('click');

    wrapper.update();
    setTimeout(function() {
        expect(wrapper.state().stateResult).toEqual("login-error");
    }, 100);
});

For testing it, I use a mock of MyService

jest.mock('../../../modules/MyService.js');

Here is the code of my mock:

//MyService.js
class MyService {

  constructor() {

  }

  login(user, password) {

    return new Promise((resolve, reject) => {

        process.nextTick(() => {
            if(user === "aaa") {
                resolve({});
            }
            else {
                reject({
                    data: {
                        message: "bad-password"
                    }
                });
            }
        });
    });
  }
}

export default new MyService();

The test fails right :-)

My question is: How to remove the setTimeout() call from my test ? Is there a better way to test this promise based function.

My problem is how to wait for the promise function to fail before expecting the result ?

Thanks in advance

like image 809
oanfr Avatar asked Apr 18 '17 20:04

oanfr


People also ask

How do you wait in Jest test?

Return a promise from your test, and Jest will wait for that promise to resolve. If the promise is rejected, the test will fail.

How do you handle promise rejection in Jest?

Try-catch with async/await (bad) It looks like using try-catch with async/await is the easiest way to achieve this as the rejected value is thrown: it("rejects (bad)", async () => { try { await promiseMe("Error"); } catch (e) { expect(e). toEqual("Error"); } }); But wait.

How do you mock a promise in Jest?

In order to mock asynchronous code in Jest, more specifically Promises, you can use the mockResolvedValue function. This will mock the return value of the Promise to be 42. In order to test a Promise in Jest, you need to turn your it block into async in order to use the await keyword in front of an expect statement.

What is Jest fn ()?

The Jest library provides the jest. fn() function for creating a “mock” function. An optional implementation function may be passed to jest. fn() to define the mock function's behavior and return value. The mock function's behavior may be further specified using various methods provided to the mock function such as .


1 Answers

Just a hunch: try adding the done callback.

// Login-test.js
test('that when the signin fails, the stateResult model is updated with login-error', (done) => {

    const wrapper = shallow(<Landing />);
    wrapper.find('a#landingjsx-signin').simulate('click');

    wrapper.update();
    setTimeout(function() {
        try {
          expect(wrapper.state().stateResult).toEqual("login-error");
          done()
        } catch (e) {
          done.fail(e)
        }
    }, 100);
});

You need to wrap the expectation in try-catch, because expect throws on error and a test failure will cause done not to be called.

Also see the jest docs for more extended examples.

like image 192
publicJorn Avatar answered Sep 29 '22 12:09

publicJorn