1<?php
2
3namespace React\Promise;
4
5use React\Promise\Exception\LengthException;
6
7class FunctionSomeTest extends TestCase
8{
9    /** @test */
10    public function shouldRejectWithLengthExceptionWithEmptyInputArray()
11    {
12        $mock = $this->createCallableMock();
13        $mock
14            ->expects($this->once())
15            ->method('__invoke')
16            ->with(
17                $this->callback(function($exception){
18                    return $exception instanceof LengthException &&
19                           'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage();
20                })
21            );
22
23        some(
24            [],
25            1
26        )->then($this->expectCallableNever(), $mock);
27    }
28
29    /** @test */
30    public function shouldRejectWithLengthExceptionWithInputArrayContainingNotEnoughItems()
31    {
32        $mock = $this->createCallableMock();
33        $mock
34            ->expects($this->once())
35            ->method('__invoke')
36            ->with(
37                $this->callback(function($exception){
38                    return $exception instanceof LengthException &&
39                           'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage();
40                })
41            );
42
43        some(
44            [1, 2, 3],
45            4
46        )->then($this->expectCallableNever(), $mock);
47    }
48
49    /** @test */
50    public function shouldResolveToEmptyArrayWithNonArrayInput()
51    {
52        $mock = $this->createCallableMock();
53        $mock
54            ->expects($this->once())
55            ->method('__invoke')
56            ->with($this->identicalTo([]));
57
58        some(
59            null,
60            1
61        )->then($mock);
62    }
63
64    /** @test */
65    public function shouldResolveValuesArray()
66    {
67        $mock = $this->createCallableMock();
68        $mock
69            ->expects($this->once())
70            ->method('__invoke')
71            ->with($this->identicalTo([1, 2]));
72
73        some(
74            [1, 2, 3],
75            2
76        )->then($mock);
77    }
78
79    /** @test */
80    public function shouldResolvePromisesArray()
81    {
82        $mock = $this->createCallableMock();
83        $mock
84            ->expects($this->once())
85            ->method('__invoke')
86            ->with($this->identicalTo([1, 2]));
87
88        some(
89            [resolve(1), resolve(2), resolve(3)],
90            2
91        )->then($mock);
92    }
93
94    /** @test */
95    public function shouldResolveSparseArrayInput()
96    {
97        $mock = $this->createCallableMock();
98        $mock
99            ->expects($this->once())
100            ->method('__invoke')
101            ->with($this->identicalTo([null, 1]));
102
103        some(
104            [null, 1, null, 2, 3],
105            2
106        )->then($mock);
107    }
108
109    /** @test */
110    public function shouldRejectIfAnyInputPromiseRejectsBeforeDesiredNumberOfInputsAreResolved()
111    {
112        $mock = $this->createCallableMock();
113        $mock
114            ->expects($this->once())
115            ->method('__invoke')
116            ->with($this->identicalTo([1 => 2, 2 => 3]));
117
118        some(
119            [resolve(1), reject(2), reject(3)],
120            2
121        )->then($this->expectCallableNever(), $mock);
122    }
123
124    /** @test */
125    public function shouldAcceptAPromiseForAnArray()
126    {
127        $mock = $this->createCallableMock();
128        $mock
129            ->expects($this->once())
130            ->method('__invoke')
131            ->with($this->identicalTo([1, 2]));
132
133        some(
134            resolve([1, 2, 3]),
135            2
136        )->then($mock);
137    }
138
139    /** @test */
140    public function shouldResolveWithEmptyArrayIfHowManyIsLessThanOne()
141    {
142        $mock = $this->createCallableMock();
143        $mock
144            ->expects($this->once())
145            ->method('__invoke')
146            ->with($this->identicalTo([]));
147
148        some(
149            [1],
150            0
151        )->then($mock);
152    }
153
154    /** @test */
155    public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
156    {
157        $mock = $this->createCallableMock();
158        $mock
159            ->expects($this->once())
160            ->method('__invoke')
161            ->with($this->identicalTo([]));
162
163        some(
164            resolve(1),
165            1
166        )->then($mock);
167    }
168
169    /** @test */
170    public function shouldRejectWhenInputPromiseRejects()
171    {
172        $mock = $this->createCallableMock();
173        $mock
174            ->expects($this->once())
175            ->method('__invoke')
176            ->with($this->identicalTo(null));
177
178        some(
179            reject(),
180            1
181        )->then($this->expectCallableNever(), $mock);
182    }
183
184    /** @test */
185    public function shouldCancelInputPromise()
186    {
187        $mock = $this
188            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
189            ->getMock();
190        $mock
191            ->expects($this->once())
192            ->method('cancel');
193
194        some($mock, 1)->cancel();
195    }
196
197    /** @test */
198    public function shouldCancelInputArrayPromises()
199    {
200        $mock1 = $this
201            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
202            ->getMock();
203        $mock1
204            ->expects($this->once())
205            ->method('cancel');
206
207        $mock2 = $this
208            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
209            ->getMock();
210        $mock2
211            ->expects($this->once())
212            ->method('cancel');
213
214        some([$mock1, $mock2], 1)->cancel();
215    }
216
217    /** @test */
218    public function shouldNotCancelOtherPendingInputArrayPromisesIfEnoughPromisesFulfill()
219    {
220        $mock = $this->createCallableMock();
221        $mock
222            ->expects($this->never())
223            ->method('__invoke');
224
225        $deferred = New Deferred($mock);
226        $deferred->resolve();
227
228        $mock2 = $this
229            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
230            ->getMock();
231        $mock2
232            ->expects($this->never())
233            ->method('cancel');
234
235        some([$deferred->promise(), $mock2], 1);
236    }
237
238    /** @test */
239    public function shouldNotCancelOtherPendingInputArrayPromisesIfEnoughPromisesReject()
240    {
241        $mock = $this->createCallableMock();
242        $mock
243            ->expects($this->never())
244            ->method('__invoke');
245
246        $deferred = New Deferred($mock);
247        $deferred->reject();
248
249        $mock2 = $this
250            ->getMockBuilder('React\Promise\CancellablePromiseInterface')
251            ->getMock();
252        $mock2
253            ->expects($this->never())
254            ->method('cancel');
255
256        some([$deferred->promise(), $mock2], 2);
257    }
258}
259