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

api-platform / core / 20598220846

30 Dec 2025 02:00PM UTC coverage: 28.861% (-0.002%) from 28.863%
20598220846

Pull #7609

github

web-flow
Merge 71b57d2e1 into d0dffea9b
Pull Request #7609: test(symfony): ensure pagination_maximum_items_per_page defaults correctly when config defaults key is absent

0 of 5 new or added lines in 1 file covered. (0.0%)

4 existing lines in 1 file now uncovered.

16767 of 58096 relevant lines covered (28.86%)

78.47 hits per line

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

0.0
/src/Symfony/Tests/Bundle/DependencyInjection/ApiPlatformExtensionTest.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\Symfony\Tests\Bundle\DependencyInjection;
15

16
use ApiPlatform\Metadata\Exception\ExceptionInterface;
17
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
18
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
19
use ApiPlatform\Metadata\IriConverterInterface;
20
use ApiPlatform\Metadata\ResourceClassResolverInterface;
21
use ApiPlatform\Metadata\UrlGeneratorInterface;
22
use ApiPlatform\Serializer\Filter\GroupFilter;
23
use ApiPlatform\Serializer\Filter\PropertyFilter;
24
use ApiPlatform\State\Pagination\Pagination;
25
use ApiPlatform\State\Pagination\PaginationOptions;
26
use ApiPlatform\State\SerializerContextBuilderInterface;
27
use ApiPlatform\Symfony\Action\NotFoundAction;
28
use ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension;
29
use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle;
30
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
31
use Doctrine\ORM\OptimisticLockException;
32
use PHPUnit\Framework\TestCase;
33
use Symfony\Bundle\SecurityBundle\SecurityBundle;
34
use Symfony\Bundle\TwigBundle\TwigBundle;
35
use Symfony\Component\DependencyInjection\ContainerBuilder;
36
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
37
use Symfony\Component\HttpFoundation\Response;
38

39
class ApiPlatformExtensionTest extends TestCase
40
{
41
    final public const DEFAULT_CONFIG = ['api_platform' => [
42
        'title' => 'title',
43
        'description' => 'description',
44
        'version' => 'version',
45
        'enable_json_streamer' => false,
46
        'serializer' => ['hydra_prefix' => true],
47
        'formats' => [
48
            'json' => ['mime_types' => ['json']],
49
            'jsonld' => ['mime_types' => ['application/ld+json']],
50
            'jsonhal' => ['mime_types' => ['application/hal+json']],
51
        ],
52
        'http_cache' => ['invalidation' => [
53
            'enabled' => true,
54
            'purger' => 'api_platform.http_cache.purger.varnish.ban',
55
            'request_options' => [
56
                'allow_redirects' => [
57
                    'max' => 5,
58
                    'protocols' => ['http', 'https'],
59
                    'stric' => false,
60
                    'referer' => false,
61
                    'track_redirects' => false,
62
                ],
63
                'http_errors' => true,
64
                'decode_content' => false,
65
                'verify' => false,
66
                'cookies' => true,
67
                'headers' => [
68
                    'User-Agent' => 'none',
69
                ],
70
            ],
71
        ]],
72
        'doctrine_mongodb_odm' => [
73
            'enabled' => true,
74
        ],
75
        'defaults' => [
76
            'extra_properties' => [],
77
            'url_generation_strategy' => UrlGeneratorInterface::ABS_URL,
78
        ],
79
        'collection' => [
80
            'exists_parameter_name' => 'exists',
81
            'order' => 'ASC',
82
            'order_parameter_name' => 'order',
83
            'order_nulls_comparison' => null,
84
            'pagination' => [
85
                'page_parameter_name' => 'page',
86
                'enabled_parameter_name' => 'pagination',
87
                'items_per_page_parameter_name' => 'itemsPerPage',
88
                'partial_parameter_name' => 'partial',
89
            ],
90
        ],
91
        'error_formats' => [
92
            'jsonproblem' => ['application/problem+json'],
93
            'jsonld' => ['application/ld+json'],
94
        ],
95
        'patch_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
        'show_webby' => true,
102
        'eager_loading' => [
103
            'enabled' => true,
104
            'max_joins' => 30,
105
            'force_eager' => true,
106
            'fetch_partial' => false,
107
        ],
108
        'asset_package' => null,
109
        'enable_entrypoint' => true,
110
        'enable_docs' => true,
111
        'enable_swagger' => true,
112
        'enable_swagger_ui' => true,
113
        'use_symfony_listeners' => false,
114
    ]];
115

116
    private ContainerBuilder $container;
117

118
    protected function setUp(): void
119
    {
120
        $containerParameterBag = new ParameterBag([
×
121
            'kernel.bundles' => [
×
122
                'DoctrineBundle' => DoctrineBundle::class,
×
123
                'SecurityBundle' => SecurityBundle::class,
×
124
                'TwigBundle' => TwigBundle::class,
×
125
            ],
×
126
            'kernel.bundles_metadata' => [
×
127
                'TestBundle' => [
×
128
                    'parent' => null,
×
129
                    'path' => realpath(__DIR__.'/../../../Fixtures/TestBundle'),
×
130
                    'namespace' => TestBundle::class,
×
131
                ],
×
132
            ],
×
133
            'kernel.project_dir' => __DIR__.'/../../../Fixtures/app',
×
134
            'kernel.debug' => false,
×
135
            'kernel.environment' => 'test',
×
136
        ]);
×
137

138
        $this->container = new ContainerBuilder($containerParameterBag);
×
139
    }
140

141
    private function assertContainerHas(array $services, array $aliases = []): void
142
    {
143
        foreach ($services as $service) {
×
144
            $this->assertTrue($this->container->hasDefinition($service), \sprintf('Definition "%s" not found.', $service));
×
145
        }
146

147
        foreach ($aliases as $alias) {
×
148
            $this->assertContainerHasAlias($alias);
×
149
        }
150
    }
151

152
    private function assertContainerHasService(string $service): void
153
    {
154
        $this->assertTrue($this->container->hasDefinition($service), \sprintf('Service "%s" not found.', $service));
×
155
    }
156

157
    private function assertNotContainerHasService(string $service): void
158
    {
159
        $this->assertFalse($this->container->hasDefinition($service), \sprintf('Service "%s" found.', $service));
×
160
    }
161

162
    private function assertContainerHasAlias(string $alias): void
163
    {
164
        $this->assertTrue($this->container->hasAlias($alias), \sprintf('Alias "%s" not found.', $alias));
×
165
    }
166

167
    private function assertServiceHasTags(string $service, array $tags = []): void
168
    {
169
        $serviceTags = $this->container->getDefinition($service)->getTags();
×
170

171
        foreach ($tags as $tag) {
×
172
            $this->assertArrayHasKey($tag, $serviceTags, \sprintf('Tag "%s" not found on the service "%s".', $tag, $service));
×
173
        }
174
    }
175

176
    public function testCommonConfiguration(): void
177
    {
178
        $config = self::DEFAULT_CONFIG;
×
179
        (new ApiPlatformExtension())->load($config, $this->container);
×
180

181
        $services = [
×
182
            'api_platform.action.documentation',
×
183
            'api_platform.action.entrypoint',
×
184
            'api_platform.action.not_found',
×
185
            'api_platform.api.identifiers_extractor',
×
186
            'api_platform.filter_locator',
×
187
            'api_platform.negotiator',
×
188
            'api_platform.pagination',
×
189
            'api_platform.pagination_options',
×
190
            'api_platform.path_segment_name_generator.dash',
×
191
            'api_platform.path_segment_name_generator.underscore',
×
192
            'api_platform.metadata.inflector',
×
193
            'api_platform.resource_class_resolver',
×
194
            'api_platform.route_loader',
×
195
            'api_platform.router',
×
196
            'api_platform.serializer.context_builder',
×
197
            'api_platform.serializer.context_builder.filter',
×
198
            'api_platform.serializer.group_filter',
×
199
            'api_platform.serializer.mapping.class_metadata_factory',
×
200
            'api_platform.serializer.normalizer.item',
×
201
            'api_platform.serializer.property_filter',
×
202
            'api_platform.serializer_locator',
×
203
            'api_platform.symfony.iri_converter',
×
204
            'api_platform.uri_variables.converter',
×
205
            'api_platform.uri_variables.transformer.date_time',
×
206
            'api_platform.uri_variables.transformer.integer',
×
207

208
            'api_platform.state_provider.content_negotiation',
×
209
            'api_platform.state_provider.deserialize',
×
210
            'api_platform.state_processor.respond',
×
211
            'api_platform.state_processor.add_link_header',
×
212
            'api_platform.state_processor.serialize',
×
213

214
            'api_platform.swagger_ui.context',
×
215
            'api_platform.swagger_ui.processor',
×
216
            'api_platform.swagger_ui.provider',
×
217
        ];
×
218

219
        $aliases = [
×
220
            NotFoundAction::class,
×
221
            IdentifiersExtractorInterface::class,
×
222
            IriConverterInterface::class,
×
223
            ResourceClassResolverInterface::class,
×
224
            UrlGeneratorInterface::class,
×
225
            GroupFilter::class,
×
226
            PropertyFilter::class,
×
227
            SerializerContextBuilderInterface::class,
×
228
            Pagination::class,
×
229
            PaginationOptions::class,
×
230
            'api_platform.identifiers_extractor',
×
231
            'api_platform.iri_converter',
×
232
            'api_platform.path_segment_name_generator',
×
233
            'api_platform.property_accessor',
×
234
            'api_platform.property_info',
×
235
            'api_platform.serializer',
×
236
            'api_platform.inflector',
×
237
        ];
×
238

239
        $this->assertContainerHas($services, $aliases);
×
240

241
        $this->assertServiceHasTags('api_platform.cache.route_name_resolver', ['cache.pool']);
×
242
        $this->assertServiceHasTags('api_platform.serializer.normalizer.item', ['serializer.normalizer']);
×
243
        $this->assertServiceHasTags('api_platform.serializer_locator', ['container.service_locator']);
×
244
        $this->assertServiceHasTags('api_platform.filter_locator', ['container.service_locator']);
×
245

246
        // api.xml
247
        $this->assertServiceHasTags('api_platform.route_loader', ['routing.loader']);
×
248
        $this->assertServiceHasTags('api_platform.uri_variables.transformer.integer', ['api_platform.uri_variables.transformer']);
×
249
        $this->assertServiceHasTags('api_platform.uri_variables.transformer.date_time', ['api_platform.uri_variables.transformer']);
×
250

251
        $services = [
×
252
            'api_platform.listener.request.read',
×
253
            'api_platform.listener.request.deserialize',
×
254
            'api_platform.listener.request.add_format',
×
255
            'api_platform.listener.view.write',
×
256
            'api_platform.listener.view.serialize',
×
257
            'api_platform.listener.view.respond',
×
258
            'api_platform.swagger_ui.documentation.provider',
×
259
        ];
×
260

261
        foreach ($services as $service) {
×
262
            $this->assertNotContainerHasService($service);
×
263
        }
264
    }
265

266
    public function testSwaggerUiDisabledConfiguration(): void
267
    {
268
        $config = self::DEFAULT_CONFIG;
×
269
        $config['api_platform']['enable_swagger'] = true;
×
270
        $config['api_platform']['enable_swagger_ui'] = false;
×
271
        $config['api_platform']['enable_re_doc'] = false;
×
272
        $config['api_platform']['use_symfony_listeners'] = true;
×
273

274
        (new ApiPlatformExtension())->load($config, $this->container);
×
275

276
        $this->assertNotContainerHasService('api_platform.swagger_ui.processor');
×
277

278
        $this->assertNotContainerHasService('api_platform.swagger_ui.context');
×
279

280
        $this->assertNotContainerHasService('api_platform.swagger_ui.provider');
×
281

282
        $this->assertNotContainerHasService('api_platform.swagger_ui.documentation.provider');
×
283
    }
284

285
    public function testSwaggerUiEnabledConfiguration(): void
286
    {
287
        $config = self::DEFAULT_CONFIG;
×
288
        $config['api_platform']['enable_swagger'] = true;
×
289
        $config['api_platform']['enable_swagger_ui'] = true;
×
290
        $config['api_platform']['use_symfony_listeners'] = true;
×
291

292
        (new ApiPlatformExtension())->load($config, $this->container);
×
293

294
        $services = [
×
295
            'api_platform.swagger_ui.processor',
×
296
            'api_platform.swagger_ui.context',
×
297
            'api_platform.swagger_ui.provider',
×
298
            'api_platform.swagger_ui.documentation.provider',
×
299
        ];
×
300

301
        $this->assertContainerHas($services);
×
302
    }
303

304
    public function testReDocEnabledWithSwaggerUiDisabledConfiguration(): void
305
    {
306
        $config = self::DEFAULT_CONFIG;
×
307
        $config['api_platform']['enable_swagger'] = true;
×
308
        $config['api_platform']['enable_swagger_ui'] = false;
×
309
        $config['api_platform']['enable_re_doc'] = true;
×
310
        $config['api_platform']['use_symfony_listeners'] = true;
×
311

312
        (new ApiPlatformExtension())->load($config, $this->container);
×
313

314
        $services = [
×
315
            'api_platform.swagger_ui.processor',
×
316
            'api_platform.swagger_ui.context',
×
317
            'api_platform.swagger_ui.provider',
×
318
            'api_platform.swagger_ui.documentation.provider',
×
319
        ];
×
320

321
        $this->assertContainerHas($services);
×
322
    }
323

324
    public function testEventListenersConfiguration(): void
325
    {
326
        $config = self::DEFAULT_CONFIG;
×
327
        $config['api_platform']['use_symfony_listeners'] = true;
×
328
        (new ApiPlatformExtension())->load($config, $this->container);
×
329

330
        $services = [
×
331
            'api_platform.listener.request.read',
×
332
            'api_platform.listener.request.deserialize',
×
333
            'api_platform.listener.request.add_format',
×
334
            'api_platform.listener.view.write',
×
335
            'api_platform.listener.view.serialize',
×
336
            'api_platform.listener.view.respond',
×
337

338
            'api_platform.state_provider.content_negotiation',
×
339
            'api_platform.state_provider.deserialize',
×
340
            'api_platform.state_processor.respond',
×
341
            'api_platform.state_processor.add_link_header',
×
342
            'api_platform.state_processor.serialize',
×
343
        ];
×
344

345
        $aliases = [
×
346
            'api_platform.action.delete_item',
×
347
            'api_platform.action.get_collection',
×
348
            'api_platform.action.get_item',
×
349
            'api_platform.action.patch_item',
×
350
            'api_platform.action.post_collection',
×
351
            'api_platform.action.put_item',
×
352
        ];
×
353

354
        $this->assertContainerHas($services, $aliases);
×
355
        $this->container->hasParameter('api_platform.swagger.http_auth');
×
356
    }
357

358
    public function testItRegistersMetadataConfiguration(): void
359
    {
360
        $config = self::DEFAULT_CONFIG;
×
361
        $config['api_platform']['mapping']['imports'] = [__DIR__.'/php'];
×
362
        (new ApiPlatformExtension())->load($config, $this->container);
×
363

364
        $emptyPhpFile = realpath(__DIR__.'/php/empty_file.php');
×
365
        $this->assertContainerHasService('api_platform.metadata.resource_extractor.php_file');
×
366
        $this->assertSame([$emptyPhpFile], $this->container->getDefinition('api_platform.metadata.resource_extractor.php_file')->getArgument(0));
×
367
    }
368

369
    public function testPaginationMaximumItemsPerPageIsNotSet(): void
370
    {
371
        $config = self::DEFAULT_CONFIG;
×
372
        (new ApiPlatformExtension())->load($config, $this->container);
×
373

374
        $this->assertTrue($this->container->hasParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
375
        $this->assertSame(30, $this->container->getParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
376
    }
377

378
    public function testPaginationMaximumItemsPerPageIsSetWithNull(): void
379
    {
380
        $config = self::DEFAULT_CONFIG;
×
381
        $config['api_platform']['defaults']['pagination_maximum_items_per_page'] = null;
×
382
        (new ApiPlatformExtension())->load($config, $this->container);
×
383

NEW
384
        $this->assertTrue($this->container->hasParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
NEW
385
        $this->assertNull($this->container->getParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
386
    }
387

388
    public function testPaginationMaximumItemsPerPageIsSetWithExplicitValue(): void
389
    {
NEW
390
        $config = self::DEFAULT_CONFIG;
×
NEW
391
        $config['api_platform']['defaults']['pagination_maximum_items_per_page'] = 22;
×
NEW
392
        (new ApiPlatformExtension())->load($config, $this->container);
×
393

394
        $this->assertSame(22, $this->container->getParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
395
    }
396

397
    public function testPaginationMaximumItemsPerPageIsSetWithZero(): void
398
    {
UNCOV
399
        $config = self::DEFAULT_CONFIG;
×
400
        $config['api_platform']['defaults']['pagination_maximum_items_per_page'] = 0;
×
401
        (new ApiPlatformExtension())->load($config, $this->container);
×
402

UNCOV
403
        $this->assertSame(0, $this->container->getParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
404
    }
405

406
    public function testPaginationMaximumItemsPerPageWhenDefaultsKeyIsMissing(): void
407
    {
UNCOV
408
        $config = self::DEFAULT_CONFIG;
×
409
        unset($config['api_platform']['defaults']);
×
410
        (new ApiPlatformExtension())->load($config, $this->container);
×
411

UNCOV
412
        $this->assertTrue($this->container->hasParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
413
        $this->assertSame(30, $this->container->getParameter('api_platform.collection.pagination.maximum_items_per_page'));
×
414
    }
415
}
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