1<?php 2 3namespace React\Promise\PromiseTest; 4 5use React\Promise; 6 7trait ResolveTestTrait 8{ 9 /** 10 * @return \React\Promise\PromiseAdapter\PromiseAdapterInterface 11 */ 12 abstract public function getPromiseTestAdapter(callable $canceller = null); 13 14 /** @test */ 15 public function resolveShouldResolve() 16 { 17 $adapter = $this->getPromiseTestAdapter(); 18 19 $mock = $this->createCallableMock(); 20 $mock 21 ->expects($this->once()) 22 ->method('__invoke') 23 ->with($this->identicalTo(1)); 24 25 $adapter->promise() 26 ->then($mock); 27 28 $adapter->resolve(1); 29 } 30 31 /** @test */ 32 public function resolveShouldResolveWithPromisedValue() 33 { 34 $adapter = $this->getPromiseTestAdapter(); 35 36 $mock = $this->createCallableMock(); 37 $mock 38 ->expects($this->once()) 39 ->method('__invoke') 40 ->with($this->identicalTo(1)); 41 42 $adapter->promise() 43 ->then($mock); 44 45 $adapter->resolve(Promise\resolve(1)); 46 } 47 48 /** @test */ 49 public function resolveShouldRejectWhenResolvedWithRejectedPromise() 50 { 51 $adapter = $this->getPromiseTestAdapter(); 52 53 $mock = $this->createCallableMock(); 54 $mock 55 ->expects($this->once()) 56 ->method('__invoke') 57 ->with($this->identicalTo(1)); 58 59 $adapter->promise() 60 ->then($this->expectCallableNever(), $mock); 61 62 $adapter->resolve(Promise\reject(1)); 63 } 64 65 /** @test */ 66 public function resolveShouldForwardValueWhenCallbackIsNull() 67 { 68 $adapter = $this->getPromiseTestAdapter(); 69 70 $mock = $this->createCallableMock(); 71 $mock 72 ->expects($this->once()) 73 ->method('__invoke') 74 ->with($this->identicalTo(1)); 75 76 $adapter->promise() 77 ->then( 78 null, 79 $this->expectCallableNever() 80 ) 81 ->then( 82 $mock, 83 $this->expectCallableNever() 84 ); 85 86 $adapter->resolve(1); 87 } 88 89 /** @test */ 90 public function resolveShouldMakePromiseImmutable() 91 { 92 $adapter = $this->getPromiseTestAdapter(); 93 94 $mock = $this->createCallableMock(); 95 $mock 96 ->expects($this->once()) 97 ->method('__invoke') 98 ->with($this->identicalTo(1)); 99 100 $adapter->promise() 101 ->then(function ($value) use ($adapter) { 102 $adapter->resolve(3); 103 104 return $value; 105 }) 106 ->then( 107 $mock, 108 $this->expectCallableNever() 109 ); 110 111 $adapter->resolve(1); 112 $adapter->resolve(2); 113 } 114 115 /** 116 * @test 117 */ 118 public function resolveShouldRejectWhenResolvedWithItself() 119 { 120 $adapter = $this->getPromiseTestAdapter(); 121 122 $mock = $this->createCallableMock(); 123 $mock 124 ->expects($this->once()) 125 ->method('__invoke') 126 ->with(new \LogicException('Cannot resolve a promise with itself.')); 127 128 $adapter->promise() 129 ->then( 130 $this->expectCallableNever(), 131 $mock 132 ); 133 134 $adapter->resolve($adapter->promise()); 135 } 136 137 /** 138 * @test 139 */ 140 public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself() 141 { 142 $adapter1 = $this->getPromiseTestAdapter(); 143 $adapter2 = $this->getPromiseTestAdapter(); 144 145 $mock = $this->createCallableMock(); 146 $mock 147 ->expects($this->once()) 148 ->method('__invoke') 149 ->with(new \LogicException('Cannot resolve a promise with itself.')); 150 151 $promise1 = $adapter1->promise(); 152 153 $promise2 = $adapter2->promise(); 154 155 $promise2->then( 156 $this->expectCallableNever(), 157 $mock 158 ); 159 160 $adapter1->resolve($promise2); 161 $adapter2->resolve($promise1); 162 } 163 164 /** @test */ 165 public function doneShouldInvokeFulfillmentHandler() 166 { 167 $adapter = $this->getPromiseTestAdapter(); 168 169 $mock = $this->createCallableMock(); 170 $mock 171 ->expects($this->once()) 172 ->method('__invoke') 173 ->with($this->identicalTo(1)); 174 175 $this->assertNull($adapter->promise()->done($mock)); 176 $adapter->resolve(1); 177 } 178 179 /** @test */ 180 public function doneShouldThrowExceptionThrownFulfillmentHandler() 181 { 182 $adapter = $this->getPromiseTestAdapter(); 183 184 $this->setExpectedException('\Exception', 'UnhandledRejectionException'); 185 186 $this->assertNull($adapter->promise()->done(function () { 187 throw new \Exception('UnhandledRejectionException'); 188 })); 189 $adapter->resolve(1); 190 } 191 192 /** @test */ 193 public function doneShouldThrowUnhandledRejectionExceptionWhenFulfillmentHandlerRejects() 194 { 195 $adapter = $this->getPromiseTestAdapter(); 196 197 $this->setExpectedException('React\\Promise\\UnhandledRejectionException'); 198 199 $this->assertNull($adapter->promise()->done(function () { 200 return \React\Promise\reject(); 201 })); 202 $adapter->resolve(1); 203 } 204 205 /** @test */ 206 public function alwaysShouldNotSuppressValue() 207 { 208 $adapter = $this->getPromiseTestAdapter(); 209 210 $value = new \stdClass(); 211 212 $mock = $this->createCallableMock(); 213 $mock 214 ->expects($this->once()) 215 ->method('__invoke') 216 ->with($this->identicalTo($value)); 217 218 $adapter->promise() 219 ->always(function () {}) 220 ->then($mock); 221 222 $adapter->resolve($value); 223 } 224 225 /** @test */ 226 public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromise() 227 { 228 $adapter = $this->getPromiseTestAdapter(); 229 230 $value = new \stdClass(); 231 232 $mock = $this->createCallableMock(); 233 $mock 234 ->expects($this->once()) 235 ->method('__invoke') 236 ->with($this->identicalTo($value)); 237 238 $adapter->promise() 239 ->always(function () { 240 return 1; 241 }) 242 ->then($mock); 243 244 $adapter->resolve($value); 245 } 246 247 /** @test */ 248 public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromise() 249 { 250 $adapter = $this->getPromiseTestAdapter(); 251 252 $value = new \stdClass(); 253 254 $mock = $this->createCallableMock(); 255 $mock 256 ->expects($this->once()) 257 ->method('__invoke') 258 ->with($this->identicalTo($value)); 259 260 $adapter->promise() 261 ->always(function () { 262 return \React\Promise\resolve(1); 263 }) 264 ->then($mock); 265 266 $adapter->resolve($value); 267 } 268 269 /** @test */ 270 public function alwaysShouldRejectWhenHandlerThrowsForFulfillment() 271 { 272 $adapter = $this->getPromiseTestAdapter(); 273 274 $exception = new \Exception(); 275 276 $mock = $this->createCallableMock(); 277 $mock 278 ->expects($this->once()) 279 ->method('__invoke') 280 ->with($this->identicalTo($exception)); 281 282 $adapter->promise() 283 ->always(function () use ($exception) { 284 throw $exception; 285 }) 286 ->then(null, $mock); 287 288 $adapter->resolve(1); 289 } 290 291 /** @test */ 292 public function alwaysShouldRejectWhenHandlerRejectsForFulfillment() 293 { 294 $adapter = $this->getPromiseTestAdapter(); 295 296 $exception = new \Exception(); 297 298 $mock = $this->createCallableMock(); 299 $mock 300 ->expects($this->once()) 301 ->method('__invoke') 302 ->with($this->identicalTo($exception)); 303 304 $adapter->promise() 305 ->always(function () use ($exception) { 306 return \React\Promise\reject($exception); 307 }) 308 ->then(null, $mock); 309 310 $adapter->resolve(1); 311 } 312} 313