Completed
Push — master ( dd40bf...739ea2 )
by Asmir
18:26 queued 13:49
created

DependencyInjection/JMSSerializerExtensionTest.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * Copyright 2011 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\SerializerBundle\Tests\DependencyInjection;
20
21
use Doctrine\Common\Annotations\AnnotationReader;
22
use JMS\Serializer\SerializationContext;
23
use JMS\SerializerBundle\JMSSerializerBundle;
24
use JMS\SerializerBundle\Tests\DependencyInjection\Fixture\ObjectUsingExpressionLanguage;
25
use JMS\SerializerBundle\Tests\DependencyInjection\Fixture\ObjectUsingExpressionProperties;
26
use JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SimpleObject;
27
use JMS\SerializerBundle\Tests\DependencyInjection\Fixture\VersionedObject;
28
use PHPUnit\Framework\TestCase;
29
use Symfony\Component\DependencyInjection\ContainerBuilder;
30
use Symfony\Component\DependencyInjection\Definition;
31
32
class JMSSerializerExtensionTest extends TestCase
33
{
34
    protected function setUp()
35
    {
36
        $this->clearTempDir();
37
    }
38
39
    protected function tearDown()
40
    {
41
        $this->clearTempDir();
42
    }
43
44
    private function clearTempDir()
45
    {
46
        // clear temporary directory
47
        $dir = sys_get_temp_dir() . '/serializer';
48
        if (is_dir($dir)) {
49
            foreach (new \RecursiveDirectoryIterator($dir) as $file) {
50
                $filename = $file->getFileName();
51
                if ('.' === $filename || '..' === $filename) {
52
                    continue;
53
                }
54
55
                @unlink($file->getPathName());
56
            }
57
58
            @rmdir($dir);
59
        }
60
    }
61
62
    public function testHasContextFactories()
63
    {
64
        $container = $this->getContainerForConfig(array(array()));
65
66
        $factory = $container->get('jms_serializer.serialization_context_factory');
67
        $this->assertInstanceOf('JMS\Serializer\ContextFactory\SerializationContextFactoryInterface', $factory);
68
69
        $factory = $container->get('jms_serializer.deserialization_context_factory');
70
        $this->assertInstanceOf('JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface', $factory);
71
    }
72
73
    public function testSerializerContextFactoriesAreSet()
74
    {
75
        $container = $this->getContainerForConfig(array(array()));
76
77
        $def = $container->getDefinition('jms_serializer');
78
        $calls = $def->getMethodCalls();
79
80
        $this->assertCount(2, $calls);
81
82
        $serializationCall = $calls[0];
83
        $this->assertEquals('setSerializationContextFactory', $serializationCall[0]);
84
        $this->assertEquals('jms_serializer.serialization_context_factory', (string)$serializationCall[1][0]);
85
86
        $serializationCall = $calls[1];
87
        $this->assertEquals('setDeserializationContextFactory', $serializationCall[0]);
88
        $this->assertEquals('jms_serializer.deserialization_context_factory', (string)$serializationCall[1][0]);
89
    }
90
91
    public function testSerializerContextFactoriesWithId()
92
    {
93
        $config = array(
94
            'default_context' => array(
95
                'serialization' => array(
96
                    'id' => 'foo'
97
                ),
98
                'deserialization' => array(
99
                    'id' => 'bar'
100
                )
101
            )
102
        );
103
104
        $foo = new Definition('stdClass');
105
        $foo->setPublic(true);
106
        $bar = new Definition('stdClass');
107
        $bar->setPublic(true);
108
109
        $container = $this->getContainerForConfig(array($config), function (ContainerBuilder $containerBuilder) use ($foo, $bar) {
110
            $containerBuilder->setDefinition('foo', $foo);
111
            $containerBuilder->setDefinition('bar', $bar);
112
        });
113
114
        $def = $container->getDefinition('jms_serializer');
115
        $calls = $def->getMethodCalls();
116
117
        $this->assertCount(2, $calls);
118
119
        $serializationCall = $calls[0];
120
        $this->assertEquals('setSerializationContextFactory', $serializationCall[0]);
121
        $this->assertEquals('foo', (string)$serializationCall[1][0]);
122
123
        $serializationCall = $calls[1];
124
        $this->assertEquals('setDeserializationContextFactory', $serializationCall[0]);
125
        $this->assertEquals('bar', (string)$serializationCall[1][0]);
126
127
        $this->assertEquals('bar', (string)$container->getAlias('jms_serializer.deserialization_context_factory'));
128
        $this->assertEquals('foo', (string)$container->getAlias('jms_serializer.serialization_context_factory'));
129
    }
130
131
    public function testLoadWithoutTranslator()
132
    {
133
        $container = $this->getContainerForConfig(array(array()), function (ContainerBuilder $containerBuilder) {
134
            $containerBuilder->set('translator', null);
135
            $containerBuilder->getDefinition('jms_serializer.form_error_handler')->setPublic(true);
136
        });
137
138
        $def = $container->getDefinition('jms_serializer.form_error_handler');
139
        $this->assertSame(null, $def->getArgument(0));
140
    }
141
142
    public function testConfiguringContextFactories()
143
    {
144
        $container = $this->getContainerForConfig(array(array()));
145
146
        $def = $container->getDefinition('jms_serializer.serialization_context_factory');
147
        $this->assertCount(0, $def->getMethodCalls());
148
149
        $def = $container->getDefinition('jms_serializer.deserialization_context_factory');
150
        $this->assertCount(0, $def->getMethodCalls());
151
    }
152
153
    public function testConfiguringContextFactoriesWithParams()
154
    {
155
        $config = array(
156
            'default_context' => array(
157
                'serialization' => array(
158
                    'version' => 1600,
159
                    'serialize_null' => true,
160
                    'attributes' => array('x' => 1720),
161
                    'groups' => array('Default', 'Registration'),
162
                    'enable_max_depth_checks' => true,
163
                ),
164
                'deserialization' => array(
165
                    'version' => 1640,
166
                    'serialize_null' => false,
167
                    'attributes' => array('x' => 1740),
168
                    'groups' => array('Default', 'Profile'),
169
                    'enable_max_depth_checks' => true,
170
                )
171
            )
172
        );
173
174
        $container = $this->getContainerForConfig(array($config));
175
        $services = [
176
            'serialization' => 'jms_serializer.serialization_context_factory',
177
            'deserialization' => 'jms_serializer.deserialization_context_factory',
178
        ];
179
        foreach ($services as $configKey => $serviceId) {
180
            $def = $container->getDefinition($serviceId);
181
            $values = $config['default_context'][$configKey];
182
183
            $this->assertSame($values['version'], $this->getDefinitionMethodCall($def, 'setVersion')[0]);
184
            $this->assertSame($values['serialize_null'], $this->getDefinitionMethodCall($def, 'setSerializeNulls')[0]);
185
            $this->assertSame($values['attributes'], $this->getDefinitionMethodCall($def, 'setAttributes')[0]);
186
            $this->assertSame($values['groups'], $this->getDefinitionMethodCall($def, 'setGroups')[0]);
187
            $this->assertSame($values['groups'], $this->getDefinitionMethodCall($def, 'setGroups')[0]);
188
            $this->assertSame(array(), $this->getDefinitionMethodCall($def, 'enableMaxDepthChecks'));
189
        }
190
    }
191
192
    public function testConfiguringContextFactoriesWithNullDefaults()
193
    {
194
        $config = array(
195
            'default_context' => array(
196
                'serialization' => array(
197
                    'version' => null,
198
                    'serialize_null' => null,
199
                    'attributes' => [],
200
                    'groups' => null,
201
                ),
202
                'deserialization' => array(
203
                    'version' => null,
204
                    'serialize_null' => null,
205
                    'attributes' => null,
206
                    'groups' => null,
207
                )
208
            )
209
        );
210
211
        $container = $this->getContainerForConfig(array($config));
212
        $services = [
213
            'serialization' => 'jms_serializer.serialization_context_factory',
214
            'deserialization' => 'jms_serializer.deserialization_context_factory',
215
        ];
216
        foreach ($services as $configKey => $serviceId) {
217
            $def = $container->getDefinition($serviceId);
218
            $this->assertCount(0, $def->getMethodCalls());
219
        }
220
    }
221
222
    private function getDefinitionMethodCall(Definition $def, $method)
223
    {
224
        foreach ($def->getMethodCalls() as $call) {
225
            if ($call[0] === $method) {
226
                return $call[1];
227
            }
228
        }
229
        return false;
230
    }
231
232
    public function testLoad()
233
    {
234
        $container = $this->getContainerForConfig(array(array()), function (ContainerBuilder $container) {
235
            $container->getDefinition('jms_serializer.doctrine_object_constructor')->setPublic(true);
236
            $container->getDefinition('jms_serializer.array_collection_handler')->setPublic(true);
237
            $container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->setPublic(true);
238
            $container->getAlias('JMS\Serializer\SerializerInterface')->setPublic(true);
239
            $container->getAlias('JMS\Serializer\ArrayTransformerInterface')->setPublic(true);
240
        });
241
242
        $simpleObject = new SimpleObject('foo', 'bar');
243
        $versionedObject = new VersionedObject('foo', 'bar');
244
        $serializer = $container->get('jms_serializer');
245
246
        $this->assertTrue($container->has('JMS\Serializer\SerializerInterface'), 'Alias should be defined to allow autowiring');
247
        $this->assertTrue($container->has('JMS\Serializer\ArrayTransformerInterface'), 'Alias should be defined to allow autowiring');
248
249
        $this->assertFalse($container->getDefinition('jms_serializer.array_collection_handler')->getArgument(0));
250
251
        // the logic is inverted because arg 0 on doctrine_proxy_subscriber is $skipVirtualTypeInit = false
252
        $this->assertTrue($container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->getArgument(0));
253
        $this->assertFalse($container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->getArgument(1));
254
255
        $this->assertEquals("null", $container->getDefinition('jms_serializer.doctrine_object_constructor')->getArgument(2));
256
257
        // test that all components have been wired correctly
258
        $this->assertEquals(json_encode(array('name' => 'bar')), $serializer->serialize($versionedObject, 'json'));
259
        $this->assertEquals($simpleObject, $serializer->deserialize($serializer->serialize($simpleObject, 'json'), get_class($simpleObject), 'json'));
260
        $this->assertEquals($simpleObject, $serializer->deserialize($serializer->serialize($simpleObject, 'xml'), get_class($simpleObject), 'xml'));
261
262
        $this->assertEquals(json_encode(array('name' => 'foo')), $serializer->serialize($versionedObject, 'json', SerializationContext::create()->setVersion('0.0.1')));
263
264
        $this->assertEquals(json_encode(array('name' => 'bar')), $serializer->serialize($versionedObject, 'json', SerializationContext::create()->setVersion('1.1.1')));
265
    }
266
267
    public function testLoadWithOptions()
268
    {
269
        $container = $this->getContainerForConfig(array(array(
270
            'subscribers' => [
271
                'doctrine_proxy' => [
272
                    'initialize_virtual_types' => true,
273
                    'initialize_excluded' => true,
274
                ],
275
            ],
276
            'object_constructors' => [
277
                'doctrine' => [
278
                    'fallback_strategy' => "exception",
279
                ],
280
            ],
281
            'handlers' => [
282
                'array_collection' => [
283
                    'initialize_excluded' => true,
284
                ],
285
            ],
286
        )), function ($container) {
287
            $container->getDefinition('jms_serializer.doctrine_object_constructor')->setPublic(true);
288
            $container->getDefinition('jms_serializer.array_collection_handler')->setPublic(true);
289
            $container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->setPublic(true);
290
        });
291
292
        $this->assertTrue($container->getDefinition('jms_serializer.array_collection_handler')->getArgument(0));
293
294
        // the logic is inverted because arg 0 on doctrine_proxy_subscriber is $skipVirtualTypeInit = false
295
        $this->assertFalse($container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->getArgument(0));
296
        $this->assertTrue($container->getDefinition('jms_serializer.doctrine_proxy_subscriber')->getArgument(1));
297
298
        $this->assertEquals("exception", $container->getDefinition('jms_serializer.doctrine_object_constructor')->getArgument(2));
299
    }
300
301
    public function testLoadExistentMetadataDir()
302
    {
303
        $container = $this->getContainerForConfig(array(array(
304
            'metadata' => [
305
                'directories' => [
306
                    'foo' => [
307
                        'namespace_prefix' => 'foo_ns',
308
                        'path' => __DIR__,
309
                    ]
310
                ]
311
            ]
312
        )), function ($container) {
313
            $container->getDefinition('jms_serializer.metadata.file_locator')->setPublic(true);
314
        });
315
316
        $fileLocatorDef = $container->getDefinition('jms_serializer.metadata.file_locator');
317
        $directories = $fileLocatorDef->getArgument(0);
318
        $this->assertEquals(['foo_ns' => __DIR__], $directories);
319
    }
320
321
    /**
322
     * @expectedException \JMS\Serializer\Exception\RuntimeException
323
     * @expectedExceptionMessage  The metadata directory "foo_dir" does not exist for the namespace "foo_ns"
324
     */
325
    public function testLoadNotExistentMetadataDir()
326
    {
327
        $this->getContainerForConfig(array(array(
328
            'metadata' => [
329
                'directories' => [
330
                    'foo' => [
331
                        'namespace_prefix' => 'foo_ns',
332
                        'path' => 'foo_dir',
333
                    ]
334
                ]
335
            ]
336
        )));
337
    }
338
339
    /**
340
     * @dataProvider getJsonVisitorConfigs
341
     */
342 View Code Duplication
    public function testJsonVisitorOptions($expectedOptions, $config)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
343
    {
344
        $container = $this->getContainerForConfig(array($config), function ($container) {
345
            $container->getDefinition('jms_serializer.json_serialization_visitor')->setPublic(true);
346
        });
347
        $this->assertSame($expectedOptions, $container->get('jms_serializer.json_serialization_visitor')->getOptions());
348
    }
349
350
    public function getJsonVisitorConfigs()
351
    {
352
        $configs = array();
353
354
        if (version_compare(PHP_VERSION, '5.4', '>=')) {
355
            $configs[] = array(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT, array(
356
                'visitors' => array(
357
                    'json' => array(
358
                        'options' => array('JSON_UNESCAPED_UNICODE', 'JSON_PRETTY_PRINT')
359
                    )
360
                )
361
            ));
362
363
            $configs[] = array(JSON_UNESCAPED_UNICODE, array(
364
                'visitors' => array(
365
                    'json' => array(
366
                        'options' => 'JSON_UNESCAPED_UNICODE'
367
                    )
368
                )
369
            ));
370
        }
371
372
        $configs[] = array(128, array(
373
            'visitors' => array(
374
                'json' => array(
375
                    'options' => 128
376
                )
377
            )
378
        ));
379
380
        $configs[] = array(0, array());
381
382
        return $configs;
383
    }
384
385
    public function testExpressionLanguage()
386
    {
387
        if (!interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
388
            $this->markTestSkipped("The Symfony Expression Language is not available");
389
        }
390
        $container = $this->getContainerForConfig(array(array()));
391
        $serializer = $container->get('jms_serializer');
392
        // test that all components have been wired correctly
393
        $object = new ObjectUsingExpressionLanguage('foo', true);
394
        $this->assertEquals('{"name":"foo"}', $serializer->serialize($object, 'json'));
395
        $object = new ObjectUsingExpressionLanguage('foo', false);
396
        $this->assertEquals('{}', $serializer->serialize($object, 'json'));
397
    }
398
399
    public function testExpressionLanguageVirtualProperties()
400
    {
401
        if (!interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
402
            $this->markTestSkipped("The Symfony Expression Language is not available");
403
        }
404
        $container = $this->getContainerForConfig(array(array()));
405
        $serializer = $container->get('jms_serializer');
406
        // test that all components have been wired correctly
407
        $object = new ObjectUsingExpressionProperties('foo');
408
        $this->assertEquals('{"v_prop_name":"foo"}', $serializer->serialize($object, 'json'));
409
    }
410
411
    /**
412
     * @expectedException \JMS\Serializer\Exception\ExpressionLanguageRequiredException
413
     */
414
    public function testExpressionLanguageDisabledVirtualProperties()
415
    {
416
        if (!interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
417
            $this->markTestSkipped("The Symfony Expression Language is not available");
418
        }
419
        $container = $this->getContainerForConfig(array(array('expression_evaluator' => array('id' => null))));
420
        $serializer = $container->get('jms_serializer');
421
        // test that all components have been wired correctly
422
        $object = new ObjectUsingExpressionProperties('foo');
423
        $serializer->serialize($object, 'json');
424
    }
425
426
    /**
427
     * @expectedException \JMS\Serializer\Exception\ExpressionLanguageRequiredException
428
     * @expectedExceptionMessage  To use conditional exclude/expose in JMS\SerializerBundle\Tests\DependencyInjection\Fixture\ObjectUsingExpressionLanguage you must configure the expression language.
429
     */
430
    public function testExpressionLanguageNotLoaded()
431
    {
432
        $container = $this->getContainerForConfig(array(array('expression_evaluator' => array('id' => null))));
433
        $serializer = $container->get('jms_serializer');
434
        // test that all components have been wired correctly
435
        $object = new ObjectUsingExpressionLanguage('foo', true);
436
        $serializer->serialize($object, 'json');
437
    }
438
439
    /**
440
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
441
     * @expectedExceptionMessage Invalid configuration for path "jms_serializer.expression_evaluator.id": You need at least symfony/expression language v2.6 or v3.0 to use the expression evaluator features
442
     */
443
    public function testExpressionInvalidEvaluator()
444
    {
445
        if (interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
446
            $this->markTestSkipped('To pass this test the "symfony/expression-language" component should be available');
447
        }
448
        $this->getContainerForConfig(array(array('expression_evaluator' => array('id' => 'foo'))));
449
    }
450
451
    /**
452
     * @dataProvider getXmlVisitorWhitelists
453
     */
454 View Code Duplication
    public function testXmlVisitorOptions($expectedOptions, $config)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
455
    {
456
        $container = $this->getContainerForConfig(array($config), function ($container) {
457
            $container->getDefinition('jms_serializer.xml_deserialization_visitor')->setPublic(true);
458
        });
459
        $this->assertSame($expectedOptions, $container->get('jms_serializer.xml_deserialization_visitor')->getDoctypeWhitelist());
460
    }
461
462
    public function getXmlVisitorWhitelists()
463
    {
464
        $configs = array();
465
466
        $configs[] = array(array('good document', 'other good document'), array(
467
            'visitors' => array(
468
                'xml' => array(
469
                    'doctype_whitelist' => array('good document', 'other good document'),
470
                )
471
            )
472
        ));
473
474
        $configs[] = array(array(), array());
475
476
        return $configs;
477
    }
478
479
    public function testXmlVisitorFormatOutput()
480
    {
481
        $config = array(
482
            'visitors' => array(
483
                'xml' => array(
484
                    'format_output' => false,
485
                )
486
            )
487
        );
488
        $container = $this->getContainerForConfig(array($config), function ($container) {
489
            $container->getDefinition('jms_serializer.xml_serialization_visitor')->setPublic(true);
490
        });
491
492
        $this->assertFalse($container->get('jms_serializer.xml_serialization_visitor')->isFormatOutput());
493
    }
494
495
    public function testXmlVisitorDefaultValueToFormatOutput()
496
    {
497
        $container = $this->getContainerForConfig(array(), function ($container) {
498
            $container->getDefinition('jms_serializer.xml_serialization_visitor')->setPublic(true);
499
        });
500
        $this->assertTrue($container->get('jms_serializer.xml_serialization_visitor')->isFormatOutput());
501
    }
502
503
    private function getContainerForConfig(array $configs, callable $configurator = null)
504
    {
505
        $bundle = new JMSSerializerBundle();
506
        $extension = $bundle->getContainerExtension();
507
508
        $container = new ContainerBuilder();
509
        $container->setParameter('kernel.debug', true);
510
        $container->setParameter('kernel.cache_dir', sys_get_temp_dir() . '/serializer');
511
        $container->setParameter('kernel.bundles', array());
512
        $container->set('annotation_reader', new AnnotationReader());
513
        $container->setDefinition('doctrine', new Definition(Registry::class));
514
        $container->set('translator', $this->getMockBuilder('Symfony\\Component\\Translation\\TranslatorInterface')->getMock());
515
        $container->set('debug.stopwatch', $this->getMockBuilder('Symfony\\Component\\Stopwatch\\Stopwatch')->getMock());
516
        $container->registerExtension($extension);
517
        $extension->load($configs, $container);
518
519
        $bundle->build($container);
520
521
        if ($configurator) {
522
            call_user_func($configurator, $container);
523
        }
524
525
        $container->compile();
526
527
        return $container;
528
    }
529
}
530