TYPO3 API  SVNRelease
TemplateParserTest.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 require_once(dirname(__FILE__) . '/Fixtures/PostParseFacetViewHelper.php');
00024 
00025 /**
00026  * Testcase for TemplateParser.
00027  *
00028  * This is to at least half a system test, as it compares rendered results to
00029  * expectations, and does not strictly check the parsing...
00030  *
00031  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
00032  */
00033 class Tx_Fluid_Tests_Unit_Core_Parser_TemplateParserTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
00034 
00035     /**
00036      * @test
00037      * @author Sebastian Kurfürst <sebastian@typo3.or>
00038      * @expectedException Tx_Fluid_Core_Parser_Exception
00039      */
00040     public function parseThrowsExceptionWhenStringArgumentMissing() {
00041         $templateParser = new Tx_Fluid_Core_Parser_TemplateParser();
00042         $templateParser->parse(123);
00043     }
00044 
00045     /**
00046      * Checks that parse() calls the expected methods internally in the
00047      * correct order:
00048      * initialize();
00049      * extractNamespaceDefinitions($templateString)
00050      * splitTemplateAtDynamicTags($templateString)
00051      * buildObjectTree($splitTemplate)
00052      *
00053      * @test
00054      * @author Karsten Dambekalns <karsten@typo3.org>
00055      */
00056     public function parseDelegatesTasksAsExpected() {
00057         $templateParser = $this->getMock('Tx_Fluid_Core_Parser_TemplateParser', array('reset', 'extractNamespaceDefinitions', 'splitTemplateAtDynamicTags', 'buildObjectTree'));
00058         $templateParser->expects($this->at(0))->method('reset');
00059         $templateParser->expects($this->at(1))->method('extractNamespaceDefinitions')->with('templateString1')->will($this->returnValue('templateString2'));
00060         $templateParser->expects($this->at(2))->method('splitTemplateAtDynamicTags')->with('templateString2')->will($this->returnValue('templateString3'));
00061         $templateParser->expects($this->at(3))->method('buildObjectTree')->with('templateString3')->will($this->returnValue('templateString4'));
00062         $this->assertEquals('templateString4', $templateParser->parse('templateString1'));
00063     }
00064 
00065     /**
00066      * @test
00067      * @author Sebastian Kurfürst <sebastian@typo3.org>
00068      * @author Karsten Dambekalns <karsten@typo3.org>
00069      */
00070     public function extractNamespaceDefinitionsExtractsNamespacesCorrectly() {
00071         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00072         $templateParser->_call('extractNamespaceDefinitions', ' \{namespace f4=F7\Rocks} {namespace f4=Tx_Fluid_Really}');
00073         $expected = array(
00074             'f' => 'Tx_Fluid_ViewHelpers',
00075             'f4' => 'Tx_Fluid_Really'
00076         );
00077         $this->assertEquals($templateParser->getNamespaces(), $expected, 'Namespaces do not match.');
00078     }
00079 
00080     /**
00081      * @test
00082      * @author Sebastian Kurfürst <sebastian@typo3.org>
00083      * @author Karsten Dambekalns <karsten@typo3.org>
00084      * @expectedException Tx_Fluid_Core_Parser_Exception
00085      */
00086     public function extractNamespaceDefinitionsThrowsExceptionIfNamespaceIsRedeclared() {
00087         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00088         $templateParser->_call('extractNamespaceDefinitions', '{namespace f3=Tx_Fluid_Blablubb} {namespace f3= Tx_Fluid_Blu}');
00089     }
00090 
00091 
00092     /**
00093      * @test
00094      * @author Jochen Rau <jochen.rau@typoplanet.de>
00095      */
00096     public function viewHelperNameWithMultipleLevelsCanBeResolvedByResolveViewHelperName() {
00097         $mockTemplateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'), array(), '', FALSE);
00098         $result = $mockTemplateParser->_call('resolveViewHelperName', 'f', 'foo.bar.baz');
00099         $expected = 'Tx_Fluid_ViewHelpers_Foo_Bar_BazViewHelper';
00100         $this->assertEquals($result, $expected, 'The name of the View Helper Name could not be resolved.');
00101     }
00102 
00103     /**
00104      * @test
00105      * @author Karsten Dambekalns <karsten@typo3.org>
00106      */
00107     public function viewHelperNameWithOneLevelCanBeResolvedByResolveViewHelperName() {
00108         $mockTemplateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'), array(), '', FALSE);
00109         $actual = $mockTemplateParser->_call('resolveViewHelperName', 'f', 'myown');
00110         $expected = 'Tx_Fluid_ViewHelpers_MyownViewHelper';
00111         $this->assertEquals($expected, $actual);
00112     }
00113 
00114     /**
00115      * @author Karsten Dambekalns <karsten@typo3.org>
00116      */
00117     public function quotedStrings() {
00118         return array(
00119             array('"no quotes here"', 'no quotes here'),
00120             array("'no quotes here'", 'no quotes here'),
00121             array("'this \"string\" had \\'quotes\\' in it'", 'this "string" had \'quotes\' in it'),
00122             array('"this \\"string\\" had \'quotes\' in it"', 'this "string" had \'quotes\' in it'),
00123             array('"a weird \"string\" \'with\' *freaky* \\\\stuff', 'a weird "string" \'with\' *freaky* \\stuff'),
00124         );
00125     }
00126 
00127     /**
00128      * @dataProvider quotedStrings
00129      * @test
00130      * @author Karsten Dambekalns <karsten@typo3.org>
00131      */
00132     public function unquoteStringReturnsUnquotedStrings($quoted, $unquoted) {
00133         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00134         $this->assertEquals($unquoted, $templateParser->_call('unquoteString', $quoted));
00135     }
00136 
00137     /**
00138      * @author Karsten Dambekalns <karsten@typo3.org>
00139      */
00140     public function templatesToSplit() {
00141         return array(
00142             array('TemplateParserTestFixture01-shorthand'),
00143             array('TemplateParserTestFixture06'),
00144             array('TemplateParserTestFixture14'),
00145         );
00146     }
00147 
00148     /**
00149      * @dataProvider templatesToSplit
00150      * @test
00151      * @author Karsten Dambekalns <karsten@typo3.org>
00152      */
00153     public function splitTemplateAtDynamicTagsReturnsCorrectlySplitTemplate($templateName) {
00154         $template = file_get_contents(dirname(__FILE__) . '/Fixtures/' . $templateName . '.html', FILE_TEXT);
00155         $result = require(dirname(__FILE__) . '/Fixtures/' . $templateName . '-split.php');
00156         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00157         $this->assertSame($result, $templateParser->_call('splitTemplateAtDynamicTags', $template));
00158     }
00159 
00160     /**
00161      * @test
00162      * @author Karsten Dambekalns <karsten@typo3.org>
00163      */
00164     public function buildObjectTreeCreatesRootNodeAndSetsUpParsingState() {
00165         $mockRootNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_RootNode');
00166 
00167         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00168         $mockState->expects($this->once())->method('setRootNode')->with($mockRootNode);
00169         $mockState->expects($this->once())->method('pushNodeToStack')->with($mockRootNode);
00170         $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(1));
00171 
00172         $mockTemplateVariableContainer = $this->getMock('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer');
00173 
00174         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00175         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_Core_Parser_ParsingState')->will($this->returnValue($mockState));
00176         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_RootNode')->will($this->returnValue($mockRootNode));
00177         $mockObjectManager->expects($this->at(2))->method('create')->with('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer')->will($this->returnValue($mockTemplateVariableContainer));
00178 
00179         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00180         $templateParser->injectObjectManager($mockObjectManager);
00181 
00182         $templateParser->_call('buildObjectTree', array());
00183     }
00184 
00185     /**
00186      * @test
00187      * @expectedException Tx_Fluid_Core_Parser_Exception
00188      * @author Karsten Dambekalns <karsten@typo3.org>
00189      */
00190     public function buildObjectTreeThrowsRootNodeIfOpentagsRemain() {
00191         $mockRootNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_RootNode');
00192 
00193         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00194         $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(2));
00195 
00196         $mockTemplateVariableContainer = $this->getMock('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer');
00197 
00198         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00199         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_Core_Parser_ParsingState')->will($this->returnValue($mockState));
00200         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_RootNode')->will($this->returnValue($mockRootNode));
00201         $mockObjectManager->expects($this->at(2))->method('create')->with('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer')->will($this->returnValue($mockTemplateVariableContainer));
00202 
00203         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00204         $templateParser->injectObjectManager($mockObjectManager);
00205 
00206         $templateParser->_call('buildObjectTree', array());
00207     }
00208 
00209     /**
00210      * @test
00211      * @author Karsten Dambekalns <karsten@typo3.org>
00212      */
00213     public function buildObjectTreeDelegatesHandlingOfTemplateElements() {
00214         $mockRootNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_RootNode');
00215 
00216         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00217         $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(1));
00218 
00219         $mockTemplateVariableContainer = $this->getMock('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer');
00220 
00221         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00222         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_Core_Parser_ParsingState')->will($this->returnValue($mockState));
00223         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_RootNode')->will($this->returnValue($mockRootNode));
00224         $mockObjectManager->expects($this->at(2))->method('create')->with('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer')->will($this->returnValue($mockTemplateVariableContainer));
00225 
00226         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('textHandler', 'openingViewHelperTagHandler', 'closingViewHelperTagHandler', 'textAndShorthandSyntaxHandler'));
00227         $templateParser->injectObjectManager($mockObjectManager);
00228         $templateParser->expects($this->at(0))->method('textAndShorthandSyntaxHandler')->with($mockState, 'The first part is simple');
00229         $templateParser->expects($this->at(1))->method('textHandler')->with($mockState, '<f3:for each="{a: {a: 0, b: 2, c: 4}}" as="array"><f3:for each="{array}" as="value">{value} </f3:for>');
00230         $templateParser->expects($this->at(2))->method('openingViewHelperTagHandler')->with($mockState, 'f', 'format.printf', ' arguments="{number : 362525200}"', FALSE);
00231         $templateParser->expects($this->at(3))->method('textAndShorthandSyntaxHandler')->with($mockState, '%.3e');
00232         $templateParser->expects($this->at(4))->method('closingViewHelperTagHandler')->with($mockState, 'f', 'format.printf');
00233         $templateParser->expects($this->at(5))->method('textAndShorthandSyntaxHandler')->with($mockState, 'and here goes some {text} that could have {shorthand}');
00234 
00235         $splitTemplate = $templateParser->_call('splitTemplateAtDynamicTags', 'The first part is simple<![CDATA[<f3:for each="{a: {a: 0, b: 2, c: 4}}" as="array"><f3:for each="{array}" as="value">{value} </f3:for>]]><f:format.printf arguments="{number : 362525200}">%.3e</f:format.printf>and here goes some {text} that could have {shorthand}');
00236 
00237         $templateParser->_call('buildObjectTree', $splitTemplate);
00238     }
00239 
00240     /**
00241      * @test
00242      * @author Karsten Dambekalns <karsten@typo3.org>
00243      */
00244     public function openingViewHelperTagHandlerDelegatesViewHelperInitialization() {
00245         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00246         $mockState->expects($this->never())->method('popNodeFromStack');
00247 
00248         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('parseArguments', 'initializeViewHelperAndAddItToStack'));
00249         $templateParser->expects($this->once())->method('parseArguments')->with(array('arguments'))->will($this->returnValue(array('parsedArguments')));
00250         $templateParser->expects($this->once())->method('initializeViewHelperAndAddItToStack')->with($mockState, 'namespaceIdentifier', 'methodIdentifier', array('parsedArguments'));
00251 
00252         $templateParser->_call('openingViewHelperTagHandler', $mockState, 'namespaceIdentifier', 'methodIdentifier', array('arguments'), FALSE);
00253     }
00254 
00255     /**
00256      * @test
00257      * @author Karsten Dambekalns <karsten@typo3.org>
00258      */
00259     public function openingViewHelperTagHandlerPopsNodeFromStackForSelfClosingTags() {
00260         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00261         $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface')));
00262 
00263         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('parseArguments', 'initializeViewHelperAndAddItToStack'));
00264 
00265         $templateParser->_call('openingViewHelperTagHandler', $mockState, '', '', array(), TRUE);
00266     }
00267 
00268     /**
00269      * @test
00270      * @author Karsten Dambekalns <karsten@typo3.org>
00271      */
00272     public function initializeViewHelperAndAddItToStackCreatesRequestedViewHelperAndViewHelperNode() {
00273         $mockViewHelper = $this->getMock('Tx_Fluid_Core_ViewHelper_AbstractViewHelper');
00274         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array(), array(), '', FALSE);
00275 
00276         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface');
00277         $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($mockViewHelperNode);
00278 
00279         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00280         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_ViewHelpers_MyownViewHelper')->will($this->returnValue($mockViewHelper));
00281         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode')->will($this->returnValue($mockViewHelperNode));
00282 
00283         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00284         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00285         $mockState->expects($this->once())->method('pushNodeToStack')->with($mockViewHelperNode);
00286 
00287         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing'));
00288         $templateParser->injectObjectManager($mockObjectManager);
00289 
00290         $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', array('arguments'));
00291     }
00292 
00293     /**
00294      * @test
00295      * @author Karsten Dambekalns <karsten@typo3.org>
00296      */
00297     public function initializeViewHelperAndAddItToStackChecksViewHelperArguments() {
00298         $expectedArguments = array('expectedArguments');
00299         $argumentsObjectTree = array('arguments');
00300 
00301         $mockViewHelper = $this->getMock('Tx_Fluid_Core_ViewHelper_AbstractViewHelper');
00302         $mockViewHelper->expects($this->once())->method('prepareArguments')->will($this->returnValue($expectedArguments));
00303         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array(), array(), '', FALSE);
00304 
00305         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface');
00306 
00307         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00308         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_ViewHelpers_MyownViewHelper')->will($this->returnValue($mockViewHelper));
00309         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode')->will($this->returnValue($mockViewHelperNode));
00310 
00311         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00312         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00313 
00314         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing'));
00315         $templateParser->injectObjectManager($mockObjectManager);
00316         $templateParser->expects($this->once())->method('abortIfUnregisteredArgumentsExist')->with($expectedArguments, $argumentsObjectTree);
00317         $templateParser->expects($this->once())->method('abortIfRequiredArgumentsAreMissing')->with($expectedArguments, $argumentsObjectTree);
00318 
00319         $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', $argumentsObjectTree);
00320     }
00321 
00322     /**
00323      * @test
00324      * @author Karsten Dambekalns <karsten@typo3.org>
00325      */
00326     public function initializeViewHelperAndAddItToStackHandlesPostParseFacets() {
00327         $mockViewHelper = $this->getMock('Tx_Fluid_Core_Parser_Fixtures_PostParseFacetViewHelper', array('prepareArguments'));
00328         $mockViewHelperNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array(), array(), '', FALSE);
00329 
00330         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface');
00331         $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($mockViewHelperNode);
00332 
00333         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00334         $mockObjectManager->expects($this->at(0))->method('create')->with('Tx_Fluid_ViewHelpers_MyownViewHelper')->will($this->returnValue($mockViewHelper));
00335         $mockObjectManager->expects($this->at(1))->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode')->will($this->returnValue($mockViewHelperNode));
00336 
00337         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00338         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00339         $mockState->expects($this->once())->method('getVariableContainer')->will($this->returnValue($this->getMock('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer')));
00340 
00341         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing'));
00342         $templateParser->injectObjectManager($mockObjectManager);
00343 
00344         $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', array('arguments'));
00345         $this->assertTrue(Tx_Fluid_Core_Parser_Fixtures_PostParseFacetViewHelper::$wasCalled, 'PostParse was not called!');
00346     }
00347 
00348     /**
00349      * @test
00350      * @expectedException Tx_Fluid_Core_Parser_Exception
00351      * @author Karsten Dambekalns <karsten@typo3.org>
00352      */
00353     public function abortIfUnregisteredArgumentsExistThrowsExceptionOnUnregisteredArguments() {
00354         $expected = array(new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('firstArgument', 'string', '', FALSE));
00355         $actual = array('firstArgument' => 'foo', 'secondArgument' => 'bar');
00356 
00357         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00358 
00359         $templateParser->_call('abortIfUnregisteredArgumentsExist', $expected, $actual);
00360     }
00361 
00362     /**
00363      * @test
00364      * @author Sebastian Kurfürst <sebastian@typo3.org>
00365      */
00366     public function abortIfUnregisteredArgumentsExistDoesNotThrowExceptionIfEverythingIsOk() {
00367         $expectedArguments = array(
00368             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('name1', 'string', 'desc', FALSE),
00369             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('name2', 'string', 'desc', TRUE)
00370         );
00371         $actualArguments = array(
00372             'name1' => 'bla'
00373         );
00374 
00375         $mockTemplateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00376 
00377         $mockTemplateParser->_call('abortIfUnregisteredArgumentsExist', $expectedArguments, $actualArguments);
00378     }
00379 
00380     /**
00381      * @test
00382      * @expectedException Tx_Fluid_Core_Parser_Exception
00383      * @author Karsten Dambekalns <karsten@typo3.org>
00384      */
00385     public function abortIfRequiredArgumentsAreMissingThrowsException() {
00386         $expected = array(
00387             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('firstArgument', 'string', '', FALSE),
00388             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('secondArgument', 'string', '', TRUE));
00389 
00390         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00391 
00392         $templateParser->_call('abortIfRequiredArgumentsAreMissing', $expected, array());
00393     }
00394 
00395     /**
00396      * @test
00397      * @author Sebastian Kurfürst <sebastian@typo3.org>
00398      */
00399     public function abortIfRequiredArgumentsAreMissingDoesNotThrowExceptionIfRequiredArgumentExists() {
00400         $expectedArguments = array(
00401             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('name1', 'string', 'desc', FALSE),
00402             new Tx_Fluid_Core_ViewHelper_ArgumentDefinition('name2', 'string', 'desc', TRUE)
00403         );
00404         $actualArguments = array(
00405             'name2' => 'bla'
00406         );
00407 
00408         $mockTemplateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00409 
00410         $mockTemplateParser->_call('abortIfRequiredArgumentsAreMissing', $expectedArguments, $actualArguments);
00411     }
00412 
00413     /**
00414      * @test
00415      * @expectedException Tx_Fluid_Core_Parser_Exception
00416      * @author Karsten Dambekalns <karsten@typo3.org>
00417      */
00418     public function closingViewHelperTagHandlerThrowsExceptionBecauseOfClosingTagWhichWasNeverOpened() {
00419         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface', array(), array(), '', FALSE);
00420         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00421         $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00422 
00423         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00424 
00425         $templateParser->_call('closingViewHelperTagHandler', $mockState, 'f', 'method');
00426     }
00427 
00428     /**
00429      * @test
00430      * @expectedException Tx_Fluid_Core_Parser_Exception
00431      * @author Karsten Dambekalns <karsten@typo3.org>
00432      */
00433     public function closingViewHelperTagHandlerThrowsExceptionBecauseOfWrongTagNesting () {
00434         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ViewHelperNode', array(), array(), '', FALSE);
00435         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00436         $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00437 
00438         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00439 
00440         $templateParser->_call('closingViewHelperTagHandler', $mockState, 'f', 'method');
00441     }
00442 
00443     /**
00444      * @test
00445      * @author Karsten Dambekalns <karsten@typo3.org>
00446      */
00447     public function objectAccessorHandlerCallsInitializeViewHelperAndAddItToStackIfViewHelperSyntaxIsPresent() {
00448         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00449         $mockState->expects($this->exactly(2))->method('popNodeFromStack')->will($this->returnValue($this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_NodeInterface')));
00450 
00451         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('recursiveArrayHandler', 'postProcessArgumentsForObjectAccessor', 'initializeViewHelperAndAddItToStack'));
00452         $templateParser->expects($this->at(0))->method('recursiveArrayHandler')->with('format: "H:i"')->will($this->returnValue(array('format' => 'H:i')));
00453         $templateParser->expects($this->at(1))->method('postProcessArgumentsForObjectAccessor')->with(array('format' => 'H:i'))->will($this->returnValue(array('processedArguments')));
00454         $templateParser->expects($this->at(2))->method('initializeViewHelperAndAddItToStack')->with($mockState, 'f', 'format.date', array('processedArguments'));
00455         $templateParser->expects($this->at(3))->method('initializeViewHelperAndAddItToStack')->with($mockState, 'f', 'base', array());
00456 
00457         $templateParser->_call('objectAccessorHandler', $mockState, '', '', 'f:base() f:format.date(format: "H:i")', '');
00458     }
00459 
00460     /**
00461      * @test
00462      * @author Karsten Dambekalns <karsten@typo3.org>
00463      */
00464     public function objectAccessorHandlerCreatesObjectAccessorNodeWithExpectedValueAndAddsItToStack() {
00465         $objectAccessorNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ObjectAccessorNode', array(), array(), '', FALSE);
00466 
00467         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00468         $mockObjectManager->expects($this->once())->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_ObjectAccessorNode', 'objectAccessorString')->will($this->returnValue($objectAccessorNode));
00469 
00470         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_AbstractNode', array(), array(), '', FALSE);
00471         $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($objectAccessorNode);
00472         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00473         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00474 
00475         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00476         $templateParser->injectObjectManager($mockObjectManager);
00477 
00478         $templateParser->_call('objectAccessorHandler', $mockState, 'objectAccessorString', '', '', '');
00479     }
00480 
00481     /**
00482      * @test
00483      * @author Karsten Dambekalns <karsten@typo3.org>
00484      */
00485     public function valuesFromObjectAccessorsAreRunThroughValueInterceptorsByDefault() {
00486         $objectAccessorNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ObjectAccessorNode', array(), array(), '', FALSE);
00487         $objectAccessorNodeInterceptor = $this->getMock('Tx_Fluid_Core_Parser_InterceptorInterface');
00488         $objectAccessorNodeInterceptor->expects($this->once())->method('process')->with($objectAccessorNode)->will($this->returnArgument(0));
00489 
00490         $parserConfiguration = $this->getMock('Tx_Fluid_Core_Parser_Configuration');
00491         $parserConfiguration->expects($this->once())->method('getInterceptors')->with(Tx_Fluid_Core_Parser_InterceptorInterface::INTERCEPT_OBJECTACCESSOR)->will($this->returnValue(array($objectAccessorNodeInterceptor)));
00492 
00493         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00494         $mockObjectManager->expects($this->once())->method('create')->will($this->returnValue($objectAccessorNode));
00495 
00496         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_AbstractNode', array(), array(), '', FALSE);
00497         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00498         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00499 
00500         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00501         $templateParser->injectObjectManager($mockObjectManager);
00502         $templateParser->_set('configuration', $parserConfiguration);
00503 
00504         $templateParser->_call('objectAccessorHandler', $mockState, 'objectAccessorString', '', '', '');
00505     }
00506 
00507     /**
00508      * @author Karsten Dambekalns <karsten@typo3.org>
00509      */
00510     public function argumentsStrings() {
00511         return array(
00512             array('a="2"', array('a' => '2')),
00513             array('a="2" b="foobar \' with \\" quotes"', array('a' => '2', 'b' => 'foobar \' with " quotes')),
00514             array(' arguments="{number : 362525200}"', array('arguments' => '{number : 362525200}')),
00515         );
00516     }
00517 
00518     /**
00519      * @test
00520      * @dataProvider argumentsStrings
00521      * @author Karsten Dambekalns <karsten@typo3.org>
00522      */
00523     public function parseArgumentsWorksAsExpected($argumentsString, $expected) {
00524         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('buildArgumentObjectTree'));
00525         $templateParser->expects($this->any())->method('buildArgumentObjectTree')->will($this->returnArgument(0));
00526 
00527         $this->assertSame($expected, $templateParser->_call('parseArguments', $argumentsString));
00528     }
00529 
00530     /**
00531      * @test
00532      * @author Karsten Dambekalns <karsten@typo3.org>
00533      */
00534     public function buildArgumentObjectTreeReturnsTextNodeForSimplyString() {
00535         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00536         $mockObjectManager->expects($this->once())->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_TextNode', 'a very plain string')->will($this->returnValue('theTextNode'));
00537 
00538         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('dummy'));
00539         $templateParser->injectObjectManager($mockObjectManager);
00540 
00541         $this->assertEquals('theTextNode', $templateParser->_call('buildArgumentObjectTree', 'a very plain string'));
00542     }
00543 
00544     /**
00545      * @test
00546      * @author Karsten Dambekalns <karsten@typo3.org>
00547      */
00548     public function buildArgumentObjectTreeBuildsObjectTreeForComlexString() {
00549         $objectTree = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00550         $objectTree->expects($this->once())->method('getRootNode')->will($this->returnValue('theRootNode'));
00551 
00552         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('splitTemplateAtDynamicTags', 'buildObjectTree'));
00553         $templateParser->expects($this->at(0))->method('splitTemplateAtDynamicTags')->with('a <very> {complex} string')->will($this->returnValue('split string'));
00554         $templateParser->expects($this->at(1))->method('buildObjectTree')->with('split string')->will($this->returnValue($objectTree));
00555 
00556         $this->assertEquals('theRootNode', $templateParser->_call('buildArgumentObjectTree', 'a <very> {complex} string'));
00557     }
00558 
00559     /**
00560      * @test
00561      * @author Karsten Dambekalns <karsten@typo3.org>
00562      */
00563     public function textAndShorthandSyntaxHandlerDelegatesAppropriately() {
00564         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00565         $mockObjectManager->expects($this->any())->method('create')->will($this->returnArgument(1));
00566         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00567 
00568         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('objectAccessorHandler', 'arrayHandler', 'textHandler'));
00569         $templateParser->injectObjectManager($mockObjectManager);
00570         $templateParser->expects($this->at(0))->method('objectAccessorHandler')->with($mockState, 'someThing.absolutely', '', '', '');
00571         $templateParser->expects($this->at(1))->method('textHandler')->with($mockState, ' "fishy" is \'going\' ');
00572         $templateParser->expects($this->at(2))->method('arrayHandler')->with($mockState, 'on: "here"');
00573 
00574         $text = '{someThing.absolutely} "fishy" is \'going\' {on: "here"}';
00575         $templateParser->_call('textAndShorthandSyntaxHandler', $mockState, $text);
00576     }
00577 
00578     /**
00579      * @test
00580      * @author Karsten Dambekalns <karsten@typo3.org>
00581      */
00582     public function arrayHandlerAddsArrayNodeWithProperContentToStack() {
00583         $arrayNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_ArrayNode', array(), array(array()));
00584         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_AbstractNode', array(), array(), '', FALSE);
00585         $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($arrayNode);
00586         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00587         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00588 
00589         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00590         $mockObjectManager->expects($this->once())->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_ArrayNode', 'processedArrayText')->will($this->returnValue($arrayNode));
00591 
00592         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('recursiveArrayHandler'));
00593         $templateParser->injectObjectManager($mockObjectManager);
00594         $templateParser->expects($this->once())->method('recursiveArrayHandler')->with('arrayText')->will($this->returnValue('processedArrayText'));
00595 
00596         $templateParser->_call('arrayHandler', $mockState, 'arrayText');
00597     }
00598 
00599     /**
00600      * @author Karsten Dambekalns <karsten@typo3.org>
00601      */
00602     public function arrayTexts() {
00603         return array(
00604             array(
00605                 'key1: "foo", key2: \'bar\', key3: someVar, key4: 123, key5: { key6: "baz" }',
00606                 array('key1' => 'foo', 'key2' => 'bar', 'key3' => 'someVar', 'key4' => 123.0, 'key5' => array('key6' => 'baz'),
00607             )),
00608         );
00609     }
00610 
00611     /**
00612      * @test
00613      * @dataProvider arrayTexts
00614      * @author Karsten Dambekalns <karsten@typo3.org>
00615      */
00616     public function recursiveArrayHandlerReturnsExpectedArray($arrayText, $expectedArray) {
00617         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00618         $mockObjectManager->expects($this->any())->method('create')->will($this->returnArgument(1));
00619 
00620         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('buildArgumentObjectTree'));
00621         $templateParser->injectObjectManager($mockObjectManager);
00622         $templateParser->expects($this->any())->method('buildArgumentObjectTree')->will($this->returnArgument(0));
00623 
00624         $this->assertSame($expectedArray, $templateParser->_call('recursiveArrayHandler', $arrayText));
00625     }
00626 
00627     /**
00628      * @test
00629      * @author Karsten Dambekalns <karsten@typo3.org>
00630      */
00631     public function textNodesAreRunThroughTextInterceptors() {
00632         $textNode = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_TextNode', array(), array(), '', FALSE);
00633         $textInterceptor = $this->getMock('Tx_Fluid_Core_Parser_InterceptorInterface');
00634         $textInterceptor->expects($this->once())->method('process')->with($textNode)->will($this->returnArgument(0));
00635 
00636         $parserConfiguration = $this->getMock('Tx_Fluid_Core_Parser_Configuration');
00637         $parserConfiguration->expects($this->once())->method('getInterceptors')->with(Tx_Fluid_Core_Parser_InterceptorInterface::INTERCEPT_TEXT)->will($this->returnValue(array($textInterceptor)));
00638 
00639         $mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
00640         $mockObjectManager->expects($this->once())->method('create')->with('Tx_Fluid_Core_Parser_SyntaxTree_TextNode', 'string')->will($this->returnValue($textNode));
00641 
00642         $mockNodeOnStack = $this->getMock('Tx_Fluid_Core_Parser_SyntaxTree_AbstractNode', array(), array(), '', FALSE);
00643         $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($textNode);
00644         $mockState = $this->getMock('Tx_Fluid_Core_Parser_ParsingState');
00645         $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
00646 
00647         $templateParser = $this->getAccessibleMock('Tx_Fluid_Core_Parser_TemplateParser', array('splitTemplateAtDynamicTags', 'buildObjectTree'));
00648         $templateParser->injectObjectManager($mockObjectManager);
00649         $templateParser->_set('configuration', $parserConfiguration);
00650 
00651         $templateParser->_call('textHandler', $mockState, 'string');
00652     }
00653 
00654 }
00655 
00656 ?>