ResolveTestTrait.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?php
  2. namespace React\Promise\PromiseTest;
  3. use Exception;
  4. use LogicException;
  5. use React\Promise;
  6. use React\Promise\PromiseAdapter\PromiseAdapterInterface;
  7. use React\Promise\PromiseInterface;
  8. use stdClass;
  9. use function React\Promise\reject;
  10. use function React\Promise\resolve;
  11. trait ResolveTestTrait
  12. {
  13. abstract public function getPromiseTestAdapter(callable $canceller = null): PromiseAdapterInterface;
  14. /** @test */
  15. public function resolveShouldResolve(): void
  16. {
  17. $adapter = $this->getPromiseTestAdapter();
  18. $mock = $this->createCallableMock();
  19. $mock
  20. ->expects($this->once())
  21. ->method('__invoke')
  22. ->with($this->identicalTo(1));
  23. $adapter->promise()
  24. ->then($mock);
  25. $adapter->resolve(1);
  26. }
  27. /** @test */
  28. public function resolveShouldResolveWithPromisedValue(): void
  29. {
  30. $adapter = $this->getPromiseTestAdapter();
  31. $mock = $this->createCallableMock();
  32. $mock
  33. ->expects($this->once())
  34. ->method('__invoke')
  35. ->with($this->identicalTo(1));
  36. $adapter->promise()
  37. ->then($mock);
  38. $adapter->resolve(resolve(1));
  39. }
  40. /** @test */
  41. public function resolveShouldRejectWhenResolvedWithRejectedPromise(): void
  42. {
  43. $adapter = $this->getPromiseTestAdapter();
  44. $exception = new Exception();
  45. $mock = $this->createCallableMock();
  46. $mock
  47. ->expects($this->once())
  48. ->method('__invoke')
  49. ->with($this->identicalTo($exception));
  50. $adapter->promise()
  51. ->then($this->expectCallableNever(), $mock);
  52. $adapter->resolve(reject($exception));
  53. }
  54. /** @test */
  55. public function resolveShouldForwardValueWhenCallbackIsNull(): void
  56. {
  57. $adapter = $this->getPromiseTestAdapter();
  58. $mock = $this->createCallableMock();
  59. $mock
  60. ->expects($this->once())
  61. ->method('__invoke')
  62. ->with($this->identicalTo(1));
  63. $adapter->promise()
  64. ->then(
  65. null,
  66. $this->expectCallableNever()
  67. )
  68. ->then(
  69. $mock,
  70. $this->expectCallableNever()
  71. );
  72. $adapter->resolve(1);
  73. }
  74. /** @test */
  75. public function resolveShouldMakePromiseImmutable(): void
  76. {
  77. $adapter = $this->getPromiseTestAdapter();
  78. $mock = $this->createCallableMock();
  79. $mock
  80. ->expects($this->once())
  81. ->method('__invoke')
  82. ->with($this->identicalTo(1));
  83. $adapter->promise()
  84. ->then(function ($value) use ($adapter) {
  85. $adapter->resolve(3);
  86. return $value;
  87. })
  88. ->then(
  89. $mock,
  90. $this->expectCallableNever()
  91. );
  92. $adapter->resolve(1);
  93. $adapter->resolve(2);
  94. }
  95. /**
  96. * @test
  97. */
  98. public function resolveShouldRejectWhenResolvedWithItself(): void
  99. {
  100. $adapter = $this->getPromiseTestAdapter();
  101. $mock = $this->createCallableMock();
  102. $mock
  103. ->expects($this->once())
  104. ->method('__invoke')
  105. ->with(new LogicException('Cannot resolve a promise with itself.'));
  106. $adapter->promise()
  107. ->then(
  108. $this->expectCallableNever(),
  109. $mock
  110. );
  111. $adapter->resolve($adapter->promise());
  112. }
  113. /**
  114. * @test
  115. */
  116. public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself(): void
  117. {
  118. $adapter1 = $this->getPromiseTestAdapter();
  119. $adapter2 = $this->getPromiseTestAdapter();
  120. $mock = $this->createCallableMock();
  121. $mock
  122. ->expects($this->once())
  123. ->method('__invoke')
  124. ->with(new LogicException('Cannot resolve a promise with itself.'));
  125. $promise1 = $adapter1->promise();
  126. $promise2 = $adapter2->promise();
  127. $promise2->then(
  128. $this->expectCallableNever(),
  129. $mock
  130. );
  131. $adapter1->resolve($promise2);
  132. $adapter2->resolve($promise1);
  133. }
  134. /** @test */
  135. public function finallyShouldNotSuppressValue(): void
  136. {
  137. $adapter = $this->getPromiseTestAdapter();
  138. $value = new stdClass();
  139. $mock = $this->createCallableMock();
  140. $mock
  141. ->expects($this->once())
  142. ->method('__invoke')
  143. ->with($this->identicalTo($value));
  144. $adapter->promise()
  145. ->finally(function () {})
  146. ->then($mock);
  147. $adapter->resolve($value);
  148. }
  149. /** @test */
  150. public function finallyShouldNotSuppressValueWhenHandlerReturnsANonPromise(): void
  151. {
  152. $adapter = $this->getPromiseTestAdapter();
  153. $value = new stdClass();
  154. $mock = $this->createCallableMock();
  155. $mock
  156. ->expects($this->once())
  157. ->method('__invoke')
  158. ->with($this->identicalTo($value));
  159. $adapter->promise()
  160. ->finally(function (): int { // @phpstan-ignore-line
  161. return 1;
  162. })
  163. ->then($mock);
  164. $adapter->resolve($value);
  165. }
  166. /** @test */
  167. public function finallyShouldNotSuppressValueWhenHandlerReturnsAPromise(): void
  168. {
  169. $adapter = $this->getPromiseTestAdapter();
  170. $value = new stdClass();
  171. $mock = $this->createCallableMock();
  172. $mock
  173. ->expects($this->once())
  174. ->method('__invoke')
  175. ->with($this->identicalTo($value));
  176. $adapter->promise()
  177. ->finally(function (): PromiseInterface { // @phpstan-ignore-line
  178. return resolve(1);
  179. })
  180. ->then($mock);
  181. $adapter->resolve($value);
  182. }
  183. /** @test */
  184. public function finallyShouldRejectWhenHandlerThrowsForFulfillment(): void
  185. {
  186. $adapter = $this->getPromiseTestAdapter();
  187. $exception = new Exception();
  188. $mock = $this->createCallableMock();
  189. $mock
  190. ->expects($this->once())
  191. ->method('__invoke')
  192. ->with($this->identicalTo($exception));
  193. $adapter->promise()
  194. ->finally(function () use ($exception) {
  195. throw $exception;
  196. })
  197. ->then(null, $mock);
  198. $adapter->resolve(1);
  199. }
  200. /** @test */
  201. public function finallyShouldRejectWhenHandlerRejectsForFulfillment(): void
  202. {
  203. $adapter = $this->getPromiseTestAdapter();
  204. $exception = new Exception();
  205. $mock = $this->createCallableMock();
  206. $mock
  207. ->expects($this->once())
  208. ->method('__invoke')
  209. ->with($this->identicalTo($exception));
  210. $adapter->promise()
  211. ->finally(function () use ($exception) {
  212. return reject($exception);
  213. })
  214. ->then(null, $mock);
  215. $adapter->resolve(1);
  216. }
  217. }