RendererTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\template\view;
  9. use stdClass;
  10. use lithium\action\Request;
  11. use lithium\action\Response;
  12. use lithium\template\Helper;
  13. use lithium\template\helper\Html;
  14. use lithium\template\view\adapter\Simple;
  15. use lithium\net\http\Router;
  16. use lithium\template\View;
  17. class RendererTest extends \lithium\test\Unit {
  18. public function setUp() {
  19. $this->_routes = Router::get();
  20. Router::reset();
  21. Router::connect('/{:controller}/{:action}');
  22. $this->subject = new Simple(array(
  23. 'request' => new Request(array(
  24. 'base' => '', 'env' => array('HTTP_HOST' => 'foo.local')
  25. )),
  26. 'response' => new Response()
  27. ));
  28. }
  29. public function tearDown() {
  30. Router::reset();
  31. foreach ($this->_routes as $route) {
  32. Router::connect($route);
  33. }
  34. }
  35. public function testInitialization() {
  36. $expected = array('url', 'path', 'options', 'title', 'value', 'scripts', 'styles', 'head');
  37. $result = array_keys($this->subject->handlers());
  38. $this->assertEqual($expected, $result);
  39. $expected = array('content', 'title', 'scripts', 'styles', 'head');
  40. $result = array_keys($this->subject->context());
  41. $this->assertEqual($expected, $result);
  42. }
  43. public function testContextQuerying() {
  44. $expected = array(
  45. 'content' => '', 'title' => '', 'scripts' => array(),
  46. 'styles' => array(), 'head' => array()
  47. );
  48. $this->assertEqual($expected, $this->subject->context());
  49. $this->assertEqual('', $this->subject->context('title'));
  50. $this->assertEqual(array(), $this->subject->context('scripts'));
  51. $this->assertEqual(array(), $this->subject->scripts);
  52. $this->assertNull($this->subject->foo());
  53. $this->assertFalse(isset($this->subject->foo));
  54. $result = $this->subject->title("<script>alert('XSS');</script>");
  55. $this->assertEqual('&lt;script&gt;alert(&#039;XSS&#039;);&lt;/script&gt;', $result);
  56. $result = $this->subject->title();
  57. $this->assertEqual('&lt;script&gt;alert(&#039;XSS&#039;);&lt;/script&gt;', $result);
  58. $this->subject = new Simple(array('context' => array(
  59. 'content' => '', 'title' => '', 'scripts' => array(), 'styles' => array(), 'foo' => '!'
  60. )));
  61. $this->assertEqual('!', $this->subject->foo());
  62. $this->assertTrue(isset($this->subject->foo));
  63. }
  64. /**
  65. * Tests that URLs are properly escaped by the URL handler.
  66. */
  67. public function testUrlAutoEscaping() {
  68. Router::connect('/{:controller}/{:action}/{:id}');
  69. $this->assertEqual('/<foo>/<bar>', $this->subject->url('/<foo>/<bar>'));
  70. $result = $this->subject->url(array('Controller::action', 'id' => '<script />'));
  71. $this->assertEqual('/controller/action/<script />', $result);
  72. $this->subject = new Simple(array(
  73. 'response' => new Response(), 'view' => new View(), 'request' => new Request(array(
  74. 'base' => '', 'env' => array('HTTP_HOST' => 'foo.local')
  75. ))
  76. ));
  77. $this->assertEqual('/&lt;foo&gt;/&lt;bar&gt;', $this->subject->url('/<foo>/<bar>'));
  78. $result = $this->subject->url(array('Controller::action', 'id' => '<script />'));
  79. $this->assertEqual('/controller/action/&lt;script /&gt;', $result);
  80. $result = $this->subject->url(array('Posts::index', '?' => array(
  81. 'foo' => 'bar', 'baz' => 'dib'
  82. )));
  83. $this->assertEqual('/posts?foo=bar&baz=dib', $result);
  84. }
  85. /**
  86. * Tests built-in content handlers for generating URLs, paths to static assets, and handling
  87. * output of elements written to the request context.
  88. */
  89. public function testCoreHandlers() {
  90. $url = $this->subject->applyHandler(null, null, 'url', array(
  91. 'controller' => 'foo', 'action' => 'bar'
  92. ));
  93. $this->assertEqual('/foo/bar', $url);
  94. $helper = new Html();
  95. $class = get_class($helper);
  96. $path = $this->subject->applyHandler($helper, "{$class}::script", 'path', 'foo/file');
  97. $this->assertEqual('/js/foo/file.js', $path);
  98. $this->assertEqual('/some/generic/path', $this->subject->path('some/generic/path'));
  99. }
  100. public function testHandlerInsertion() {
  101. $this->subject = new Simple(array('context' => array(
  102. 'content' => '', 'title' => '', 'scripts' => array(), 'styles' => array(), 'foo' => '!'
  103. )));
  104. $foo = function($value) { return "Foo: {$value}"; };
  105. $expected = array(
  106. 'url', 'path', 'options', 'title', 'value', 'scripts', 'styles', 'head', 'foo'
  107. );
  108. $result = array_keys($this->subject->handlers(compact('foo')));
  109. $this->assertEqual($expected, $result);
  110. $result = $this->subject->applyHandler(null, null, 'foo', 'test value');
  111. $this->assertEqual('Foo: test value', $result);
  112. $this->assertEqual('Foo: !', $this->subject->foo());
  113. $this->assertEqual($foo, $this->subject->handlers('foo'));
  114. $this->assertNull($this->subject->handlers('bar'));
  115. $bar = function($value) { return "Bar: {$value}"; };
  116. $this->subject->handlers(compact('bar'));
  117. $result = $this->subject->applyHandler(null, null, 'bar', 'test value');
  118. $expected = 'Bar: test value';
  119. $this->assertEqual($expected, $result);
  120. $result = $this->subject->bar('test value');
  121. $this->assertEqual($expected, $result);
  122. }
  123. public function testHandlerQuerying() {
  124. $result = $this->subject->nonExistent('test value');
  125. $expected = 'test value';
  126. $this->assertEqual($expected, $result);
  127. $result = $this->subject->applyHandler(null, null, 'nonExistent', 'test value');
  128. $this->assertEqual($expected, $result);
  129. $html = new Html();
  130. $script = '<script>alert("XSS!");</script>';
  131. $escaped = '&lt;script&gt;alert(&quot;XSS!&quot;);&lt;/script&gt;';
  132. $result = $this->subject->applyHandler($html, null, 'title', $script);
  133. $expected = $escaped;
  134. $this->assertEqual($expected, $result);
  135. $result = $this->subject->applyHandler($html, null, 'foo', $script);
  136. $expected = $script;
  137. $this->assertEqual($expected, $result);
  138. $result = $this->subject->applyHandler($html, null, 'bar', $script);
  139. $this->assertEqual($expected, $result);
  140. $this->subject->handlers(array('foo' => array($html, 'escape'), 'bar' => 42));
  141. $result = $this->subject->applyHandler($html, null, 'bar', $script);
  142. $this->assertEqual($expected, $result);
  143. $result = $this->subject->applyHandler($html, null, 'foo', $script);
  144. $expected = $escaped;
  145. $this->assertEqual($expected, $result);
  146. }
  147. public function testHelperLoading() {
  148. $helper = $this->subject->helper('html');
  149. $this->assertTrue($helper instanceof Helper);
  150. $this->expectException('/invalidFoo/');
  151. $this->assertNull($this->subject->helper('invalidFoo'));
  152. }
  153. public function testHelperQuerying() {
  154. $helper = $this->subject->html;
  155. $this->assertTrue($helper instanceof Helper);
  156. }
  157. public function testTemplateStrings() {
  158. $result = $this->subject->strings();
  159. $this->assertTrue(is_array($result));
  160. $this->assertFalse($result);
  161. $expected = array('data' => 'The data goes here: {:data}');
  162. $result = $this->subject->strings($expected);
  163. $this->assertEqual($expected, $result);
  164. $result = $this->subject->strings();
  165. $this->assertEqual($expected, $result);
  166. $result = $this->subject->strings('data');
  167. $expected = $expected['data'];
  168. $this->assertEqual($expected, $result);
  169. }
  170. public function testGetters() {
  171. $this->assertTrue($this->subject->request() instanceof Request);
  172. $this->assertTrue($this->subject->response() instanceof Response);
  173. $this->subject = new Simple();
  174. $this->assertNull($this->subject->request());
  175. $this->assertNull($this->subject->response());
  176. }
  177. public function testSetAndData() {
  178. $data = array('one' => 1, 'two' => 2, 'three' => 'value');
  179. $result = $this->subject->set($data);
  180. $this->assertNull($result);
  181. $result = $this->subject->data();
  182. $this->assertEqual($data, $result);
  183. $result = $this->subject->set(array('more' => new stdClass()));
  184. $this->assertNull($result);
  185. $result = $this->subject->data();
  186. $this->assertEqual($data + array('more' => new stdClass()), $result);
  187. }
  188. /**
  189. * @todo Add integration test for Renderer being composed with a view object.
  190. */
  191. public function testView() {
  192. $result = $this->subject->view();
  193. $this->assertNull($result);
  194. }
  195. public function testHandlers() {
  196. $this->assertTrue($this->subject->url());
  197. $this->assertPattern('/\/posts\/foo/', $this->subject->url('Posts::foo'));
  198. $absolute = $this->subject->url('Posts::foo', array('absolute' => true));
  199. $this->assertEqual('http://foo.local/posts/foo', $absolute);
  200. $this->assertFalse(trim($this->subject->scripts()));
  201. $this->assertEqual('foobar', trim($this->subject->scripts('foobar')));
  202. $this->assertEqual('foobar', trim($this->subject->scripts()));
  203. $this->assertFalse(trim($this->subject->styles()));
  204. $this->assertEqual('foobar', trim($this->subject->styles('foobar')));
  205. $this->assertEqual('foobar', trim($this->subject->styles()));
  206. $this->assertFalse($this->subject->title());
  207. $this->assertEqual('Foo', $this->subject->title('Foo'));
  208. $this->assertEqual('Bar', $this->subject->title('Bar'));
  209. $this->assertEqual('Bar', $this->subject->title());
  210. $this->assertFalse(trim($this->subject->head()));
  211. $this->assertEqual('foo', trim($this->subject->head('foo')));
  212. $this->assertEqual("foo\n\tbar", trim($this->subject->head('bar')));
  213. $this->assertEqual("foo\n\tbar", trim($this->subject->head()));
  214. }
  215. public function testRespondsTo() {
  216. $this->assertTrue($this->subject->respondsTo('foobarbaz'));
  217. $this->assertFalse($this->subject->respondsTo(0));
  218. }
  219. }
  220. ?>