TYPO3 CMS  TYPO3_7-6
JsonViewTest.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
18 
24 {
28  protected $view;
29 
33  protected $controllerContext;
34 
38  protected $response;
39 
44  protected function setUp()
45  {
46  $this->view = $this->getMock(\TYPO3\CMS\Extbase\Mvc\View\JsonView::class, ['loadConfigurationFromYamlFile']);
47  $this->controllerContext = $this->getMock(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext::class, [], [], '', false);
48  $this->response = $this->getMock(\TYPO3\CMS\Extbase\Mvc\Web\Response::class, []);
49  $this->controllerContext->expects($this->any())->method('getResponse')->will($this->returnValue($this->response));
50  $this->view->setControllerContext($this->controllerContext);
51  }
52 
57  public function jsonViewTestData()
58  {
59  $output = [];
60 
61  $object = new \stdClass();
62  $object->value1 = 'foo';
63  $object->value2 = 1;
64  $configuration = [];
65  $expected = ['value1' => 'foo', 'value2' => 1];
66  $output[] = [$object, $configuration, $expected, 'all direct child properties should be serialized'];
67 
68  $configuration = ['_only' => ['value1']];
69  $expected = ['value1' => 'foo'];
70  $output[] = [$object, $configuration, $expected, 'if "only" properties are specified, only these should be serialized'];
71 
72  $configuration = ['_exclude' => ['value1']];
73  $expected = ['value2' => 1];
74  $output[] = [$object, $configuration, $expected, 'if "exclude" properties are specified, they should not be serialized'];
75 
76  $object = new \stdClass();
77  $object->value1 = new \stdClass();
78  $object->value1->subvalue1 = 'Foo';
79  $object->value2 = 1;
80  $configuration = [];
81  $expected = ['value2' => 1];
82  $output[] = [$object, $configuration, $expected, 'by default, sub objects of objects should not be serialized.'];
83 
84  $object = new \stdClass();
85  $object->value1 = ['subarray' => 'value'];
86  $object->value2 = 1;
87  $configuration = [];
88  $expected = ['value2' => 1];
89  $output[] = [$object, $configuration, $expected, 'by default, sub arrays of objects should not be serialized.'];
90 
91  $object = ['foo' => 'bar', 1 => 'baz', 'deep' => ['test' => 'value']];
92  $configuration = [];
93  $expected = ['foo' => 'bar', 1 => 'baz', 'deep' => ['test' => 'value']];
94  $output[] = [$object, $configuration, $expected, 'associative arrays should be serialized deeply'];
95 
96  $object = ['foo', 'bar'];
97  $configuration = [];
98  $expected = ['foo', 'bar'];
99  $output[] = [$object, $configuration, $expected, 'numeric arrays should be serialized'];
100 
101  $nestedObject = new \stdClass();
102  $nestedObject->value1 = 'foo';
103  $object = [$nestedObject];
104  $configuration = [];
105  $expected = [['value1' => 'foo']];
106  $output[] = [$object, $configuration, $expected, 'array of objects should be serialized'];
107 
108  $properties = ['foo' => 'bar', 'prohibited' => 'xxx'];
109  $nestedObject = $this->getMock($this->getUniqueId('Test'), ['getName', 'getPath', 'getProperties', 'getOther']);
110  $nestedObject->expects($this->any())->method('getName')->will($this->returnValue('name'));
111  $nestedObject->expects($this->any())->method('getPath')->will($this->returnValue('path'));
112  $nestedObject->expects($this->any())->method('getProperties')->will($this->returnValue($properties));
113  $nestedObject->expects($this->never())->method('getOther');
114  $object = $nestedObject;
115  $configuration = [
116  '_only' => ['name', 'path', 'properties'],
117  '_descend' => [
118  'properties' => [
119  '_exclude' => ['prohibited']
120  ]
121  ]
122  ];
123  $expected = [
124  'name' => 'name',
125  'path' => 'path',
126  'properties' => ['foo' => 'bar']
127  ];
128  $output[] = [$object, $configuration, $expected, 'descending into arrays should be possible'];
129 
130  $nestedObject = new \stdClass();
131  $nestedObject->value1 = 'foo';
132  $value = new \SplObjectStorage();
133  $value->attach($nestedObject);
134  $configuration = [];
135  $expected = [['value1' => 'foo']];
136  $output[] = [$value, $configuration, $expected, 'SplObjectStorage with objects should be serialized'];
137 
138  $dateTimeObject = new \DateTime('2011-02-03T03:15:23', new \DateTimeZone('UTC'));
139  $configuration = [];
140  $expected = '2011-02-03T03:15:23+0000';
141  $output[] = [$dateTimeObject, $configuration, $expected, 'DateTime object in UTC time zone could not be serialized.'];
142 
143  $dateTimeObject = new \DateTime('2013-08-15T15:25:30', new \DateTimeZone('America/Los_Angeles'));
144  $configuration = [];
145  $expected = '2013-08-15T15:25:30-0700';
146  $output[] = [$dateTimeObject, $configuration, $expected, 'DateTime object in America/Los_Angeles time zone could not be serialized.'];
147  return $output;
148  }
149 
154  public function testTransformValue($object, $configuration, $expected, $description)
155  {
156  $jsonView = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\View\JsonView::class, ['dummy'], [], '', false);
157 
158  $actual = $jsonView->_call('transformValue', $object, $configuration);
159 
160  $this->assertEquals($expected, $actual, $description);
161  }
162 
168  {
169  $output = [];
170 
171  $dummyIdentifier = 'e4f40dfc-8c6e-4414-a5b1-6fd3c5cf7a53';
172 
173  $object = new \stdClass();
174  $object->value1 = new \stdClass();
175  $configuration = [
176  '_descend' => [
177  'value1' => [
178  '_exposeObjectIdentifier' => true
179  ]
180  ]
181  ];
182 
183  $expected = ['value1' => ['__identity' => $dummyIdentifier]];
184  $output[] = [$object, $configuration, $expected, $dummyIdentifier, 'boolean TRUE should result in __identity key'];
185 
186  $configuration['_descend']['value1']['_exposedObjectIdentifierKey'] = 'guid';
187  $expected = ['value1' => ['guid' => $dummyIdentifier]];
188  $output[] = [$object, $configuration, $expected, $dummyIdentifier, 'string value should result in string-equal key'];
189 
190  return $output;
191  }
192 
197  public function testTransformValueWithObjectIdentifierExposure($object, $configuration, $expected, $dummyIdentifier, $description)
198  {
199  $persistenceManagerMock = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class, ['getIdentifierByObject']);
200  $jsonView = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\View\JsonView::class, ['dummy'], [], '', false);
201  $jsonView->_set('persistenceManager', $persistenceManagerMock);
202 
203  $persistenceManagerMock->expects($this->once())->method('getIdentifierByObject')->with($object->value1)->will($this->returnValue($dummyIdentifier));
204 
205  $actual = $jsonView->_call('transformValue', $object, $configuration);
206 
207  $this->assertEquals($expected, $actual, $description);
208  }
209 
214  {
215  $className = $this->getUniqueId('DummyClass');
216  $namespace = 'TYPO3\CMS\Extbase\Tests\Unit\Mvc\View\\' . $className;
217  return [
218  [
220  $className,
221  $namespace,
222  ['value1' => ['__class' => $namespace . '\\' . $className]]
223  ],
224  [
226  $className,
227  $namespace,
228  ['value1' => ['__class' => $className]]
229  ],
230  [
231  null,
232  $className,
233  $namespace,
234  ['value1' => []]
235  ]
236  ];
237  }
238 
243  public function viewExposesClassNameFullyIfConfiguredSo($exposeClassNameSetting, $className, $namespace, $expected)
244  {
245  $fullyQualifiedClassName = $namespace . '\\' . $className;
246  if (class_exists($fullyQualifiedClassName) === false) {
247  eval('namespace ' . $namespace . '; class ' . $className . ' {}');
248  }
249 
250  $object = new \stdClass();
251  $object->value1 = new $fullyQualifiedClassName();
252  $configuration = [
253  '_descend' => [
254  'value1' => [
255  '_exposeClassName' => $exposeClassNameSetting
256  ]
257  ]
258  ];
259  $reflectionService = $this->getMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class);
260  $reflectionService->expects($this->any())->method('getClassNameByObject')->will($this->returnCallback(function ($object) {
261  return get_class($object);
262  }));
263 
264  $jsonView = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\View\JsonView::class, ['dummy'], [], '', false);
265  $this->inject($jsonView, 'reflectionService', $reflectionService);
266  $actual = $jsonView->_call('transformValue', $object, $configuration);
267  $this->assertEquals($expected, $actual);
268  }
269 
273  public function renderSetsContentTypeHeader()
274  {
275  $this->response->expects($this->once())->method('setHeader')->with('Content-Type', 'application/json');
276 
277  $this->view->render();
278  }
279 
284  {
285  $object = new \stdClass();
286  $object->foo = 'Foo';
287  $this->view->assign('value', $object);
288 
289  $expectedResult = '{"foo":"Foo"}';
290  $actualResult = $this->view->render();
291  $this->assertEquals($expectedResult, $actualResult);
292  }
293 
298  {
299  $array = ['foo' => 'Foo', 'bar' => 'Bar'];
300  $this->view->assign('value', $array);
301 
302  $expectedResult = '{"foo":"Foo","bar":"Bar"}';
303  $actualResult = $this->view->render();
304  $this->assertEquals($expectedResult, $actualResult);
305  }
306 
311  {
312  $value = 'Foo';
313  $this->view->assign('value', $value);
314 
315  $expectedResult = '"Foo"';
316  $actualResult = $this->view->render();
317  $this->assertEquals($expectedResult, $actualResult);
318  }
319 
324  {
325  $value = 'Foo';
326  $this->view->assign('foo', $value);
327 
328  $expectedResult = 'null';
329  $actualResult = $this->view->render();
330  $this->assertEquals($expectedResult, $actualResult);
331  }
332 
337  {
338  $this->view
339  ->assign('value', 'Value')
340  ->assign('someOtherVariable', 'Foo');
341 
342  $expectedResult = '"Value"';
343  $actualResult = $this->view->render();
344  $this->assertEquals($expectedResult, $actualResult);
345  }
346 
351  {
352  $value = 'Foo';
353  $this->view->assign('foo', $value);
354  $this->view->setVariablesToRender(['foo']);
355 
356  $expectedResult = '"Foo"';
357  $actualResult = $this->view->render();
358  $this->assertEquals($expectedResult, $actualResult);
359  }
360 
365  {
366  $this->view
367  ->assign('value', 'Value1')
368  ->assign('secondValue', 'Value2')
369  ->assign('someOtherVariable', 'Value3');
370  $this->view->setVariablesToRender(['value', 'secondValue']);
371 
372  $expectedResult = '{"value":"Value1","secondValue":"Value2"}';
373  $actualResult = $this->view->render();
374  $this->assertEquals($expectedResult, $actualResult);
375  }
376 
381  {
382  $array = ['foo' => ['bar' => 'Baz']];
383  $object = new \stdClass();
384  $object->foo = 'Foo';
385 
386  $this->view
387  ->assign('array', $array)
388  ->assign('object', $object)
389  ->assign('someOtherVariable', 'Value3');
390  $this->view->setVariablesToRender(['array', 'object']);
391 
392  $expectedResult = '{"array":{"foo":{"bar":"Baz"}},"object":{"foo":"Foo"}}';
393  $actualResult = $this->view->render();
394  $this->assertEquals($expectedResult, $actualResult);
395  }
396 
400  public function renderCanRenderPlainArray()
401  {
402  $array = [['name' => 'Foo', 'secret' => true], ['name' => 'Bar', 'secret' => true]];
403 
404  $this->view->assign('value', $array);
405  $this->view->setConfiguration([
406  'value' => [
407  '_descendAll' => [
408  '_only' => ['name']
409  ]
410  ]
411  ]);
412 
413  $expectedResult = '[{"name":"Foo"},{"name":"Bar"}]';
414  $actualResult = $this->view->render();
415  $this->assertEquals($expectedResult, $actualResult);
416  }
417 
421  public function descendAllKeepsArrayIndexes()
422  {
423  $array = [['name' => 'Foo', 'secret' => true], ['name' => 'Bar', 'secret' => true]];
424 
425  $this->view->assign('value', $array);
426  $this->view->setConfiguration([
427  'value' => [
428  '_descendAll' => [
429  '_descendAll' => []
430  ]
431  ]
432  ]);
433 
434  $expectedResult = '[{"name":"Foo","secret":true},{"name":"Bar","secret":true}]';
435  $actualResult = $this->view->render();
436  $this->assertEquals($expectedResult, $actualResult);
437  }
438 }
inject($target, $name, $dependency)
viewExposesClassNameFullyIfConfiguredSo($exposeClassNameSetting, $className, $namespace, $expected)
testTransformValueWithObjectIdentifierExposure($object, $configuration, $expected, $dummyIdentifier, $description)
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)
testTransformValue($object, $configuration, $expected, $description)