Passed
Pull Request — master (#19)
by James
02:55
created

TypesTest   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
eloc 80
dl 0
loc 159
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A testCanGetUserDefinedScalarTypes() 0 10 1
A testDoctrineWithMappingDriverChainMissingNamespace() 0 9 1
A testDoctrineWithoutAnnotationDriverMustThrow() 0 9 1
A testDoctrineWithMappingDriverChainUsingDefault() 0 10 1
A testCanGetMappedTypesEitherByMappedPhpClassOrDirectTypeClass() 0 5 1
A testGraphQLSchemaFromDocumentationMustBeValid() 0 55 1
A testHas() 0 7 1
A testNonRegisteredCustomTypeMustThrow() 0 4 1
A testCanGetUserMappedTypes() 0 6 1
A testBlogMapping() 0 6 1
A testDoctrineWithMappingDriverChainUsingNamespace() 0 13 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLTests\Doctrine;
6
7
use DateTime;
8
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
9
use Doctrine\ORM\Mapping\Driver\XmlDriver;
10
use Doctrine\ORM\Tools\SchemaValidator;
11
use GraphQL\Type\Definition\BooleanType;
12
use GraphQL\Type\Definition\ObjectType;
13
use GraphQL\Type\Definition\Type;
14
use GraphQL\Type\Schema;
15
use GraphQLTests\Doctrine\Blog\Model\Post;
16
use GraphQLTests\Doctrine\Blog\Types\CustomType;
17
use GraphQLTests\Doctrine\Blog\Types\DateTimeType;
18
use GraphQLTests\Doctrine\Blog\Types\PostStatusType;
19
use stdClass;
20
21
final class TypesTest extends \PHPUnit\Framework\TestCase
22
{
23
    use TypesTrait;
24
25
    public function testBlogMapping(): void
26
    {
27
        $validator = new SchemaValidator($this->entityManager);
28
        $errors = $validator->validateMapping();
29
30
        self::assertEmpty($errors, 'doctrine annotations should be valid');
31
    }
32
33
    public function testGraphQLSchemaFromDocumentationMustBeValid(): void
34
    {
35
        $types = $this->types;
36
        $schema = new Schema([
37
            'query' => new ObjectType([
38
                'name' => 'query',
39
                'fields' => [
40
                    'posts' => [
41
                        'type' => Type::listOf($types->getOutput(Post::class)), // Use automated ObjectType for output
42
                        'args' => [
43
                            [
44
                                'name' => 'filter',
45
                                'type' => $types->getFilter(Post::class), // Use automated filtering options
46
                            ],
47
                            [
48
                                'name' => 'sorting',
49
                                'type' => $types->getSorting(Post::class), // Use automated sorting options
50
                            ],
51
                        ],
52
                        'resolve' => function ($root, $args) use ($types): void {
53
                            $queryBuilder = $types->createFilteredQueryBuilder(Post::class, $args['filter'] ?? [], $args['sorting'] ?? []);
0 ignored issues
show
Unused Code introduced by
The assignment to $queryBuilder is dead and can be removed.
Loading history...
54
55
                        // execute query...
56
                        },
57
                    ],
58
                ],
59
            ]),
60
            'mutation' => new ObjectType([
61
                'name' => 'mutation',
62
                'fields' => [
63
                    'createPost' => [
64
                        'type' => Type::nonNull($types->getOutput(Post::class)),
65
                        'args' => [
66
                            'input' => Type::nonNull($types->getInput(Post::class)), // Use automated InputObjectType for input
67
                        ],
68
                        'resolve' => function ($root, $args): void {
2 ignored issues
show
Unused Code introduced by
The parameter $args 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

68
                        'resolve' => function ($root, /** @scrutinizer ignore-unused */ $args): void {

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 $root 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

68
                        'resolve' => function (/** @scrutinizer ignore-unused */ $root, $args): void {

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...
69
                            // create new post and flush...
70
                        },
71
                    ],
72
                    'updatePost' => [
73
                        'type' => Type::nonNull($types->getOutput(Post::class)),
74
                        'args' => [
75
                            'id' => Type::nonNull(Type::id()), // Use standard API when needed
76
                            'input' => $types->getPartialInput(Post::class),  // Use automated InputObjectType for partial input for updates
77
                        ],
78
                        'resolve' => function ($root, $args): void {
2 ignored issues
show
Unused Code introduced by
The parameter $args 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

78
                        'resolve' => function ($root, /** @scrutinizer ignore-unused */ $args): void {

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 $root 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

78
                        'resolve' => function (/** @scrutinizer ignore-unused */ $root, $args): void {

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...
79
                            // update existing post and flush...
80
                        },
81
                    ],
82
                ],
83
            ]),
84
        ]);
85
86
        $schema->assertValid();
87
        self::assertTrue(true, 'passed validation successfully');
88
    }
89
90
    public function testCanGetUserDefinedScalarTypes(): void
91
    {
92
        $bool = $this->types->get(BooleanType::class);
93
        $status = $this->types->get(PostStatusType::class);
94
95
        self::assertInstanceOf(BooleanType::class, $bool, 'must be a instance of bool');
96
        self::assertInstanceOf(PostStatusType::class, $status, 'must be an instance of post status');
97
98
        self::assertSame($bool, $this->types->get(BooleanType::class), 'must returns the same instance of bool');
99
        self::assertSame($status, $this->types->get(PostStatusType::class), 'must returns the same instance of post status');
100
    }
101
102
    public function testCanGetUserMappedTypes(): void
103
    {
104
        $type = $this->types->get(stdClass::class);
105
106
        self::assertInstanceOf(CustomType::class, $type, 'must be a instance of CustomType');
107
        self::assertSame($type, $this->types->get('customName'));
108
    }
109
110
    public function testCanGetMappedTypesEitherByMappedPhpClassOrDirectTypeClass(): void
111
    {
112
        $viaPhp = $this->types->get(DateTime::class);
113
        $viaType = $this->types->get(DateTimeType::class);
114
        self::assertSame($viaPhp, $viaType);
115
    }
116
117
    public function testDoctrineWithMappingDriverChainUsingDefault(): void
118
    {
119
        // Replace annotation driver with a driver chain
120
        $config = $this->entityManager->getConfiguration();
121
        $chain = new MappingDriverChain();
122
        $chain->setDefaultDriver($config->getMetadataDriverImpl());
123
        $config->setMetadataDriverImpl($chain);
124
125
        $type = $this->types->getOutput(Post::class);
126
        self::assertNotEmpty($type->getFields());
127
    }
128
129
    public function testDoctrineWithMappingDriverChainUsingNamespace(): void
130
    {
131
        // Replace annotation driver with a driver chain
132
        $config = $this->entityManager->getConfiguration();
133
        $chain = new MappingDriverChain();
134
        $driver = $config->getMetadataDriverImpl();
135
        if ($driver === null) {
136
            self::fail('driver missing');
137
        } else {
138
            $chain->addDriver($driver, 'GraphQLTests\Doctrine\Blog\Model');
139
            $config->setMetadataDriverImpl($chain);
140
            $type = $this->types->getOutput(Post::class);
141
            self::assertNotEmpty($type->getFields());
142
        }
143
    }
144
145
    public function testDoctrineWithMappingDriverChainMissingNamespace(): void
146
    {
147
        $config = $this->entityManager->getConfiguration();
148
        $chain = new MappingDriverChain();
149
        $type = $this->types->getOutput(Post::class);
150
151
        $config->setMetadataDriverImpl($chain);
152
        $this->expectExceptionMessage('graphql-doctrine requires GraphQLTests\Doctrine\Blog\Model\Post entity to be configured with a `Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver`.');
153
        $type->getFields();
154
    }
155
156
    public function testDoctrineWithoutAnnotationDriverMustThrow(): void
157
    {
158
        // Replace annotation driver with a driver chain
159
        $config = $this->entityManager->getConfiguration();
160
        $type = $this->types->getOutput(Post::class);
161
162
        $config->setMetadataDriverImpl(new XmlDriver([]));
163
        $this->expectExceptionMessage('graphql-doctrine requires Doctrine to be configured with a `Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver`.');
164
        $type->getFields();
165
    }
166
167
    public function testNonRegisteredCustomTypeMustThrow(): void
168
    {
169
        $this->expectExceptionMessage('No type registered with key `foo`. Either correct the usage, or register it in your custom types container when instantiating `GraphQL\Doctrine\Types`');
170
        $this->types->get('foo');
171
    }
172
173
    public function testHas(): void
174
    {
175
        $this->assertTrue($this->types->has(stdClass::class), 'should have custom registered key');
176
        $this->assertFalse($this->types->has('non-existing'), 'should not have non-existing things');
177
178
        $this->types->get(stdClass::class);
179
        $this->assertTrue($this->types->has('customName'), 'should have custom registered type by its name, even if custom key was different, once type is created');
180
    }
181
}
182