Failed Conditions
Push — master ( 48b44f...392b56 )
by Vladimir
04:42
created

AstFromValueTest::testConvertsStringValuesToASTs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace GraphQL\Tests\Utils;
3
4
use GraphQL\Language\AST\BooleanValueNode;
5
use GraphQL\Language\AST\EnumValueNode;
6
use GraphQL\Language\AST\FloatValueNode;
7
use GraphQL\Language\AST\IntValueNode;
8
use GraphQL\Language\AST\ListValueNode;
9
use GraphQL\Language\AST\NameNode;
10
use GraphQL\Language\AST\NullValueNode;
11
use GraphQL\Language\AST\ObjectFieldNode;
12
use GraphQL\Language\AST\ObjectValueNode;
13
use GraphQL\Language\AST\StringValueNode;
14
use GraphQL\Type\Definition\EnumType;
15
use GraphQL\Type\Definition\InputObjectType;
16
use GraphQL\Type\Definition\Type;
17
use GraphQL\Utils\AST;
18
use PHPUnit\Framework\TestCase;
19
20
class AstFromValueTest extends TestCase
21
{
22
    // Describe: astFromValue
23
24
    /**
25
     * @it converts boolean values to ASTs
26
     */
27
    public function testConvertsBooleanValueToASTs()
28
    {
29
        $this->assertEquals(new BooleanValueNode(['value' => true]), AST::astFromValue(true, Type::boolean()));
30
        $this->assertEquals(new BooleanValueNode(['value' => false]), AST::astFromValue(false, Type::boolean()));
31
        $this->assertEquals(new NullValueNode([]), AST::astFromValue(null, Type::boolean()));
32
        $this->assertEquals(new BooleanValueNode(['value' => false]), AST::astFromValue(0, Type::boolean()));
33
        $this->assertEquals(new BooleanValueNode(['value' => true]), AST::astFromValue(1, Type::boolean()));
34
        $this->assertEquals(new BooleanValueNode(['value' => false]), AST::astFromValue(0, Type::nonNull(Type::boolean())));
35
        $this->assertEquals(null, AST::astFromValue(null, Type::nonNull(Type::boolean()))); // Note: null means that AST cannot
36
    }
37
38
    /**
39
     * @it converts Int values to Int ASTs
40
     */
41
    public function testConvertsIntValuesToASTs()
42
    {
43
        $this->assertEquals(new IntValueNode(['value' => '123']), AST::astFromValue(123.0, Type::int()));
44
        $this->assertEquals(new IntValueNode(['value' => '10000']), AST::astFromValue(1e4, Type::int()));
45
        $this->assertEquals(new IntValueNode(['value' => '0']), AST::astFromValue(0e4, Type::int()));
46
    }
47
48
    public function testConvertsIntValuesToASTsCannotRepresentNonInteger()
49
    {
50
        // GraphQL spec does not allow coercing non-integer values to Int to avoid
51
        // accidental data loss.
52
        $this->expectException(\Throwable::class);
53
        $this->expectExceptionMessage('Int cannot represent non-integer value: 123.5');
54
        AST::astFromValue(123.5, Type::int());
55
    }
56
57
    public function testConvertsIntValuesToASTsCannotRepresentNon32bitsInteger()
58
    {
59
        $this->expectException(\Throwable::class);
60
        $this->expectExceptionMessage('Int cannot represent non 32-bit signed integer value: 1.0E+40');
61
        AST::astFromValue(1e40, Type::int()); // Note: js version will produce 1e+40, both values are valid GraphQL floats
62
    }
63
64
    /**
65
     * @it converts Float values to Int/Float ASTs
66
     */
67
    public function testConvertsFloatValuesToIntOrFloatASTs()
68
    {
69
        $this->assertEquals(new IntValueNode(['value' => '123']), AST::astFromValue(123, Type::float()));
70
        $this->assertEquals(new IntValueNode(['value' => '123']), AST::astFromValue(123.0, Type::float()));
71
        $this->assertEquals(new FloatValueNode(['value' => '123.5']), AST::astFromValue(123.5, Type::float()));
72
        $this->assertEquals(new IntValueNode(['value' => '10000']), AST::astFromValue(1e4, Type::float()));
73
        $this->assertEquals(new FloatValueNode(['value' => '1e+40']), AST::astFromValue(1e40, Type::float()));
74
        $this->assertEquals(new IntValueNode(['value' => '0']), AST::astFromValue(0e40, Type::float()));
75
    }
76
77
    /**
78
     * @it converts String values to String ASTs
79
     */
80
    public function testConvertsStringValuesToASTs()
81
    {
82
        $this->assertEquals(new StringValueNode(['value' => 'hello']), AST::astFromValue('hello', Type::string()));
83
        $this->assertEquals(new StringValueNode(['value' => 'VALUE']), AST::astFromValue('VALUE', Type::string()));
84
        $this->assertEquals(new StringValueNode(['value' => 'VA\\nLUE']), AST::astFromValue("VA\nLUE", Type::string()));
85
        $this->assertEquals(new StringValueNode(['value' => '123']), AST::astFromValue(123, Type::string()));
86
        $this->assertEquals(new StringValueNode(['value' => 'false']), AST::astFromValue(false, Type::string()));
87
        $this->assertEquals(new NullValueNode([]), AST::astFromValue(null, Type::string()));
88
        $this->assertEquals(null, AST::astFromValue(null, Type::nonNull(Type::string())));
89
    }
90
91
    /**
92
     * @it converts ID values to Int/String ASTs
93
     */
94
    public function testConvertIdValuesToIntOrStringASTs()
95
    {
96
        $this->assertEquals(new StringValueNode(['value' => 'hello']), AST::astFromValue('hello', Type::id()));
97
        $this->assertEquals(new StringValueNode(['value' => 'VALUE']), AST::astFromValue('VALUE', Type::id()));
98
        $this->assertEquals(new StringValueNode(['value' => 'VA\\nLUE']), AST::astFromValue("VA\nLUE", Type::id()));
99
        $this->assertEquals(new IntValueNode(['value' => '123']), AST::astFromValue(123, Type::id()));
100
        $this->assertEquals(new StringValueNode(['value' => 'false']), AST::astFromValue(false, Type::id()));
101
        $this->assertEquals(new NullValueNode([]), AST::astFromValue(null, Type::id()));
102
        $this->assertEquals(null, AST::astFromValue(null, Type::nonNull(Type::id())));
103
    }
104
105
    /**
106
     * @it does not converts NonNull values to NullValue
107
     */
108
    public function testDoesNotConvertsNonNullValuestoNullValue()
109
    {
110
        $this->assertSame(null, AST::astFromValue(null, Type::nonNull(Type::boolean())));
111
    }
112
113
    /**
114
     * @it converts string values to Enum ASTs if possible
115
     */
116
    public function testConvertsStringValuesToEnumASTsIfPossible()
117
    {
118
        $this->assertEquals(new EnumValueNode(['value' => 'HELLO']), AST::astFromValue('HELLO', $this->myEnum()));
119
        $this->assertEquals(new EnumValueNode(['value' => 'COMPLEX']), AST::astFromValue($this->complexValue(), $this->myEnum()));
120
121
        // Note: case sensitive
122
        $this->assertEquals(null, AST::astFromValue('hello', $this->myEnum()));
123
124
        // Note: Not a valid enum value
125
        $this->assertEquals(null, AST::astFromValue('VALUE', $this->myEnum()));
126
    }
127
128
    /**
129
     * @it converts array values to List ASTs
130
     */
131
    public function testConvertsArrayValuesToListASTs()
132
    {
133
        $value1 = new ListValueNode([
134
            'values' => [
135
                new StringValueNode(['value' => 'FOO']),
136
                new StringValueNode(['value' => 'BAR'])
137
            ]
138
        ]);
139
        $this->assertEquals($value1, AST::astFromValue(['FOO', 'BAR'], Type::listOf(Type::string())));
140
141
        $value2 = new ListValueNode([
142
            'values' => [
143
                new EnumValueNode(['value' => 'HELLO']),
144
                new EnumValueNode(['value' => 'GOODBYE']),
145
            ]
146
        ]);
147
        $this->assertEquals($value2, AST::astFromValue(['HELLO', 'GOODBYE'], Type::listOf($this->myEnum())));
148
    }
149
150
    /**
151
     * @it converts list singletons
152
     */
153
    public function testConvertsListSingletons()
154
    {
155
        $this->assertEquals(new StringValueNode(['value' => 'FOO']), AST::astFromValue('FOO', Type::listOf(Type::string())));
156
    }
157
158
    /**
159
     * @it converts input objects
160
     */
161
    public function testConvertsInputObjects()
162
    {
163
        $inputObj = new InputObjectType([
164
            'name' => 'MyInputObj',
165
            'fields' => [
166
                'foo' => Type::float(),
167
                'bar' => $this->myEnum()
168
            ]
169
        ]);
170
171
        $expected = new ObjectValueNode([
172
            'fields' => [
173
                $this->objectField('foo', new IntValueNode(['value' => '3'])),
174
                $this->objectField('bar', new EnumValueNode(['value' => 'HELLO']))
175
            ]
176
        ]);
177
178
        $data = ['foo' => 3, 'bar' => 'HELLO'];
179
        $this->assertEquals($expected, AST::astFromValue($data, $inputObj));
180
        $this->assertEquals($expected, AST::astFromValue((object) $data, $inputObj));
181
    }
182
183
    /**
184
     * @it converts input objects with explicit nulls
185
     */
186
    public function testConvertsInputObjectsWithExplicitNulls()
187
    {
188
        $inputObj = new InputObjectType([
189
            'name' => 'MyInputObj',
190
            'fields' => [
191
                'foo' => Type::float(),
192
                'bar' => $this->myEnum()
193
            ]
194
        ]);
195
196
        $this->assertEquals(new ObjectValueNode([
197
            'fields' => [
198
                $this->objectField('foo', new NullValueNode([]))
199
            ]
200
        ]), AST::astFromValue(['foo' => null], $inputObj));
201
    }
202
203
    private $complexValue;
204
205
    private function complexValue()
206
    {
207
        if (!$this->complexValue) {
208
            $this->complexValue = new \stdClass();
209
            $this->complexValue->someArbitrary = 'complexValue';
210
        }
211
        return $this->complexValue;
212
    }
213
214
    /**
215
     * @return EnumType
216
     */
217
    private function myEnum()
218
    {
219
        return new EnumType([
220
            'name' => 'MyEnum',
221
            'values' => [
222
                'HELLO' => [],
223
                'GOODBYE' => [],
224
                'COMPLEX' => ['value' => $this->complexValue()]
225
            ]
226
        ]);
227
    }
228
229
    /**
230
     * @param $name
231
     * @param $value
232
     * @return ObjectFieldNode
233
     */
234
    private function objectField($name, $value)
235
    {
236
        return new ObjectFieldNode([
237
            'name' => new NameNode(['value' => $name]),
238
            'value' => $value
239
        ]);
240
    }
241
}
242