TYPO3 API  SVNRelease
ForViewHelperTest.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*                                                                        *
00004  * This script belongs to the FLOW3 package "Fluid".                      *
00005  *                                                                        *
00006  * It is free software; you can redistribute it and/or modify it under    *
00007  * the terms of the GNU Lesser General Public License as published by the *
00008  * Free Software Foundation, either version 3 of the License, or (at your *
00009  * option) any later version.                                             *
00010  *                                                                        *
00011  * This script is distributed in the hope that it will be useful, but     *
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
00013  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
00014  * General Public License for more details.                               *
00015  *                                                                        *
00016  * You should have received a copy of the GNU Lesser General Public       *
00017  * License along with the script.                                         *
00018  * If not, see http://www.gnu.org/licenses/lgpl.html                      *
00019  *                                                                        *
00020  * The TYPO3 project - inspiring people to share!                         *
00021  *                                                                        */
00022 
00023 include_once(dirname(__FILE__) . '/Fixtures/ConstraintSyntaxTreeNode.php');
00024 require_once(dirname(__FILE__) . '/ViewHelperBaseTestcase.php');
00025 
00026 /**
00027  * Testcase for ForViewHelper
00028  *
00029  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
00030  */
00031 class Tx_Fluid_Tests_Unit_ViewHelpers_ForViewHelperTest extends Tx_Fluid_ViewHelpers_ViewHelperBaseTestcase {
00032 
00033     /**
00034      * @test
00035      * @author Sebastian Kurfürst <sebastian@typo3.org>
00036      * @author Bastian Waidelich <bastian@typo3.org>
00037      */
00038     public function renderExecutesTheLoopCorrectly() {
00039         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00040 
00041         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00042 
00043         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00044         $viewHelper->setTemplateVariableContainer($variableContainer);
00045         $viewHelper->setViewHelperNode($viewHelperNode);
00046         $viewHelper->setRenderingContext($this->renderingContext);
00047         $viewHelper->render(array(0,1,2,3), 'innerVariable');
00048 
00049         $expectedCallProtocol = array(
00050             array('innerVariable' => 0),
00051             array('innerVariable' => 1),
00052             array('innerVariable' => 2),
00053             array('innerVariable' => 3)
00054         );
00055         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00056     }
00057 
00058     /**
00059      * @test
00060      * @author Bastian Waidelich <bastian@typo3.org>
00061      */
00062     public function renderPreservesKeys() {
00063         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00064 
00065         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00066 
00067         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00068         $viewHelper->setTemplateVariableContainer($variableContainer);
00069         $viewHelper->setViewHelperNode($viewHelperNode);
00070         $viewHelper->setRenderingContext($this->renderingContext);
00071         $viewHelper->render(array('key1' => 'value1', 'key2' => 'value2'), 'innerVariable', 'someKey');
00072 
00073         $expectedCallProtocol = array(
00074             array(
00075                 'innerVariable' => 'value1',
00076                 'someKey' => 'key1'
00077             ),
00078             array(
00079                 'innerVariable' => 'value2',
00080                 'someKey' => 'key2'
00081             )
00082         );
00083         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00084     }
00085 
00086     /**
00087      * @test
00088      * @author Bastian Waidelich <bastian@typo3.org>
00089      */
00090     public function renderReturnsEmptyStringIfObjectIsNull() {
00091         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00092 
00093         $this->assertEquals('', $viewHelper->render(NULL, 'foo'));
00094     }
00095 
00096     /**
00097      * @test
00098      * @author Bastian Waidelich <bastian@typo3.org>
00099      */
00100     public function renderReturnsEmptyStringIfObjectIsEmptyArray() {
00101         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00102 
00103         $this->assertEquals('', $viewHelper->render(array(), 'foo'));
00104     }
00105 
00106     /**
00107      * @test
00108      * @author Bastian Waidelich <bastian@typo3.org>
00109      */
00110     public function renderAddsCurrentValueToTemplateVariableContainerAndRemovesItAfterRendering() {
00111         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00112 
00113         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
00114         $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
00115 
00116         $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
00117         $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
00118         $this->templateVariableContainer->expects($this->at(2))->method('add')->with('innerVariable', 'Fluid');
00119         $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerVariable');
00120 
00121         $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
00122         $viewHelper->setViewHelperNode($mockViewHelperNode);
00123         $viewHelper->setRenderingContext($this->renderingContext);
00124         $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid'), 'innerVariable');
00125     }
00126 
00127     /**
00128      * @test
00129      * @author Bastian Waidelich <bastian@typo3.org>
00130      */
00131     public function renderAddsCurrentKeyToTemplateVariableContainerAndRemovesItAfterRendering() {
00132         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00133 
00134         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
00135         $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
00136 
00137         $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
00138         $this->templateVariableContainer->expects($this->at(1))->method('add')->with('someKey', 'foo');
00139         $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('innerVariable');
00140         $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('someKey');
00141         $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'Fluid');
00142         $this->templateVariableContainer->expects($this->at(5))->method('add')->with('someKey', 'FLOW3');
00143         $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('innerVariable');
00144         $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('someKey');
00145 
00146         $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
00147         $viewHelper->setRenderingContext($this->renderingContext);
00148         $viewHelper->setViewHelperNode($mockViewHelperNode);
00149         $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid'), 'innerVariable', 'someKey');
00150     }
00151 
00152     /**
00153      * @test
00154      * @author Bastian Waidelich <bastian@typo3.org>
00155      */
00156     public function renderIteratesElementsInReverseOrderIfReverseIsTrue() {
00157         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00158 
00159         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00160 
00161         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00162         $viewHelper->setTemplateVariableContainer($variableContainer);
00163         $viewHelper->setViewHelperNode($viewHelperNode);
00164         $viewHelper->setRenderingContext($this->renderingContext);
00165         $viewHelper->render(array(0,1,2,3), 'innerVariable', '', TRUE);
00166 
00167         $expectedCallProtocol = array(
00168             array('innerVariable' => 3),
00169             array('innerVariable' => 2),
00170             array('innerVariable' => 1),
00171             array('innerVariable' => 0)
00172         );
00173         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00174     }
00175 
00176     /**
00177      * @test
00178      * @author Bastian Waidelich <bastian@typo3.org>
00179      */
00180     public function renderPreservesKeysIfReverseIsTrue() {
00181         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00182 
00183         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00184 
00185         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00186         $viewHelper->setTemplateVariableContainer($variableContainer);
00187         $viewHelper->setViewHelperNode($viewHelperNode);
00188         $viewHelper->setRenderingContext($this->renderingContext);
00189         $viewHelper->render(array('key1' => 'value1', 'key2' => 'value2'), 'innerVariable', 'someKey', TRUE);
00190 
00191         $expectedCallProtocol = array(
00192             array(
00193                 'innerVariable' => 'value2',
00194                 'someKey' => 'key2'
00195             ),
00196             array(
00197                 'innerVariable' => 'value1',
00198                 'someKey' => 'key1'
00199             )
00200         );
00201         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00202     }
00203 
00204     /**
00205      * @test
00206      * @author Bastian Waidelich <bastian@typo3.org>
00207      */
00208     public function keyContainsNumericalIndexIfTheGivenArrayDoesNotHaveAKey() {
00209         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00210 
00211         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00212 
00213         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00214         $viewHelper->setTemplateVariableContainer($variableContainer);
00215         $viewHelper->setViewHelperNode($viewHelperNode);
00216         $viewHelper->setRenderingContext($this->renderingContext);
00217         $viewHelper->render(array('foo', 'bar', 'baz'), 'innerVariable', 'someKey');
00218 
00219         $expectedCallProtocol = array(
00220             array(
00221                 'innerVariable' => 'foo',
00222                 'someKey' => 0
00223             ),
00224             array(
00225                 'innerVariable' => 'bar',
00226                 'someKey' => 1
00227             ),
00228             array(
00229                 'innerVariable' => 'baz',
00230                 'someKey' => 2
00231             )
00232         );
00233         $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00234     }
00235 
00236     /**
00237      * @test
00238      * @author Bastian Waidelich <bastian@typo3.org>
00239      */
00240     public function keyContainsNumericalIndexInAscendingOrderEvenIfReverseIsTrueIfTheGivenArrayDoesNotHaveAKey() {
00241         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00242 
00243         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00244 
00245         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00246         $viewHelper->setTemplateVariableContainer($variableContainer);
00247         $viewHelper->setViewHelperNode($viewHelperNode);
00248         $viewHelper->setRenderingContext($this->renderingContext);
00249         $viewHelper->render(array('foo', 'bar', 'baz'), 'innerVariable', 'someKey', TRUE);
00250 
00251         $expectedCallProtocol = array(
00252             array(
00253                 'innerVariable' => 'baz',
00254                 'someKey' => 0
00255             ),
00256             array(
00257                 'innerVariable' => 'bar',
00258                 'someKey' => 1
00259             ),
00260             array(
00261                 'innerVariable' => 'foo',
00262                 'someKey' => 2
00263             )
00264         );
00265         $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00266     }
00267 
00268     /**
00269      * @test
00270      * @expectedException Tx_Fluid_Core_ViewHelper_Exception
00271      * @author Bastian Waidelich <bastian@typo3.org>
00272      */
00273     public function renderThrowsExceptionWhenPassingObjectsToEachThatAreNotTraversable() {
00274         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00275         $object = new stdClass();
00276 
00277         $viewHelper->render($object, 'innerVariable', 'someKey');
00278     }
00279 
00280 
00281     /**
00282      * @test
00283      * @author Bastian Waidelich <bastian@typo3.org>
00284      */
00285     public function renderIteratesThroughElementsOfTraversableObjects() {
00286         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00287 
00288         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00289 
00290         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00291         $viewHelper->setTemplateVariableContainer($variableContainer);
00292         $viewHelper->setViewHelperNode($viewHelperNode);
00293         $viewHelper->setRenderingContext($this->renderingContext);
00294         $traversableObject = new ArrayObject(array('key1' => 'value1', 'key2' => 'value2'));
00295         $viewHelper->render($traversableObject, 'innerVariable');
00296 
00297         $expectedCallProtocol = array(
00298             array('innerVariable' => 'value1'),
00299             array('innerVariable' => 'value2'),
00300         );
00301         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00302     }
00303 
00304     /**
00305      * @test
00306      * @author Bastian Waidelich <bastian@typo3.org>
00307      */
00308     public function renderPreservesKeyWhenIteratingThroughElementsOfObjectsThatImplementIteratorInterface() {
00309         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00310 
00311         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00312 
00313         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00314         $viewHelper->setTemplateVariableContainer($variableContainer);
00315         $viewHelper->setViewHelperNode($viewHelperNode);
00316         $viewHelper->setRenderingContext($this->renderingContext);
00317         $iteratorObject = new ArrayIterator(array('key1' => 'value1', 'key2' => 'value2'));
00318         $viewHelper->render($iteratorObject, 'innerVariable', 'someKey');
00319 
00320         $expectedCallProtocol = array(
00321             array(
00322                 'innerVariable' => 'value1',
00323                 'someKey' => 'key1'
00324             ),
00325             array(
00326                 'innerVariable' => 'value2',
00327                 'someKey' => 'key2'
00328             )
00329         );
00330         $this->assertEquals($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00331     }
00332 
00333     /**
00334      * @test
00335      * @author Bastian Waidelich <bastian@typo3.org>
00336      */
00337     public function keyContainsTheNumericalIndexWhenIteratingThroughElementsOfObjectsOfTyeSplObjectStorage() {
00338         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00339 
00340         $variableContainer = new Tx_Fluid_Core_ViewHelper_TemplateVariableContainer(array());
00341 
00342         $viewHelperNode = new Tx_Fluid_ViewHelpers_Fixtures_ConstraintSyntaxTreeNode($variableContainer);
00343         $viewHelper->setTemplateVariableContainer($variableContainer);
00344         $viewHelper->setViewHelperNode($viewHelperNode);
00345         $viewHelper->setRenderingContext($this->renderingContext);
00346         $splObjectStorageObject = new SplObjectStorage();
00347         $object1 = new stdClass();
00348         $splObjectStorageObject->attach($object1);
00349         $object2 = new stdClass();
00350         $splObjectStorageObject->attach($object2);
00351         $object3 = new stdClass();
00352         $splObjectStorageObject->attach($object3);
00353         $viewHelper->render($splObjectStorageObject, 'innerVariable', 'someKey');
00354 
00355         $expectedCallProtocol = array(
00356             array(
00357                 'innerVariable' => $object1,
00358                 'someKey' => 0
00359             ),
00360             array(
00361                 'innerVariable' => $object2,
00362                 'someKey' => 1
00363             ),
00364             array(
00365                 'innerVariable' => $object3,
00366                 'someKey' => 2
00367             )
00368         );
00369         $this->assertSame($expectedCallProtocol, $viewHelperNode->callProtocol, 'The call protocol differs -> The for loop does not work as it should!');
00370     }
00371 
00372     /**
00373      * @test
00374      * @author Bastian Waidelich <bastian@typo3.org>
00375      */
00376     public function iterationDataIsAddedToTemplateVariableContainerIfIterationArgumentIsSet() {
00377         $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
00378 
00379         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array('evaluateChildNodes'), array(), '', FALSE);
00380         $mockViewHelperNode->expects($this->any())->method('evaluateChildNodes')->will($this->returnValue('foo'));
00381 
00382         $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
00383         $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));
00384         $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('innerVariable');
00385         $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('iteration');
00386         $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'Fluid');
00387         $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));
00388         $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('innerVariable');
00389         $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('iteration');
00390         $this->templateVariableContainer->expects($this->at(8))->method('add')->with('innerVariable', 'rocks');
00391         $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));
00392         $this->templateVariableContainer->expects($this->at(10))->method('remove')->with('innerVariable');
00393         $this->templateVariableContainer->expects($this->at(11))->method('remove')->with('iteration');
00394 
00395         $viewHelper->setTemplateVariableContainer($this->templateVariableContainer);
00396         $viewHelper->setRenderingContext($this->renderingContext);
00397         $viewHelper->setViewHelperNode($mockViewHelperNode);
00398         $viewHelper->render(array('foo' => 'bar', 'FLOW3' => 'Fluid', 'TYPO3' => 'rocks'), 'innerVariable', '', FALSE, 'iteration');
00399     }
00400 }
00401 
00402 ?>