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

api-platform / core / 15927526370

27 Jun 2025 01:30PM UTC coverage: 22.016% (-0.008%) from 22.024%
15927526370

push

github

web-flow
refactor(metadata): cascade resource to operation (#7246)

12 of 46 new or added lines in 12 files covered. (26.09%)

63 existing lines in 2 files now uncovered.

11494 of 52207 relevant lines covered (22.02%)

21.67 hits per line

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

0.0
/src/Metadata/Tests/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.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\Metadata\Tests\Resource\Factory;
15

16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\Delete;
18
use ApiPlatform\Metadata\Get;
19
use ApiPlatform\Metadata\GetCollection;
20
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
21
use ApiPlatform\Metadata\GraphQl\Mutation;
22
use ApiPlatform\Metadata\GraphQl\Query;
23
use ApiPlatform\Metadata\GraphQl\QueryCollection;
24
use ApiPlatform\Metadata\HttpOperation;
25
use ApiPlatform\Metadata\Patch;
26
use ApiPlatform\Metadata\Post;
27
use ApiPlatform\Metadata\Put;
28
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory;
29
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
30
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeConfigOperations;
31
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeDefaultOperations;
32
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeOnlyOperation;
33
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeResource;
34
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeResources;
35
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\ExtraPropertiesResource;
36
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\PasswordResource;
37
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\WithParameter;
38
use ApiPlatform\Metadata\Tests\Fixtures\State\AttributeResourceProcessor;
39
use ApiPlatform\Metadata\Tests\Fixtures\State\AttributeResourceProvider;
40
use PHPUnit\Framework\TestCase;
41
use Prophecy\PhpUnit\ProphecyTrait;
42

43
/**
44
 * @author Antoine Bluchet <soyuka@gmail.com>
45
 */
46
class AttributesResourceMetadataCollectionFactoryTest extends TestCase
47
{
48
    use ProphecyTrait;
49

50
    private function getDefaultGraphqlOperations(string $shortName, string $class, mixed $provider = null): array
51
    {
52
        return [
×
53
            'collection_query' => new QueryCollection(shortName: $shortName, class: $class, normalizationContext: ['skip_null_values' => true], provider: $provider),
×
54
            'item_query' => new Query(shortName: $shortName, class: $class, normalizationContext: ['skip_null_values' => true], provider: $provider),
×
55
            'update' => new Mutation(shortName: $shortName, class: $class, normalizationContext: ['skip_null_values' => true], name: 'update', description: "Updates a $shortName.", provider: $provider),
×
56
            'delete' => new DeleteMutation(shortName: $shortName, class: $class, normalizationContext: ['skip_null_values' => true], name: 'delete', description: "Deletes a $shortName.", provider: $provider),
×
57
            'create' => new Mutation(shortName: $shortName, class: $class, normalizationContext: ['skip_null_values' => true], name: 'create', description: "Creates a $shortName.", provider: $provider),
×
58
        ];
×
59
    }
60

61
    public function testCreate(): void
62
    {
63
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(graphQlEnabled: true);
×
64

65
        $this->assertEquals(
×
66
            new ResourceMetadataCollection(AttributeResource::class, [
×
67
                new ApiResource(
×
68
                    shortName: 'AttributeResource',
×
69
                    normalizationContext: ['skip_null_values' => true],
×
70
                    class: AttributeResource::class,
×
71
                    provider: AttributeResourceProvider::class,
×
72
                    operations: [
×
73
                        '_api_AttributeResource_get' => new Get(
×
NEW
74
                            shortName: 'AttributeResource',
×
NEW
75
                            class: AttributeResource::class,
×
NEW
76
                            normalizationContext: ['skip_null_values' => true],
×
NEW
77
                            priority: 1,
×
NEW
78
                            provider: AttributeResourceProvider::class,
×
79
                        ),
×
80
                        '_api_AttributeResource_put' => new Put(
×
NEW
81
                            shortName: 'AttributeResource',
×
NEW
82
                            class: AttributeResource::class,
×
NEW
83
                            normalizationContext: ['skip_null_values' => true],
×
NEW
84
                            priority: 2,
×
NEW
85
                            provider: AttributeResourceProvider::class,
×
86
                        ),
×
87
                        '_api_AttributeResource_delete' => new Delete(
×
NEW
88
                            shortName: 'AttributeResource',
×
NEW
89
                            class: AttributeResource::class,
×
NEW
90
                            normalizationContext: ['skip_null_values' => true],
×
NEW
91
                            priority: 3,
×
NEW
92
                            provider: AttributeResourceProvider::class,
×
93
                        ),
×
94
                    ],
×
95
                    graphQlOperations: $this->getDefaultGraphqlOperations('AttributeResource', AttributeResource::class, AttributeResourceProvider::class)
×
96
                ),
×
97
                new ApiResource(
×
98
                    shortName: 'AttributeResource',
×
99
                    class: AttributeResource::class,
×
100
                    uriTemplate: '/dummy/{dummyId}/attribute_resources/{identifier}{._format}',
×
101
                    operations: [
×
102
                        '_api_/dummy/{dummyId}/attribute_resources/{identifier}{._format}_get' => new Get(
×
103
                            class: AttributeResource::class,
×
104
                            uriTemplate: '/dummy/{dummyId}/attribute_resources/{identifier}{._format}',
×
105
                            shortName: 'AttributeResource',
×
106
                            inputFormats: ['json' => ['application/merge-patch+json']],
×
107
                            priority: 4,
×
108
                            status: 301,
×
109
                            provider: AttributeResourceProvider::class,
×
110
                            processor: [AttributeResourceProcessor::class, 'process']
×
111
                        ),
×
112
                        '_api_/dummy/{dummyId}/attribute_resources/{identifier}{._format}_patch' => new Patch(
×
113
                            class: AttributeResource::class,
×
114
                            uriTemplate: '/dummy/{dummyId}/attribute_resources/{identifier}{._format}',
×
115
                            shortName: 'AttributeResource',
×
116
                            inputFormats: ['json' => ['application/merge-patch+json']],
×
117
                            priority: 5,
×
118
                            status: 301,
×
119
                            provider: AttributeResourceProvider::class,
×
120
                            processor: [AttributeResourceProcessor::class, 'process']
×
121
                        ),
×
122
                    ],
×
123
                    inputFormats: ['json' => ['application/merge-patch+json']],
×
124
                    status: 301,
×
125
                    provider: AttributeResourceProvider::class,
×
126
                    processor: [AttributeResourceProcessor::class, 'process']
×
127
                ),
×
128
            ]),
×
129
            $attributeResourceMetadataCollectionFactory->create(AttributeResource::class)
×
130
        );
×
131

132
        $this->assertEquals(
×
133
            new ResourceMetadataCollection(AttributeResources::class, [
×
134
                new ApiResource(
×
135
                    uriTemplate: '/attribute_resources{._format}',
×
136
                    shortName: 'AttributeResources',
×
137
                    normalizationContext: ['skip_null_values' => true],
×
138
                    class: AttributeResources::class,
×
139
                    provider: AttributeResourceProvider::class,
×
140
                    operations: [
×
141
                        '_api_/attribute_resources{._format}_get_collection' => new GetCollection(
×
142
                            shortName: 'AttributeResources', class: AttributeResources::class, uriTemplate: '/attribute_resources{._format}', normalizationContext: ['skip_null_values' => true], priority: 1, provider: AttributeResourceProvider::class,
×
143
                        ),
×
144
                        '_api_/attribute_resources{._format}_post' => new Post(
×
145
                            shortName: 'AttributeResources', class: AttributeResources::class, uriTemplate: '/attribute_resources{._format}', normalizationContext: ['skip_null_values' => true], priority: 2, provider: AttributeResourceProvider::class,
×
146
                        ),
×
147
                    ],
×
148
                    graphQlOperations: $this->getDefaultGraphqlOperations('AttributeResources', AttributeResources::class, AttributeResourceProvider::class)
×
149
                ),
×
150
            ]),
×
151
            $attributeResourceMetadataCollectionFactory->create(AttributeResources::class)
×
152
        );
×
153
    }
154

155
    public function testCreateWithDefaults(): void
156
    {
157
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(null, null, [
×
158
            'cache_headers' => [
×
159
                'max_age' => 60,
×
160
                'shared_max_age' => 120,
×
161
                'public' => true,
×
162
            ],
×
163
            'extra_properties' => ['standard_put' => true],
×
164
            'non_existing_attribute' => 'foo',
×
165
        ]);
×
166

167
        // Check the AttributeDefaultOperations it specifies a shared_max_age that should not be overridden
168
        $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, cacheHeaders: ['max_age' => 60, 'shared_max_age' => 60, 'public' => true], paginationItemsPerPage: 10, extraProperties: ['non_existing_attribute' => 'foo', 'generated_operation' => true, 'standard_put' => true]);
×
169

170
        $this->assertEquals(new ResourceMetadataCollection(AttributeDefaultOperations::class, [
×
171
            new ApiResource(
×
172
                shortName: 'AttributeDefaultOperations',
×
173
                class: AttributeDefaultOperations::class,
×
174
                graphQlOperations: [],
×
175
                operations: [
×
176
                    '_api_AttributeDefaultOperations_get' => (new Get())->withOperation($operation),
×
177
                    '_api_AttributeDefaultOperations_get_collection' => (new GetCollection())->withOperation($operation),
×
178
                    '_api_AttributeDefaultOperations_post' => (new Post())->withOperation($operation),
×
179
                    '_api_AttributeDefaultOperations_patch' => (new Patch())->withOperation($operation),
×
180
                    '_api_AttributeDefaultOperations_delete' => (new Delete())->withOperation($operation),
×
181
                ],
×
182
                cacheHeaders: ['max_age' => 60, 'shared_max_age' => 60, 'public' => true],
×
183
                paginationItemsPerPage: 10,
×
184
                extraProperties: ['non_existing_attribute' => 'foo', 'standard_put' => true]
×
185
            ),
×
186
        ]), $attributeResourceMetadataCollectionFactory->create(AttributeDefaultOperations::class));
×
187
    }
188

189
    public function testCreateWithConfigOperations(): void
190
    {
191
        $attributesResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(defaults: ['operations' => [Get::class, Post::class]]);
×
192

193
        $this->assertEquals(new ResourceMetadataCollection(AttributeConfigOperations::class, [
×
194
            new ApiResource(
×
195
                shortName: 'AttributeConfigOperations',
×
196
                operations: [
×
197
                    '_api_AttributeConfigOperations_get' => new Get(shortName: 'AttributeConfigOperations', class: AttributeConfigOperations::class, priority: 0, extraProperties: ['generated_operation' => true]),
×
198
                    '_api_AttributeConfigOperations_post' => new Post(shortName: 'AttributeConfigOperations', class: AttributeConfigOperations::class, priority: 1, extraProperties: ['generated_operation' => true]),
×
199
                ],
×
200
                class: AttributeConfigOperations::class,
×
201
            ),
×
202
        ]), $attributesResourceMetadataCollectionFactory->create(AttributeConfigOperations::class));
×
203
    }
204

205
    public function testCreateShouldNotOverrideWithDefault(): void
206
    {
207
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(
×
208
            null, null, [
×
209
                'pagination_items_per_page' => 3,
×
210
            ]
×
211
        );
×
212

213
        $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, paginationItemsPerPage: 10, cacheHeaders: ['shared_max_age' => 60], extraProperties: ['generated_operation' => true]);
×
214
        $this->assertEquals(new ResourceMetadataCollection(AttributeDefaultOperations::class, [
×
215
            new ApiResource(
×
216
                shortName: 'AttributeDefaultOperations',
×
217
                class: AttributeDefaultOperations::class,
×
218
                operations: [
×
219
                    '_api_AttributeDefaultOperations_get' => (new Get())->withOperation($operation),
×
220
                    '_api_AttributeDefaultOperations_get_collection' => (new GetCollection())->withOperation($operation),
×
221
                    '_api_AttributeDefaultOperations_post' => (new Post())->withOperation($operation),
×
222
                    '_api_AttributeDefaultOperations_patch' => (new Patch())->withOperation($operation),
×
223
                    '_api_AttributeDefaultOperations_delete' => (new Delete())->withOperation($operation),
×
224
                ],
×
225
                cacheHeaders: ['shared_max_age' => 60],
×
226
                graphQlOperations: [],
×
227
                paginationItemsPerPage: 10
×
228
            ),
×
229
        ]), $attributeResourceMetadataCollectionFactory->create(AttributeDefaultOperations::class));
×
230
    }
231

232
    public function testExtraProperties(): void
233
    {
234
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory();
×
235
        $extraPropertiesResource = $attributeResourceMetadataCollectionFactory->create(ExtraPropertiesResource::class);
×
236

237
        $this->assertEquals($extraPropertiesResource[0]->getExtraProperties(), ['foo' => 'bar']);
×
238
        $this->assertEquals($extraPropertiesResource->getOperation('_api_ExtraPropertiesResource_get')->getExtraProperties(), ['foo' => 'bar']);
×
239
    }
240

241
    public function testOverrideNameWithoutOperations(): void
242
    {
243
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory();
×
244

245
        $operation = new HttpOperation(shortName: 'AttributeOnlyOperation', class: AttributeOnlyOperation::class);
×
246
        $this->assertEquals(new ResourceMetadataCollection(AttributeOnlyOperation::class, [
×
247
            new ApiResource(
×
248
                shortName: 'AttributeOnlyOperation',
×
249
                class: AttributeOnlyOperation::class,
×
250
                operations: [
×
251
                    'my own name' => (new Get(name: 'my own name', priority: 1))->withOperation($operation),
×
252
                ]
×
253
            ),
×
254
        ]), $attributeResourceMetadataCollectionFactory->create(AttributeOnlyOperation::class));
×
255
    }
256

257
    /**
258
     * Tests issue #5235.
259
     */
260
    public function testNameDeclarationShouldNotBeRemoved(): void
261
    {
262
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory();
×
263

264
        $metadataCollection = $attributeResourceMetadataCollectionFactory->create(PasswordResource::class);
×
265
        $operations = $metadataCollection[0]->getOperations();
×
266
        $this->assertTrue($operations->has('password_set'));
×
267
        $this->assertTrue($operations->has('password_reset_token'));
×
268
        $this->assertTrue($operations->has('password_reset'));
×
269
    }
270

271
    public function testWithParameters(): void
272
    {
273
        $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory();
×
274

275
        $metadataCollection = $attributeResourceMetadataCollectionFactory->create(WithParameter::class);
×
276
        $parameters = $metadataCollection[0]->getParameters();
×
277
        $this->assertCount(2, $parameters);
×
278
        $parameters = $metadataCollection->getOperation('collection')->getParameters();
×
279
        $this->assertCount(3, $parameters);
×
280
    }
281
}
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