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