Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promises broken in Jest tests #6104

Closed
cgreening opened this issue Feb 23, 2016 · 11 comments
Closed

Promises broken in Jest tests #6104

cgreening opened this issue Feb 23, 2016 · 11 comments
Assignees
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@cgreening
Copy link

We have a very simple test case that reproduces this issue:

describe('promises', function() {
  it('should resolve', function(done) {
    new Promise((resolve, reject) => {
      resolve('it works');
    }).then((result) => {
      expect(result).toEqual('it works');
      done();
    }, (error) => {
      expect(error).toBeFalsy();
      done(error);
    });
  });
});

result:

Using Jest CLI v0.8.2, jasmine2
 FAIL  __tests__/api_tests.js (5.02s)
● promises › it should resolve
  - Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
1 test failed, 0 tests passed (1 total in 1 test suite, run time 5.736s)
npm ERR! Test failed.  See above for more details.

expected:

Using Jest CLI v0.8.2, jasmine2
 PASS  __tests__/api_tests.js (0.212s)
1 test passed (1 total in 1 test suite, run time 0.894s)

We've tracked it down to this commit:

3ff3987

and this line in file jestSupport/env.js

global.Promise = require('promise');

When we comment out this line the promise resolves as expected.

cgreening referenced this issue Mar 5, 2016
Summary:
We weren't exposing a mock for the batched bridge, which resulted in the WebSocket test failure but only in the open source copy of react-native.

public

Reviewed By: voideanvalue, vjeux

Differential Revision: D2782151

fb-gh-sync-id: e896097dd6060bc26963bc4c23db87b7277b3eba
@brentvatne
Copy link
Collaborator

@cpojer :)

@cpojer
Copy link
Contributor

cpojer commented Mar 6, 2016

Ugh, this is so annoying that it keeps popping up. Once the testing docs are rewritten, this will hopefully not be an issue any longer. I'll take a look soon.

@brentvatne
Copy link
Collaborator

great, sorry for bothering you on a Sunday :)

@dooburt
Copy link

dooburt commented Apr 12, 2016

Any update on this issue? I've just started getting it and don't really want to touch the library...

@cpojer
Copy link
Contributor

cpojer commented Jul 27, 2016

Thank you for your patience. We launched Jest 14.0 with experimental react-native support:

Please feel free to create new issues after trying out the new integration if any issues remain.

@cpojer cpojer closed this as completed Jul 27, 2016
@hanpanpan200
Copy link

@cpojer
I also got this error, but I found an interesting law here. Promise wrote in ./jestSupport/env.js can resolve but if it is wrote in some test files, it will not resolve so leading to error:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

I was trying to mock AsyncStorage in my test, the code below can reproduce that bug. I had two versions for the mock, versionA works but versionB does not.

VersionA

./jestSupport/AsyncStorage.js

var AsyncStorage = {
  getItem: jest.fn().mockReturnValue(
    new Promise((resolve, reject) => {
      resolve(JSON.stringify({
        id: 32,
        name: "Grace Han"
      }))
    })
  ),

  setItem: jest.fn(),
}

module.exports = AsyncStorage

./jestSupport/env.js

import AsyncStorage from './AsyncStorage'
jest.setMock('AsyncStorage', AsyncStorage)

actions-test.js

// Some other test code

it('should get user info', () => {
    const expectedActions = [
      { type: PATIENT_AUTH.GET_DEFAULT_USERINFO }
    ]
    const store = mockStore({})
    //the action: getUserInfo will call AsyncStorage.getItem() 
    return store.dispatch(actions.getUserInfo())
      .then(() => {
        expect(store.getActions()[0].type).toEqual(expectedActions[0].type)
      })
  })

VersionB

./jestSupport/AsyncStorage.js

var AsyncStorage = {
  getItem: jest.fn(),
  setItem: jest.fn(),
}

module.exports = AsyncStorage

./jestSupport/env.js

import AsyncStorage from './AsyncStorage'
jest.setMock('AsyncStorage', AsyncStorage)

actions-test.js

// Some other test code

it('should get user info', () => {
    const expectedActions = [
      { type: PATIENT_AUTH.GET_DEFAULT_USERINFO }
    ]
    const store = mockStore({})
    const AsyncStorage = require('react-native').AsyncStorage
    AsyncStorage.getItem.mockReturnValue(
      new Promise((resolve, reject) => {
        resolve(JSON.stringify({
          id: 32,
          name: "Grace Han"
        }))
      })
    )
   //the action: getUserInfo will call AsyncStorage.getItem() 
    return store.dispatch(actions.getUserInfo())
      .then(() => {
        expect(store.getActions()[0].type).toEqual(expectedActions[0].type)
      })
  })

Actually versionB can meet my requirements, because I want to mock different return values for different test, versionA can only return then same promise for me. So this troubles me a lot.
I had seen the Solutions but that does not work for me.
Hope this can help for tracking down the reason. and wait for response.

@mikelovesrobots
Copy link

mikelovesrobots commented Aug 25, 2016

Yeah. I'm getting weird results:

    it("promises work?", () => {
      return Promise.resolve().then(() => {
        expect(true).toBe(false)
      })
    })

    it("async works?", async () => {
      await Promise.resolve()
      expect(true).toBe(false)
    })

both time out instead of hitting the expectation

For what it's worth:

Using Jest CLI v14.1.0, jasmine2, babel-jest, jest-react-native preset

@skurgansky-sugarcrm
Copy link

skurgansky-sugarcrm commented Sep 4, 2016

I'm wondering is this issue still not fixed ? (jest-cli: 14.1.0)
Im trying to test a view method called in chain of bluebird promises and get this error all the time
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. at callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:477:19) at Timer.listOnTimeout (timers.js:92:15)
But if I move this async it to the top of my describe block where are 4 other sync tests, It passes.

first time I noticed that replacing
import Promise from 'bluebird';
for
const Promise = require('bluebird');
helps. But there is still some problem with mixing async tests that relates to testing methods with use of Promises with sync tests. And yes I pass done callback and call it when test should be finished.

@skurgansky-sugarcrm
Copy link

looks like it's fixed on "jest-cli": "15.1.1".

@nyura123
Copy link

nyura123 commented Sep 9, 2016

I was still seeing this issue with v15.1.1, but fixed it by saving Promise, then restoring it after requiring (not importing) react-native.

//importing 'react-native' seems to break Promise and setTimeout.
//use require() instead of import, so we can save these first, and restore them after require('react-native')
const SavePromise = Promise;
const saveSetTimeout = setTimeout;

import React, { Component } from 'react';
const {
  View,
  Text,
  StyleSheet,
  Dimensions,
  Platform
} = require('react-native');

Promise = SavePromise;
setTimeout = saveSetTimeout;

it("promises work?", () => {
  return Promise.resolve().then(() => {
    expect(true).toBe(true)
  })
})

it("async works?", async () => {
  await Promise.resolve()
  expect(true).toBe(true)
})

it('works with async/await', async () => {
  const userName = await 'Mark'
  expect(userName).toEqual('Mark');
});

it('works after timeout', () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      expect(true).toBe(true)
      resolve()
    }, 10)
  })
})

@cooperka
Copy link
Contributor

Since this issue has been closed, I opened a new one here with updated details and the latest versions of Jest and React Native.

@facebook facebook locked as resolved and limited conversation to collaborators Jul 20, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 20, 2018