You are here

class PromiseTest in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/guzzlehttp/promises/tests/PromiseTest.php \GuzzleHttp\Promise\Tests\PromiseTest

@covers GuzzleHttp\Promise\Promise

Hierarchy

  • class \GuzzleHttp\Promise\Tests\PromiseTest extends \GuzzleHttp\Promise\Tests\PHPUnit_Framework_TestCase

Expanded class hierarchy of PromiseTest

File

vendor/guzzlehttp/promises/tests/PromiseTest.php, line 13

Namespace

GuzzleHttp\Promise\Tests
View source
class PromiseTest extends \PHPUnit_Framework_TestCase {

  /**
   * @expectedException \LogicException
   * @expectedExceptionMessage The promise is already fulfilled
   */
  public function testCannotResolveNonPendingPromise() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p
      ->resolve('bar');
    $this
      ->assertEquals('foo', $p
      ->wait());
  }
  public function testCanResolveWithSameValue() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p
      ->resolve('foo');
  }

  /**
   * @expectedException \LogicException
   * @expectedExceptionMessage Cannot change a fulfilled promise to rejected
   */
  public function testCannotRejectNonPendingPromise() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p
      ->reject('bar');
    $this
      ->assertEquals('foo', $p
      ->wait());
  }
  public function testCanRejectWithSameValue() {
    $p = new Promise();
    $p
      ->reject('foo');
    $p
      ->reject('foo');
  }

  /**
   * @expectedException \LogicException
   * @expectedExceptionMessage Cannot change a fulfilled promise to rejected
   */
  public function testCannotRejectResolveWithSameValue() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p
      ->reject('foo');
  }
  public function testInvokesWaitFunction() {
    $p = new Promise(function () use (&$p) {
      $p
        ->resolve('10');
    });
    $this
      ->assertEquals('10', $p
      ->wait());
  }

  /**
   * @expectedException \GuzzleHttp\Promise\RejectionException
   */
  public function testRejectsAndThrowsWhenWaitFailsToResolve() {
    $p = new Promise(function () {
    });
    $p
      ->wait();
  }

  /**
   * @expectedException \GuzzleHttp\Promise\RejectionException
   * @expectedExceptionMessage The promise was rejected with reason: foo
   */
  public function testThrowsWhenUnwrapIsRejectedWithNonException() {
    $p = new Promise(function () use (&$p) {
      $p
        ->reject('foo');
    });
    $p
      ->wait();
  }

  /**
   * @expectedException \UnexpectedValueException
   * @expectedExceptionMessage foo
   */
  public function testThrowsWhenUnwrapIsRejectedWithException() {
    $e = new \UnexpectedValueException('foo');
    $p = new Promise(function () use (&$p, $e) {
      $p
        ->reject($e);
    });
    $p
      ->wait();
  }
  public function testDoesNotUnwrapExceptionsWhenDisabled() {
    $p = new Promise(function () use (&$p) {
      $p
        ->reject('foo');
    });
    $this
      ->assertEquals('pending', $p
      ->getState());
    $p
      ->wait(false);
    $this
      ->assertEquals('rejected', $p
      ->getState());
  }
  public function testRejectsSelfWhenWaitThrows() {
    $e = new \UnexpectedValueException('foo');
    $p = new Promise(function () use ($e) {
      throw $e;
    });
    try {
      $p
        ->wait();
      $this
        ->fail();
    } catch (\UnexpectedValueException $e) {
      $this
        ->assertEquals('rejected', $p
        ->getState());
    }
  }
  public function testWaitsOnNestedPromises() {
    $p = new Promise(function () use (&$p) {
      $p
        ->resolve('_');
    });
    $p2 = new Promise(function () use (&$p2) {
      $p2
        ->resolve('foo');
    });
    $p3 = $p
      ->then(function () use ($p2) {
      return $p2;
    });
    $this
      ->assertSame('foo', $p3
      ->wait());
  }

  /**
   * @expectedException \GuzzleHttp\Promise\RejectionException
   */
  public function testThrowsWhenWaitingOnPromiseWithNoWaitFunction() {
    $p = new Promise();
    $p
      ->wait();
  }
  public function testThrowsWaitExceptionAfterPromiseIsResolved() {
    $p = new Promise(function () use (&$p) {
      $p
        ->reject('Foo!');
      throw new \Exception('Bar?');
    });
    try {
      $p
        ->wait();
      $this
        ->fail();
    } catch (\Exception $e) {
      $this
        ->assertEquals('Bar?', $e
        ->getMessage());
    }
  }
  public function testGetsActualWaitValueFromThen() {
    $p = new Promise(function () use (&$p) {
      $p
        ->reject('Foo!');
    });
    $p2 = $p
      ->then(null, function ($reason) {
      return new RejectedPromise([
        $reason,
      ]);
    });
    try {
      $p2
        ->wait();
      $this
        ->fail('Should have thrown');
    } catch (RejectionException $e) {
      $this
        ->assertEquals([
        'Foo!',
      ], $e
        ->getReason());
    }
  }
  public function testWaitBehaviorIsBasedOnLastPromiseInChain() {
    $p3 = new Promise(function () use (&$p3) {
      $p3
        ->resolve('Whoop');
    });
    $p2 = new Promise(function () use (&$p2, $p3) {
      $p2
        ->reject($p3);
    });
    $p = new Promise(function () use (&$p, $p2) {
      $p
        ->reject($p2);
    });
    $this
      ->assertEquals('Whoop', $p
      ->wait());
  }
  public function testCannotCancelNonPending() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p
      ->cancel();
    $this
      ->assertEquals('fulfilled', $p
      ->getState());
  }

  /**
   * @expectedException \GuzzleHttp\Promise\CancellationException
   */
  public function testCancelsPromiseWhenNoCancelFunction() {
    $p = new Promise();
    $p
      ->cancel();
    $this
      ->assertEquals('rejected', $p
      ->getState());
    $p
      ->wait();
  }
  public function testCancelsPromiseWithCancelFunction() {
    $called = false;
    $p = new Promise(null, function () use (&$called) {
      $called = true;
    });
    $p
      ->cancel();
    $this
      ->assertEquals('rejected', $p
      ->getState());
    $this
      ->assertTrue($called);
  }
  public function testCancelsUppermostPendingPromise() {
    $called = false;
    $p1 = new Promise(null, function () use (&$called) {
      $called = true;
    });
    $p2 = $p1
      ->then(function () {
    });
    $p3 = $p2
      ->then(function () {
    });
    $p4 = $p3
      ->then(function () {
    });
    $p3
      ->cancel();
    $this
      ->assertEquals('rejected', $p1
      ->getState());
    $this
      ->assertEquals('rejected', $p2
      ->getState());
    $this
      ->assertEquals('rejected', $p3
      ->getState());
    $this
      ->assertEquals('pending', $p4
      ->getState());
    $this
      ->assertTrue($called);
    try {
      $p3
        ->wait();
      $this
        ->fail();
    } catch (CancellationException $e) {
      $this
        ->assertContains('cancelled', $e
        ->getMessage());
    }
    try {
      $p4
        ->wait();
      $this
        ->fail();
    } catch (CancellationException $e) {
      $this
        ->assertContains('cancelled', $e
        ->getMessage());
    }
    $this
      ->assertEquals('rejected', $p4
      ->getState());
  }
  public function testCancelsChildPromises() {
    $called1 = $called2 = $called3 = false;
    $p1 = new Promise(null, function () use (&$called1) {
      $called1 = true;
    });
    $p2 = new Promise(null, function () use (&$called2) {
      $called2 = true;
    });
    $p3 = new Promise(null, function () use (&$called3) {
      $called3 = true;
    });
    $p4 = $p2
      ->then(function () use ($p3) {
      return $p3;
    });
    $p5 = $p4
      ->then(function () {
      $this
        ->fail();
    });
    $p4
      ->cancel();
    $this
      ->assertEquals('pending', $p1
      ->getState());
    $this
      ->assertEquals('rejected', $p2
      ->getState());
    $this
      ->assertEquals('rejected', $p4
      ->getState());
    $this
      ->assertEquals('pending', $p5
      ->getState());
    $this
      ->assertFalse($called1);
    $this
      ->assertTrue($called2);
    $this
      ->assertFalse($called3);
  }
  public function testRejectsPromiseWhenCancelFails() {
    $called = false;
    $p = new Promise(null, function () use (&$called) {
      $called = true;
      throw new \Exception('e');
    });
    $p
      ->cancel();
    $this
      ->assertEquals('rejected', $p
      ->getState());
    $this
      ->assertTrue($called);
    try {
      $p
        ->wait();
      $this
        ->fail();
    } catch (\Exception $e) {
      $this
        ->assertEquals('e', $e
        ->getMessage());
    }
  }
  public function testCreatesPromiseWhenFulfilledAfterThen() {
    $p = new Promise();
    $carry = null;
    $p2 = $p
      ->then(function ($v) use (&$carry) {
      $carry = $v;
    });
    $this
      ->assertNotSame($p, $p2);
    $p
      ->resolve('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $carry);
  }
  public function testCreatesPromiseWhenFulfilledBeforeThen() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $carry = null;
    $p2 = $p
      ->then(function ($v) use (&$carry) {
      $carry = $v;
    });
    $this
      ->assertNotSame($p, $p2);
    $this
      ->assertNull($carry);
    \GuzzleHttp\Promise\queue()
      ->run();
    $this
      ->assertEquals('foo', $carry);
  }
  public function testCreatesPromiseWhenFulfilledWithNoCallback() {
    $p = new Promise();
    $p
      ->resolve('foo');
    $p2 = $p
      ->then();
    $this
      ->assertNotSame($p, $p2);
    $this
      ->assertInstanceOf('GuzzleHttp\\Promise\\FulfilledPromise', $p2);
  }
  public function testCreatesPromiseWhenRejectedAfterThen() {
    $p = new Promise();
    $carry = null;
    $p2 = $p
      ->then(null, function ($v) use (&$carry) {
      $carry = $v;
    });
    $this
      ->assertNotSame($p, $p2);
    $p
      ->reject('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $carry);
  }
  public function testCreatesPromiseWhenRejectedBeforeThen() {
    $p = new Promise();
    $p
      ->reject('foo');
    $carry = null;
    $p2 = $p
      ->then(null, function ($v) use (&$carry) {
      $carry = $v;
    });
    $this
      ->assertNotSame($p, $p2);
    $this
      ->assertNull($carry);
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $carry);
  }
  public function testCreatesPromiseWhenRejectedWithNoCallback() {
    $p = new Promise();
    $p
      ->reject('foo');
    $p2 = $p
      ->then();
    $this
      ->assertNotSame($p, $p2);
    $this
      ->assertInstanceOf('GuzzleHttp\\Promise\\RejectedPromise', $p2);
  }
  public function testInvokesWaitFnsForThens() {
    $p = new Promise(function () use (&$p) {
      $p
        ->resolve('a');
    });
    $p2 = $p
      ->then(function ($v) {
      return $v . '-1-';
    })
      ->then(function ($v) {
      return $v . '2';
    });
    $this
      ->assertEquals('a-1-2', $p2
      ->wait());
  }
  public function testStacksThenWaitFunctions() {
    $p1 = new Promise(function () use (&$p1) {
      $p1
        ->resolve('a');
    });
    $p2 = new Promise(function () use (&$p2) {
      $p2
        ->resolve('b');
    });
    $p3 = new Promise(function () use (&$p3) {
      $p3
        ->resolve('c');
    });
    $p4 = $p1
      ->then(function () use ($p2) {
      return $p2;
    })
      ->then(function () use ($p3) {
      return $p3;
    });
    $this
      ->assertEquals('c', $p4
      ->wait());
  }
  public function testForwardsFulfilledDownChainBetweenGaps() {
    $p = new Promise();
    $r = $r2 = null;
    $p
      ->then(null, null)
      ->then(function ($v) use (&$r) {
      $r = $v;
      return $v . '2';
    })
      ->then(function ($v) use (&$r2) {
      $r2 = $v;
    });
    $p
      ->resolve('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $r);
    $this
      ->assertEquals('foo2', $r2);
  }
  public function testForwardsRejectedPromisesDownChainBetweenGaps() {
    $p = new Promise();
    $r = $r2 = null;
    $p
      ->then(null, null)
      ->then(null, function ($v) use (&$r) {
      $r = $v;
      return $v . '2';
    })
      ->then(function ($v) use (&$r2) {
      $r2 = $v;
    });
    $p
      ->reject('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $r);
    $this
      ->assertEquals('foo2', $r2);
  }
  public function testForwardsThrownPromisesDownChainBetweenGaps() {
    $e = new \Exception();
    $p = new Promise();
    $r = $r2 = null;
    $p
      ->then(null, null)
      ->then(null, function ($v) use (&$r, $e) {
      $r = $v;
      throw $e;
    })
      ->then(null, function ($v) use (&$r2) {
      $r2 = $v;
    });
    $p
      ->reject('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $r);
    $this
      ->assertSame($e, $r2);
  }
  public function testForwardsReturnedRejectedPromisesDownChainBetweenGaps() {
    $p = new Promise();
    $rejected = new RejectedPromise('bar');
    $r = $r2 = null;
    $p
      ->then(null, null)
      ->then(null, function ($v) use (&$r, $rejected) {
      $r = $v;
      return $rejected;
    })
      ->then(null, function ($v) use (&$r2) {
      $r2 = $v;
    });
    $p
      ->reject('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals('foo', $r);
    $this
      ->assertEquals('bar', $r2);
    try {
      $p
        ->wait();
    } catch (RejectionException $e) {
      $this
        ->assertEquals('foo', $e
        ->getReason());
    }
  }
  public function testForwardsHandlersToNextPromise() {
    $p = new Promise();
    $p2 = new Promise();
    $resolved = null;
    $p
      ->then(function ($v) use ($p2) {
      return $p2;
    })
      ->then(function ($value) use (&$resolved) {
      $resolved = $value;
    });
    $p
      ->resolve('a');
    $p2
      ->resolve('b');
    P\queue()
      ->run();
    $this
      ->assertEquals('b', $resolved);
  }
  public function testRemovesReferenceFromChildWhenParentWaitedUpon() {
    $r = null;
    $p = new Promise(function () use (&$p) {
      $p
        ->resolve('a');
    });
    $p2 = new Promise(function () use (&$p2) {
      $p2
        ->resolve('b');
    });
    $pb = $p
      ->then(function ($v) use ($p2, &$r) {
      $r = $v;
      return $p2;
    })
      ->then(function ($v) {
      return $v . '.';
    });
    $this
      ->assertEquals('a', $p
      ->wait());
    $this
      ->assertEquals('b', $p2
      ->wait());
    $this
      ->assertEquals('b.', $pb
      ->wait());
    $this
      ->assertEquals('a', $r);
  }
  public function testForwardsHandlersWhenFulfilledPromiseIsReturned() {
    $res = [];
    $p = new Promise();
    $p2 = new Promise();
    $p2
      ->resolve('foo');
    $p2
      ->then(function ($v) use (&$res) {
      $res[] = 'A:' . $v;
    });

    // $res is A:foo
    $p
      ->then(function () use ($p2, &$res) {
      $res[] = 'B';
      return $p2;
    })
      ->then(function ($v) use (&$res) {
      $res[] = 'C:' . $v;
    });
    $p
      ->resolve('a');
    $p
      ->then(function ($v) use (&$res) {
      $res[] = 'D:' . $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'A:foo',
      'B',
      'D:a',
      'C:foo',
    ], $res);
  }
  public function testForwardsHandlersWhenRejectedPromiseIsReturned() {
    $res = [];
    $p = new Promise();
    $p2 = new Promise();
    $p2
      ->reject('foo');
    $p2
      ->then(null, function ($v) use (&$res) {
      $res[] = 'A:' . $v;
    });
    $p
      ->then(null, function () use ($p2, &$res) {
      $res[] = 'B';
      return $p2;
    })
      ->then(null, function ($v) use (&$res) {
      $res[] = 'C:' . $v;
    });
    $p
      ->reject('a');
    $p
      ->then(null, function ($v) use (&$res) {
      $res[] = 'D:' . $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'A:foo',
      'B',
      'D:a',
      'C:foo',
    ], $res);
  }
  public function testDoesNotForwardRejectedPromise() {
    $res = [];
    $p = new Promise();
    $p2 = new Promise();
    $p2
      ->cancel();
    $p2
      ->then(function ($v) use (&$res) {
      $res[] = "B:{$v}";
      return $v;
    });
    $p
      ->then(function ($v) use ($p2, &$res) {
      $res[] = "B:{$v}";
      return $p2;
    })
      ->then(function ($v) use (&$res) {
      $res[] = 'C:' . $v;
    });
    $p
      ->resolve('a');
    $p
      ->then(function ($v) use (&$res) {
      $res[] = 'D:' . $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'B:a',
      'D:a',
    ], $res);
  }
  public function testRecursivelyForwardsWhenOnlyThennable() {
    $res = [];
    $p = new Promise();
    $p2 = new Thennable();
    $p2
      ->resolve('foo');
    $p2
      ->then(function ($v) use (&$res) {
      $res[] = 'A:' . $v;
    });
    $p
      ->then(function () use ($p2, &$res) {
      $res[] = 'B';
      return $p2;
    })
      ->then(function ($v) use (&$res) {
      $res[] = 'C:' . $v;
    });
    $p
      ->resolve('a');
    $p
      ->then(function ($v) use (&$res) {
      $res[] = 'D:' . $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'A:foo',
      'B',
      'D:a',
      'C:foo',
    ], $res);
  }
  public function testRecursivelyForwardsWhenNotInstanceOfPromise() {
    $res = [];
    $p = new Promise();
    $p2 = new NotPromiseInstance();
    $p2
      ->then(function ($v) use (&$res) {
      $res[] = 'A:' . $v;
    });
    $p
      ->then(function () use ($p2, &$res) {
      $res[] = 'B';
      return $p2;
    })
      ->then(function ($v) use (&$res) {
      $res[] = 'C:' . $v;
    });
    $p
      ->resolve('a');
    $p
      ->then(function ($v) use (&$res) {
      $res[] = 'D:' . $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'B',
      'D:a',
    ], $res);
    $p2
      ->resolve('foo');
    P\queue()
      ->run();
    $this
      ->assertEquals([
      'B',
      'D:a',
      'A:foo',
      'C:foo',
    ], $res);
  }

  /**
   * @expectedException \LogicException
   * @expectedExceptionMessage Cannot fulfill or reject a promise with itself
   */
  public function testCannotResolveWithSelf() {
    $p = new Promise();
    $p
      ->resolve($p);
  }

  /**
   * @expectedException \LogicException
   * @expectedExceptionMessage Cannot fulfill or reject a promise with itself
   */
  public function testCannotRejectWithSelf() {
    $p = new Promise();
    $p
      ->reject($p);
  }
  public function testDoesNotBlowStackWhenWaitingOnNestedThens() {
    $inner = new Promise(function () use (&$inner) {
      $inner
        ->resolve(0);
    });
    $prev = $inner;
    for ($i = 1; $i < 100; $i++) {
      $prev = $prev
        ->then(function ($i) {
        return $i + 1;
      });
    }
    $parent = new Promise(function () use (&$parent, $prev) {
      $parent
        ->resolve($prev);
    });
    $this
      ->assertEquals(99, $parent
      ->wait());
  }
  public function testOtherwiseIsSugarForRejections() {
    $p = new Promise();
    $p
      ->reject('foo');
    $p
      ->otherwise(function ($v) use (&$c) {
      $c = $v;
    });
    P\queue()
      ->run();
    $this
      ->assertEquals($c, 'foo');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PromiseTest::testCancelsChildPromises public function
PromiseTest::testCancelsPromiseWhenNoCancelFunction public function @expectedException \GuzzleHttp\Promise\CancellationException
PromiseTest::testCancelsPromiseWithCancelFunction public function
PromiseTest::testCancelsUppermostPendingPromise public function
PromiseTest::testCannotCancelNonPending public function
PromiseTest::testCannotRejectNonPendingPromise public function @expectedException \LogicException @expectedExceptionMessage Cannot change a fulfilled promise to rejected
PromiseTest::testCannotRejectResolveWithSameValue public function @expectedException \LogicException @expectedExceptionMessage Cannot change a fulfilled promise to rejected
PromiseTest::testCannotRejectWithSelf public function @expectedException \LogicException @expectedExceptionMessage Cannot fulfill or reject a promise with itself
PromiseTest::testCannotResolveNonPendingPromise public function @expectedException \LogicException @expectedExceptionMessage The promise is already fulfilled
PromiseTest::testCannotResolveWithSelf public function @expectedException \LogicException @expectedExceptionMessage Cannot fulfill or reject a promise with itself
PromiseTest::testCanRejectWithSameValue public function
PromiseTest::testCanResolveWithSameValue public function
PromiseTest::testCreatesPromiseWhenFulfilledAfterThen public function
PromiseTest::testCreatesPromiseWhenFulfilledBeforeThen public function
PromiseTest::testCreatesPromiseWhenFulfilledWithNoCallback public function
PromiseTest::testCreatesPromiseWhenRejectedAfterThen public function
PromiseTest::testCreatesPromiseWhenRejectedBeforeThen public function
PromiseTest::testCreatesPromiseWhenRejectedWithNoCallback public function
PromiseTest::testDoesNotBlowStackWhenWaitingOnNestedThens public function
PromiseTest::testDoesNotForwardRejectedPromise public function
PromiseTest::testDoesNotUnwrapExceptionsWhenDisabled public function
PromiseTest::testForwardsFulfilledDownChainBetweenGaps public function
PromiseTest::testForwardsHandlersToNextPromise public function
PromiseTest::testForwardsHandlersWhenFulfilledPromiseIsReturned public function
PromiseTest::testForwardsHandlersWhenRejectedPromiseIsReturned public function
PromiseTest::testForwardsRejectedPromisesDownChainBetweenGaps public function
PromiseTest::testForwardsReturnedRejectedPromisesDownChainBetweenGaps public function
PromiseTest::testForwardsThrownPromisesDownChainBetweenGaps public function
PromiseTest::testGetsActualWaitValueFromThen public function
PromiseTest::testInvokesWaitFnsForThens public function
PromiseTest::testInvokesWaitFunction public function
PromiseTest::testOtherwiseIsSugarForRejections public function
PromiseTest::testRecursivelyForwardsWhenNotInstanceOfPromise public function
PromiseTest::testRecursivelyForwardsWhenOnlyThennable public function
PromiseTest::testRejectsAndThrowsWhenWaitFailsToResolve public function @expectedException \GuzzleHttp\Promise\RejectionException
PromiseTest::testRejectsPromiseWhenCancelFails public function
PromiseTest::testRejectsSelfWhenWaitThrows public function
PromiseTest::testRemovesReferenceFromChildWhenParentWaitedUpon public function
PromiseTest::testStacksThenWaitFunctions public function
PromiseTest::testThrowsWaitExceptionAfterPromiseIsResolved public function
PromiseTest::testThrowsWhenUnwrapIsRejectedWithException public function @expectedException \UnexpectedValueException @expectedExceptionMessage foo
PromiseTest::testThrowsWhenUnwrapIsRejectedWithNonException public function @expectedException \GuzzleHttp\Promise\RejectionException @expectedExceptionMessage The promise was rejected with reason: foo
PromiseTest::testThrowsWhenWaitingOnPromiseWithNoWaitFunction public function @expectedException \GuzzleHttp\Promise\RejectionException
PromiseTest::testWaitBehaviorIsBasedOnLastPromiseInChain public function
PromiseTest::testWaitsOnNestedPromises public function