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