1<?php
2
3namespace React\Promise;
4
5class FunctionRaceTest extends TestCase
6{
7    /** @test */
8    public function shouldResolveEmptyInput()
9    {
10        $mock = $this->createCallableMock();
11        $mock
12            ->expects($this->once())
13            ->method('__invoke')
14            ->with($this->identicalTo(null));
15
16        race(
17            []
18        )->then($mock);
19    }
20
21    /** @test */
22    public function shouldResolveValuesArray()
23    {
24        $mock = $this->createCallableMock();
25        $mock
26            ->expects($this->once())
27            ->method('__invoke')
28            ->with($this->identicalTo(1));
29
30        race(
31            [1, 2, 3]
32        )->then($mock);
33    }
34
35    /** @test */
36    public function shouldResolvePromisesArray()
37    {
38        $mock = $this->createCallableMock();
39        $mock
40            ->expects($this->once())
41            ->method('__invoke')
42            ->with($this->identicalTo(2));
43
44        $d1 = new Deferred();
45        $d2 = new Deferred();
46        $d3 = new Deferred();
47
48        race(
49            [$d1->promise(), $d2->promise(), $d3->promise()]
50        )->then($mock);
51
52        $d2->resolve(2);
53
54        $d1->resolve(1);
55        $d3->resolve(3);
56    }
57
58    /** @test */
59    public function shouldResolveSparseArrayInput()
60    {
61        $mock = $this->createCallableMock();
62        $mock
63            ->expects($this->once())
64            ->method('__invoke')
65            ->with($this->identicalTo(null));
66
67        race(
68            [null, 1, null, 2, 3]
69        )->then($mock);
70    }
71
72    /** @test */
73    public function shouldRejectIfFirstSettledPromiseRejects()
74    {
75        $mock = $this->createCallableMock();
76        $mock
77            ->expects($this->once())
78            ->method('__invoke')
79            ->with($this->identicalTo(2));
80
81        $d1 = new Deferred();
82        $d2 = new Deferred();
83        $d3 = new Deferred();
84
85        race(
86            [$d1->promise(), $d2->promise(), $d3->promise()]
87        )->then($this->expectCallableNever(), $mock);
88
89        $d2->reject(2);
90
91        $d1->resolve(1);
92        $d3->resolve(3);
93    }
94
95    /** @test */
96    public function shouldAcceptAPromiseForAnArray()
97    {
98        $mock = $this->createCallableMock();
99        $mock
100            ->expects($this->once())
101            ->method('__invoke')
102            ->with($this->identicalTo(1));
103
104        race(
105            resolve([1, 2, 3])
106        )->then($mock);
107    }
108
109    /** @test */
110    public function shouldResolveToNullWhenInputPromiseDoesNotResolveToArray()
111    {
112        $mock = $this->createCallableMock();
113        $mock
114            ->expects($this->once())
115            ->method('__invoke')
116            ->with($this->identicalTo(null));
117
118        race(
119            resolve(1)
120        )->then($mock);
121    }
122
123    /** @test */
124    public function shouldRejectWhenInputPromiseRejects()
125    {
126        $mock = $this->createCallableMock();
127        $mock
128            ->expects($this->once())
129            ->method('__invoke')
130            ->with($this->identicalTo(null));
131
132        race(
133            reject()
134        )->then($this->expectCallableNever(), $mock);
135    }
136
137    /** @test */
138    public function shouldCancelInputPromise()
139    {
140        $mock = $this
141            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
142            ->getMock();
143        $mock
144            ->expects($this->once())
145            ->method('cancel');
146
147        race($mock)->cancel();
148    }
149
150    /** @test */
151    public function shouldCancelInputArrayPromises()
152    {
153        $mock1 = $this
154            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
155            ->getMock();
156        $mock1
157            ->expects($this->once())
158            ->method('cancel');
159
160        $mock2 = $this
161            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
162            ->getMock();
163        $mock2
164            ->expects($this->once())
165            ->method('cancel');
166
167        race([$mock1, $mock2])->cancel();
168    }
169
170    /** @test */
171    public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfills()
172    {
173        $mock = $this->createCallableMock();
174        $mock
175            ->expects($this->never())
176            ->method('__invoke');
177
178        $deferred = New Deferred($mock);
179        $deferred->resolve();
180
181        $mock2 = $this
182            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
183            ->getMock();
184        $mock2
185            ->expects($this->never())
186            ->method('cancel');
187
188        race([$deferred->promise(), $mock2])->cancel();
189    }
190
191    /** @test */
192    public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects()
193    {
194        $mock = $this->createCallableMock();
195        $mock
196            ->expects($this->never())
197            ->method('__invoke');
198
199        $deferred = New Deferred($mock);
200        $deferred->reject();
201
202        $mock2 = $this
203            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
204            ->getMock();
205        $mock2
206            ->expects($this->never())
207            ->method('cancel');
208
209        race([$deferred->promise(), $mock2])->cancel();
210    }
211}
212