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

api-platform / core / 20519317585

26 Dec 2025 08:38AM UTC coverage: 25.193% (-0.01%) from 25.206%
20519317585

push

github

web-flow
fix(test): change string to int for status in JsonApiTest::testError (#7631)

14623 of 58043 relevant lines covered (25.19%)

29.57 hits per line

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

0.0
/src/Serializer/Tests/SerializerContextBuilderTest.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\Serializer\Tests;
15

16
use ApiPlatform\Metadata\ApiResource;
17
use ApiPlatform\Metadata\Exception\RuntimeException;
18
use ApiPlatform\Metadata\Get;
19
use ApiPlatform\Metadata\HttpOperation;
20
use ApiPlatform\Metadata\Patch;
21
use ApiPlatform\Metadata\Put;
22
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
23
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
24
use ApiPlatform\Serializer\SerializerContextBuilder;
25
use PHPUnit\Framework\TestCase;
26
use Prophecy\PhpUnit\ProphecyTrait;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\Serializer\Encoder\CsvEncoder;
29

30
/**
31
 * @author Kévin Dunglas <dunglas@gmail.com>
32
 */
33
class SerializerContextBuilderTest extends TestCase
34
{
35
    use ProphecyTrait;
36

37
    private SerializerContextBuilder $builder;
38
    private HttpOperation $operation;
39
    private HttpOperation $patchOperation;
40
    private HttpOperation $patchCollectionOperation;
41

42
    protected function setUp(): void
43
    {
44
        $this->operation = new Get(normalizationContext: ['foo' => 'bar'], denormalizationContext: ['bar' => 'baz'], name: 'get');
×
45
        $resourceMetadata = new ResourceMetadataCollection('Foo', [
×
46
            new ApiResource(operations: [
×
47
                'get' => $this->operation,
×
48
                'post' => $this->operation->withName('post'),
×
49
                'put' => (new Put(name: 'put'))->withOperation($this->operation),
×
50
                'get_collection' => $this->operation->withName('get_collection'),
×
51
            ]),
×
52
        ]);
×
53

54
        $this->patchOperation = new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'csv' => ['text/csv']], name: 'patch');
×
55
        $this->patchCollectionOperation = $this->patchOperation
×
56
            ->withDenormalizationContext([CsvEncoder::AS_COLLECTION_KEY => true])
×
57
            ->withName('patch_collection');
×
58
        $resourceMetadataWithPatch = new ResourceMetadataCollection('Foo', [
×
59
            new ApiResource(operations: [
×
60
                'patch' => $this->patchOperation,
×
61
                'patch_collection' => $this->patchCollectionOperation,
×
62
            ]),
×
63
        ]);
×
64

65
        $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
×
66
        $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata);
×
67
        $resourceMetadataFactoryProphecy->create('FooWithPatch')->willReturn($resourceMetadataWithPatch);
×
68

69
        $this->builder = new SerializerContextBuilder($resourceMetadataFactoryProphecy->reveal());
×
70
    }
71

72
    public function testCreateFromRequest(): void
73
    {
74
        $request = Request::create('/foos/1');
×
75
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
76
        $expected = ['foo' => 'bar', 'operation_name' => 'get',  'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
77
        $this->assertEquals($expected, $this->builder->createFromRequest($request, true));
×
78

79
        $request = Request::create('/foos');
×
80
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get_collection', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
81
        $expected = ['foo' => 'bar', 'operation_name' => 'get_collection',  'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata',  'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
82
        $this->assertEquals($expected, $this->builder->createFromRequest($request, true));
×
83

84
        $request = Request::create('/foos/1');
×
85
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
86
        $expected = ['bar' => 'baz', 'operation_name' => 'get',  'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
87
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
88

89
        $request = Request::create('/foos', 'POST');
×
90
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
91
        $expected = ['bar' => 'baz', 'operation_name' => 'post',  'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
92
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
93

94
        $request = Request::create('/foos', 'PUT');
×
95
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
96
        $expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => (new Put(name: 'put'))->withOperation($this->operation), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
97
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
98

99
        $request = Request::create('/bars/1/foos');
×
100
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
×
101
        $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
102
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
103

104
        $request = Request::create('/foowithpatch/1', 'PATCH');
×
105
        $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']);
×
106
        $expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
107
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
108

109
        $request = Request::create('/bars/1/foos');
×
110
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', 'id' => '1']);
×
111
        $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
112
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
113

114
        $request = Request::create('/foowithpatch/1', 'PATCH', server: ['CONTENT_TYPE' => 'text/csv']);
×
115
        $request->setFormat('csv', ['text/csv']);
×
116
        $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'csv', '_api_mime_type' => 'text/csv']);
×
117
        $expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
118
        $expected[CsvEncoder::AS_COLLECTION_KEY] = false;
×
119
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
120

121
        $request = Request::create('/foowithpatch/1', 'PATCH', server: ['CONTENT_TYPE' => 'text/csv']);
×
122
        $request->setFormat('csv', ['text/csv']);
×
123
        $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch_collection', '_api_format' => 'csv', '_api_mime_type' => 'text/csv']);
×
124
        $expected = ['operation_name' => 'patch_collection', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchCollectionOperation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
125
        $expected[CsvEncoder::AS_COLLECTION_KEY] = true;
×
126
        $this->assertEquals($expected, $this->builder->createFromRequest($request, false));
×
127
    }
128

129
    public function testThrowExceptionOnInvalidRequest(): void
130
    {
131
        $this->expectException(RuntimeException::class);
×
132

133
        $this->builder->createFromRequest(new Request(), false);
×
134
    }
135

136
    public function testReuseExistingAttributes(): void
137
    {
138
        $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id'], 'skip_null_to_one_relations' => true];
×
139
        $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'operation_name' => 'get']));
×
140
    }
141

142
    public function testCreateFromRequestKeyCollectDenormalizationErrorsIsInContext(): void
143
    {
144
        $operationWithCollectDenormalizationErrors = $this->operation->withCollectDenormalizationErrors(true);
×
145
        $request = Request::create('/foos', 'POST');
×
146
        $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_operation' => $operationWithCollectDenormalizationErrors]);
×
147
        $serializerContext = $this->builder->createFromRequest($request, false);
×
148
        $this->assertArrayHasKey('collect_denormalization_errors', $serializerContext);
×
149
        $this->assertTrue($serializerContext['collect_denormalization_errors']);
×
150
    }
151
}
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