Passed
Push — master ( 581283...087f55 )
by Adrien
14:24
created

testDoctrineWithMappingDriverChainUsingNamespace()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 13
rs 9.9332
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLTests\Doctrine;
6
7
use DateTimeImmutable;
8
use Doctrine\ORM\Tools\SchemaValidator;
9
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
10
use GraphQL\Type\Definition\BooleanType;
11
use GraphQL\Type\Definition\ObjectType;
12
use GraphQL\Type\Definition\Type;
13
use GraphQL\Type\Schema;
14
use GraphQLTests\Doctrine\Blog\Model\Post;
15
use GraphQLTests\Doctrine\Blog\Types\CustomType;
16
use GraphQLTests\Doctrine\Blog\Types\DateTimeType;
17
use GraphQLTests\Doctrine\Blog\Types\PostStatusType;
18
use PHPUnit\Framework\TestCase;
19
use stdClass;
20
21
final class TypesTest extends 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 attributes 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 {
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 {
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(DateTimeImmutable::class);
113
        $viaType = $this->types->get(DateTimeType::class);
114
        self::assertSame($viaPhp, $viaType);
115
    }
116
117
    public function testDoctrineWithMappingDriverChainUsingDefault(): void
118
    {
119
        // Replace attribute driver with a driver chain
120
        $config = $this->entityManager->getConfiguration();
121
        $chain = new MappingDriverChain();
122
        $chain->setDefaultDriver($config->getMetadataDriverImpl());
0 ignored issues
show
Bug introduced by
It seems like $config->getMetadataDriverImpl() can also be of type null; however, parameter $driver of Doctrine\Persistence\Map...ain::setDefaultDriver() does only seem to accept Doctrine\Persistence\Mapping\Driver\MappingDriver, maybe add an additional type check? ( Ignorable by Annotation )

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

122
        $chain->setDefaultDriver(/** @scrutinizer ignore-type */ $config->getMetadataDriverImpl());
Loading history...
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 attribute 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 testNonRegisteredCustomTypeMustThrow(): void
146
    {
147
        $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`');
148
        $this->types->get('foo');
149
    }
150
151
    public function testHas(): void
152
    {
153
        self::assertTrue($this->types->has(stdClass::class), 'should have custom registered key');
154
        self::assertFalse($this->types->has('non-existing'), 'should not have non-existing things');
155
156
        $this->types->get(stdClass::class);
157
        self::assertTrue($this->types->has('customName'), 'should have custom registered type by its name, even if custom key was different, once type is created');
158
    }
159
160
    /**
161
     * @dataProvider provideLoadType
162
     */
163
    public function testLoadType(string $typeName): void
164
    {
165
        $type = $this->types->loadType($typeName, 'GraphQLTests\Doctrine\Blog\Model');
166
        self::assertNotNull($type, 'should be able to lazy load a generated type by its name only');
167
        self::assertSame($typeName, $type->name(), 'loaded type must have same name');
0 ignored issues
show
Bug introduced by
The method name() does not exist on GraphQL\Type\Definition\Type. It seems like you code against a sub-type of said class. However, the method does not exist in GraphQL\Type\Definition\ListOfType or GraphQL\Type\Definition\NonNull. Are you sure you never get one of those? ( Ignorable by Annotation )

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

167
        self::assertSame($typeName, $type->/** @scrutinizer ignore-call */ name(), 'loaded type must have same name');
Loading history...
168
    }
169
170
    public static function provideLoadType(): iterable
171
    {
172
        yield 'PostInput' => ['PostInput'];
173
        yield 'PostPartialInput' => ['PostPartialInput'];
174
        yield 'Post' => ['Post'];
175
        yield 'PostID' => ['PostID'];
176
        yield 'PostFilter' => ['PostFilter'];
177
        yield 'PostFilterGroupJoin' => ['PostFilterGroupJoin'];
178
        yield 'PostSorting' => ['PostSorting'];
179
        yield 'PostStatus' => ['PostStatus'];
180
        yield 'PostFilterGroupCondition' => ['PostFilterGroupCondition'];
181
        yield 'JoinOnPost' => ['JoinOnPost'];
182
    }
183
184
    public function testLoadUnknownType(): void
185
    {
186
        $type = $this->types->loadType('unknown-type-name', 'GraphQLTests\Doctrine\Blog\Model');
187
        self::assertNull($type, 'should return null if type is not found to be chainable');
188
    }
189
190
    public function testLoadTypeInUnknownNamespace(): void
191
    {
192
        $type = $this->types->loadType('Post', 'Unknown\Model');
193
        self::assertNull($type, 'should return null if namespace is not found to be chainable');
194
    }
195
}
196