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

api-platform / core / 15629538569

13 Jun 2025 07:58AM UTC coverage: 21.874% (-0.002%) from 21.876%
15629538569

Pull #7207

github

web-flow
Merge 3fb5fafc9 into cff61eab8
Pull Request #7207: feat(metadata) customize resource & operations

16 of 92 new or added lines in 9 files covered. (17.39%)

37 existing lines in 2 files now uncovered.

11410 of 52163 relevant lines covered (21.87%)

20.98 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
        'serializer' => ['hydra_prefix' => true],
46
        'formats' => [
47
            'json' => ['mime_types' => ['json']],
48
            'jsonld' => ['mime_types' => ['application/ld+json']],
49
            'jsonhal' => ['mime_types' => ['application/hal+json']],
50
        ],
51
        'http_cache' => ['invalidation' => [
52
            'enabled' => true,
53
            'purger' => 'api_platform.http_cache.purger.varnish.ban',
54
            'request_options' => [
55
                'allow_redirects' => [
56
                    'max' => 5,
57
                    'protocols' => ['http', 'https'],
58
                    'stric' => false,
59
                    'referer' => false,
60
                    'track_redirects' => false,
61
                ],
62
                'http_errors' => true,
63
                'decode_content' => false,
64
                'verify' => false,
65
                'cookies' => true,
66
                'headers' => [
67
                    'User-Agent' => 'none',
68
                ],
69
            ],
70
        ]],
71
        'doctrine_mongodb_odm' => [
72
            'enabled' => true,
73
        ],
74
        'defaults' => [
75
            'extra_properties' => [],
76
            'url_generation_strategy' => UrlGeneratorInterface::ABS_URL,
77
        ],
78
        'collection' => [
79
            'exists_parameter_name' => 'exists',
80
            'order' => 'ASC',
81
            'order_parameter_name' => 'order',
82
            'order_nulls_comparison' => null,
83
            'pagination' => [
84
                'page_parameter_name' => 'page',
85
                'enabled_parameter_name' => 'pagination',
86
                'items_per_page_parameter_name' => 'itemsPerPage',
87
                'partial_parameter_name' => 'partial',
88
            ],
89
        ],
90
        'error_formats' => [
91
            'jsonproblem' => ['application/problem+json'],
92
            'jsonld' => ['application/ld+json'],
93
        ],
94
        'patch_formats' => [],
95
        'exception_to_status' => [
96
            ExceptionInterface::class => Response::HTTP_BAD_REQUEST,
97
            InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
98
            OptimisticLockException::class => Response::HTTP_CONFLICT,
99
        ],
100
        'show_webby' => true,
101
        'eager_loading' => [
102
            'enabled' => true,
103
            'max_joins' => 30,
104
            'force_eager' => true,
105
            'fetch_partial' => false,
106
        ],
107
        'asset_package' => null,
108
        'enable_entrypoint' => true,
109
        'enable_docs' => true,
110
        'graphql' => [
111
            'graphql_playground' => ['enabled' => false],
112
        ],
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

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

235
        $this->assertContainerHas($services, $aliases);
×
236

237
        $this->assertServiceHasTags('api_platform.cache.route_name_resolver', ['cache.pool']);
×
238
        $this->assertServiceHasTags('api_platform.serializer.normalizer.item', ['serializer.normalizer']);
×
239
        $this->assertServiceHasTags('api_platform.serializer_locator', ['container.service_locator']);
×
240
        $this->assertServiceHasTags('api_platform.filter_locator', ['container.service_locator']);
×
241

242
        // api.xml
243
        $this->assertServiceHasTags('api_platform.route_loader', ['routing.loader']);
×
244
        $this->assertServiceHasTags('api_platform.uri_variables.transformer.integer', ['api_platform.uri_variables.transformer']);
×
245
        $this->assertServiceHasTags('api_platform.uri_variables.transformer.date_time', ['api_platform.uri_variables.transformer']);
×
246

247
        $services = [
×
248
            'api_platform.listener.request.read',
×
249
            'api_platform.listener.request.deserialize',
×
250
            'api_platform.listener.request.add_format',
×
251
            'api_platform.listener.view.write',
×
252
            'api_platform.listener.view.serialize',
×
253
            'api_platform.listener.view.respond',
×
254
        ];
×
255

256
        foreach ($services as $service) {
×
257
            $this->assertNotContainerHasService($service);
×
258
        }
259
    }
260

261
    public function testEventListenersConfiguration(): void
262
    {
263
        $config = self::DEFAULT_CONFIG;
×
264
        $config['api_platform']['use_symfony_listeners'] = true;
×
265
        (new ApiPlatformExtension())->load($config, $this->container);
×
266

267
        $services = [
×
268
            'api_platform.listener.request.read',
×
269
            'api_platform.listener.request.deserialize',
×
270
            'api_platform.listener.request.add_format',
×
271
            'api_platform.listener.view.write',
×
272
            'api_platform.listener.view.serialize',
×
273
            'api_platform.listener.view.respond',
×
274

275
            'api_platform.state_provider.content_negotiation',
×
276
            'api_platform.state_provider.deserialize',
×
277
            'api_platform.state_processor.respond',
×
278
            'api_platform.state_processor.add_link_header',
×
279
            'api_platform.state_processor.serialize',
×
280
        ];
×
281

282
        $aliases = [
×
283
            'api_platform.action.delete_item',
×
284
            'api_platform.action.get_collection',
×
285
            'api_platform.action.get_item',
×
286
            'api_platform.action.patch_item',
×
287
            'api_platform.action.post_collection',
×
288
            'api_platform.action.put_item',
×
289
        ];
×
290

291
        $this->assertContainerHas($services, $aliases);
×
292
        $this->container->hasParameter('api_platform.swagger.http_auth');
×
293
    }
294

295
    public function testItRegistersMetadataConfiguration(): void
296
    {
297
        $config = self::DEFAULT_CONFIG;
×
298
        $config['api_platform']['mapping']['imports'] = [__DIR__.'/php'];
×
299
        (new ApiPlatformExtension())->load($config, $this->container);
×
300

301
        $emptyPhpFile = realpath(__DIR__.'/php/empty_file.php');
×
302

303
        $this->assertContainerHasService('api_platform.metadata.resource_extractor.php_file');
×
304
        $this->assertSame([$emptyPhpFile], $this->container->getDefinition('api_platform.metadata.resource_extractor.php_file')->getArgument(0));
×
305

NEW
306
        $this->assertContainerHasService('api_platform.metadata.closure_extractor.php_file.resource');
×
NEW
307
        $this->assertSame([$emptyPhpFile], $this->container->getDefinition('api_platform.metadata.closure_extractor.php_file.resource')->getArgument(0));
×
308
    }
309
}
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