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

api-platform / core / 15022984576

14 May 2025 02:11PM UTC coverage: 8.423% (+1.5%) from 6.943%
15022984576

push

github

web-flow
feat(symfony): add error classes options to open api config (#7143)

5 of 7 new or added lines in 3 files covered. (71.43%)

184 existing lines in 13 files now uncovered.

13502 of 160304 relevant lines covered (8.42%)

22.9 hits per line

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

0.0
/tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.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\Symfony\Bundle\DependencyInjection;
15

16
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
17
use ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration;
18
use Doctrine\ORM\OptimisticLockException;
19
use PHPUnit\Framework\TestCase;
20
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
21
use Symfony\Component\Config\Definition\ConfigurationInterface;
22
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
23
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
24
use Symfony\Component\Config\Definition\Processor;
25
use Symfony\Component\HttpFoundation\Response;
26
use Symfony\Component\Serializer\Exception\ExceptionInterface;
27

28
/**
29
 * @author Kévin Dunglas <dunglas@gmail.com>
30
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
31
 */
32
class ConfigurationTest extends TestCase
33
{
34
    private Configuration $configuration;
35

36
    private Processor $processor;
37

38
    protected function setUp(): void
39
    {
40
        $this->configuration = new Configuration();
×
41
        $this->processor = new Processor();
×
42
    }
43

44
    public function testDefaultConfig(): void
45
    {
46
        $this->runDefaultConfigTests();
×
47
    }
48

49
    public function testDefaultConfigWithMongoDbOdm(): void
50
    {
51
        $this->runDefaultConfigTests(['orm', 'odm']);
×
52
    }
53

54
    private function runDefaultConfigTests(array $doctrineIntegrationsToLoad = ['orm']): void
55
    {
56
        $treeBuilder = $this->configuration->getConfigTreeBuilder();
×
57
        $config = $this->processor->processConfiguration($this->configuration, [
×
58
            'api_platform' => [
×
59
                'title' => 'title',
×
60
                'description' => 'description',
×
61
                'version' => '1.0.0',
×
62
                'doctrine' => [
×
63
                    'enabled' => \in_array('orm', $doctrineIntegrationsToLoad, true),
×
64
                ],
×
65
                'doctrine_mongodb_odm' => [
×
66
                    'enabled' => \in_array('odm', $doctrineIntegrationsToLoad, true),
×
67
                ],
×
68
            ],
×
69
        ]);
×
70

71
        $this->assertInstanceOf(ConfigurationInterface::class, $this->configuration);
×
72
        $this->assertInstanceOf(TreeBuilder::class, $treeBuilder);
×
73
        $this->assertEquals([
×
74
            'title' => 'title',
×
75
            'description' => 'description',
×
76
            'version' => '1.0.0',
×
77
            'show_webby' => true,
×
78
            'formats' => [
×
79
                'jsonld' => ['mime_types' => ['application/ld+json']],
×
80
            ],
×
81
            'docs_formats' => [
×
82
                'jsonopenapi' => ['mime_types' => ['application/vnd.openapi+json']],
×
83
                'yamlopenapi' => ['mime_types' => ['application/vnd.openapi+yaml']],
×
84
                'jsonld' => ['mime_types' => ['application/ld+json']],
×
85
                'html' => ['mime_types' => ['text/html']],
×
86
            ],
×
87
            'patch_formats' => [
×
88
                'json' => ['mime_types' => ['application/merge-patch+json']],
×
89
            ],
×
90
            'error_formats' => [
×
91
                'jsonproblem' => ['mime_types' => ['application/problem+json']],
×
92
                'jsonld' => ['mime_types' => ['application/ld+json']],
×
93
                'json' => ['mime_types' => ['application/problem+json', 'application/json']],
×
94
            ],
×
95
            'jsonschema_formats' => [],
×
96
            'exception_to_status' => [
×
97
                ExceptionInterface::class => Response::HTTP_BAD_REQUEST,
×
98
                InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
×
99
                OptimisticLockException::class => Response::HTTP_CONFLICT,
×
100
            ],
×
101
            'path_segment_name_generator' => 'api_platform.metadata.path_segment_name_generator.underscore',
×
102
            'inflector' => 'api_platform.metadata.inflector',
×
103
            'validator' => [
×
104
                'serialize_payload_fields' => [],
×
105
                'query_parameter_validation' => true,
×
106
            ],
×
107
            'name_converter' => null,
×
108
            'enable_swagger' => true,
×
109
            'enable_swagger_ui' => true,
×
110
            'enable_entrypoint' => true,
×
111
            'enable_re_doc' => true,
×
112
            'enable_docs' => true,
×
113
            'enable_profiler' => true,
×
114
            'graphql' => [
×
115
                'enabled' => true,
×
116
                'default_ide' => 'graphiql',
×
117
                'graphql_playground' => [
×
118
                    'enabled' => true,
×
119
                ],
×
120
                'graphiql' => [
×
121
                    'enabled' => true,
×
122
                ],
×
123
                'introspection' => [
×
124
                    'enabled' => true,
×
125
                ],
×
126
                'max_query_depth' => 20,
×
127
                'max_query_complexity' => 500,
×
128
                'nesting_separator' => '_',
×
129
                'collection' => [
×
130
                    'pagination' => [
×
131
                        'enabled' => true,
×
132
                    ],
×
133
                ],
×
134
            ],
×
135
            'elasticsearch' => [
×
136
                'enabled' => false,
×
137
                'hosts' => [],
×
138
            ],
×
139
            'oauth' => [
×
140
                'enabled' => false,
×
141
                'clientId' => '',
×
142
                'clientSecret' => '',
×
143
                'type' => 'oauth2',
×
144
                'flow' => 'application',
×
145
                'tokenUrl' => '',
×
146
                'authorizationUrl' => '',
×
147
                'refreshUrl' => '',
×
148
                'scopes' => [],
×
149
                'pkce' => false,
×
150
            ],
×
151
            'swagger' => [
×
152
                'versions' => [3],
×
153
                'api_keys' => [],
×
154
                'http_auth' => [],
×
155
                'swagger_ui_extra_configuration' => [],
×
156
                'persist_authorization' => false,
×
157
            ],
×
158
            'eager_loading' => [
×
159
                'enabled' => true,
×
160
                'max_joins' => 30,
×
161
                'force_eager' => true,
×
162
                'fetch_partial' => false,
×
163
            ],
×
164
            'collection' => [
×
165
                'exists_parameter_name' => 'exists',
×
166
                'order' => 'ASC',
×
167
                'order_parameter_name' => 'order',
×
168
                'order_nulls_comparison' => null,
×
169
                'pagination' => [
×
170
                    'enabled' => true,
×
171
                    'page_parameter_name' => 'page',
×
172
                    'enabled_parameter_name' => 'pagination',
×
173
                    'items_per_page_parameter_name' => 'itemsPerPage',
×
174
                    'partial_parameter_name' => 'partial',
×
175
                ],
×
176
            ],
×
177
            'mapping' => [
×
178
                'paths' => [],
×
179
            ],
×
180
            'http_cache' => [
×
181
                'invalidation' => [
×
182
                    'enabled' => false,
×
183
                    'varnish_urls' => [],
×
184
                    'request_options' => [],
×
185
                    'max_header_length' => 7500,
×
186
                    'purger' => 'api_platform.http_cache.purger.varnish',
×
187
                    'xkey' => ['glue' => ' '],
×
188
                    'urls' => [],
×
189
                    'scoped_clients' => [],
×
190
                ],
×
191
                'public' => null,
×
192
            ],
×
193
            'doctrine' => [
×
194
                'enabled' => \in_array('orm', $doctrineIntegrationsToLoad, true),
×
195
            ],
×
196
            'doctrine_mongodb_odm' => [
×
197
                'enabled' => \in_array('odm', $doctrineIntegrationsToLoad, true),
×
198
            ],
×
199
            'messenger' => [
×
200
                'enabled' => true,
×
201
            ],
×
202
            'mercure' => [
×
203
                'enabled' => true,
×
204
                'hub_url' => null,
×
205
                'include_type' => false,
×
206
            ],
×
207
            'resource_class_directories' => [],
×
208
            'asset_package' => null,
×
209
            'openapi' => [
×
210
                'contact' => [
×
211
                    'name' => null,
×
212
                    'url' => null,
×
213
                    'email' => null,
×
214
                ],
×
215
                'termsOfService' => null,
×
216
                'license' => [
×
217
                    'name' => null,
×
218
                    'url' => null,
×
219
                    'identifier' => null,
×
220
                ],
×
221
                'swagger_ui_extra_configuration' => [],
×
222
                'overrideResponses' => true,
×
223
                'tags' => [],
×
NEW
224
                'error_resource_class' => null,
×
NEW
225
                'validation_error_resource_class' => null,
×
226
            ],
×
227
            'maker' => [
×
228
                'enabled' => true,
×
229
            ],
×
230
            'use_symfony_listeners' => false,
×
231
            'handle_symfony_errors' => false,
×
232
            'enable_link_security' => false,
×
233
            'serializer' => [
×
234
                'hydra_prefix' => null,
×
235
            ],
×
236
        ], $config);
×
237
    }
238

239
    public static function invalidHttpStatusCodeProvider(): array
240
    {
241
        return [
×
242
            [0],
×
243
            [99],
×
244
            [700],
×
245
            [1000],
×
246
        ];
×
247
    }
248

249
    #[\PHPUnit\Framework\Attributes\DataProvider('invalidHttpStatusCodeProvider')]
250
    public function testExceptionToStatusConfigWithInvalidHttpStatusCode($invalidHttpStatusCode): void
251
    {
252
        $this->expectException(InvalidConfigurationException::class);
×
253
        $this->expectExceptionMessageMatches('/The HTTP status code ".+" is not valid\\./');
×
254

255
        $this->processor->processConfiguration($this->configuration, [
×
256
            'api_platform' => [
×
257
                'exception_to_status' => [
×
258
                    \Exception::class => $invalidHttpStatusCode,
×
259
                ],
×
260
            ],
×
261
        ]);
×
262
    }
263

264
    public static function invalidHttpStatusCodeValueProvider(): array
265
    {
266
        return [
×
267
            [true],
×
268
            [null],
×
269
            [-\INF],
×
270
            [40.4],
×
271
            ['foo'],
×
272
            ['HTTP_FOO_BAR'],
×
273
        ];
×
274
    }
275

276
    #[\PHPUnit\Framework\Attributes\DataProvider('invalidHttpStatusCodeValueProvider')]
277
    public function testExceptionToStatusConfigWithInvalidHttpStatusCodeValue($invalidHttpStatusCodeValue): void
278
    {
279
        $this->expectException(InvalidTypeException::class);
×
280
        $this->expectExceptionMessageMatches('/Invalid type for path "api_platform\\.exception_to_status\\.Exception". Expected "?int"?, but got .+\\./');
×
281

282
        $this->processor->processConfiguration($this->configuration, [
×
283
            'api_platform' => [
×
284
                'exception_to_status' => [
×
285
                    \Exception::class => $invalidHttpStatusCodeValue,
×
286
                ],
×
287
            ],
×
288
        ]);
×
289
    }
290

291
    /**
292
     * Test config for api keys.
293
     */
294
    public function testInvalidApiKeysConfig(): void
295
    {
296
        $this->expectExceptionMessage('The api keys "key" is not valid according to the pattern enforced by OpenAPI 3.1 ^[a-zA-Z0-9._-]+$.');
×
297
        $exampleConfig = [
×
298
            'name' => 'Authorization',
×
299
            'type' => 'query',
×
300
        ];
×
301

302
        $config = $this->processor->processConfiguration($this->configuration, [
×
303
            'api_platform' => [
×
304
                'swagger' => [
×
305
                    'api_keys' => ['Some Authorization name, like JWT' => $exampleConfig, 'Another-Auth' => $exampleConfig],
×
306
                ],
×
307
            ],
×
308
        ]);
×
309
    }
310

311
    /**
312
     * Test config for api keys.
313
     */
314
    public function testApiKeysConfig(): void
315
    {
316
        $exampleConfig = [
×
317
            'name' => 'Authorization',
×
318
            'type' => 'query',
×
319
        ];
×
320

321
        $config = $this->processor->processConfiguration($this->configuration, [
×
322
            'api_platform' => [
×
323
                'swagger' => [
×
324
                    'api_keys' => ['authorization_name_like_JWT' => $exampleConfig],
×
325
                ],
×
326
            ],
×
327
        ]);
×
328

329
        $this->assertArrayHasKey('api_keys', $config['swagger']);
×
330
        $this->assertSame($exampleConfig, $config['swagger']['api_keys']['authorization_name_like_JWT']);
×
331
    }
332

333
    /**
334
     * Test config for disabled swagger versions.
335
     */
336
    public function testDisabledSwaggerVersionConfig(): void
337
    {
338
        $config = $this->processor->processConfiguration($this->configuration, [
×
339
            'api_platform' => [
×
340
                'enable_swagger' => false,
×
341
                'swagger' => [
×
342
                    'versions' => [3],
×
343
                ],
×
344
            ],
×
345
        ]);
×
346

347
        $this->assertArrayHasKey('versions', $config['swagger']);
×
348
        $this->assertEmpty($config['swagger']['versions']);
×
349
    }
350

351
    /**
352
     * Test config for swagger versions.
353
     */
354
    public function testSwaggerVersionConfig(): void
355
    {
356
        $config = $this->processor->processConfiguration($this->configuration, [
×
357
            'api_platform' => [
×
358
                'swagger' => [
×
359
                    'versions' => [3],
×
360
                ],
×
361
            ],
×
362
        ]);
×
363

364
        $this->assertArrayHasKey('versions', $config['swagger']);
×
365
        $this->assertEquals([3], $config['swagger']['versions']);
×
366

367
        $this->expectException(InvalidConfigurationException::class);
×
368
        $this->expectExceptionMessageMatches('/Only the versions .+ are supported. Got .+./');
×
369

370
        $this->processor->processConfiguration($this->configuration, [
×
371
            'api_platform' => [
×
372
                'swagger' => [
×
373
                    'versions' => [1],
×
374
                ],
×
375
            ],
×
376
        ]);
×
377
    }
378

379
    /**
380
     * Test config for empty title and description.
381
     */
382
    public function testEmptyTitleDescriptionConfig(): void
383
    {
384
        $config = $this->processor->processConfiguration($this->configuration, [
×
385
            'api_platform' => [],
×
386
        ]);
×
387

388
        $this->assertSame('', $config['title']);
×
389
        $this->assertSame('', $config['description']);
×
390
    }
391

392
    public function testEnableElasticsearch(): void
393
    {
394
        $config = $this->processor->processConfiguration($this->configuration, [
×
395
            'api_platform' => [
×
396
                'elasticsearch' => true,
×
397
            ],
×
398
        ]);
×
399

400
        $this->assertTrue($config['elasticsearch']['enabled']);
×
401
    }
402

403
    /**
404
     * Test config for http auth.
405
     */
406
    public function testHttpAuth(): void
407
    {
408
        $config = $this->processor->processConfiguration($this->configuration, [
×
409
            'api_platform' => [
×
410
                'swagger' => [
×
411
                    'http_auth' => ['PAT' => [
×
412
                        'scheme' => 'bearer',
×
413
                        'bearerFormat' => 'JWT',
×
414
                    ]],
×
415
                ],
×
416
            ],
×
417
        ]);
×
418

419
        $this->assertArrayHasKey('http_auth', $config['swagger']);
×
420
        $this->assertSame(['scheme' => 'bearer', 'bearerFormat' => 'JWT'], $config['swagger']['http_auth']['PAT']);
×
421
    }
422

423
    /**
424
     * Test openapi tags.
425
     */
426
    public function testOpenApiTags(): void
427
    {
428
        $config = $this->processor->processConfiguration($this->configuration, [
×
429
            'api_platform' => [
×
430
                'openapi' => [
×
431
                    'tags' => [
×
432
                        ['name' => 'test', 'description' => 'test2'],
×
433
                        ['name' => 'test3'],
×
434
                    ],
×
435
                ],
×
436
            ],
×
437
        ]);
×
438

439
        $this->assertEquals(['name' => 'test3', 'description' => null], $config['openapi']['tags'][1]);
×
440
    }
441
}
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