‪TYPO3CMS  9.5
JsonViewTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
3 
5 
6 /*
7  * This file is part of the TYPO3 CMS project.
8  *
9  * It is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License, either version 2
11  * of the License, or any later version.
12  *
13  * For the full copyright and license information, please read the
14  * LICENSE.txt file that was distributed with this source code.
15  *
16  * The TYPO3 project - inspiring people to share!
17  */
18 
23 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
24 
28 class ‪JsonViewTest extends UnitTestCase
29 {
33  protected ‪$view;
34 
38  protected ‪$controllerContext;
39 
43  protected ‪$response;
44 
48  protected function ‪setUp(): void
49  {
50  $this->view = $this->getMockBuilder(JsonView::class)
51  ->setMethods(['loadConfigurationFromYamlFile'])
52  ->getMock();
53  $this->controllerContext = $this->createMock(ControllerContext::class);
54  $this->response = $this->createMock(Response::class);
55  $this->controllerContext->expects($this->any())->method('getResponse')->will($this->returnValue($this->response));
56  $this->view->setControllerContext($this->controllerContext);
57  }
58 
63  public function ‪jsonViewTestData(): array
64  {
65  ‪$output = [];
66 
67  $object = new \stdClass();
68  $object->value1 = 'foo';
69  $object->value2 = 1;
70  $configuration = [];
71  $expected = ['value1' => 'foo', 'value2' => 1];
72  ‪$output[] = [$object, $configuration, $expected, 'all direct child properties should be serialized'];
73 
74  $configuration = ['_only' => ['value1']];
75  $expected = ['value1' => 'foo'];
76  ‪$output[] = [$object, $configuration, $expected, 'if "only" properties are specified, only these should be serialized'];
77 
78  $configuration = ['_exclude' => ['value1']];
79  $expected = ['value2' => 1];
80  ‪$output[] = [$object, $configuration, $expected, 'if "exclude" properties are specified, they should not be serialized'];
81 
82  $object = new \stdClass();
83  $object->value1 = new \stdClass();
84  $object->value1->subvalue1 = 'Foo';
85  $object->value2 = 1;
86  $configuration = [];
87  $expected = ['value2' => 1];
88  ‪$output[] = [$object, $configuration, $expected, 'by default, sub objects of objects should not be serialized.'];
89 
90  $object = new \stdClass();
91  $object->value1 = ['subarray' => 'value'];
92  $object->value2 = 1;
93  $configuration = [];
94  $expected = ['value2' => 1];
95  ‪$output[] = [$object, $configuration, $expected, 'by default, sub arrays of objects should not be serialized.'];
96 
97  $object = ['foo' => 'bar', 1 => 'baz', 'deep' => ['test' => 'value']];
98  $configuration = [];
99  $expected = ['foo' => 'bar', 1 => 'baz', 'deep' => ['test' => 'value']];
100  ‪$output[] = [$object, $configuration, $expected, 'associative arrays should be serialized deeply'];
101 
102  $object = ['foo', 'bar'];
103  $configuration = [];
104  $expected = ['foo', 'bar'];
105  ‪$output[] = [$object, $configuration, $expected, 'numeric arrays should be serialized'];
106 
107  $nestedObject = new \stdClass();
108  $nestedObject->value1 = 'foo';
109  $object = [$nestedObject];
110  $configuration = [];
111  $expected = [['value1' => 'foo']];
112  ‪$output[] = [$object, $configuration, $expected, 'array of objects should be serialized'];
113 
114  $properties = ['foo' => 'bar', 'prohibited' => 'xxx'];
115  $nestedObject = $this->getMockBuilder($this->getUniqueId('Test'))
116  ->setMethods(['getName', 'getPath', 'getProperties', 'getOther'])
117  ->getMock();
118  $nestedObject->expects($this->any())->method('getName')->will($this->returnValue('name'));
119  $nestedObject->expects($this->any())->method('getPath')->will($this->returnValue('path'));
120  $nestedObject->expects($this->any())->method('getProperties')->will($this->returnValue($properties));
121  $nestedObject->expects($this->never())->method('getOther');
122  $object = $nestedObject;
123  $configuration = [
124  '_only' => ['name', 'path', 'properties'],
125  '_descend' => [
126  'properties' => [
127  '_exclude' => ['prohibited'],
128  ],
129  ],
130  ];
131  $expected = [
132  'name' => 'name',
133  'path' => 'path',
134  'properties' => ['foo' => 'bar'],
135  ];
136  ‪$output[] = [$object, $configuration, $expected, 'descending into arrays should be possible'];
137 
138  $nestedObject = new \stdClass();
139  $nestedObject->value1 = 'foo';
140  $value = new \SplObjectStorage();
141  $value->attach($nestedObject);
142  $configuration = [];
143  $expected = [['value1' => 'foo']];
144  ‪$output[] = [$value, $configuration, $expected, 'SplObjectStorage with objects should be serialized'];
145 
146  $dateTimeObject = new \DateTime('2011-02-03T03:15:23', new \DateTimeZone('UTC'));
147  $configuration = [];
148  $expected = '2011-02-03T03:15:23+00:00';
149  ‪$output[] = [$dateTimeObject, $configuration, $expected, 'DateTime object in UTC time zone could not be serialized.'];
150 
151  $dateTimeObject = new \DateTime('2013-08-15T15:25:30', new \DateTimeZone('America/Los_Angeles'));
152  $configuration = [];
153  $expected = '2013-08-15T15:25:30-07:00';
154  ‪$output[] = [$dateTimeObject, $configuration, $expected, 'DateTime object in America/Los_Angeles time zone could not be serialized.'];
155 
156  return ‪$output;
157  }
158 
167  public function ‪testTransformValue($object, array $configuration, $expected, string $description): void
168  {
169  $jsonView = $this->getAccessibleMock(JsonView::class, ['dummy'], [], '', false);
170 
171  $actual = $jsonView->_call('transformValue', $object, $configuration);
172 
173  $this->assertSame($expected, $actual, $description);
174  }
175 
180  public function ‪objectIdentifierExposureTestData(): array
181  {
182  ‪$output = [];
183 
184  $dummyIdentifier = 'e4f40dfc-8c6e-4414-a5b1-6fd3c5cf7a53';
185 
186  $object = new \stdClass();
187  $object->value1 = new \stdClass();
188  $configuration = [
189  '_descend' => [
190  'value1' => [
191  '_exposeObjectIdentifier' => true,
192  ],
193  ],
194  ];
195 
196  $expected = ['value1' => ['__identity' => $dummyIdentifier]];
197  ‪$output[] = [$object, $configuration, $expected, $dummyIdentifier, 'boolean TRUE should result in __identity key'];
198 
199  $configuration['_descend']['value1']['_exposedObjectIdentifierKey'] = 'guid';
200  $expected = ['value1' => ['guid' => $dummyIdentifier]];
201  ‪$output[] = [$object, $configuration, $expected, $dummyIdentifier, 'string value should result in string-equal key'];
202 
203  return ‪$output;
204  }
205 
216  object $object,
217  array $configuration,
218  array $expected,
219  string $dummyIdentifier,
220  string $description
221  ): void {
222  $persistenceManagerMock = $this->getMockBuilder(PersistenceManager::class)
223  ->setMethods(['getIdentifierByObject'])
224  ->getMock();
225  $jsonView = $this->getAccessibleMock(JsonView::class, ['dummy'], [], '', false);
226  $jsonView->_set('persistenceManager', $persistenceManagerMock);
227 
228  $persistenceManagerMock->expects($this->once())->method('getIdentifierByObject')->with($object->value1)->will($this->returnValue($dummyIdentifier));
229 
230  $actual = $jsonView->_call('transformValue', $object, $configuration);
231 
232  $this->assertSame($expected, $actual, $description);
233  }
234 
238  public function ‪exposeClassNameSettingsAndResults(): array
239  {
240  $className = $this->getUniqueId('DummyClass');
241  $namespace = 'TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\\' . $className;
242  return [
243  [
245  $className,
246  $namespace,
247  ['value1' => ['__class' => $namespace . '\\' . $className]],
248  ],
249  [
251  $className,
252  $namespace,
253  ['value1' => ['__class' => $className]],
254  ],
255  [
256  null,
257  $className,
258  $namespace,
259  ['value1' => []],
260  ]
261  ];
262  }
263 
273  ?int $exposeClassNameSetting,
274  string $className,
275  string $namespace,
276  array $expected
277  ): void {
278  $fullyQualifiedClassName = $namespace . '\\' . $className;
279  if (class_exists($fullyQualifiedClassName) === false) {
280  eval('namespace ' . $namespace . '; class ' . $className . ' {}');
281  }
282 
283  $object = new \stdClass();
284  $object->value1 = new $fullyQualifiedClassName();
285  $configuration = [
286  '_descend' => [
287  'value1' => [
288  '_exposeClassName' => $exposeClassNameSetting,
289  ],
290  ],
291  ];
292  $reflectionService = $this->getMockBuilder(\‪TYPO3\CMS\‪Extbase\Reflection\ReflectionService::class)
293  ->setMethods([ 'getClassNameByObject' ])
294  ->getMock();
295  $reflectionService->expects($this->any())->method('getClassNameByObject')->will($this->returnCallback(function ($object) {
296  return get_class($object);
297  }));
298 
299  $jsonView = $this->getAccessibleMock(\‪TYPO3\CMS\‪Extbase\Mvc\View\JsonView::class, ['dummy'], [], '', false);
300  $this->inject($jsonView, 'reflectionService', $reflectionService);
301  $actual = $jsonView->_call('transformValue', $object, $configuration);
302  $this->assertSame($expected, $actual);
303  }
304 
308  public function ‪renderSetsContentTypeHeader(): void
309  {
310  $this->response->expects($this->once())->method('setHeader')->with('Content-Type', 'application/json');
311 
312  $this->view->render();
313  }
314 
319  {
320  $object = new \stdClass();
321  $object->foo = 'Foo';
322  $this->view->assign('value', $object);
323 
324  $expectedResult = '{"foo":"Foo"}';
325  $actualResult = $this->view->render();
326  $this->assertSame($expectedResult, $actualResult);
327  }
328 
333  {
334  $array = ['foo' => 'Foo', 'bar' => 'Bar'];
335  $this->view->assign('value', $array);
336 
337  $expectedResult = '{"foo":"Foo","bar":"Bar"}';
338  $actualResult = $this->view->render();
339  $this->assertSame($expectedResult, $actualResult);
340  }
341 
346  {
347  $value = 'Foo';
348  $this->view->assign('value', $value);
349 
350  $expectedResult = '"Foo"';
351  $actualResult = $this->view->render();
352  $this->assertSame($expectedResult, $actualResult);
353  }
354 
358  public function ‪renderKeepsUtf8CharactersUnescaped(): void
359  {
360  $value = 'Gürkchen';
361  $this->view->assign('value', $value);
362 
363  $actualResult = $this->view->render();
364 
365  $expectedResult = '"' . $value . '"';
366  $this->assertSame($expectedResult, $actualResult);
367  }
368 
372  public function ‪escapeCharacterDataProvider(): array
373  {
374  return [
375  'backslash' => ['\\'],
376  'double quote' => ['"'],
377  ];
378  }
379 
385  public function ‪renderEscapesEscapeCharacters(string $character): void
386  {
387  $this->view->assign('value', $character);
388 
389  $actualResult = $this->view->render();
390 
391  $expectedResult = '"\\' . $character . '"';
392  $this->assertSame($expectedResult, $actualResult);
393  }
394 
399  {
400  $value = 'Foo';
401  $this->view->assign('foo', $value);
402 
403  $expectedResult = 'null';
404  $actualResult = $this->view->render();
405  $this->assertSame($expectedResult, $actualResult);
406  }
407 
411  public function ‪renderOnlyRendersVariableWithTheNameValue(): void
412  {
413  $this->view
414  ->assign('value', 'Value')
415  ->assign('someOtherVariable', 'Foo');
416 
417  $expectedResult = '"Value"';
418  $actualResult = $this->view->render();
419  $this->assertSame($expectedResult, $actualResult);
420  }
421 
425  public function ‪setVariablesToRenderOverridesValueToRender(): void
426  {
427  $value = 'Foo';
428  $this->view->assign('foo', $value);
429  $this->view->setVariablesToRender(['foo']);
430 
431  $expectedResult = '"Foo"';
432  $actualResult = $this->view->render();
433  $this->assertSame($expectedResult, $actualResult);
434  }
435 
440  {
441  $this->view
442  ->assign('value', 'Value1')
443  ->assign('secondValue', 'Value2')
444  ->assign('someOtherVariable', 'Value3');
445  $this->view->setVariablesToRender(['value', 'secondValue']);
446 
447  $expectedResult = '{"value":"Value1","secondValue":"Value2"}';
448  $actualResult = $this->view->render();
449  $this->assertSame($expectedResult, $actualResult);
450  }
451 
455  public function ‪renderCanRenderMultipleComplexObjects(): void
456  {
457  $array = ['foo' => ['bar' => 'Baz']];
458  $object = new \stdClass();
459  $object->foo = 'Foo';
460 
461  $this->view
462  ->assign('array', $array)
463  ->assign('object', $object)
464  ->assign('someOtherVariable', 'Value3');
465  $this->view->setVariablesToRender(['array', 'object']);
466 
467  $expectedResult = '{"array":{"foo":{"bar":"Baz"}},"object":{"foo":"Foo"}}';
468  $actualResult = $this->view->render();
469  $this->assertSame($expectedResult, $actualResult);
470  }
471 
475  public function ‪renderCanRenderPlainArray(): void
476  {
477  $array = [['name' => 'Foo', 'secret' => true], ['name' => 'Bar', 'secret' => true]];
478 
479  $this->view->assign('value', $array);
480  $this->view->setConfiguration([
481  'value' => [
482  '_descendAll' => [
483  '_only' => ['name'],
484  ],
485  ],
486  ]);
487 
488  $expectedResult = '[{"name":"Foo"},{"name":"Bar"}]';
489  $actualResult = $this->view->render();
490  $this->assertSame($expectedResult, $actualResult);
491  }
492 
496  public function ‪renderCanRenderPlainArrayWithNumericKeys(): void
497  {
498  $array = [
499  'items' => [
500  ['name' => 'Foo'],
501  ['name' => 'Bar']
502  ],
503  ];
504 
505  $this->view->assign('value', $array);
506  $this->view->setConfiguration([
507  'value' => [
508  'items' => [
509  // note: this exclude is just here, and should have no effect as the items have numeric keys
510  '_exclude' => ['secret']
511  ]
512  ],
513  ]);
514 
515  $expectedResult = '{"items":[{"name":"Foo"},{"name":"Bar"}]}';
516  $actualResult = $this->view->render();
517  self::assertSame($expectedResult, $actualResult);
518  }
519 
523  public function ‪descendAllKeepsArrayIndexes(): void
524  {
525  $array = [['name' => 'Foo', 'secret' => true], ['name' => 'Bar', 'secret' => true]];
526 
527  $this->view->assign('value', $array);
528  $this->view->setConfiguration([
529  'value' => [
530  '_descendAll' => [
531  '_descendAll' => [],
532  ],
533  ],
534  ]);
535 
536  $expectedResult = '[{"name":"Foo","secret":true},{"name":"Bar","secret":true}]';
537  $actualResult = $this->view->render();
538  $this->assertSame($expectedResult, $actualResult);
539  }
540 }
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\jsonViewTestData
‪array jsonViewTestData()
Definition: JsonViewTest.php:60
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderReturnsJsonRepresentationOfAssignedArray
‪renderReturnsJsonRepresentationOfAssignedArray()
Definition: JsonViewTest.php:329
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\testTransformValue
‪testTransformValue($object, array $configuration, $expected, string $description)
Definition: JsonViewTest.php:164
‪TYPO3\CMS\Extbase\Annotation
Definition: IgnoreValidation.php:4
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderOnlyRendersVariableWithTheNameValue
‪renderOnlyRendersVariableWithTheNameValue()
Definition: JsonViewTest.php:408
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderKeepsUtf8CharactersUnescaped
‪renderKeepsUtf8CharactersUnescaped()
Definition: JsonViewTest.php:355
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\$controllerContext
‪ControllerContext $controllerContext
Definition: JsonViewTest.php:36
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\setUp
‪setUp()
Definition: JsonViewTest.php:45
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\testTransformValueWithObjectIdentifierExposure
‪testTransformValueWithObjectIdentifierExposure(object $object, array $configuration, array $expected, string $dummyIdentifier, string $description)
Definition: JsonViewTest.php:212
‪TYPO3
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\descendAllKeepsArrayIndexes
‪descendAllKeepsArrayIndexes()
Definition: JsonViewTest.php:520
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderSetsContentTypeHeader
‪renderSetsContentTypeHeader()
Definition: JsonViewTest.php:305
‪TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
Definition: ControllerContext.php:21
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\exposeClassNameSettingsAndResults
‪exposeClassNameSettingsAndResults()
Definition: JsonViewTest.php:235
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\objectIdentifierExposureTestData
‪array objectIdentifierExposureTestData()
Definition: JsonViewTest.php:177
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\$view
‪TYPO3 CMS Extbase Mvc View JsonView $view
Definition: JsonViewTest.php:32
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderCanRenderPlainArray
‪renderCanRenderPlainArray()
Definition: JsonViewTest.php:472
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\$response
‪Response $response
Definition: JsonViewTest.php:40
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderReturnsJsonRepresentationOfAssignedObject
‪renderReturnsJsonRepresentationOfAssignedObject()
Definition: JsonViewTest.php:315
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\viewExposesClassNameFullyIfConfiguredSo
‪viewExposesClassNameFullyIfConfiguredSo(?int $exposeClassNameSetting, string $className, string $namespace, array $expected)
Definition: JsonViewTest.php:269
‪TYPO3\CMS\Extbase\Mvc\View\JsonView\EXPOSE_CLASSNAME_FULLY_QUALIFIED
‪const EXPOSE_CLASSNAME_FULLY_QUALIFIED
Definition: JsonView.php:38
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderRendersMultipleValuesIfTheyAreSpecifiedAsVariablesToRender
‪renderRendersMultipleValuesIfTheyAreSpecifiedAsVariablesToRender()
Definition: JsonViewTest.php:436
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\escapeCharacterDataProvider
‪string[][] escapeCharacterDataProvider()
Definition: JsonViewTest.php:369
‪TYPO3\CMS\Extbase\Mvc\Web\Response
Definition: Response.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
Definition: PersistenceManager.php:24
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderReturnsNullIfNameOfAssignedVariableIsNotEqualToValue
‪renderReturnsNullIfNameOfAssignedVariableIsNotEqualToValue()
Definition: JsonViewTest.php:395
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderReturnsJsonRepresentationOfAssignedSimpleValue
‪renderReturnsJsonRepresentationOfAssignedSimpleValue()
Definition: JsonViewTest.php:342
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\setVariablesToRenderOverridesValueToRender
‪setVariablesToRenderOverridesValueToRender()
Definition: JsonViewTest.php:422
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderEscapesEscapeCharacters
‪renderEscapesEscapeCharacters(string $character)
Definition: JsonViewTest.php:382
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View
Definition: JsonViewTest.php:4
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderCanRenderPlainArrayWithNumericKeys
‪renderCanRenderPlainArrayWithNumericKeys()
Definition: JsonViewTest.php:493
‪TYPO3\CMS\Extbase\Mvc\View\JsonView\EXPOSE_CLASSNAME_UNQUALIFIED
‪const EXPOSE_CLASSNAME_UNQUALIFIED
Definition: JsonView.php:44
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest
Definition: JsonViewTest.php:29
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\JsonViewTest\renderCanRenderMultipleComplexObjects
‪renderCanRenderMultipleComplexObjects()
Definition: JsonViewTest.php:452
‪TYPO3\CMS\Extbase\Mvc\View\JsonView
Definition: JsonView.php:29