ViewRendererTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yiiunit\twig;
  8. use yii\helpers\FileHelper;
  9. use yii\web\AssetManager;
  10. use yii\web\View;
  11. use Yii;
  12. use yiiunit\twig\data\Order;
  13. use yiiunit\twig\data\Singer;
  14. /**
  15. * Tests Twig view renderer
  16. *
  17. * @author Alexander Makarov <sam@rmcreative.ru>
  18. * @author Carsten Brandt <mail@cebe.cc>
  19. */
  20. class ViewRendererTest extends TestCase
  21. {
  22. public static function setUpBeforeClass()
  23. {
  24. parent::setUpBeforeClass();
  25. Order::setUp();
  26. }
  27. protected function setUp()
  28. {
  29. parent::setUp();
  30. $this->mockWebApplication();
  31. }
  32. protected function tearDown()
  33. {
  34. parent::tearDown();
  35. FileHelper::removeDirectory(Yii::getAlias('@runtime/assets'));
  36. }
  37. /**
  38. * https://github.com/yiisoft/yii2/issues/1755
  39. */
  40. public function testLayoutAssets()
  41. {
  42. $view = $this->mockView();
  43. $content = $view->renderFile('@yiiunit/twig/views/layout.twig');
  44. $this->assertEquals(1, preg_match('#<script src="/assets/[0-9a-z]+/jquery\\.js"></script>\s*</body>#', $content), 'Content does not contain the jquery js:' . $content);
  45. }
  46. public function testAppGlobal()
  47. {
  48. $view = $this->mockView();
  49. $content = $view->renderFile('@yiiunit/twig/views/layout.twig');
  50. $this->assertEquals(1, preg_match('#<meta charset="' . Yii::$app->charset . '"/>#', $content), 'Content does not contain charset:' . $content);
  51. }
  52. /**
  53. * https://github.com/yiisoft/yii2/issues/3877
  54. */
  55. public function testLexerOptions()
  56. {
  57. $view = $this->mockView();
  58. $content = $view->renderFile('@yiiunit/twig/views/comments.twig');
  59. $this->assertFalse(strpos($content, 'CUSTOM_LEXER_TWIG_COMMENT'), 'Custom comment lexerOptions were not applied: ' . $content);
  60. $this->assertTrue(strpos($content, 'DEFAULT_TWIG_COMMENT') !== false, 'Default comment style was not modified via lexerOptions:' . $content);
  61. }
  62. public function testForm()
  63. {
  64. $view = $this->mockView();
  65. $model = new Singer();
  66. $content = $view->renderFile('@yiiunit/twig/views/form.twig', ['model' => $model]);
  67. $this->assertEquals(1, preg_match('#<form id="login-form" class="form-horizontal" action="/form-handler" method="post">.*?</form>#s', $content), 'Content does not contain form:' . $content);
  68. }
  69. public function testCalls()
  70. {
  71. $view = $this->mockView();
  72. $model = new Singer();
  73. $content = $view->renderFile('@yiiunit/twig/views/calls.twig', ['model' => $model]);
  74. $this->assertNotContains('silence', $content, 'silence should not be echoed when void() used');
  75. $this->assertContains('echo', $content);
  76. $this->assertContains('variable', $content);
  77. }
  78. public function testInheritance()
  79. {
  80. $view = $this->mockView();
  81. $content = $view->renderFile('@yiiunit/twig/views/extends2.twig');
  82. $this->assertContains('Hello, I\'m inheritance test!', $content);
  83. $this->assertContains('extends2 block', $content);
  84. $this->assertNotContains('extends1 block', $content);
  85. $content = $view->renderFile('@yiiunit/twig/views/extends3.twig');
  86. $this->assertContains('Hello, I\'m inheritance test!', $content);
  87. $this->assertContains('extends3 block', $content);
  88. $this->assertNotContains('extends1 block', $content);
  89. }
  90. public function testChangeTitle()
  91. {
  92. $view = $this->mockView();
  93. $view->title = 'Original title';
  94. $content = $view->renderFile('@yiiunit/twig/views/changeTitle.twig');
  95. $this->assertContains('New title', $content);
  96. $this->assertNotContains('Original title', $content);
  97. }
  98. public function testNullsInAr()
  99. {
  100. $view = $this->mockView();
  101. $order = new Order();
  102. $content = $view->renderFile('@yiiunit/twig/views/nulls.twig', ['order' => $order]);
  103. $this->assertSame('', $content);
  104. }
  105. public function testPropertyAccess()
  106. {
  107. $view = $this->mockView();
  108. $order = new Order();
  109. $order->total = 42;
  110. $content = $view->renderFile('@yiiunit/twig/views/property.twig', ['order' => $order]);
  111. $this->assertContains('42', $content);
  112. }
  113. public function testSimpleFilters()
  114. {
  115. $view = $this->mockView();
  116. $content = $view->renderFile('@yiiunit/twig/views/simpleFilters1.twig');
  117. $this->assertEquals($content, 'Gjvt');
  118. $content = $view->renderFile('@yiiunit/twig/views/simpleFilters2.twig');
  119. $this->assertEquals($content, 'val42');
  120. $content = $view->renderFile('@yiiunit/twig/views/simpleFilters3.twig');
  121. $this->assertEquals($content, 'Gjvt');
  122. $content = $view->renderFile('@yiiunit/twig/views/simpleFilters4.twig');
  123. $this->assertEquals($content, 'val42');
  124. $content = $view->renderFile('@yiiunit/twig/views/simpleFilters5.twig');
  125. $this->assertEquals($content, 'Gjvt');
  126. }
  127. public function testSimpleFunctions()
  128. {
  129. $view = $this->mockView();
  130. $content = $view->renderFile('@yiiunit/twig/views/simpleFunctions1.twig');
  131. $this->assertEquals($content, 'Gjvt');
  132. $content = $view->renderFile('@yiiunit/twig/views/simpleFunctions2.twig');
  133. $this->assertEquals($content, 'val43');
  134. $content = $view->renderFile('@yiiunit/twig/views/simpleFunctions3.twig');
  135. $this->assertEquals($content, 'Gjvt');
  136. $content = $view->renderFile('@yiiunit/twig/views/simpleFunctions4.twig');
  137. $this->assertEquals($content, 'val43');
  138. $content = $view->renderFile('@yiiunit/twig/views/simpleFunctions5.twig');
  139. $this->assertEquals($content, '6');
  140. }
  141. public function testHtmlExtension()
  142. {
  143. $params = [
  144. 'options' => [
  145. 'class' => 'btn btn-default',
  146. 'style' => 'color:red; font-size: 24px'
  147. ]
  148. ];
  149. $view = $this->mockView();
  150. $content = $view->renderFile('@yiiunit/twig/views/html/add_class.twig', $params);
  151. $this->assertEquals($content, "btn btn-default btn-primary");
  152. $content = $view->renderFile('@yiiunit/twig/views/html/remove_class.twig', $params);
  153. $this->assertEquals($content, "btn");
  154. $content = $view->renderFile('@yiiunit/twig/views/html/add_style.twig', $params);
  155. $this->assertEquals($content, "color: red; font-size: 24px; display: none;");
  156. $content = $view->renderFile('@yiiunit/twig/views/html/remove_style.twig', $params);
  157. $this->assertEquals($content, "color: red; font-size: 24px;/color: red; font-size: 24px;");
  158. }
  159. public function testRegisterAssetBundle()
  160. {
  161. $view = $this->mockView();
  162. $content = $view->renderFile('@yiiunit/twig/views/register_asset_bundle.twig');
  163. $this->assertEquals(Yii::getAlias('@bower/jquery/dist'), $content);
  164. }
  165. public function testPath()
  166. {
  167. $this->mockWebApplication([
  168. 'components' => [
  169. 'urlManager' => [
  170. 'enablePrettyUrl' => true,
  171. 'enableStrictParsing' => true,
  172. 'showScriptName' => false,
  173. 'rules' => [
  174. 'GET mypath' => 'mycontroller/myaction',
  175. 'GET mypath2/<myparam>' => 'mycontroller2/myaction2'
  176. ],
  177. ]
  178. ]
  179. ]);
  180. $view = $this->mockView();
  181. $this->assertEquals('/mypath?myparam=123', $view->renderFile('@yiiunit/twig/views/path/pathWithParams.twig'));//bc
  182. $this->assertEquals('/mypath2/123', $view->renderFile('@yiiunit/twig/views/path/path2WithParams.twig'));//bc
  183. $this->assertEquals('/some/custom/path', $view->renderFile('@yiiunit/twig/views/path/pathCustom.twig'));
  184. //to resolve url as a route first arg should be an array
  185. $this->assertEquals('/mycontroller/myaction', $view->renderFile('@yiiunit/twig/views/path/pathWithoutParams.twig'));
  186. $this->assertEquals('/mypath', $view->renderFile('@yiiunit/twig/views/path/pathWithoutParamsAsArray.twig'));
  187. $this->assertEquals('/mypath?myparam=123', $view->renderFile('@yiiunit/twig/views/path/pathWithParamsAsArray.twig'));
  188. $this->assertEquals('/mypath2/123', $view->renderFile('@yiiunit/twig/views/path/path2WithParamsAsArray.twig'));
  189. }
  190. public function testUrl()
  191. {
  192. $this->mockWebApplication([
  193. 'components' => [
  194. 'urlManager' => [
  195. 'enablePrettyUrl' => true,
  196. 'enableStrictParsing' => true,
  197. 'showScriptName' => false,
  198. 'rules' => [
  199. 'GET mypath' => 'mycontroller/myaction',
  200. 'GET mypath2/<myparam>' => 'mycontroller2/myaction2'
  201. ],
  202. ]
  203. ]
  204. ]);
  205. Yii::$app->request->setHostInfo('http://testurl.com');
  206. $view = $this->mockView();
  207. $this->assertEquals('http://testurl.com/mypath?myparam=123', $view->renderFile('@yiiunit/twig/views/url/urlWithParams.twig'));//bc
  208. $this->assertEquals('http://testurl.com/mypath2/123', $view->renderFile('@yiiunit/twig/views/url/url2WithParams.twig'));//bc
  209. $this->assertEquals('http://testurl.com/some/custom/path', $view->renderFile('@yiiunit/twig/views/url/urlCustom.twig'));
  210. //to resolve url as a route first arg should be an array
  211. $this->assertEquals('http://testurl.com/mycontroller/myaction', $view->renderFile('@yiiunit/twig/views/url/urlWithoutParams.twig'));
  212. $this->assertEquals('http://testurl.com/mypath', $view->renderFile('@yiiunit/twig/views/url/urlWithoutParamsAsArray.twig'));
  213. $this->assertEquals('http://testurl.com/mypath?myparam=123', $view->renderFile('@yiiunit/twig/views/url/urlWithParamsAsArray.twig'));
  214. $this->assertEquals('http://testurl.com/mypath2/123', $view->renderFile('@yiiunit/twig/views/url/url2WithParamsAsArray.twig'));
  215. }
  216. public function testStaticAndConsts()
  217. {
  218. $view = $this->mockView();
  219. $view->renderers['twig']['globals']['staticClass'] = ['class' => \yiiunit\twig\data\StaticAndConsts::class];
  220. $content = $view->renderFile('@yiiunit/twig/views/staticAndConsts.twig');
  221. $this->assertContains('I am a const!', $content);
  222. $this->assertContains('I am a static var!', $content);
  223. $this->assertContains('I am a static function with param pam-param!', $content);
  224. }
  225. public function testDate()
  226. {
  227. $view = $this->mockView();
  228. $date = new \DateTime();
  229. $content = $view->renderFile('@yiiunit/twig/views/date.twig', compact('date'));
  230. $this->assertEquals($content, $date->format('Y-m-d'));
  231. }
  232. /**
  233. * Mocks view instance
  234. * @return View
  235. */
  236. protected function mockView()
  237. {
  238. return new View([
  239. 'renderers' => [
  240. 'twig' => [
  241. 'class' => 'yii\twig\ViewRenderer',
  242. 'options' => [
  243. 'cache' => false,
  244. ],
  245. 'globals' => [
  246. 'pos_begin' => View::POS_BEGIN,
  247. ],
  248. 'functions' => [
  249. 't' => '\Yii::t',
  250. 'json_encode' => '\yii\helpers\Json::encode',
  251. new \Twig_SimpleFunction('rot13', 'str_rot13'),
  252. new \Twig_SimpleFunction('add_*', function ($symbols, $val) {
  253. return $val . $symbols;
  254. }, ['is_safe' => ['html']]),
  255. 'callable_rot13' => function($string) {
  256. return str_rot13($string);
  257. },
  258. 'callable_add_*' => function ($symbols, $val) {
  259. return $val . $symbols;
  260. },
  261. 'callable_sum' => function ($a, $b) {
  262. return $a + $b;
  263. }
  264. ],
  265. 'filters' => [
  266. 'string_rot13' => 'str_rot13',
  267. new \Twig_SimpleFilter('rot13', 'str_rot13'),
  268. new \Twig_SimpleFilter('add_*', function ($symbols, $val) {
  269. return $val . $symbols;
  270. }, ['is_safe' => ['html']]),
  271. 'callable_rot13' => function($string) {
  272. return str_rot13($string);
  273. },
  274. 'callable_add_*' => function ($symbols, $val) {
  275. return $val . $symbols;
  276. }
  277. ],
  278. 'lexerOptions' => [
  279. 'tag_comment' => [ '{*', '*}' ],
  280. ],
  281. 'extensions' => [
  282. '\yii\twig\html\HtmlHelperExtension'
  283. ]
  284. ],
  285. ],
  286. 'assetManager' => $this->mockAssetManager(),
  287. ]);
  288. }
  289. /**
  290. * Mocks asset manager
  291. * @return AssetManager
  292. */
  293. protected function mockAssetManager()
  294. {
  295. $assetDir = Yii::getAlias('@runtime/assets');
  296. if (!is_dir($assetDir)) {
  297. mkdir($assetDir, 0777, true);
  298. }
  299. return new AssetManager([
  300. 'basePath' => $assetDir,
  301. 'baseUrl' => '/assets',
  302. ]);
  303. }
  304. }