1<?php
2
3namespace React\Promise;
4
5class FunctionResolveTest extends TestCase
6{
7    /** @test */
8    public function shouldResolveAnImmediateValue()
9    {
10        $expected = 123;
11
12        $mock = $this->createCallableMock();
13        $mock
14            ->expects($this->once())
15            ->method('__invoke')
16            ->with($this->identicalTo($expected));
17
18        resolve($expected)
19            ->then(
20                $mock,
21                $this->expectCallableNever()
22            );
23    }
24
25    /** @test */
26    public function shouldResolveAFulfilledPromise()
27    {
28        $expected = 123;
29
30        $resolved = new FulfilledPromise($expected);
31
32        $mock = $this->createCallableMock();
33        $mock
34            ->expects($this->once())
35            ->method('__invoke')
36            ->with($this->identicalTo($expected));
37
38        resolve($resolved)
39            ->then(
40                $mock,
41                $this->expectCallableNever()
42            );
43    }
44
45    /** @test */
46    public function shouldResolveAThenable()
47    {
48        $thenable = new SimpleFulfilledTestThenable();
49
50        $mock = $this->createCallableMock();
51        $mock
52            ->expects($this->once())
53            ->method('__invoke')
54            ->with($this->identicalTo('foo'));
55
56        resolve($thenable)
57            ->then(
58                $mock,
59                $this->expectCallableNever()
60            );
61    }
62
63    /** @test */
64    public function shouldResolveACancellableThenable()
65    {
66        $thenable = new SimpleTestCancellableThenable();
67
68        $promise = resolve($thenable);
69        $promise->cancel();
70
71        $this->assertTrue($thenable->cancelCalled);
72    }
73
74    /** @test */
75    public function shouldRejectARejectedPromise()
76    {
77        $expected = 123;
78
79        $resolved = new RejectedPromise($expected);
80
81        $mock = $this->createCallableMock();
82        $mock
83            ->expects($this->once())
84            ->method('__invoke')
85            ->with($this->identicalTo($expected));
86
87        resolve($resolved)
88            ->then(
89                $this->expectCallableNever(),
90                $mock
91            );
92    }
93
94    /** @test */
95    public function shouldSupportDeepNestingInPromiseChains()
96    {
97        $d = new Deferred();
98        $d->resolve(false);
99
100        $result = resolve(resolve($d->promise()->then(function ($val) {
101            $d = new Deferred();
102            $d->resolve($val);
103
104            $identity = function ($val) {
105                return $val;
106            };
107
108            return resolve($d->promise()->then($identity))->then(
109                function ($val) {
110                    return !$val;
111                }
112            );
113        })));
114
115        $mock = $this->createCallableMock();
116        $mock
117            ->expects($this->once())
118            ->method('__invoke')
119            ->with($this->identicalTo(true));
120
121        $result->then($mock);
122    }
123
124    /** @test */
125    public function shouldSupportVeryDeepNestedPromises()
126    {
127        $deferreds = [];
128
129        // @TODO Increase count once global-queue is merged
130        for ($i = 0; $i < 10; $i++) {
131            $deferreds[] = $d = new Deferred();
132            $p = $d->promise();
133
134            $last = $p;
135            for ($j = 0; $j < 10; $j++) {
136                $last = $last->then(function($result) {
137                    return $result;
138                });
139            }
140        }
141
142        $p = null;
143        foreach ($deferreds as $d) {
144            if ($p) {
145                $d->resolve($p);
146            }
147
148            $p = $d->promise();
149        }
150
151        $deferreds[0]->resolve(true);
152
153        $mock = $this->createCallableMock();
154        $mock
155            ->expects($this->once())
156            ->method('__invoke')
157            ->with($this->identicalTo(true));
158
159        $deferreds[0]->promise()->then($mock);
160    }
161
162    /** @test */
163    public function returnsExtendePromiseForSimplePromise()
164    {
165        $promise = $this
166            ->getMockBuilder('React\Promise\PromiseInterface')
167            ->getMock();
168
169        $this->assertInstanceOf('React\Promise\ExtendedPromiseInterface', resolve($promise));
170    }
171}
172