* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice * * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package Cake.Test.Case.View * @since CakePHP(tm) v 1.2.0.4206 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('View', 'View'); App::uses('Helper', 'View'); App::uses('Controller', 'Controller'); App::uses('CacheHelper', 'View/Helper'); App::uses('ErrorHandler', 'Error'); /** * ViewPostsController class * * @package Cake.Test.Case.View */ class ViewPostsController extends Controller { /** * name property * * @var string 'Posts' */ public $name = 'Posts'; /** * uses property * * @var mixed null */ public $uses = null; /** * index method * * @return void */ public function index() { $this->set('testData', 'Some test data'); $test2 = 'more data'; $test3 = 'even more data'; $this->set(compact('test2', 'test3')); } /** * nocache_tags_with_element method * * @return void */ public function nocache_multiple_element() { $this->set('foo', 'this is foo var'); $this->set('bar', 'this is bar var'); } } /** * TestView class * * @package Cake.Test.Case.View */ class TestView extends View { /** * getViewFileName method * * @param mixed $name * @return void */ public function getViewFileName($name = null) { return $this->_getViewFileName($name); } /** * getLayoutFileName method * * @param mixed $name * @return void */ public function getLayoutFileName($name = null) { return $this->_getLayoutFileName($name); } /** * paths method * * @param string $plugin * @param boolean $cached * @return void */ public function paths($plugin = null, $cached = true) { return $this->_paths($plugin, $cached); } /** * _render wrapper for testing (temporary). * * @param string $___viewFn * @param string $___dataForView * @param string $loadHelpers * @param string $cached * @return void */ public function render_($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) { return $this->_render($___viewFn, $___dataForView, $loadHelpers, $cached); } /** * Test only function to return instance scripts. * * @return array Scripts */ public function scripts() { return $this->_scripts; } } /** * TestAfterHelper class * * @package Cake.Test.Case.View */ class TestAfterHelper extends Helper { /** * property property * * @var string '' */ public $property = ''; /** * beforeLayout method * * @return void */ public function beforeLayout($viewFile) { $this->property = 'Valuation'; } /** * afterLayout method * * @return void */ public function afterLayout($layoutFile) { $this->_View->output .= 'modified in the afterlife'; } } /** * ViewTest class * * @package Cake.Test.Case.View */ class ViewTest extends CakeTestCase { /** * Fixtures used in this test. * * @var array */ public $fixtures = array('core.user', 'core.post'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $request = $this->getMock('CakeRequest'); $this->Controller = new Controller($request); $this->PostsController = new ViewPostsController($request); $this->PostsController->viewPath = 'Posts'; $this->PostsController->index(); $this->View = new View($this->PostsController); App::build(array( 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'View'. DS ) ), true); CakePlugin::load(array('TestPlugin', 'TestPlugin', 'PluginJs')); Configure::write('debug', 2); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); unset($this->View); unset($this->PostsController); unset($this->Controller); } /** * testPluginGetTemplate method * * @return void */ public function testPluginGetTemplate() { $this->Controller->plugin = 'TestPlugin'; $this->Controller->name = 'TestPlugin'; $this->Controller->viewPath = 'Tests'; $this->Controller->action = 'index'; $View = new TestView($this->Controller); $expected = CakePlugin::path('TestPlugin') . 'View' . DS .'Tests' . DS .'index.ctp'; $result = $View->getViewFileName('index'); $this->assertEquals($expected, $result); $expected = CakePlugin::path('TestPlugin') . 'View' . DS . 'Layouts' . DS .'default.ctp'; $result = $View->getLayoutFileName(); $this->assertEquals($expected, $result); } /** * test that plugin/$plugin_name is only appended to the paths it should be. * * @return void */ public function testPluginPathGeneration() { $this->Controller->plugin = 'TestPlugin'; $this->Controller->name = 'TestPlugin'; $this->Controller->viewPath = 'Tests'; $this->Controller->action = 'index'; $View = new TestView($this->Controller); $paths = $View->paths(); $expected = array_merge(App::path('View'), App::core('View')); $this->assertEquals($paths, $expected); $paths = $View->paths('TestPlugin'); $pluginPath = CakePlugin::path('TestPlugin'); $expected = array( CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Plugin' . DS . 'TestPlugin' . DS, $pluginPath . 'View' . DS, $pluginPath . 'Lib' . DS . 'View' . DS, CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS, CAKE . 'View' . DS ); $this->assertEquals($paths, $expected); } /** * test that CamelCase plugins still find their view files. * * @return void */ public function testCamelCasePluginGetTemplate() { $this->Controller->plugin = 'TestPlugin'; $this->Controller->name = 'TestPlugin'; $this->Controller->viewPath = 'Tests'; $this->Controller->action = 'index'; $View = new TestView($this->Controller); App::build(array( 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View'. DS) )); $pluginPath = CakePlugin::path('TestPlugin'); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS .'TestPlugin' . DS . 'View' . DS .'Tests' . DS .'index.ctp'; $result = $View->getViewFileName('index'); $this->assertEquals($expected, $result); $expected = $pluginPath. 'View' . DS . 'Layouts' . DS .'default.ctp'; $result = $View->getLayoutFileName(); $this->assertEquals($expected, $result); } /** * testGetTemplate method * * @return void */ public function testGetViewFileNames() { $this->Controller->plugin = null; $this->Controller->name = 'Pages'; $this->Controller->viewPath = 'Pages'; $this->Controller->action = 'display'; $this->Controller->params['pass'] = array('home'); $View = new TestView($this->Controller); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS .'Pages' . DS .'home.ctp'; $result = $View->getViewFileName('home'); $this->assertEquals($expected, $result); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS .'Posts' . DS .'index.ctp'; $result = $View->getViewFileName('/Posts/index'); $this->assertEquals($expected, $result); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS .'Posts' . DS .'index.ctp'; $result = $View->getViewFileName('../Posts/index'); $this->assertEquals($expected, $result); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS .'Pages' . DS .'page.home.ctp'; $result = $View->getViewFileName('page.home'); $this->assertEquals($expected, $result, 'Should not ruin files with dots.'); CakePlugin::load('TestPlugin'); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS .'Pages' . DS .'home.ctp'; $result = $View->getViewFileName('TestPlugin.home'); $this->assertEquals($expected, $result, 'Plugin is missing the view, cascade to app.'); $View->viewPath = 'Tests'; $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS . 'View' . DS .'Tests' . DS .'index.ctp'; $result = $View->getViewFileName('TestPlugin.index'); $this->assertEquals($expected, $result); } /** * Test getting layout filenames * * @return void */ public function testGetLayoutFileName() { $this->Controller->plugin = null; $this->Controller->name = 'Pages'; $this->Controller->viewPath = 'Pages'; $this->Controller->action = 'display'; $View = new TestView($this->Controller); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Layouts' . DS .'default.ctp'; $result = $View->getLayoutFileName(); $this->assertEquals($expected, $result); $View->layoutPath = 'rss'; $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Layouts' . DS . 'rss' . DS . 'default.ctp'; $result = $View->getLayoutFileName(); $this->assertEquals($expected, $result); $View->layoutPath = 'Emails' . DS . 'html'; $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Layouts' . DS . 'Emails' . DS . 'html' . DS . 'default.ctp'; $result = $View->getLayoutFileName(); $this->assertEquals($expected, $result); } /** * Test getting layout filenames for plugins. * * @return void */ public function testGetLayoutFileNamePlugin() { $this->Controller->plugin = null; $this->Controller->name = 'Pages'; $this->Controller->viewPath = 'Pages'; $this->Controller->action = 'display'; $View = new TestView($this->Controller); CakePlugin::load('TestPlugin'); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS . 'View' . DS . 'Layouts' . DS .'default.ctp'; $result = $View->getLayoutFileName('TestPlugin.default'); $this->assertEquals($expected, $result); $View->plugin = 'TestPlugin'; $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS . 'View' . DS . 'Layouts' . DS .'default.ctp'; $result = $View->getLayoutFileName('default'); $this->assertEquals($expected, $result); } /** * testMissingView method * * @expectedException MissingViewException * @return void */ public function testMissingView() { $this->Controller->plugin = null; $this->Controller->name = 'Pages'; $this->Controller->viewPath = 'Pages'; $this->Controller->action = 'display'; $this->Controller->params['pass'] = array('home'); $View = new TestView($this->Controller); ob_start(); $result = $View->getViewFileName('does_not_exist'); } /** * testMissingLayout method * * @expectedException MissingLayoutException * @return void */ public function testMissingLayout() { $this->Controller->plugin = null; $this->Controller->name = 'Posts'; $this->Controller->viewPath = 'Posts'; $this->Controller->layout = 'whatever'; $View = new TestView($this->Controller); ob_start(); $result = $View->getLayoutFileName(); $expected = str_replace(array("\t", "\r\n", "\n"), "", ob_get_clean()); } /** * testViewVars method * * @return void */ public function testViewVars() { $this->assertEquals($this->View->viewVars, array('testData' => 'Some test data', 'test2' => 'more data', 'test3' => 'even more data')); } /** * testUUIDGeneration method * * @return void */ public function testUUIDGeneration() { $result = $this->View->uuid('form', array('controller' => 'posts', 'action' => 'index')); $this->assertEquals($result, 'form5988016017'); $result = $this->View->uuid('form', array('controller' => 'posts', 'action' => 'index')); $this->assertEquals($result, 'formc3dc6be854'); $result = $this->View->uuid('form', array('controller' => 'posts', 'action' => 'index')); $this->assertEquals($result, 'form28f92cc87f'); } /** * testAddInlineScripts method * * @return void */ public function testAddInlineScripts() { $View = new TestView($this->Controller); $View->addScript('prototype.js'); $View->addScript('prototype.js'); $this->assertEquals($View->scripts(), array('prototype.js')); $View->addScript('mainEvent', 'Event.observe(window, "load", function() { doSomething(); }, true);'); $this->assertEquals($View->scripts(), array('prototype.js', 'mainEvent' => 'Event.observe(window, "load", function() { doSomething(); }, true);')); } /** * testElement method * * @return void */ public function testElement() { $result = $this->View->element('test_element'); $this->assertEquals($result, 'this is the test element'); $result = $this->View->element('plugin_element', array(), array('plugin' => 'TestPlugin')); $this->assertEquals($result, 'this is the plugin element using params[plugin]'); $result = $this->View->element('plugin_element', array(), array('plugin' => 'test_plugin')); $this->assertEquals($result, 'this is the plugin element using params[plugin]'); $result = $this->View->element('TestPlugin.plugin_element'); $this->assertEquals($result, 'this is the plugin element using params[plugin]'); $result = $this->View->element('test_plugin.plugin_element'); $this->assertPattern('/Not Found:/', $result); $this->assertPattern('/test_plugin.plugin_element/', $result); $this->View->plugin = 'TestPlugin'; $result = $this->View->element('test_plugin_element'); $this->assertEquals($result, 'this is the test set using View::$plugin plugin element'); $result = $this->View->element('non_existant_element'); $this->assertRegExp('/Not Found:/', $result); $this->assertRegExp('/non_existant_element/', $result); $result = $this->View->element('TestPlugin.plugin_element', array(), array('plugin' => 'test_plugin')); $this->assertRegExp('/Not Found:/', $result); $this->assertRegExp('/TestPlugin.plugin_element/', $result); } /** * test that elements can have callbacks * */ public function testElementCallbacks() { $this->getMock('HtmlHelper', array(), array($this->View), 'ElementCallbackMockHtmlHelper'); $this->View->helpers = array('ElementCallbackMockHtml'); $this->View->loadHelpers(); $this->View->ElementCallbackMockHtml->expects($this->at(0))->method('beforeRender'); $this->View->ElementCallbackMockHtml->expects($this->at(1))->method('afterRender'); $this->View->element('test_element', array(), array('callbacks' => true)); $this->mockObjects[] = $this->View->ElementCallbackMockHtml; } /** * test that additional element viewVars don't get overwritten with helpers. * * @return void */ public function testElementParamsDontOverwriteHelpers() { $Controller = new ViewPostsController(); $Controller->helpers = array('Form'); $View = new View($Controller); $result = $View->element('type_check', array('form' => 'string'), array('callbacks' => true)); $this->assertEquals('string', $result); $View->set('form', 'string'); $result = $View->element('type_check', array(), array('callbacks' => true)); $this->assertEquals('string', $result); } /** * testElementCacheHelperNoCache method * * @return void */ public function testElementCacheHelperNoCache() { $Controller = new ViewPostsController(); $View = new TestView($Controller); $helpers = $View->loadHelpers(); $result = $View->element('test_element', array('ram' => 'val', 'test' => array('foo', 'bar'))); $this->assertEquals($result, 'this is the test element'); } /** * testElementCache method * * @return void */ public function testElementCache() { Cache::drop('test_view'); Cache::config('test_view', array( 'engine' => 'File', 'duration' => '+1 day', 'path' => CACHE . 'views' . DS, 'prefix' => '' )); Cache::clear('test_view'); $View = new TestView($this->PostsController); $View->elementCache = 'test_view'; $result = $View->element('test_element', array(), array('cache' => true)); $expected = 'this is the test element'; $this->assertEquals($expected, $result); $result = Cache::read('element__test_element_cache', 'test_view'); $this->assertEquals($expected, $result); $result = $View->element('test_element', array('param' => 'one', 'foo' => 'two'), array('cache' => true)); $this->assertEquals($expected, $result); $result = Cache::read('element__test_element_cache_param_foo', 'test_view'); $this->assertEquals($expected, $result); $result = $View->element('test_element', array( 'param' => 'one', 'foo' => 'two' ), array( 'cache' => array('key' => 'custom_key') )); $result = Cache::read('element_custom_key', 'test_view'); $this->assertEquals($expected, $result); $View->elementCache = 'default'; $result = $View->element('test_element', array( 'param' => 'one', 'foo' => 'two' ), array( 'cache' => array('config' => 'test_view'), )); $result = Cache::read('element__test_element_cache_param_foo', 'test_view'); $this->assertEquals($expected, $result); Cache::drop('test_view'); } /** * test __get allowing access to helpers. * * @return void */ public function test__get() { $View = new View($this->PostsController); $View->loadHelper('Html'); $this->assertInstanceOf('HtmlHelper', $View->Html); } /** * test that ctp is used as a fallback file extension for elements * * @return void */ public function testElementCtpFallback() { $View = new TestView($this->PostsController); $View->ext = '.missing'; $element = 'test_element'; $expected = 'this is the test element'; $result = $View->element($element); $this->assertEquals($expected, $result); } /** * testLoadHelpers method * * @return void */ public function testLoadHelpers() { $View = new View($this->PostsController); $View->helpers = array('Html', 'Form'); $View->loadHelpers(); $this->assertInstanceOf('HtmlHelper', $View->Html, 'Object type is wrong.'); $this->assertInstanceOf('FormHelper', $View->Form, 'Object type is wrong.'); } /** * test the correct triggering of helper callbacks * * @return void */ public function testHelperCallbackTriggering() { $View = new View($this->PostsController); $View->helpers = array(); $View->Helpers = $this->getMock('HelperCollection', array('trigger'), array($View)); $View->Helpers->expects($this->at(0))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.beforeRender'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(1))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.beforeRenderFile'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(2))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.afterRenderFile'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(3))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.afterRender'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(4))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.beforeLayout'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(5))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.beforeRenderFile'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(6))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.afterRenderFile'), $this->attributeEqualTo('_subject', $View) ) ); $View->Helpers->expects($this->at(7))->method('trigger') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'View.afterLayout'), $this->attributeEqualTo('_subject', $View) ) ); $View->render('index'); } /** * testBeforeLayout method * * @return void */ public function testBeforeLayout() { $this->PostsController->helpers = array('Session', 'TestAfter', 'Html'); $View = new View($this->PostsController); $View->render('index'); $this->assertEquals($View->Helpers->TestAfter->property, 'Valuation'); } /** * testAfterLayout method * * @return void */ public function testAfterLayout() { $this->PostsController->helpers = array('Session', 'TestAfter', 'Html'); $this->PostsController->set('variable', 'values'); $View = new View($this->PostsController); ClassRegistry::addObject('afterView', $View); $content = 'This is my view output'; $result = $View->renderLayout($content, 'default'); $this->assertRegExp('/modified in the afterlife/', $result); $this->assertRegExp('/This is my view output/', $result); } /** * testRenderLoadHelper method * * @return void */ public function testRenderLoadHelper() { $this->PostsController->helpers = array('Session', 'Html', 'Form', 'Number'); $View = new TestView($this->PostsController); $result = $View->render('index', false); $this->assertEquals($result, 'posts index'); $attached = $View->Helpers->attached(); $this->assertEquals($attached, array('Session', 'Html', 'Form', 'Number')); $this->PostsController->helpers = array('Html', 'Form', 'Number', 'TestPlugin.PluggedHelper'); $View = new TestView($this->PostsController); $result = $View->render('index', false); $this->assertEquals($result, 'posts index'); $attached = $View->Helpers->attached(); $expected = array('Html', 'Form', 'Number', 'PluggedHelper'); $this->assertEquals($expected, $attached, 'Attached helpers are wrong.'); } /** * testRender method * * @return void */ public function testRender() { $View = new TestView($this->PostsController); $result = str_replace(array("\t", "\r\n", "\n"), "", $View->render('index')); $this->assertRegExp("/