Failed Conditions
Pull Request — master (#333)
by Jérémiah
04:09
created

SyncPromiseAdapterTest::testCreatePromise()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Tests\Executor\Promise;
6
7
use GraphQL\Deferred;
8
use GraphQL\Error\InvariantViolation;
9
use GraphQL\Executor\Promise\Adapter\SyncPromise;
10
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
11
use GraphQL\Executor\Promise\Promise;
12
use PHPUnit\Framework\TestCase;
13
14
class SyncPromiseAdapterTest extends TestCase
15
{
16
    /** @var SyncPromiseAdapter */
17
    private $promises;
18
19
    public function setUp()
20
    {
21
        $this->promises = new SyncPromiseAdapter();
22
    }
23
24
    public function testIsThenable() : void
25
    {
26
        $this->assertEquals(
27
            true,
28
            $this->promises->isThenable(new Deferred(function () {
29
            }))
30
        );
31
        $this->assertEquals(false, $this->promises->isThenable(false));
32
        $this->assertEquals(false, $this->promises->isThenable(true));
33
        $this->assertEquals(false, $this->promises->isThenable(1));
34
        $this->assertEquals(false, $this->promises->isThenable(0));
35
        $this->assertEquals(false, $this->promises->isThenable('test'));
36
        $this->assertEquals(false, $this->promises->isThenable(''));
37
        $this->assertEquals(false, $this->promises->isThenable([]));
38
        $this->assertEquals(false, $this->promises->isThenable(new \stdClass()));
39
    }
40
41
    public function testConvert() : void
42
    {
43
        $dfd    = new Deferred(function () {
44
        });
45
        $result = $this->promises->convertThenable($dfd);
46
47
        $this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $result);
48
        $this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $result->adoptedPromise);
49
50
        $this->expectException(InvariantViolation::class);
51
        $this->expectExceptionMessage('Expected instance of GraphQL\Deferred, got (empty string)');
52
        $this->promises->convertThenable('');
53
    }
54
55
    public function testThen() : void
56
    {
57
        $dfd     = new Deferred(function () {
58
        });
59
        $promise = $this->promises->convertThenable($dfd);
60
61
        $result = $this->promises->then($promise);
62
63
        $this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $result);
64
        $this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $result->adoptedPromise);
65
    }
66
67
    public function testCreatePromise() : void
68
    {
69
        $promise = $this->promises->create(function ($resolve, $reject) {
0 ignored issues
show
Unused Code introduced by
The parameter $reject is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

69
        $promise = $this->promises->create(function ($resolve, /** @scrutinizer ignore-unused */ $reject) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $resolve is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

69
        $promise = $this->promises->create(function (/** @scrutinizer ignore-unused */ $resolve, $reject) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
70
        });
71
72
        $this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $promise);
73
        $this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $promise->adoptedPromise);
74
75
        $promise = $this->promises->create(function ($resolve, $reject) {
0 ignored issues
show
Unused Code introduced by
The parameter $reject is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
        $promise = $this->promises->create(function ($resolve, /** @scrutinizer ignore-unused */ $reject) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
76
            $resolve('A');
77
        });
78
79
        $this->assertValidPromise($promise, null, 'A', SyncPromise::FULFILLED);
80
    }
81
82
    private function assertValidPromise($promise, $expectedNextReason, $expectedNextValue, $expectedNextState)
83
    {
84
        $this->assertInstanceOf('GraphQL\Executor\Promise\Promise', $promise);
85
        $this->assertInstanceOf('GraphQL\Executor\Promise\Adapter\SyncPromise', $promise->adoptedPromise);
86
87
        $actualNextValue   = null;
88
        $actualNextReason  = null;
89
        $onFulfilledCalled = false;
90
        $onRejectedCalled  = false;
91
92
        $promise->then(
93
            function ($nextValue) use (&$actualNextValue, &$onFulfilledCalled) {
94
                $onFulfilledCalled = true;
95
                $actualNextValue   = $nextValue;
96
            },
97
            function (\Throwable $reason) use (&$actualNextReason, &$onRejectedCalled) {
98
                $onRejectedCalled = true;
99
                $actualNextReason = $reason->getMessage();
100
            }
101
        );
102
103
        $this->assertSame($onFulfilledCalled, false);
104
        $this->assertSame($onRejectedCalled, false);
105
106
        SyncPromise::runQueue();
107
108
        if ($expectedNextState !== SyncPromise::PENDING) {
109
            $this->assertSame(! $expectedNextReason, $onFulfilledCalled);
110
            $this->assertSame(! ! $expectedNextReason, $onRejectedCalled);
111
        }
112
113
        $this->assertSame($expectedNextValue, $actualNextValue);
114
        $this->assertSame($expectedNextReason, $actualNextReason);
115
        $this->assertSame($expectedNextState, $promise->adoptedPromise->state);
116
    }
117
118
    public function testCreateFulfilledPromise() : void
119
    {
120
        $promise = $this->promises->createFulfilled('test');
121
        $this->assertValidPromise($promise, null, 'test', SyncPromise::FULFILLED);
122
    }
123
124
    public function testCreateRejectedPromise() : void
125
    {
126
        $promise = $this->promises->createRejected(new \Exception('test reason'));
127
        $this->assertValidPromise($promise, 'test reason', null, SyncPromise::REJECTED);
128
    }
129
130
    public function testCreatePromiseAll() : void
131
    {
132
        $promise = $this->promises->all([]);
133
        $this->assertValidPromise($promise, null, [], SyncPromise::FULFILLED);
134
135
        $promise = $this->promises->all(['1']);
136
        $this->assertValidPromise($promise, null, ['1'], SyncPromise::FULFILLED);
137
138
        $promise1 = new SyncPromise();
139
        $promise2 = new SyncPromise();
140
        $promise3 = $promise2->then(
141
            function ($value) {
142
                return $value . '-value3';
143
            }
144
        );
145
146
        $data = [
147
            '1',
148
            new Promise($promise1, $this->promises),
149
            new Promise($promise2, $this->promises),
150
            3,
151
            new Promise($promise3, $this->promises),
152
            [],
153
        ];
154
155
        $promise = $this->promises->all($data);
156
        $this->assertValidPromise($promise, null, null, SyncPromise::PENDING);
157
158
        $promise1->resolve('value1');
159
        $this->assertValidPromise($promise, null, null, SyncPromise::PENDING);
160
        $promise2->resolve('value2');
161
        $this->assertValidPromise(
162
            $promise,
163
            null,
164
            ['1', 'value1', 'value2', 3, 'value2-value3', []],
165
            SyncPromise::FULFILLED
166
        );
167
    }
168
169
    public function testWait() : void
170
    {
171
        $called = [];
172
173
        $deferred1 = new Deferred(function () use (&$called) {
174
            $called[] = 1;
175
176
            return 1;
177
        });
178
        $deferred2 = new Deferred(function () use (&$called) {
179
            $called[] = 2;
180
181
            return 2;
182
        });
183
184
        $p1 = $this->promises->convertThenable($deferred1);
185
        $p2 = $this->promises->convertThenable($deferred2);
186
187
        $p3 = $p2->then(function () use (&$called) {
188
            $dfd = new Deferred(function () use (&$called) {
189
                $called[] = 3;
190
191
                return 3;
192
            });
193
194
            return $this->promises->convertThenable($dfd);
195
        });
196
197
        $p4 = $p3->then(function () use (&$called) {
198
            return new Deferred(function () use (&$called) {
199
                $called[] = 4;
200
201
                return 4;
202
            });
203
        });
204
205
        $all = $this->promises->all([0, $p1, $p2, $p3, $p4]);
206
207
        $result = $this->promises->wait($p2);
208
        $this->assertEquals(2, $result);
209
        $this->assertEquals(SyncPromise::PENDING, $p3->adoptedPromise->state);
0 ignored issues
show
Bug introduced by
The property state does not seem to exist on React\Promise\Promise.
Loading history...
210
        $this->assertEquals(SyncPromise::PENDING, $all->adoptedPromise->state);
211
        $this->assertEquals([1, 2], $called);
212
213
        $expectedResult = [0, 1, 2, 3, 4];
214
        $result         = $this->promises->wait($all);
215
        $this->assertEquals($expectedResult, $result);
216
        $this->assertEquals([1, 2, 3, 4], $called);
217
        $this->assertValidPromise($all, null, [0, 1, 2, 3, 4], SyncPromise::FULFILLED);
218
    }
219
}
220