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

api-platform / core / 10019490364

20 Jul 2024 10:21AM UTC coverage: 7.847% (-0.009%) from 7.856%
10019490364

push

github

soyuka
Merge 3.3

3 of 27 new or added lines in 5 files covered. (11.11%)

6 existing lines in 2 files now uncovered.

12688 of 161690 relevant lines covered (7.85%)

26.88 hits per line

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

0.0
/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.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\Tests\JsonSchema\Command;
15

16
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Animal;
17
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\AnimalObservation;
18
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BackedEnumIntegerResource;
19
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BackedEnumStringResource;
20
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5501\BrokenDocs;
21
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6299\Issue6299;
22
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6317\Issue6317;
23
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ResourceWithEnumProperty;
24
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Species;
25
use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DocumentDummy;
26
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer;
27
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
28
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5793\BagOfTests;
29
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5998\Issue5998Product;
30
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5998\ProductCode;
31
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5998\SaveProduct;
32
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6212\Nest;
33
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question;
34
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
35
use ApiPlatform\Tests\SetupClassResourcesTrait;
36
use Symfony\Bundle\FrameworkBundle\Console\Application;
37
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
38
use Symfony\Component\Console\Tester\ApplicationTester;
39

40
/**
41
 * @author Jacques Lefebvre <jacques@les-tilleuls.coop>
42
 */
43
class JsonSchemaGenerateCommandTest extends KernelTestCase
44
{
45
    use SetupClassResourcesTrait;
46
    private ApplicationTester $tester;
47
    private string $entityClass;
48

49
    protected function setUp(): void
50
    {
51
        $kernel = self::bootKernel();
×
52

53
        $application = new Application(static::$kernel);
×
54
        $application->setCatchExceptions(true);
×
55
        $application->setAutoExit(false);
×
56

57
        $this->entityClass = 'mongodb' === $kernel->getEnvironment() ? DocumentDummy::class : Dummy::class;
×
58
        $this->tester = new ApplicationTester($application);
×
59
    }
60

61
    /**
62
     * @return class-string[]
63
     */
64
    public static function getResources(): array
65
    {
66
        return [
×
67
            Dummy::class,
×
68
            BrokenDocs::class,
×
69
            Nest::class,
×
70
            BagOfTests::class,
×
71
            ResourceWithEnumProperty::class,
×
72
            Issue6299::class,
×
73
            RelatedDummy::class,
×
74
            Question::class,
×
75
            Answer::class,
×
76
            AnimalObservation::class,
×
77
            Animal::class,
×
78
            Species::class,
×
79
            Issue6317::class,
×
80
            ProductCode::class,
×
81
            Issue5998Product::class,
×
82
            BackedEnumIntegerResource::class,
×
83
            BackedEnumStringResource::class,
×
84
        ];
×
85
    }
86

87
    public function testExecuteWithoutOption(): void
88
    {
89
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass]);
×
90

91
        $this->assertJson($this->tester->getDisplay());
×
92
    }
93

94
    public function testExecuteWithItemOperationGet(): void
95
    {
96
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies/{id}{._format}_get', '--type' => 'output']);
×
97

98
        $this->assertJson($this->tester->getDisplay());
×
99
    }
100

101
    public function testExecuteWithCollectionOperationGet(): void
102
    {
103
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies{._format}_get_collection', '--type' => 'output']);
×
104

105
        $this->assertJson($this->tester->getDisplay());
×
106
    }
107

108
    public function testExecuteWithJsonldFormatOption(): void
109
    {
110
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies{._format}_post', '--format' => 'jsonld', '--type' => 'output']);
×
111
        $result = $this->tester->getDisplay();
×
112

113
        $this->assertStringContainsString('@id', $result);
×
114
        $this->assertStringContainsString('@context', $result);
×
115
        $this->assertStringContainsString('@type', $result);
×
116
    }
117

118
    public function testExecuteWithJsonldTypeInput(): void
119
    {
120
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies{._format}_post', '--format' => 'jsonld', '--type' => 'input']);
×
121
        $result = $this->tester->getDisplay();
×
122

NEW
123
        $this->assertStringNotContainsString('@id', $result);
×
NEW
124
        $this->assertStringNotContainsString('@context', $result);
×
NEW
125
        $this->assertStringNotContainsString('@type', $result);
×
126
    }
127

128
    /**
129
     * Test issue #5501, the locations relation inside BrokenDocs is a Resource (named Related) but its only operation is a NotExposed.
130
     * Still, serializer groups are set, and therefore it is a "readableLink" so we actually want to compute the schema, even if it's not accessible
131
     * directly, it is accessible through that relation.
132
     */
133
    public function testExecuteWithNotExposedResourceAndReadableLink(): void
134
    {
135
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => BrokenDocs::class, '--type' => 'output']);
×
136
        $result = $this->tester->getDisplay();
×
137

138
        $this->assertStringContainsString('Related.jsonld-location.read_collection', $result);
×
139
    }
140

141
    /**
142
     * When serializer groups are present the Schema should have an embed resource. #5470 breaks array references when serializer groups are present.
143
     */
144
    #[\PHPUnit\Framework\Attributes\Group('orm')]
145
    public function testArraySchemaWithReference(): void
146
    {
147
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => BagOfTests::class, '--type' => 'input']);
×
148
        $result = $this->tester->getDisplay();
×
149
        $json = json_decode($result, associative: true);
×
150

NEW
151
        $this->assertEquals($json['definitions']['BagOfTests.jsonld-write']['properties']['tests'], [
×
152
            'type' => 'string',
×
153
            'foo' => 'bar',
×
154
        ]);
×
155

NEW
156
        $this->assertEquals($json['definitions']['BagOfTests.jsonld-write']['properties']['nonResourceTests'], [
×
157
            'type' => 'array',
×
158
            'items' => [
×
NEW
159
                '$ref' => '#/definitions/NonResourceTestEntity.jsonld-write',
×
160
            ],
×
161
        ]);
×
162

NEW
163
        $this->assertEquals($json['definitions']['BagOfTests.jsonld-write']['properties']['description'], [
×
164
            'maxLength' => 255,
×
165
        ]);
×
166

NEW
167
        $this->assertEquals($json['definitions']['BagOfTests.jsonld-write']['properties']['type'], [
×
NEW
168
            '$ref' => '#/definitions/TestEntity.jsonld-write',
×
UNCOV
169
        ]);
×
170
    }
171

172
    public function testArraySchemaWithMultipleUnionTypesJsonLd(): void
173
    {
174
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Nest::class, '--type' => 'output', '--format' => 'jsonld']);
×
175
        $result = $this->tester->getDisplay();
×
176
        $json = json_decode($result, associative: true);
×
177

NEW
178
        $this->assertEquals($json['definitions']['Nest.jsonld']['properties']['owner']['anyOf'], [
×
NEW
179
            ['$ref' => '#/definitions/Wren.jsonld'],
×
NEW
180
            ['$ref' => '#/definitions/Robin.jsonld'],
×
181
            ['type' => 'null'],
×
182
        ]);
×
183

NEW
184
        $this->assertArrayHasKey('Wren.jsonld', $json['definitions']);
×
NEW
185
        $this->assertArrayHasKey('Robin.jsonld', $json['definitions']);
×
186
    }
187

188
    public function testArraySchemaWithMultipleUnionTypesJsonApi(): void
189
    {
190
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Nest::class, '--type' => 'output', '--format' => 'jsonapi']);
×
191
        $result = $this->tester->getDisplay();
×
192
        $json = json_decode($result, associative: true);
×
193

194
        $this->assertEquals($json['definitions']['Nest.jsonapi']['properties']['data']['properties']['attributes']['properties']['owner']['anyOf'], [
×
195
            ['$ref' => '#/definitions/Wren.jsonapi'],
×
196
            ['$ref' => '#/definitions/Robin.jsonapi'],
×
197
            ['type' => 'null'],
×
198
        ]);
×
199

200
        $this->assertArrayHasKey('Wren.jsonapi', $json['definitions']);
×
201
        $this->assertArrayHasKey('Robin.jsonapi', $json['definitions']);
×
202
    }
203

204
    public function testArraySchemaWithMultipleUnionTypesJsonHal(): void
205
    {
206
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Nest::class, '--type' => 'output', '--format' => 'jsonhal']);
×
207
        $result = $this->tester->getDisplay();
×
208
        $json = json_decode($result, associative: true);
×
209

210
        $this->assertEquals($json['definitions']['Nest.jsonhal']['properties']['owner']['anyOf'], [
×
211
            ['$ref' => '#/definitions/Wren.jsonhal'],
×
212
            ['$ref' => '#/definitions/Robin.jsonhal'],
×
213
            ['type' => 'null'],
×
214
        ]);
×
215

216
        $this->assertArrayHasKey('Wren.jsonhal', $json['definitions']);
×
217
        $this->assertArrayHasKey('Robin.jsonhal', $json['definitions']);
×
218
    }
219

220
    /**
221
     * Test issue #5998.
222
     */
223
    public function testWritableNonResourceRef(): void
224
    {
225
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => SaveProduct::class, '--type' => 'input']);
×
226
        $result = $this->tester->getDisplay();
×
227
        $json = json_decode($result, associative: true);
×
228

NEW
229
        $this->assertEquals($json['definitions']['SaveProduct.jsonld']['properties']['codes']['items']['$ref'], '#/definitions/ProductCode.jsonld');
×
230
    }
231

232
    /**
233
     * Test issue #6299.
234
     */
235
    public function testOpenApiResourceRefIsNotOverwritten(): void
236
    {
237
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Issue6299::class, '--type' => 'output']);
×
238
        $result = $this->tester->getDisplay();
×
239
        $json = json_decode($result, associative: true);
×
240

NEW
241
        $this->assertEquals('#/definitions/DummyFriend', $json['definitions']['Issue6299.Issue6299OutputDto.jsonld']['properties']['itemDto']['$ref']);
×
NEW
242
        $this->assertEquals('#/definitions/DummyDate', $json['definitions']['Issue6299.Issue6299OutputDto.jsonld']['properties']['collectionDto']['items']['$ref']);
×
243
    }
244

245
    /**
246
     * Test related Schema keeps json-ld context.
247
     */
248
    #[\PHPUnit\Framework\Attributes\Group('orm')]
249
    public function testSubSchemaJsonLd(): void
250
    {
251
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => RelatedDummy::class, '--type' => 'output', '--format' => 'jsonld']);
×
252
        $result = $this->tester->getDisplay();
×
253
        $json = json_decode($result, associative: true);
×
254

NEW
255
        $this->assertArrayHasKey('@id', $json['definitions']['ThirdLevel.jsonld-friends']['properties']);
×
256
    }
257

258
    #[\PHPUnit\Framework\Attributes\Group('orm')]
259
    public function testJsonApiIncludesSchema(): void
260
    {
261
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Question::class, '--type' => 'output', '--format' => 'jsonapi']);
×
262
        $result = $this->tester->getDisplay();
×
263
        $json = json_decode($result, associative: true);
×
264
        $properties = $json['definitions']['Question.jsonapi']['properties']['data']['properties'];
×
265
        $included = $json['definitions']['Question.jsonapi']['properties']['included'];
×
266

267
        $this->assertArrayHasKey('answer', $properties['relationships']['properties']);
×
268
        $this->assertArrayHasKey('anyOf', $included['items']);
×
269
        $this->assertCount(1, $included['items']['anyOf']);
×
270
        $this->assertArrayHasKey('$ref', $included['items']['anyOf'][0]);
×
271
        $this->assertSame('#/definitions/Answer.jsonapi', $included['items']['anyOf'][0]['$ref']);
×
272

273
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => AnimalObservation::class, '--type' => 'output', '--format' => 'jsonapi']);
×
274
        $result = $this->tester->getDisplay();
×
275
        $json = json_decode($result, associative: true);
×
276
        $properties = $json['definitions']['AnimalObservation.jsonapi']['properties']['data']['properties'];
×
277
        $included = $json['definitions']['AnimalObservation.jsonapi']['properties']['included'];
×
278

279
        $this->assertArrayHasKey('individuals', $properties['relationships']['properties']);
×
280
        $this->assertArrayNotHasKey('individuals', $properties['attributes']['properties']);
×
281
        $this->assertArrayHasKey('anyOf', $included['items']);
×
282
        $this->assertCount(1, $included['items']['anyOf']);
×
283
        $this->assertSame('#/definitions/Animal.jsonapi', $included['items']['anyOf'][0]['$ref']);
×
284

285
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Animal::class, '--type' => 'output', '--format' => 'jsonapi']);
×
286
        $result = $this->tester->getDisplay();
×
287
        $json = json_decode($result, associative: true);
×
288
        $properties = $json['definitions']['Animal.jsonapi']['properties']['data']['properties'];
×
289
        $included = $json['definitions']['Animal.jsonapi']['properties']['included'];
×
290

291
        $this->assertArrayHasKey('species', $properties['relationships']['properties']);
×
292
        $this->assertArrayNotHasKey('species', $properties['attributes']['properties']);
×
293
        $this->assertArrayHasKey('anyOf', $included['items']);
×
294
        $this->assertCount(1, $included['items']['anyOf']);
×
295
        $this->assertSame('#/definitions/Species.jsonapi', $included['items']['anyOf'][0]['$ref']);
×
296

297
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Species::class, '--type' => 'output', '--format' => 'jsonapi']);
×
298
        $result = $this->tester->getDisplay();
×
299
        $json = json_decode($result, associative: true);
×
300
        $properties = $json['definitions']['Species.jsonapi']['properties']['data']['properties'];
×
301

302
        $this->assertArrayHasKey('kingdom', $properties['attributes']['properties']);
×
303
        $this->assertArrayHasKey('phylum', $properties['attributes']['properties']);
×
304
    }
305

306
    /**
307
     * Test issue #6317.
308
     */
309
    public function testBackedEnumExamplesAreNotLost(): void
310
    {
311
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => Issue6317::class, '--type' => 'output', '--format' => 'jsonld']);
×
312
        $result = $this->tester->getDisplay();
×
313
        $json = json_decode($result, associative: true);
×
NEW
314
        $properties = $json['definitions']['Issue6317.jsonld']['properties'];
×
315

316
        $this->assertArrayHasKey('example', $properties['id']);
×
317
        $this->assertArrayHasKey('example', $properties['name']);
×
318
        // jsonldContext
319
        $this->assertArrayNotHasKey('example', $properties['ordinal']);
×
320
        // openapiContext
321
        $this->assertArrayNotHasKey('example', $properties['cardinal']);
×
322
    }
323

324
    public function testResourceWithEnumPropertiesSchema(): void
325
    {
326
        $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => ResourceWithEnumProperty::class, '--type' => 'output', '--format' => 'jsonld']);
×
327
        $result = $this->tester->getDisplay();
×
328
        $json = json_decode($result, associative: true);
×
NEW
329
        $properties = $json['definitions']['ResourceWithEnumProperty.jsonld']['properties'];
×
330

331
        $this->assertSame(
×
332
            [
×
333
                'type' => ['string', 'null'],
×
334
                'format' => 'iri-reference',
×
335
                'example' => 'https://example.com/',
×
336
            ],
×
337
            $properties['intEnum']
×
338
        );
×
339
        $this->assertSame(
×
340
            [
×
341
                'type' => 'array',
×
342
                'items' => [
×
343
                    'type' => 'string',
×
344
                    'format' => 'iri-reference',
×
345
                    'example' => 'https://example.com/',
×
346
                ],
×
347
            ],
×
348
            $properties['stringEnum']
×
349
        );
×
350
        $this->assertSame(
×
351
            [
×
352
                'type' => ['string', 'null'],
×
353
                'enum' => ['male', 'female', null],
×
354
            ],
×
355
            $properties['gender']
×
356
        );
×
357
        $this->assertSame(
×
358
            [
×
359
                'type' => 'array',
×
360
                'items' => [
×
361
                    'type' => 'string',
×
362
                    'enum' => ['male', 'female'],
×
363
                ],
×
364
            ],
×
365
            $properties['genders']
×
366
        );
×
367
    }
368
}
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