text: // jscs:disable maximumLineLength
  /* jshint evil:true */
  'use strict';
  
  // Bail if we're not running in node >= 0.11
  var ver = process.versions.node.split('.').map(function(s) {
    return parseInt(s, 10);
  });
  var node11 = ver[0] > 0 || ver[1] >= 11;
  if (!node11) { return; }
  
  var assert = require('assert');
  var Promise = require('../');
  
  function get(arg) {
    return {
      then: function(ful, rej) {
        ful(arg);
      },
    };
  }
  
  function fail(arg) {
    return {
      then: function(ful, rej) {
        rej(arg);
      },
    };
  }
  
  function delay() {
    return new Promise(function(a) {
      setTimeout(a, 15);
    });
  }
  
  var error = new Error('asd');
  
  describe('Promise.async', function() {
    describe('thenables', function() {
      specify('when they fulfill, the yielded value should be that fulfilled value', function() {
  
        return Promise.async(eval('(function*(){' +
  
          'var a = yield get(3);' +
          'assert.equal(a, 3);' +
          'return 4;' +
  
        '})'))().then(function(arg) {
          assert.equal(arg, 4);
        });
  
      });
  
  
      specify("when they reject, and the generator doesn't have try.caught, it should immediately reject the promise", function() {
  
        return Promise.async(eval('(function*(){' +
          'var a = yield fail(error);' +
          'assert.fail();' +
  
        '})'))().then(assert.fail, function(e) {
          assert.equal(e, error);
        });
  
      });
  
      specify('when they reject, and the generator has try.caught, it should continue working normally', function() {
  
        return Promise.async(eval('(function*(){' +
          'try {' +
          '  var a = yield fail(error);' +
          '} catch(e) {' +
          '  return e;' +
          '}' +
          'assert.fail();' +
        '})'))().then(function(v) {
          assert.equal(v, error);
        });
  
      });
  
      specify('when they fulfill but then throw, it should become rejection', function() {
  
        return Promise.async(eval('(function*(){' +
          'var a = yield get(3);' +
          'assert.equal(a, 3);' +
          'throw error;' +
        '})'))().then(assert.fail, function(e) {
          assert.equal(e, error);
        });
      });
    });
  
    describe('yield loop', function() {
  
      specify('should work', function() {
        return Promise.async(eval('(function*() {' +
          'var a = [1,2,3,4,5];' +
  
          'for( var i = 0, len = a.length; i < len; ++i ) {' +
          '  a[i] = yield get(a[i] * 2);' +
          '}' +
  
          'return a;' +
        '})'))().then(function(arr) {
          assert.deepEqual([2, 4, 6, 8, 10], arr);
        });
      });
  
      specify('inside yield should work', function() {
        return Promise.async(eval('(function*() {' +
          'var a = [1,2,3,4,5];' +
  
          'return yield Promise.all(a.map(function(v){' +
          '  return Promise.async(function *() {' +
          '    return yield get(v*2);' +
          '  })();' +
          '}));' +
        '})'))().then(function(arr) {
          assert.deepEqual([2, 4, 6, 8, 10], arr);
        });
      });
  
      specify('with simple map should work', function() {
        return Promise.async(eval('(function*() {' +
          'var a = [1,2,3,4,5];' +
  
          'return yield Promise.map(a, function(v){' +
          '  return Promise.resolve(get(v*2));' +
          '});' +
        '})'))().then(function(arr) {
          assert.deepEqual([2, 4, 6, 8, 10], arr);
        });
      });
  
    });
  
    describe('when using async as a method', function() {
  
      function MyClass() {
        this.goblins = 3;
      }
  
      MyClass.prototype.noOp = Promise.async(eval('(function*(){})'));
      MyClass.prototype.spawnGoblins = Promise.async(eval('(function*(){' +
      '  this.goblins = yield get(this.goblins+1);' +
      '})'));
  
  
      specify('should always return a promise', function() {
        var a = new MyClass();
        assert(a.noOp() instanceof Promise);
        return a.noOp().then(function(v) {
          assert.equal(v, undefined);
        });
      });
  
      specify("generator function's receiver should be the instance too", function() {
        var a = new MyClass();
        var b = new MyClass();
  
        return Promise.join(a.spawnGoblins().then(function() {
          return a.spawnGoblins();
        }), b.spawnGoblins()).then(function() {
          assert.equal(a.goblins, 5);
          assert.equal(b.goblins, 4);
        });
  
      });
    });
  });
  