Completed
Push — master ( b20fc0...792db9 )
by David
03:22 queued 01:33
created

anonymous//tests/ControllerQueryProviderTest.php$2   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 4
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace TheCodingMachine\GraphQL\Controllers;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use PHPUnit\Framework\TestCase;
7
use TheCodingMachine\GraphQL\Controllers\Fixtures\TestController;
8
use TheCodingMachine\GraphQL\Controllers\Fixtures\TestObject;
9
use TheCodingMachine\GraphQL\Controllers\Fixtures\TestType;
10
use TheCodingMachine\GraphQL\Controllers\Fixtures\TestTypeMissingAnnotation;
11
use TheCodingMachine\GraphQL\Controllers\Fixtures\TestTypeMissingField;
12
use TheCodingMachine\GraphQL\Controllers\Registry\EmptyContainer;
13
use TheCodingMachine\GraphQL\Controllers\Registry\Registry;
14
use TheCodingMachine\GraphQL\Controllers\Security\AuthenticationServiceInterface;
15
use TheCodingMachine\GraphQL\Controllers\Security\AuthorizationServiceInterface;
16
use TheCodingMachine\GraphQL\Controllers\Security\VoidAuthenticationService;
17
use TheCodingMachine\GraphQL\Controllers\Security\VoidAuthorizationService;
18
use Youshido\GraphQL\Execution\ResolveInfo;
19
use Youshido\GraphQL\Type\InputObject\InputObjectType;
20
use Youshido\GraphQL\Type\ListType\ListType;
21
use Youshido\GraphQL\Type\NonNullType;
22
use Youshido\GraphQL\Type\Object\ObjectType;
23
use Youshido\GraphQL\Type\Scalar\BooleanType;
24
use Youshido\GraphQL\Type\Scalar\DateTimeType;
25
use Youshido\GraphQL\Type\Scalar\FloatType;
26
use Youshido\GraphQL\Type\Scalar\IntType;
27
use Youshido\GraphQL\Type\Scalar\StringType;
28
use Youshido\GraphQL\Type\TypeInterface;
29
use TheCodingMachine\GraphQL\Controllers\Annotations\Query;
30
31
class ControllerQueryProviderTest extends AbstractQueryProviderTest
32
{
33
    public function testQueryProvider()
34
    {
35
        $controller = new TestController();
36
37
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
38
39
        $queries = $queryProvider->getQueries();
40
41
        $this->assertCount(3, $queries);
42
        $usersQuery = $queries[0];
43
        $this->assertSame('test', $usersQuery->getName());
44
45
        $this->assertCount(8, $usersQuery->getArguments());
46
        $this->assertInstanceOf(NonNullType::class, $usersQuery->getArgument('int')->getType());
47
        $this->assertInstanceOf(IntType::class, $usersQuery->getArgument('int')->getType()->getTypeOf());
48
        $this->assertInstanceOf(StringType::class, $usersQuery->getArgument('string')->getType());
49
        $this->assertInstanceOf(NonNullType::class, $usersQuery->getArgument('list')->getType());
50
        $this->assertInstanceOf(ListType::class, $usersQuery->getArgument('list')->getType()->getTypeOf());
51
        $this->assertInstanceOf(NonNullType::class, $usersQuery->getArgument('list')->getType()->getTypeOf()->getItemType());
52
        $this->assertInstanceOf(InputObjectType::class, $usersQuery->getArgument('list')->getType()->getTypeOf()->getItemType()->getTypeOf());
53
        $this->assertInstanceOf(BooleanType::class, $usersQuery->getArgument('boolean')->getType());
54
        $this->assertInstanceOf(FloatType::class, $usersQuery->getArgument('float')->getType());
55
        $this->assertInstanceOf(DateTimeType::class, $usersQuery->getArgument('dateTimeImmutable')->getType());
56
        $this->assertInstanceOf(DateTimeType::class, $usersQuery->getArgument('dateTime')->getType());
57
        $this->assertInstanceOf(StringType::class, $usersQuery->getArgument('withDefault')->getType());
58
        $this->assertSame('TestObject', $usersQuery->getArgument('list')->getType()->getTypeOf()->getItemType()->getTypeOf()->getName());
59
60
        $mockResolveInfo = $this->createMock(ResolveInfo::class);
61
62
        $context = ['int' => 42, 'string' => 'foo', 'list' => [
63
            ['test' => 42],
64
            ['test' => 12],
65
        ],
66
            'boolean' => true,
67
            'float' => 4.2,
68
            'dateTimeImmutable' => '2017-01-01 01:01:01',
69
            'dateTime' => '2017-01-01 01:01:01'
70
        ];
71
72
        $result = $usersQuery->resolve('foo', $context, $mockResolveInfo);
73
74
        $this->assertInstanceOf(TestObject::class, $result);
75
        $this->assertSame('foo424212true4.22017010101010120170101010101default', $result->getTest());
76
77
        unset($context['string']); // Testing null default value
78
        $result = $usersQuery->resolve('foo', $context, $mockResolveInfo);
79
80
        $this->assertSame('424212true4.22017010101010120170101010101default', $result->getTest());
81
    }
82
83
    public function testMutations()
84
    {
85
        $controller = new TestController();
86
87
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
88
89
        $mutations = $queryProvider->getMutations();
90
91
        $this->assertCount(1, $mutations);
92
        $mutation = $mutations[0];
93
        $this->assertSame('mutation', $mutation->getName());
94
95
        $mockResolveInfo = $this->createMock(ResolveInfo::class);
96
97
        $result = $mutation->resolve('foo', ['testObject' => ['test' => 42]], $mockResolveInfo);
98
99
        $this->assertInstanceOf(TestObject::class, $result);
100
        $this->assertEquals('42', $result->getTest());
101
    }
102
103
    public function testErrors()
104
    {
105
        $controller = new class
106
        {
107
            /**
108
             * @Query
109
             * @return string
110
             */
111
            public function test($noTypeHint): string
0 ignored issues
show
Unused Code introduced by
The parameter $noTypeHint 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

111
            public function test(/** @scrutinizer ignore-unused */ $noTypeHint): string

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...
112
            {
113
                return 'foo';
114
            }
115
        };
116
117
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
118
119
        $this->expectException(MissingTypeHintException::class);
120
        $queryProvider->getQueries();
121
    }
122
123
    public function testQueryProviderWithFixedReturnType()
124
    {
125
        $controller = new TestController();
126
127
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
128
129
        $queries = $queryProvider->getQueries();
130
131
        $this->assertCount(3, $queries);
132
        $fixedQuery = $queries[1];
133
134
        $this->assertInstanceOf(TestType::class, $fixedQuery->getType());
135
    }
136
137
    public function testNameFromAnnotation()
138
    {
139
        $controller = new TestController();
140
141
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
142
143
        $queries = $queryProvider->getQueries();
144
145
        $query = $queries[2];
146
147
        $this->assertSame('nameFromAnnotation', $query->getName());
148
    }
149
150
    public function testSourceField()
151
    {
152
        $controller = new TestType($this->getRegistry());
153
154
        $queryProvider = new ControllerQueryProvider($controller, $this->getRegistry());
155
156
        $fields = $queryProvider->getFields();
157
158
        $this->assertCount(2, $fields);
159
160
        $this->assertSame('customField', $fields[0]->getName());
161
        $this->assertSame('test', $fields[1]->getName());
162
    }
163
164
    public function testLoggedInSourceField()
165
    {
166
        $registry = new Registry(new EmptyContainer(),
167
            new VoidAuthorizationService(),
168
            new class implements AuthenticationServiceInterface {
169
                public function isLogged(): bool
170
                {
171
                    return true;
172
                }
173
            },
174
            new AnnotationReader(),
175
            $this->getTypeMapper(),
176
            $this->getHydrator());
177
178
        $queryProvider = new ControllerQueryProvider(new TestType($this->getRegistry()), $registry);
179
        $fields = $queryProvider->getFields();
180
        $this->assertCount(3, $fields);
181
182
        $this->assertSame('testBool', $fields[2]->getName());
183
184
    }
185
186
    public function testRightInSourceField()
187
    {
188
        $registry = new Registry(new EmptyContainer(),
189
            new class implements AuthorizationServiceInterface {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
190
                public function isAllowed(string $right): bool
191
                {
192
                    return true;
193
                }
194
            },
195
            new VoidAuthenticationService(),
196
            new AnnotationReader(),
197
            $this->getTypeMapper(),
198
            $this->getHydrator());
199
200
        $queryProvider = new ControllerQueryProvider(new TestType($this->getRegistry()), $registry);
201
        $fields = $queryProvider->getFields();
202
        $this->assertCount(3, $fields);
203
204
        $this->assertSame('testRight', $fields[2]->getName());
205
206
    }
207
208
    public function testMissingTypeAnnotation()
209
    {
210
        $queryProvider = new ControllerQueryProvider(new TestTypeMissingAnnotation(), $this->getRegistry());
211
212
        $this->expectException(MissingAnnotationException::class);
213
        $queryProvider->getFields();
214
    }
215
216
    public function testSourceFieldDoesNotExists()
217
    {
218
        $queryProvider = new ControllerQueryProvider(new TestTypeMissingField(), $this->getRegistry());
219
220
        $this->expectException(FieldNotFoundException::class);
221
        $this->expectExceptionMessage("There is an issue with a @SourceField annotation in class \"TheCodingMachine\GraphQL\Controllers\Fixtures\TestTypeMissingField\": Could not find a getter or a isser for field \"notExists\". Looked for: \"TheCodingMachine\GraphQL\Controllers\Fixtures\TestObject::getNotExists()\", \"TheCodingMachine\GraphQL\Controllers\Fixtures\TestObject::isNotExists()");
222
        $queryProvider->getFields();
223
    }
224
}
225