const isFunction = require('lodash.isfunction');
const invariant = require('invariant');

let oldJasmineFns = {it, fit, xit, beforeEach, afterEach, beforeAll, afterAll};

function withAsync(fns) {
  return Object.keys(fns).reduce((memo, name) => {
    memo[name] = fns[name];
    memo[name].async = function(...args) {
      const callback = args.pop();
      invariant(isFunction(callback), `${name} must be provided a function!`);
      return (fns[name])(...args, done => {
        const promise = this::callback();
        invariant(promise instanceof Promise, `${name} must return a promise!`);
        promise.then(done, done.fail);
      });
    };
    return memo;
  }, {});
}

module.exports = {
  install() {
    Object.assign(global, {...withAsync(oldJasmineFns)});
  },

  uninstall() {
    Object.assign(global, oldJasmineFns);
  }
};
const isFunction = require('lodash.isfunction');
const invariant = require('invariant');

let oldJasmineFns = {it, fit, xit, beforeEach, afterEach, beforeAll, afterAll};

function withAsync(fns) {
  return Object.keys(fns).reduce((memo, name) => {
    memo[name] = fns[name];
    memo[name].async = function(...args) {
      const callback = args.pop();
      invariant(isFunction(callback), `${name} must be provided a function!`);
      return (fns[name])(...args, done => {
        const promise = this::callback();
        invariant(promise && isFunction(promise.then), `${name} must return a promise!`);
        promise.then(done, done.fail);
      });
    };
    return memo;
  }, {});
}

module.exports = {
  install() {
    Object.assign(global, {...withAsync(oldJasmineFns)});
  },

  uninstall() {
    Object.assign(global, oldJasmineFns);
  }
};

Check for promise.then instead of using instanceof
Check for promise.then instead of using instanceof

When using polyfills for Promise, different polyfills have different implementations of Promise. An `instanceof` check can lead to unexpected results.