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

api-platform / core / 7275126587

20 Dec 2023 12:09PM UTC coverage: 37.298% (+0.04%) from 37.262%
7275126587

push

github

soyuka
Merge 3.2

24 of 134 new or added lines in 24 files covered. (17.91%)

4 existing lines in 2 files now uncovered.

10338 of 27717 relevant lines covered (37.3%)

28.58 hits per line

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

0.0
/src/JsonSchema/Tests/TypeFactoryTest.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\SchemaFactoryInterface;
18
use ApiPlatform\JsonSchema\Tests\Fixtures\ApiResource\Dummy;
19
use ApiPlatform\JsonSchema\Tests\Fixtures\Enum\GamePlayMode;
20
use ApiPlatform\JsonSchema\Tests\Fixtures\Enum\GenderTypeEnum;
21
use ApiPlatform\JsonSchema\TypeFactory;
22
use ApiPlatform\Metadata\ResourceClassResolverInterface;
23
use PHPUnit\Framework\TestCase;
24
use Prophecy\Argument;
25
use Prophecy\PhpUnit\ProphecyTrait;
26
use Symfony\Component\PropertyInfo\Type;
27

28
class TypeFactoryTest extends TestCase
29
{
30
    use ProphecyTrait;
31

32
    /**
33
     * @dataProvider typeProvider
34
     */
35
    public function testGetType(array $schema, Type $type): void
36
    {
37
        $resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class);
×
38
        $resourceClassResolver->isResourceClass(GenderTypeEnum::class)->willReturn(false);
×
39
        $resourceClassResolver->isResourceClass(Argument::type('string'))->willReturn(true);
×
40
        $typeFactory = new TypeFactory($resourceClassResolver->reveal());
×
41
        $this->assertEquals($schema, $typeFactory->getType($type, 'json', null, null, new Schema(Schema::VERSION_OPENAPI)));
×
42
    }
43

44
    public static function typeProvider(): iterable
45
    {
46
        yield [['type' => 'integer'], new Type(Type::BUILTIN_TYPE_INT)];
×
47
        yield [['nullable' => true, 'type' => 'integer'], new Type(Type::BUILTIN_TYPE_INT, true)];
×
48
        yield [['type' => 'number'], new Type(Type::BUILTIN_TYPE_FLOAT)];
×
49
        yield [['nullable' => true, 'type' => 'number'], new Type(Type::BUILTIN_TYPE_FLOAT, true)];
×
50
        yield [['type' => 'boolean'], new Type(Type::BUILTIN_TYPE_BOOL)];
×
51
        yield [['nullable' => true, 'type' => 'boolean'], new Type(Type::BUILTIN_TYPE_BOOL, true)];
×
52
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_STRING)];
×
53
        yield [['nullable' => true, 'type' => 'string'], new Type(Type::BUILTIN_TYPE_STRING, true)];
×
54
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_OBJECT)];
×
55
        yield [['nullable' => true, 'type' => 'string'], new Type(Type::BUILTIN_TYPE_OBJECT, true)];
×
56
        yield [['type' => 'string', 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTimeImmutable::class)];
×
57
        yield [['nullable' => true, 'type' => 'string', 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTimeImmutable::class)];
×
58
        yield [['type' => 'string', 'format' => 'duration'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateInterval::class)];
×
59
        yield [['type' => 'string', 'format' => 'binary'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \SplFileInfo::class)];
×
NEW
60
        yield [['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)];
×
NEW
61
        yield [['nullable' => true, 'type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)];
×
62
        yield ['enum' => ['type' => 'string', 'enum' => ['male', 'female']], new Type(Type::BUILTIN_TYPE_OBJECT, false, GenderTypeEnum::class)];
×
63
        yield ['nullable enum' => ['type' => 'string', 'enum' => ['male', 'female', null], 'nullable' => true], new Type(Type::BUILTIN_TYPE_OBJECT, true, GenderTypeEnum::class)];
×
NEW
64
        yield ['enum resource' => ['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, GamePlayMode::class)];
×
NEW
65
        yield ['nullable enum resource' => ['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/', 'nullable' => true], new Type(Type::BUILTIN_TYPE_OBJECT, true, GamePlayMode::class)];
×
66
        yield [['type' => 'array', 'items' => ['type' => 'string']], new Type(Type::BUILTIN_TYPE_STRING, false, null, true)];
×
67
        yield 'array can be itself nullable' => [
×
68
            ['nullable' => true, 'type' => 'array', 'items' => ['type' => 'string']],
×
69
            new Type(Type::BUILTIN_TYPE_STRING, true, null, true),
×
70
        ];
×
71

72
        yield 'array can contain nullable values' => [
×
73
            [
×
74
                'type' => 'array',
×
75
                'items' => [
×
76
                    'nullable' => true,
×
77
                    'type' => 'string',
×
78
                ],
×
79
            ],
×
80
            new Type(Type::BUILTIN_TYPE_STRING, false, null, true, null, new Type(Type::BUILTIN_TYPE_STRING, true, null, false)),
×
81
        ];
×
82

83
        yield 'map with string keys becomes an object' => [
×
84
            ['type' => 'object', 'additionalProperties' => ['type' => 'string']],
×
85
            new Type(
×
86
                Type::BUILTIN_TYPE_STRING,
×
87
                false,
×
88
                null,
×
89
                true,
×
90
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
91
            ),
×
92
        ];
×
93

94
        yield 'nullable map with string keys becomes a nullable object' => [
×
95
            [
×
96
                'nullable' => true,
×
97
                'type' => 'object',
×
98
                'additionalProperties' => ['type' => 'string'],
×
99
            ],
×
100
            new Type(
×
101
                Type::BUILTIN_TYPE_STRING,
×
102
                true,
×
103
                null,
×
104
                true,
×
105
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
106
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
107
            ),
×
108
        ];
×
109

110
        yield 'map value type will be considered' => [
×
111
            ['type' => 'object', 'additionalProperties' => ['type' => 'integer']],
×
112
            new Type(
×
113
                Type::BUILTIN_TYPE_ARRAY,
×
114
                false,
×
115
                null,
×
116
                true,
×
117
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
118
                new Type(Type::BUILTIN_TYPE_INT, false, null, false)
×
119
            ),
×
120
        ];
×
121

122
        yield 'map value type nullability will be considered' => [
×
123
            [
×
124
                'type' => 'object',
×
125
                'additionalProperties' => [
×
126
                    'nullable' => true,
×
127
                    'type' => 'integer',
×
128
                ],
×
129
            ],
×
130
            new Type(
×
131
                Type::BUILTIN_TYPE_ARRAY,
×
132
                false,
×
133
                null,
×
134
                true,
×
135
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
136
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
137
            ),
×
138
        ];
×
139

140
        yield 'nullable map can contain nullable values' => [
×
141
            [
×
142
                'nullable' => true,
×
143
                'type' => 'object',
×
144
                'additionalProperties' => [
×
145
                    'nullable' => true,
×
146
                    'type' => 'integer',
×
147
                ],
×
148
            ],
×
149
            new Type(
×
150
                Type::BUILTIN_TYPE_ARRAY,
×
151
                true,
×
152
                null,
×
153
                true,
×
154
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
155
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
156
            ),
×
157
        ];
×
158
    }
159

160
    /**
161
     * @dataProvider jsonSchemaTypeProvider
162
     */
163
    public function testGetTypeWithJsonSchemaSyntax(array $schema, Type $type): void
164
    {
165
        $resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class);
×
166
        $resourceClassResolver->isResourceClass(GenderTypeEnum::class)->willReturn(false);
×
167
        $resourceClassResolver->isResourceClass(Argument::type('string'))->willReturn(true);
×
168
        $typeFactory = new TypeFactory($resourceClassResolver->reveal());
×
169
        $this->assertEquals($schema, $typeFactory->getType($type, 'json', null, null, new Schema(Schema::VERSION_JSON_SCHEMA)));
×
170
    }
171

172
    public static function jsonSchemaTypeProvider(): iterable
173
    {
174
        yield [['type' => 'integer'], new Type(Type::BUILTIN_TYPE_INT)];
×
175
        yield [['type' => ['integer', 'null']], new Type(Type::BUILTIN_TYPE_INT, true)];
×
176
        yield [['type' => 'number'], new Type(Type::BUILTIN_TYPE_FLOAT)];
×
177
        yield [['type' => ['number', 'null']], new Type(Type::BUILTIN_TYPE_FLOAT, true)];
×
178
        yield [['type' => 'boolean'], new Type(Type::BUILTIN_TYPE_BOOL)];
×
179
        yield [['type' => ['boolean', 'null']], new Type(Type::BUILTIN_TYPE_BOOL, true)];
×
180
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_STRING)];
×
181
        yield [['type' => ['string', 'null']], new Type(Type::BUILTIN_TYPE_STRING, true)];
×
182
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_OBJECT)];
×
183
        yield [['type' => ['string', 'null']], new Type(Type::BUILTIN_TYPE_OBJECT, true)];
×
184
        yield [['type' => 'string', 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTimeImmutable::class)];
×
185
        yield [['type' => ['string', 'null'], 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTimeImmutable::class)];
×
186
        yield [['type' => 'string', 'format' => 'duration'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateInterval::class)];
×
187
        yield [['type' => 'string', 'format' => 'binary'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \SplFileInfo::class)];
×
NEW
188
        yield [['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)];
×
NEW
189
        yield [['type' => ['string', 'null'], 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)];
×
190
        yield ['enum' => ['type' => 'string', 'enum' => ['male', 'female']], new Type(Type::BUILTIN_TYPE_OBJECT, false, GenderTypeEnum::class)];
×
191
        yield ['nullable enum' => ['type' => ['string', 'null'], 'enum' => ['male', 'female', null]], new Type(Type::BUILTIN_TYPE_OBJECT, true, GenderTypeEnum::class)];
×
NEW
192
        yield ['enum resource' => ['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, GamePlayMode::class)];
×
NEW
193
        yield ['nullable enum resource' => ['type' => ['string', 'null'], 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, true, GamePlayMode::class)];
×
194
        yield [['type' => 'array', 'items' => ['type' => 'string']], new Type(Type::BUILTIN_TYPE_STRING, false, null, true)];
×
195
        yield 'array can be itself nullable' => [
×
196
            ['type' => ['array', 'null'], 'items' => ['type' => 'string']],
×
197
            new Type(Type::BUILTIN_TYPE_STRING, true, null, true),
×
198
        ];
×
199

200
        yield 'array can contain nullable values' => [
×
201
            [
×
202
                'type' => 'array',
×
203
                'items' => [
×
204
                    'type' => ['string', 'null'],
×
205
                ],
×
206
            ],
×
207
            new Type(Type::BUILTIN_TYPE_STRING, false, null, true, null, new Type(Type::BUILTIN_TYPE_STRING, true, null, false)),
×
208
        ];
×
209

210
        yield 'map with string keys becomes an object' => [
×
211
            ['type' => 'object', 'additionalProperties' => ['type' => 'string']],
×
212
            new Type(
×
213
                Type::BUILTIN_TYPE_STRING,
×
214
                false,
×
215
                null,
×
216
                true,
×
217
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
218
            ),
×
219
        ];
×
220

221
        yield 'nullable map with string keys becomes a nullable object' => [
×
222
            [
×
223
                'type' => ['object', 'null'],
×
224
                'additionalProperties' => ['type' => 'string'],
×
225
            ],
×
226
            new Type(
×
227
                Type::BUILTIN_TYPE_STRING,
×
228
                true,
×
229
                null,
×
230
                true,
×
231
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
232
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
233
            ),
×
234
        ];
×
235

236
        yield 'map value type will be considered' => [
×
237
            ['type' => 'object', 'additionalProperties' => ['type' => 'integer']],
×
238
            new Type(
×
239
                Type::BUILTIN_TYPE_ARRAY,
×
240
                false,
×
241
                null,
×
242
                true,
×
243
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
244
                new Type(Type::BUILTIN_TYPE_INT, false, null, false)
×
245
            ),
×
246
        ];
×
247

248
        yield 'map value type nullability will be considered' => [
×
249
            [
×
250
                'type' => 'object',
×
251
                'additionalProperties' => [
×
252
                    'type' => ['integer', 'null'],
×
253
                ],
×
254
            ],
×
255
            new Type(
×
256
                Type::BUILTIN_TYPE_ARRAY,
×
257
                false,
×
258
                null,
×
259
                true,
×
260
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
261
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
262
            ),
×
263
        ];
×
264

265
        yield 'nullable map can contain nullable values' => [
×
266
            [
×
267
                'type' => ['object', 'null'],
×
268
                'additionalProperties' => [
×
269
                    'type' => ['integer', 'null'],
×
270
                ],
×
271
            ],
×
272
            new Type(
×
273
                Type::BUILTIN_TYPE_ARRAY,
×
274
                true,
×
275
                null,
×
276
                true,
×
277
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
278
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
279
            ),
×
280
        ];
×
281
    }
282

283
    /** @dataProvider openAPIV2TypeProvider */
284
    public function testGetTypeWithOpenAPIV2Syntax(array $schema, Type $type): void
285
    {
286
        $resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class);
×
287
        $resourceClassResolver->isResourceClass(GenderTypeEnum::class)->willReturn(false);
×
288
        $resourceClassResolver->isResourceClass(Argument::type('string'))->willReturn(true);
×
289
        $typeFactory = new TypeFactory($resourceClassResolver->reveal());
×
290
        $this->assertEquals($schema, $typeFactory->getType($type, 'json', null, null, new Schema(Schema::VERSION_SWAGGER)));
×
291
    }
292

293
    public static function openAPIV2TypeProvider(): iterable
294
    {
295
        yield [['type' => 'integer'], new Type(Type::BUILTIN_TYPE_INT)];
×
296
        yield [['type' => 'integer'], new Type(Type::BUILTIN_TYPE_INT, true)];
×
297
        yield [['type' => 'number'], new Type(Type::BUILTIN_TYPE_FLOAT)];
×
298
        yield [['type' => 'number'], new Type(Type::BUILTIN_TYPE_FLOAT, true)];
×
299
        yield [['type' => 'boolean'], new Type(Type::BUILTIN_TYPE_BOOL)];
×
300
        yield [['type' => 'boolean'], new Type(Type::BUILTIN_TYPE_BOOL, true)];
×
301
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_STRING)];
×
302
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_STRING, true)];
×
303
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_OBJECT)];
×
304
        yield [['type' => 'string'], new Type(Type::BUILTIN_TYPE_OBJECT, true)];
×
305
        yield [['type' => 'string', 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTimeImmutable::class)];
×
306
        yield [['type' => 'string', 'format' => 'date-time'], new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTimeImmutable::class)];
×
307
        yield [['type' => 'string', 'format' => 'duration'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateInterval::class)];
×
308
        yield [['type' => 'string', 'format' => 'binary'], new Type(Type::BUILTIN_TYPE_OBJECT, false, \SplFileInfo::class)];
×
NEW
309
        yield [['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)];
×
NEW
310
        yield [['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)];
×
311
        yield ['enum' => ['type' => 'string', 'enum' => ['male', 'female']], new Type(Type::BUILTIN_TYPE_OBJECT, false, GenderTypeEnum::class)];
×
312
        yield ['nullable enum' => ['type' => 'string', 'enum' => ['male', 'female', null]], new Type(Type::BUILTIN_TYPE_OBJECT, true, GenderTypeEnum::class)];
×
NEW
313
        yield ['enum resource' => ['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, false, GamePlayMode::class)];
×
NEW
314
        yield ['nullable enum resource' => ['type' => 'string', 'format' => 'iri-reference', 'example' => 'https://example.com/'], new Type(Type::BUILTIN_TYPE_OBJECT, true, GamePlayMode::class)];
×
315
        yield [['type' => 'array', 'items' => ['type' => 'string']], new Type(Type::BUILTIN_TYPE_STRING, false, null, true)];
×
316
        yield 'array can be itself nullable, but ignored in OpenAPI V2' => [
×
317
            ['type' => 'array', 'items' => ['type' => 'string']],
×
318
            new Type(Type::BUILTIN_TYPE_STRING, true, null, true),
×
319
        ];
×
320

321
        yield 'array can contain nullable values, but ignored in OpenAPI V2' => [
×
322
            [
×
323
                'type' => 'array',
×
324
                'items' => ['type' => 'string'],
×
325
            ],
×
326
            new Type(Type::BUILTIN_TYPE_STRING, false, null, true, null, new Type(Type::BUILTIN_TYPE_STRING, true, null, false)),
×
327
        ];
×
328

329
        yield 'map with string keys becomes an object' => [
×
330
            ['type' => 'object', 'additionalProperties' => ['type' => 'string']],
×
331
            new Type(
×
332
                Type::BUILTIN_TYPE_STRING,
×
333
                false,
×
334
                null,
×
335
                true,
×
336
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
337
            ),
×
338
        ];
×
339

340
        yield 'nullable map with string keys becomes a nullable object, but ignored in OpenAPI V2' => [
×
341
            [
×
342
                'type' => 'object',
×
343
                'additionalProperties' => ['type' => 'string'],
×
344
            ],
×
345
            new Type(
×
346
                Type::BUILTIN_TYPE_STRING,
×
347
                true,
×
348
                null,
×
349
                true,
×
350
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
351
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false)
×
352
            ),
×
353
        ];
×
354

355
        yield 'map value type will be considered' => [
×
356
            ['type' => 'object', 'additionalProperties' => ['type' => 'integer']],
×
357
            new Type(
×
358
                Type::BUILTIN_TYPE_ARRAY,
×
359
                false,
×
360
                null,
×
361
                true,
×
362
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
363
                new Type(Type::BUILTIN_TYPE_INT, false, null, false)
×
364
            ),
×
365
        ];
×
366

367
        yield 'map value type nullability will be considered, but ignored in OpenAPI V2' => [
×
368
            [
×
369
                'type' => 'object',
×
370
                'additionalProperties' => ['type' => 'integer'],
×
371
            ],
×
372
            new Type(
×
373
                Type::BUILTIN_TYPE_ARRAY,
×
374
                false,
×
375
                null,
×
376
                true,
×
377
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
378
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
379
            ),
×
380
        ];
×
381

382
        yield 'nullable map can contain nullable values, but ignored in OpenAPI V2' => [
×
383
            [
×
384
                'type' => 'object',
×
385
                'additionalProperties' => ['type' => 'integer'],
×
386
            ],
×
387
            new Type(
×
388
                Type::BUILTIN_TYPE_ARRAY,
×
389
                true,
×
390
                null,
×
391
                true,
×
392
                new Type(Type::BUILTIN_TYPE_STRING, false, null, false),
×
393
                new Type(Type::BUILTIN_TYPE_INT, true, null, false)
×
394
            ),
×
395
        ];
×
396
    }
397

398
    public function testGetClassType(): void
399
    {
400
        $schemaFactoryProphecy = $this->prophesize(SchemaFactoryInterface::class);
×
401

402
        $schemaFactoryProphecy->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, null, Argument::type(Schema::class), Argument::type('array'), false)->will(function (array $args) {
×
403
            $args[4]['$ref'] = 'ref';
×
404

405
            return $args[4];
×
406
        });
×
407

408
        $typeFactory = new TypeFactory();
×
409
        $typeFactory->setSchemaFactory($schemaFactoryProphecy->reveal());
×
410

411
        $this->assertEquals(['$ref' => 'ref'], $typeFactory->getType(new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class), 'jsonld', true, ['foo' => 'bar'], new Schema()));
×
412
    }
413

414
    /** @dataProvider classTypeWithNullabilityDataProvider */
415
    public function testGetClassTypeWithNullability(array $expected, callable $schemaFactoryFactory, Schema $schema): void
416
    {
417
        $typeFactory = new TypeFactory();
×
418
        $typeFactory->setSchemaFactory($schemaFactoryFactory($this));
×
419

420
        self::assertEquals(
×
421
            $expected,
×
422
            $typeFactory->getType(new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class), 'jsonld', true, ['foo' => 'bar'], $schema)
×
423
        );
×
424
    }
425

426
    public static function classTypeWithNullabilityDataProvider(): iterable
427
    {
428
        $schema = new Schema();
×
429
        $schemaFactoryFactory = fn (self $that): SchemaFactoryInterface => $that->createSchemaFactoryMock($schema);
×
430

431
        yield 'JSON-Schema version' => [
×
432
            [
×
433
                'anyOf' => [
×
434
                    ['$ref' => 'the-ref-name'],
×
435
                    ['type' => 'null'],
×
436
                ],
×
437
            ],
×
438
            $schemaFactoryFactory,
×
439
            $schema,
×
440
        ];
×
441

442
        $schema = new Schema(Schema::VERSION_OPENAPI);
×
443
        $schemaFactoryFactory = fn (self $that): SchemaFactoryInterface => $that->createSchemaFactoryMock($schema);
×
444

445
        yield 'OpenAPI < 3.1 version' => [
×
446
            [
×
447
                'anyOf' => [
×
448
                    ['$ref' => 'the-ref-name'],
×
449
                ],
×
450
                'nullable' => true,
×
451
            ],
×
452
            $schemaFactoryFactory,
×
453
            $schema,
×
454
        ];
×
455
    }
456

457
    private function createSchemaFactoryMock(Schema $schema): SchemaFactoryInterface
458
    {
459
        $schemaFactory = $this->createMock(SchemaFactoryInterface::class);
×
460

461
        $schemaFactory
×
462
            ->method('buildSchema')
×
463
            ->willReturnCallback(static function () use ($schema): Schema {
×
464
                $schema['$ref'] = 'the-ref-name';
×
465
                $schema['description'] = 'more stuff here';
×
466

467
                return $schema;
×
468
            });
×
469

470
        return $schemaFactory;
×
471
    }
472
}
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

© 2025 Coveralls, Inc