• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 6067528200

04 Sep 2023 12:12AM UTC coverage: 36.875% (-21.9%) from 58.794%
6067528200

Pull #5791

github

web-flow
Merge 64157e578 into d09cfc9d2
Pull Request #5791: fix: strip down any sql function name

3096 of 3096 new or added lines in 205 files covered. (100.0%)

9926 of 26918 relevant lines covered (36.87%)

6.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/JsonSchema/Tests/SchemaFactoryTest.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\JsonSchema\Tests;
15

16
use ApiPlatform\JsonSchema\Schema;
17
use ApiPlatform\JsonSchema\SchemaFactory;
18
use ApiPlatform\JsonSchema\Tests\Fixtures\ApiResource\OverriddenOperationDummy;
19
use ApiPlatform\JsonSchema\Tests\Fixtures\DummyResourceInterface;
20
use ApiPlatform\JsonSchema\Tests\Fixtures\Enum\GenderTypeEnum;
21
use ApiPlatform\JsonSchema\Tests\Fixtures\NotAResource;
22
use ApiPlatform\JsonSchema\Tests\Fixtures\NotAResourceWithUnionIntersectTypes;
23
use ApiPlatform\JsonSchema\Tests\Fixtures\Serializable;
24
use ApiPlatform\Metadata\ApiProperty;
25
use ApiPlatform\Metadata\ApiResource;
26
use ApiPlatform\Metadata\Operations;
27
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
28
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
29
use ApiPlatform\Metadata\Property\PropertyNameCollection;
30
use ApiPlatform\Metadata\Put;
31
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
32
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
33
use ApiPlatform\Metadata\ResourceClassResolverInterface;
34
use PHPUnit\Framework\TestCase;
35
use Prophecy\Argument;
36
use Prophecy\PhpUnit\ProphecyTrait;
37
use Symfony\Component\PropertyInfo\Type;
38
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
39

40
class SchemaFactoryTest extends TestCase
41
{
42
    use ProphecyTrait;
43

44
    public function testBuildSchemaForNonResourceClass(): void
45
    {
46
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
47

48
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
49
        $propertyNameCollectionFactoryProphecy->create(NotAResource::class, Argument::cetera())->willReturn(new PropertyNameCollection(['foo', 'bar', 'genderType']));
×
50

51
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
52
        $propertyMetadataFactoryProphecy->create(NotAResource::class, 'foo', Argument::cetera())->willReturn(
×
53
            (new ApiProperty())
×
54
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])
×
55
                ->withReadable(true)
×
56
                ->withSchema(['type' => 'string'])
×
57
        );
×
58
        $propertyMetadataFactoryProphecy->create(NotAResource::class, 'bar', Argument::cetera())->willReturn(
×
59
            (new ApiProperty())
×
60
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)])
×
61
                ->withReadable(true)
×
62
                ->withDefault('default_bar')
×
63
                ->withExample('example_bar')
×
64
                ->withSchema(['type' => 'integer', 'default' => 'default_bar', 'example' => 'example_bar'])
×
65
        );
×
66
        $propertyMetadataFactoryProphecy->create(NotAResource::class, 'genderType', Argument::cetera())->willReturn(
×
67
            (new ApiProperty())
×
68
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT)])
×
69
                ->withReadable(true)
×
70
                ->withDefault('male')
×
71
                ->withSchema(['type' => 'object', 'default' => 'male', 'example' => 'male'])
×
72
        );
×
73

74
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
75
        $resourceClassResolverProphecy->isResourceClass(NotAResource::class)->willReturn(false);
×
76

77
        $schemaFactory = new SchemaFactory(null, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal());
×
78
        $resultSchema = $schemaFactory->buildSchema(NotAResource::class);
×
79

80
        $rootDefinitionKey = $resultSchema->getRootDefinitionKey();
×
81
        $definitions = $resultSchema->getDefinitions();
×
82

83
        $this->assertSame((new \ReflectionClass(NotAResource::class))->getShortName(), $rootDefinitionKey);
×
84
        // @noRector
85
        $this->assertTrue(isset($definitions[$rootDefinitionKey]));
×
86
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]);
×
87
        $this->assertSame('object', $definitions[$rootDefinitionKey]['type']);
×
88
        $this->assertArrayNotHasKey('additionalProperties', $definitions[$rootDefinitionKey]);
×
89
        $this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
×
90
        $this->assertArrayHasKey('foo', $definitions[$rootDefinitionKey]['properties']);
×
91
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['foo']);
×
92
        $this->assertArrayNotHasKey('default', $definitions[$rootDefinitionKey]['properties']['foo']);
×
93
        $this->assertArrayNotHasKey('example', $definitions[$rootDefinitionKey]['properties']['foo']);
×
94
        $this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['foo']['type']);
×
95
        $this->assertArrayHasKey('bar', $definitions[$rootDefinitionKey]['properties']);
×
96
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['bar']);
×
97
        $this->assertArrayHasKey('default', $definitions[$rootDefinitionKey]['properties']['bar']);
×
98
        $this->assertArrayHasKey('example', $definitions[$rootDefinitionKey]['properties']['bar']);
×
99
        $this->assertSame('integer', $definitions[$rootDefinitionKey]['properties']['bar']['type']);
×
100
        $this->assertSame('default_bar', $definitions[$rootDefinitionKey]['properties']['bar']['default']);
×
101
        $this->assertSame('example_bar', $definitions[$rootDefinitionKey]['properties']['bar']['example']);
×
102

103
        $this->assertArrayHasKey('genderType', $definitions[$rootDefinitionKey]['properties']);
×
104
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
105
        $this->assertArrayHasKey('default', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
106
        $this->assertArrayHasKey('example', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
107
        $this->assertSame('object', $definitions[$rootDefinitionKey]['properties']['genderType']['type']);
×
108
        $this->assertSame('male', $definitions[$rootDefinitionKey]['properties']['genderType']['default']);
×
109
        $this->assertSame('male', $definitions[$rootDefinitionKey]['properties']['genderType']['example']);
×
110
    }
111

112
    public function testBuildSchemaForNonResourceClassWithUnionIntersectTypes(): void
113
    {
114
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
115

116
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
117
        $propertyNameCollectionFactoryProphecy->create(NotAResourceWithUnionIntersectTypes::class, Argument::cetera())->willReturn(new PropertyNameCollection(['ignoredProperty', 'unionType', 'intersectType']));
×
118

119
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
120
        $propertyMetadataFactoryProphecy->create(NotAResourceWithUnionIntersectTypes::class, 'ignoredProperty', Argument::cetera())->willReturn(
×
121
            (new ApiProperty())
×
122
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING, nullable: true)])
×
123
                ->withReadable(true)
×
124
                ->withSchema(['type' => ['string', 'null']])
×
125
        );
×
126
        $propertyMetadataFactoryProphecy->create(NotAResourceWithUnionIntersectTypes::class, 'unionType', Argument::cetera())->willReturn(
×
127
            (new ApiProperty())
×
128
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING, nullable: true), new Type(Type::BUILTIN_TYPE_INT, nullable: true), new Type(Type::BUILTIN_TYPE_FLOAT, nullable: true)])
×
129
                ->withReadable(true)
×
130
                ->withSchema(['oneOf' => [
×
131
                    ['type' => ['string', 'null']],
×
132
                    ['type' => ['integer', 'null']],
×
133
                ]])
×
134
        );
×
135
        $propertyMetadataFactoryProphecy->create(NotAResourceWithUnionIntersectTypes::class, 'intersectType', Argument::cetera())->willReturn(
×
136
            (new ApiProperty())
×
137
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, class: Serializable::class), new Type(Type::BUILTIN_TYPE_OBJECT, class: DummyResourceInterface::class)])
×
138
                ->withReadable(true)
×
139
                ->withSchema(['type' => 'object'])
×
140
        );
×
141

142
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
143
        $resourceClassResolverProphecy->isResourceClass(NotAResourceWithUnionIntersectTypes::class)->willReturn(false);
×
144

145
        $schemaFactory = new SchemaFactory(null, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal());
×
146
        $resultSchema = $schemaFactory->buildSchema(NotAResourceWithUnionIntersectTypes::class);
×
147

148
        $rootDefinitionKey = $resultSchema->getRootDefinitionKey();
×
149
        $definitions = $resultSchema->getDefinitions();
×
150

151
        $this->assertSame((new \ReflectionClass(NotAResourceWithUnionIntersectTypes::class))->getShortName(), $rootDefinitionKey);
×
152
        // @noRector
153
        $this->assertTrue(isset($definitions[$rootDefinitionKey]));
×
154
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]);
×
155
        $this->assertSame('object', $definitions[$rootDefinitionKey]['type']);
×
156
        $this->assertArrayNotHasKey('additionalProperties', $definitions[$rootDefinitionKey]);
×
157
        $this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
×
158

159
        $this->assertArrayHasKey('ignoredProperty', $definitions[$rootDefinitionKey]['properties']);
×
160
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['ignoredProperty']);
×
161
        $this->assertSame(['string', 'null'], $definitions[$rootDefinitionKey]['properties']['ignoredProperty']['type']);
×
162

163
        $this->assertArrayHasKey('unionType', $definitions[$rootDefinitionKey]['properties']);
×
164
        $this->assertArrayHasKey('oneOf', $definitions[$rootDefinitionKey]['properties']['unionType']);
×
165
        $this->assertCount(2, $definitions[$rootDefinitionKey]['properties']['unionType']['oneOf']);
×
166
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['unionType']['oneOf'][0]);
×
167
        $this->assertSame(['string', 'null'], $definitions[$rootDefinitionKey]['properties']['unionType']['oneOf'][0]['type']);
×
168
        $this->assertSame(['integer', 'null'], $definitions[$rootDefinitionKey]['properties']['unionType']['oneOf'][1]['type']);
×
169

170
        $this->assertArrayHasKey('intersectType', $definitions[$rootDefinitionKey]['properties']);
×
171
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['intersectType']);
×
172
        $this->assertSame('object', $definitions[$rootDefinitionKey]['properties']['intersectType']['type']);
×
173
    }
174

175
    public function testBuildSchemaWithSerializerGroups(): void
176
    {
177
        $shortName = (new \ReflectionClass(OverriddenOperationDummy::class))->getShortName();
×
178
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
179
        $operation = (new Put())->withName('put')->withNormalizationContext([
×
180
            'groups' => 'overridden_operation_dummy_put',
×
181
            AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
×
182
        ])->withShortName($shortName)->withValidationContext(['groups' => ['validation_groups_dummy_put']]);
×
183
        $resourceMetadataFactoryProphecy->create(OverriddenOperationDummy::class)
×
184
            ->willReturn(
×
185
                new ResourceMetadataCollection(OverriddenOperationDummy::class, [
×
186
                    (new ApiResource())->withOperations(new Operations(['put' => $operation])),
×
187
                ])
×
188
            );
×
189

190
        $serializerGroup = 'custom_operation_dummy';
×
191

192
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
193
        $propertyNameCollectionFactoryProphecy->create(OverriddenOperationDummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['alias', 'description', 'genderType']));
×
194

195
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
196
        $propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'alias', Argument::type('array'))->willReturn(
×
197
            (new ApiProperty())
×
198
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])
×
199
                ->withReadable(true)
×
200
                ->withSchema(['type' => 'string'])
×
201
        );
×
202
        $propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'description', Argument::type('array'))->willReturn(
×
203
            (new ApiProperty())
×
204
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])
×
205
                ->withReadable(true)
×
206
                ->withSchema(['type' => 'string'])
×
207
        );
×
208
        $propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'genderType', Argument::type('array'))->willReturn(
×
209
            (new ApiProperty())
×
210
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, GenderTypeEnum::class)])
×
211
                ->withReadable(true)
×
212
                ->withDefault(GenderTypeEnum::MALE)
×
213
                ->withSchema(['type' => 'object'])
×
214
        );
×
215

216
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
217
        $resourceClassResolverProphecy->isResourceClass(OverriddenOperationDummy::class)->willReturn(true);
×
218
        $resourceClassResolverProphecy->isResourceClass(GenderTypeEnum::class)->willReturn(true);
×
219

220
        $schemaFactory = new SchemaFactory(null, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal());
×
221
        $resultSchema = $schemaFactory->buildSchema(OverriddenOperationDummy::class, 'json', Schema::TYPE_OUTPUT, null, null, ['groups' => $serializerGroup, AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]);
×
222

223
        $rootDefinitionKey = $resultSchema->getRootDefinitionKey();
×
224
        $definitions = $resultSchema->getDefinitions();
×
225

226
        $this->assertSame((new \ReflectionClass(OverriddenOperationDummy::class))->getShortName().'-'.$serializerGroup, $rootDefinitionKey);
×
227
        // @noRector
228
        $this->assertTrue(isset($definitions[$rootDefinitionKey]));
×
229
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]);
×
230
        $this->assertSame('object', $definitions[$rootDefinitionKey]['type']);
×
231
        $this->assertFalse($definitions[$rootDefinitionKey]['additionalProperties']);
×
232
        $this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
×
233
        $this->assertArrayHasKey('alias', $definitions[$rootDefinitionKey]['properties']);
×
234
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['alias']);
×
235
        $this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['alias']['type']);
×
236
        $this->assertArrayHasKey('description', $definitions[$rootDefinitionKey]['properties']);
×
237
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['description']);
×
238
        $this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['description']['type']);
×
239
        $this->assertArrayHasKey('genderType', $definitions[$rootDefinitionKey]['properties']);
×
240
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
241
        $this->assertArrayNotHasKey('default', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
242
        $this->assertArrayNotHasKey('example', $definitions[$rootDefinitionKey]['properties']['genderType']);
×
243
        $this->assertSame('object', $definitions[$rootDefinitionKey]['properties']['genderType']['type']);
×
244
    }
245

246
    public function testBuildSchemaForAssociativeArray(): void
247
    {
248
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
249

250
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
251
        $propertyNameCollectionFactoryProphecy->create(NotAResource::class, Argument::cetera())->willReturn(new PropertyNameCollection(['foo', 'bar']));
×
252

253
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
254
        $propertyMetadataFactoryProphecy->create(NotAResource::class, 'foo', Argument::cetera())->willReturn(
×
255
            (new ApiProperty())
×
256
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))])
×
257
                ->withReadable(true)
×
258
                ->withSchema(['type' => 'array', 'items' => ['string', 'int']])
×
259
        );
×
260
        $propertyMetadataFactoryProphecy->create(NotAResource::class, 'bar', Argument::cetera())->willReturn(
×
261
            (new ApiProperty())
×
262
                ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_STRING))])
×
263
                ->withReadable(true)
×
264
                ->withSchema(['type' => 'object', 'additionalProperties' => 'string'])
×
265
        );
×
266

267
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
268
        $resourceClassResolverProphecy->isResourceClass(NotAResource::class)->willReturn(false);
×
269

270
        $schemaFactory = new SchemaFactory(null, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal());
×
271
        $resultSchema = $schemaFactory->buildSchema(NotAResource::class);
×
272

273
        $rootDefinitionKey = $resultSchema->getRootDefinitionKey();
×
274
        $definitions = $resultSchema->getDefinitions();
×
275

276
        $this->assertSame((new \ReflectionClass(NotAResource::class))->getShortName(), $rootDefinitionKey);
×
277
        // @noRector
278
        $this->assertTrue(isset($definitions[$rootDefinitionKey]));
×
279
        $this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
×
280
        $this->assertArrayHasKey('foo', $definitions[$rootDefinitionKey]['properties']);
×
281
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['foo']);
×
282
        $this->assertArrayNotHasKey('additionalProperties', $definitions[$rootDefinitionKey]['properties']['foo']);
×
283
        $this->assertSame('array', $definitions[$rootDefinitionKey]['properties']['foo']['type']);
×
284
        $this->assertArrayHasKey('bar', $definitions[$rootDefinitionKey]['properties']);
×
285
        $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['bar']);
×
286
        $this->assertArrayHasKey('additionalProperties', $definitions[$rootDefinitionKey]['properties']['bar']);
×
287
        $this->assertSame('object', $definitions[$rootDefinitionKey]['properties']['bar']['type']);
×
288
        $this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['bar']['additionalProperties']);
×
289
    }
290
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc