Raised Extbase and Fluid to version 1.3.0
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Tests / Unit / ViewHelpers / ForViewHelperTest.php
1 <?php
2
3 /* *
4 * This script belongs to the FLOW3 package "Fluid". *
5 * *
6 * It is free software; you can redistribute it and/or modify it under *
7 * the terms of the GNU Lesser General Public License as published by the *
8 * Free Software Foundation, either version 3 of the License, or (at your *
9 * option) any later version. *
10 * *
11 * This script is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
13 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
14 * General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with the script. *
18 * If not, see http://www.gnu.org/licenses/lgpl.html *
19 * *
20 * The TYPO3 project - inspiring people to share! *
21 * */
22
23 include_once(dirname(__FILE__) . '/Fixtures/ConstraintSyntaxTreeNode.php');
24 require_once(dirname(__FILE__) . '/ViewHelperBaseTestcase.php');
25
26 /**
27 * Testcase for ForViewHelper
28 *
29 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
30 */
31 class Tx_Fluid_Tests_Unit_ViewHelpers_ForViewHelperTest extends Tx_Fluid_ViewHelpers_ViewHelperBaseTestcase {
32
33 /**
34 * @test
35 * @author Sebastian Kurf├╝rst <sebastian@typo3.org>
36 * @author Bastian Waidelich <bastian@typo3.org>
37 */
38 public function renderExecutesTheLoopCorrectly() {
39 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
40
41 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
42
43 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
44 $viewHelper->setTemplateVariableContainer($variableContainer);
45 $viewHelper->setViewHelperNode($viewHelperNode);
46 $viewHelper->setRenderingContext($this->renderingContext);
47 $viewHelper->render(array(0,1,2,3), 'innerVariable');
48
49 $expectedCallProtocol = array(
50 array('innerVariable' => 0),
51 array('innerVariable' => 1),
52 array('innerVariable' => 2),
53 array('innerVariable' => 3)
54 );
55 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
56 }
57
58 /**
59 * @test
60 * @author Bastian Waidelich <bastian@typo3.org>
61 */
62 public function renderPreservesKeys() {
63 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
64
65 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
66
67 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
68 $viewHelper->setTemplateVariableContainer($variableContainer);
69 $viewHelper->setViewHelperNode($viewHelperNode);
70 $viewHelper->setRenderingContext($this->renderingContext);
71 $viewHelper->render(array('key1' => 'value1', 'key2' => 'value2'), 'innerVariable', 'someKey');
72
73 $expectedCallProtocol = array(
74 array(
75 'innerVariable' => 'value1',
76 'someKey' => 'key1'
77 ),
78 array(
79 'innerVariable' => 'value2',
80 'someKey' => 'key2'
81 )
82 );
83 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
84 }
85
86 /**
87 * @test
88 * @author Bastian Waidelich <bastian@typo3.org>
89 */
90 public function renderReturnsEmptyStringIfObjectIsNull() {
91 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
92
93 $this->assertEquals('', $viewHelper->render(NULL, 'foo'));
94 }
95
96 /**
97 * @test
98 * @author Bastian Waidelich <bastian@typo3.org>
99 */
100 public function renderReturnsEmptyStringIfObjectIsEmptyArray() {
101 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
102
103 $this->assertEquals('', $viewHelper->render(array(), 'foo'));
104 }
105
106 /**
107 * @test
108 * @author Bastian Waidelich <bastian@typo3.org>
109 */
110 public function renderAddsCurrentValueToTemplateVariableContainerAndRemovesItAfterRendering() {
111 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
112
113 $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
114 $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
115
116 $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
117 $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
118 $this->templateVariableContainer->expects($this->at(2))->method('add')->with('innerVariable', 'Fluid');
119 $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerVariable');
120
121 $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
122 $viewHelper->setViewHelperNode($mockViewHelperNode);
123 $viewHelper->setRenderingContext($this->renderingContext);
124 $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid'), 'innerVariable');
125 }
126
127 /**
128 * @test
129 * @author Bastian Waidelich <bastian@typo3.org>
130 */
131 public function renderAddsCurrentKeyToTemplateVariableContainerAndRemovesItAfterRendering() {
132 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
133
134 $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
135 $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
136
137 $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
138 $this->templateVariableContainer->expects($this->at(1))->method('add')->with('someKey', 'foo');
139 $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('innerVariable');
140 $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('someKey');
141 $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'Fluid');
142 $this->templateVariableContainer->expects($this->at(5))->method('add')->with('someKey', 'FLOW3');
143 $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('innerVariable');
144 $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('someKey');
145
146 $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
147 $viewHelper->setRenderingContext($this->renderingContext);
148 $viewHelper->setViewHelperNode($mockViewHelperNode);
149 $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid'), 'innerVariable', 'someKey');
150 }
151
152 /**
153 * @test
154 * @author Bastian Waidelich <bastian@typo3.org>
155 */
156 public function renderIteratesElementsInReverseOrderIfReverseIsTrue() {
157 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
158
159 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
160
161 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
162 $viewHelper->setTemplateVariableContainer($variableContainer);
163 $viewHelper->setViewHelperNode($viewHelperNode);
164 $viewHelper->setRenderingContext($this->renderingContext);
165 $viewHelper->render(array(0,1,2,3), 'innerVariable', '', TRUE);
166
167 $expectedCallProtocol = array(
168 array('innerVariable' => 3),
169 array('innerVariable' => 2),
170 array('innerVariable' => 1),
171 array('innerVariable' => 0)
172 );
173 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
174 }
175
176 /**
177 * @test
178 * @author Bastian Waidelich <bastian@typo3.org>
179 */
180 public function renderPreservesKeysIfReverseIsTrue() {
181 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
182
183 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
184
185 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
186 $viewHelper->setTemplateVariableContainer($variableContainer);
187 $viewHelper->setViewHelperNode($viewHelperNode);
188 $viewHelper->setRenderingContext($this->renderingContext);
189 $viewHelper->render(array('key1' => 'value1', 'key2' => 'value2'), 'innerVariable', 'someKey', TRUE);
190
191 $expectedCallProtocol = array(
192 array(
193 'innerVariable' => 'value2',
194 'someKey' => 'key2'
195 ),
196 array(
197 'innerVariable' => 'value1',
198 'someKey' => 'key1'
199 )
200 );
201 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
202 }
203
204 /**
205 * @test
206 * @author Bastian Waidelich <bastian@typo3.org>
207 */
208 public function keyContainsNumericalIndexIfTheGivenArrayDoesNotHaveAKey() {
209 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
210
211 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
212
213 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
214 $viewHelper->setTemplateVariableContainer($variableContainer);
215 $viewHelper->setViewHelperNode($viewHelperNode);
216 $viewHelper->setRenderingContext($this->renderingContext);
217 $viewHelper->render(array('foo', 'bar', 'baz'), 'innerVariable', 'someKey');
218
219 $expectedCallProtocol = array(
220 array(
221 'innerVariable' => 'foo',
222 'someKey' => 0
223 ),
224 array(
225 'innerVariable' => 'bar',
226 'someKey' => 1
227 ),
228 array(
229 'innerVariable' => 'baz',
230 'someKey' => 2
231 )
232 );
233 $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
234 }
235
236 /**
237 * @test
238 * @author Bastian Waidelich <bastian@typo3.org>
239 */
240 public function keyContainsNumericalIndexInAscendingOrderEvenIfReverseIsTrueIfTheGivenArrayDoesNotHaveAKey() {
241 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
242
243 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
244
245 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
246 $viewHelper->setTemplateVariableContainer($variableContainer);
247 $viewHelper->setViewHelperNode($viewHelperNode);
248 $viewHelper->setRenderingContext($this->renderingContext);
249 $viewHelper->render(array('foo', 'bar', 'baz'), 'innerVariable', 'someKey', TRUE);
250
251 $expectedCallProtocol = array(
252 array(
253 'innerVariable' => 'baz',
254 'someKey' => 0
255 ),
256 array(
257 'innerVariable' => 'bar',
258 'someKey' => 1
259 ),
260 array(
261 'innerVariable' => 'foo',
262 'someKey' => 2
263 )
264 );
265 $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
266 }
267
268 /**
269 * @test
270 * @expectedException Tx_Fluid_Core_ViewHelper_Exception
271 * @author Bastian Waidelich <bastian@typo3.org>
272 */
273 public function renderThrowsExceptionWhenPassingObjectsToEachThatAreNotTraversable() {
274 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
275 $object = new stdClass();
276
277 $viewHelper->render($object, 'innerVariable', 'someKey');
278 }
279
280
281 /**
282 * @test
283 * @author Bastian Waidelich <bastian@typo3.org>
284 */
285 public function renderIteratesThroughElementsOfTraversableObjects() {
286 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
287
288 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
289
290 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
291 $viewHelper->setTemplateVariableContainer($variableContainer);
292 $viewHelper->setViewHelperNode($viewHelperNode);
293 $viewHelper->setRenderingContext($this->renderingContext);
294 $traversableObject = new ArrayObject(array('key1' => 'value1', 'key2' => 'value2'));
295 $viewHelper->render($traversableObject, 'innerVariable');
296
297 $expectedCallProtocol = array(
298 array('innerVariable' => 'value1'),
299 array('innerVariable' => 'value2'),
300 );
301 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
302 }
303
304 /**
305 * @test
306 * @author Bastian Waidelich <bastian@typo3.org>
307 */
308 public function renderPreservesKeyWhenIteratingThroughElementsOfObjectsThatImplementIteratorInterface() {
309 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
310
311 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
312
313 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
314 $viewHelper->setTemplateVariableContainer($variableContainer);
315 $viewHelper->setViewHelperNode($viewHelperNode);
316 $viewHelper->setRenderingContext($this->renderingContext);
317 $iteratorObject = new ArrayIterator(array('key1' => 'value1', 'key2' => 'value2'));
318 $viewHelper->render($iteratorObject, 'innerVariable', 'someKey');
319
320 $expectedCallProtocol = array(
321 array(
322 'innerVariable' => 'value1',
323 'someKey' => 'key1'
324 ),
325 array(
326 'innerVariable' => 'value2',
327 'someKey' => 'key2'
328 )
329 );
330 $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
331 }
332
333 /**
334 * @test
335 * @author Bastian Waidelich <bastian@typo3.org>
336 */
337 public function keyContainsTheNumericalIndexWhenIteratingThroughElementsOfObjectsOfTyeSplObjectStorage() {
338 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
339
340 $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
341
342 $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
343 $viewHelper->setTemplateVariableContainer($variableContainer);
344 $viewHelper->setViewHelperNode($viewHelperNode);
345 $viewHelper->setRenderingContext($this->renderingContext);
346 $splObjectStorageObject = new SplObjectStorage();
347 $object1 = new stdClass();
348 $splObjectStorageObject->attach($object1);
349 $object2 = new stdClass();
350 $splObjectStorageObject->attach($object2);
351 $object3 = new stdClass();
352 $splObjectStorageObject->attach($object3);
353 $viewHelper->render($splObjectStorageObject, 'innerVariable', 'someKey');
354
355 $expectedCallProtocol = array(
356 array(
357 'innerVariable' => $object1,
358 'someKey' => 0
359 ),
360 array(
361 'innerVariable' => $object2,
362 'someKey' => 1
363 ),
364 array(
365 'innerVariable' => $object3,
366 'someKey' => 2
367 )
368 );
369 $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
370 }
371
372 /**
373 * @test
374 * @author Bastian Waidelich <bastian@typo3.org>
375 */
376 public function iterationDataIsAddedToTemplateVariableContainerIfIterationArgumentIsSet() {
377 $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
378
379 $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
380 $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
381
382 $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
383 $this->templateVariableContainer->expects($this->at(1))->method('add')->with('iteration', array('index' => 0, 'cycle' => 1, 'total' => 3, 'isFirst' => TRUE, 'isLast' => FALSE, 'isEven' => FALSE, 'isOdd' => TRUE));
384 $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('innerVariable');
385 $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('iteration');
386 $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'Fluid');
387 $this->templateVariableContainer->expects($this->at(5))->method('add')->with('iteration', array('index' => 1, 'cycle' => 2, 'total' => 3, 'isFirst' => FALSE, 'isLast' => FALSE, 'isEven' => TRUE, 'isOdd' => FALSE));
388 $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('innerVariable');
389 $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('iteration');
390 $this->templateVariableContainer->expects($this->at(8))->method('add')->with('innerVariable', 'rocks');
391 $this->templateVariableContainer->expects($this->at(9))->method('add')->with('iteration', array('index' => 2, 'cycle' => 3, 'total' => 3, 'isFirst' => FALSE, 'isLast' => TRUE, 'isEven' => FALSE, 'isOdd' => TRUE));
392 $this->templateVariableContainer->expects($this->at(10))->method('remove')->with('innerVariable');
393 $this->templateVariableContainer->expects($this->at(11))->method('remove')->with('iteration');
394
395 $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
396 $viewHelper->setRenderingContext($this->renderingContext);
397 $viewHelper->setViewHelperNode($mockViewHelperNode);
398 $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid', 'TYPO3' => 'rocks'), 'innerVariable', '', FALSE, 'iteration');
399 }
400 }
401
402 ?>