Failed Conditions
Push — master ( 6e7cf2...804daa )
by Vladimir
04:26
created

SyncTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 35
rs 9.584
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace GraphQL\Tests\Executor;
3
4
use GraphQL\Deferred;
5
use GraphQL\Error\Error;
6
use GraphQL\Error\FormattedError;
7
use GraphQL\Executor\ExecutionResult;
8
use GraphQL\Executor\Executor;
9
use GraphQL\Executor\Promise\Adapter\SyncPromise;
10
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
11
use GraphQL\Executor\Promise\Promise;
12
use GraphQL\GraphQL;
13
use GraphQL\Language\Parser;
14
use GraphQL\Type\Definition\ObjectType;
15
use GraphQL\Type\Definition\Type;
16
use GraphQL\Type\Schema;
17
use GraphQL\Utils\Utils;
18
use GraphQL\Validator\DocumentValidator;
19
use PHPUnit\Framework\TestCase;
20
21
class SyncTest extends TestCase
22
{
23
    /** @var Schema */
24
    private $schema;
25
26
    /** @var SyncPromiseAdapter */
27
    private $promiseAdapter;
28
29
    public function setUp()
30
    {
31
        $this->schema = new Schema([
32
            'query' => new ObjectType([
33
                'name' => 'Query',
34
                'fields' => [
35
                    'syncField' => [
36
                        'type' => Type::string(),
37
                        'resolve' => function ($rootValue) {
38
                            return $rootValue;
39
                        }
40
                    ],
41
                    'asyncField' => [
42
                        'type' => Type::string(),
43
                        'resolve' => function ($rootValue) {
44
                            return new Deferred(function () use ($rootValue) {
45
                                return $rootValue;
46
                            });
47
                        }
48
                    ]
49
                ]
50
            ]),
51
            'mutation' => new ObjectType([
52
                'name' => 'Mutation',
53
                'fields' => [
54
                    'syncMutationField' => [
55
                        'type' => Type::string(),
56
                        'resolve' => function ($rootValue) {
57
                            return $rootValue;
58
                        }
59
                    ]
60
                ]
61
            ])
62
        ]);
63
        $this->promiseAdapter = new SyncPromiseAdapter();
64
    }
65
66
    // Describe: Execute: synchronously when possible
67
68
    /**
69
     * @it does not return a Promise for initial errors
70
     */
71
    public function testDoesNotReturnAPromiseForInitialErrors()
72
    {
73
        $doc = 'fragment Example on Query { syncField }';
74
        $result = $this->execute(
75
            $this->schema,
76
            Parser::parse($doc),
77
            'rootValue'
78
        );
79
        $this->assertSync(['errors' => [['message' => 'Must provide an operation.']]], $result);
80
    }
81
82
    /**
83
     * @it does not return a Promise if fields are all synchronous
84
     */
85
    public function testDoesNotReturnAPromiseIfFieldsAreAllSynchronous()
86
    {
87
        $doc = 'query Example { syncField }';
88
        $result = $this->execute(
89
            $this->schema,
90
            Parser::parse($doc),
91
            'rootValue'
92
        );
93
        $this->assertSync(['data' => ['syncField' => 'rootValue']], $result);
94
    }
95
96
    /**
97
     * @it does not return a Promise if mutation fields are all synchronous
98
     */
99
    public function testDoesNotReturnAPromiseIfMutationFieldsAreAllSynchronous()
100
    {
101
        $doc = 'mutation Example { syncMutationField }';
102
        $result = $this->execute(
103
            $this->schema,
104
            Parser::parse($doc),
105
            'rootValue'
106
        );
107
        $this->assertSync(['data' => ['syncMutationField' => 'rootValue']], $result);
108
    }
109
110
    /**
111
     * @it returns a Promise if any field is asynchronous
112
     */
113
    public function testReturnsAPromiseIfAnyFieldIsAsynchronous()
114
    {
115
        $doc = 'query Example { syncField, asyncField }';
116
        $result = $this->execute(
117
            $this->schema,
118
            Parser::parse($doc),
119
            'rootValue'
120
        );
121
        $this->assertAsync(['data' => ['syncField' => 'rootValue', 'asyncField' => 'rootValue']], $result);
122
    }
123
124
    // Describe: graphqlSync
125
126
    /**
127
     * @it does not return a Promise for syntax errors
128
     */
129
    public function testDoesNotReturnAPromiseForSyntaxErrors()
130
    {
131
        $doc = 'fragment Example on Query { { { syncField }';
132
        $result = $this->graphqlSync(
133
            $this->schema,
134
            $doc
135
        );
136
        $this->assertSync([
137
            'errors' => [
138
                ['message' => 'Syntax Error: Expected Name, found {',
139
                'locations' => [['line' => 1, 'column' => 29]]]
140
            ]
141
        ], $result);
142
    }
143
144
    /**
145
     * @it does not return a Promise for validation errors
146
     */
147
    public function testDoesNotReturnAPromiseForValidationErrors()
148
    {
149
        $doc = 'fragment Example on Query { unknownField }';
150
        $validationErrors = DocumentValidator::validate($this->schema, Parser::parse($doc));
151
        $result = $this->graphqlSync(
152
            $this->schema,
153
            $doc
154
        );
155
        $expected = [
156
            'errors' => Utils::map($validationErrors, function ($e) {
157
                return FormattedError::createFromException($e);
158
            })
159
        ];
160
        $this->assertSync($expected, $result);
161
    }
162
163
    /**
164
     * @it does not return a Promise for sync execution
165
     */
166
    public function testDoesNotReturnAPromiseForSyncExecution()
167
    {
168
        $doc = 'query Example { syncField }';
169
        $result = $this->graphqlSync(
170
            $this->schema,
171
            $doc,
172
            'rootValue'
173
        );
174
        $this->assertSync(['data' => ['syncField' => 'rootValue']], $result);
175
    }
176
177
    private function graphqlSync($schema, $doc, $rootValue = null)
178
    {
179
        return GraphQL::promiseToExecute($this->promiseAdapter, $schema, $doc, $rootValue);
180
    }
181
182
    private function execute($schema, $doc, $rootValue = null)
183
    {
184
        return Executor::promiseToExecute($this->promiseAdapter, $schema, $doc, $rootValue);
185
    }
186
187
    private function assertSync($expectedFinalArray, $actualResult)
188
    {
189
        $message = 'Failed assertion that execution was synchronous';
190
        $this->assertInstanceOf(Promise::class, $actualResult, $message);
191
        $this->assertInstanceOf(SyncPromise::class, $actualResult->adoptedPromise, $message);
192
        $this->assertEquals(SyncPromise::FULFILLED, $actualResult->adoptedPromise->state, $message);
193
        $this->assertInstanceOf(ExecutionResult::class, $actualResult->adoptedPromise->result, $message);
194
        $this->assertArraySubset($expectedFinalArray, $actualResult->adoptedPromise->result->toArray(), $message);
0 ignored issues
show
Bug introduced by
$message of type string is incompatible with the type boolean expected by parameter $checkForObjectIdentity of PHPUnit\Framework\Assert::assertArraySubset(). ( Ignorable by Annotation )

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

194
        $this->assertArraySubset($expectedFinalArray, $actualResult->adoptedPromise->result->toArray(), /** @scrutinizer ignore-type */ $message);
Loading history...
195
    }
196
197
    private function assertAsync($expectedFinalArray, $actualResult)
198
    {
199
        $message = 'Failed assertion that execution was asynchronous';
200
        $this->assertInstanceOf(Promise::class, $actualResult, $message);
201
        $this->assertInstanceOf(SyncPromise::class, $actualResult->adoptedPromise, $message);
202
        $this->assertEquals(SyncPromise::PENDING, $actualResult->adoptedPromise->state, $message);
203
        $resolvedResult = $this->promiseAdapter->wait($actualResult);
204
        $this->assertInstanceOf(ExecutionResult::class, $resolvedResult, $message);
205
        $this->assertArraySubset($expectedFinalArray, $resolvedResult->toArray(), $message);
0 ignored issues
show
Bug introduced by
$message of type string is incompatible with the type boolean expected by parameter $checkForObjectIdentity of PHPUnit\Framework\Assert::assertArraySubset(). ( Ignorable by Annotation )

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

205
        $this->assertArraySubset($expectedFinalArray, $resolvedResult->toArray(), /** @scrutinizer ignore-type */ $message);
Loading history...
206
    }
207
}
208