LayoutTest.php 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Test\Unit;
  7. use Magento\Framework\Serialize\SerializerInterface;
  8. /**
  9. * @SuppressWarnings(PHPMD.TooManyFields)
  10. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  11. */
  12. class LayoutTest extends \PHPUnit\Framework\TestCase
  13. {
  14. /**
  15. * @var \Magento\Framework\View\Layout
  16. */
  17. protected $model;
  18. /**
  19. * @var \PHPUnit_Framework_MockObject_MockObject
  20. */
  21. protected $structureMock;
  22. /**
  23. * @var \Magento\Framework\View\Layout\ProcessorFactory|\PHPUnit_Framework_MockObject_MockObject
  24. */
  25. protected $processorFactoryMock;
  26. /**
  27. * @var \Magento\Framework\View\Design\Theme\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject
  28. */
  29. protected $themeResolverMock;
  30. /**
  31. * @var \Magento\Framework\View\Model\Layout\Merge|\PHPUnit_Framework_MockObject_MockObject
  32. */
  33. protected $processorMock;
  34. /**
  35. * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
  36. */
  37. protected $eventManagerMock;
  38. /**
  39. * @var \Magento\Framework\View\Layout\Generator\Block|\PHPUnit_Framework_MockObject_MockObject
  40. */
  41. protected $generatorBlockMock;
  42. /**
  43. * @var \Magento\Framework\View\Layout\Generator\Container|\PHPUnit_Framework_MockObject_MockObject
  44. */
  45. protected $generatorContainerMock;
  46. /**
  47. * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject
  48. */
  49. protected $cacheMock;
  50. /**
  51. * @var \Magento\Framework\View\Layout\ReaderPool|\PHPUnit_Framework_MockObject_MockObject
  52. */
  53. protected $readerPoolMock;
  54. /**
  55. * @var \Magento\Framework\View\Layout\GeneratorPool|\PHPUnit_Framework_MockObject_MockObject
  56. */
  57. protected $generatorPoolMock;
  58. /**
  59. * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
  60. */
  61. protected $messageManagerMock;
  62. /**
  63. * @var \Magento\Framework\View\Layout\Reader\ContextFactory|\PHPUnit_Framework_MockObject_MockObject
  64. */
  65. protected $readerContextFactoryMock;
  66. /**
  67. * @var \Magento\Framework\View\Layout\Reader\Context|\PHPUnit_Framework_MockObject_MockObject
  68. */
  69. protected $readerContextMock;
  70. /**
  71. * @var \Magento\Framework\View\Page\Config\Structure|\PHPUnit_Framework_MockObject_MockObject
  72. */
  73. private $pageConfigStructure;
  74. /**
  75. * @var \Magento\Framework\View\Layout\ScheduledStructure|\PHPUnit_Framework_MockObject_MockObject
  76. */
  77. private $layoutScheduledSructure;
  78. /**
  79. * @var \Magento\Framework\View\Layout\Generator\ContextFactory|\PHPUnit_Framework_MockObject_MockObject
  80. */
  81. protected $generatorContextFactoryMock;
  82. /**
  83. * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject
  84. */
  85. protected $appStateMock;
  86. /**
  87. * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
  88. */
  89. protected $loggerMock;
  90. /**
  91. * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject
  92. */
  93. private $serializer;
  94. protected function setUp()
  95. {
  96. $this->structureMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Data\Structure::class)
  97. ->disableOriginalConstructor()
  98. ->getMock();
  99. $this->processorFactoryMock = $this->createPartialMock(
  100. \Magento\Framework\View\Layout\ProcessorFactory::class,
  101. ['create']
  102. );
  103. $this->themeResolverMock = $this->getMockForAbstractClass(
  104. \Magento\Framework\View\Design\Theme\ResolverInterface::class
  105. );
  106. $this->processorMock = $this->createMock(\Magento\Framework\View\Model\Layout\Merge::class);
  107. $this->eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class);
  108. $this->generatorBlockMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Generator\Block::class)
  109. ->disableOriginalConstructor()->getMock();
  110. $this->generatorContainerMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Generator\Container::class)
  111. ->disableOriginalConstructor()->getMock();
  112. $this->cacheMock = $this->getMockBuilder(\Magento\Framework\Cache\FrontendInterface::class)
  113. ->disableOriginalConstructor()
  114. ->getMock();
  115. $this->readerPoolMock = $this->getMockBuilder(\Magento\Framework\View\Layout\ReaderPool::class)
  116. ->disableOriginalConstructor()
  117. ->getMock();
  118. $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
  119. ->disableOriginalConstructor()
  120. ->getMock();
  121. $this->generatorPoolMock = $this->getMockBuilder(\Magento\Framework\View\Layout\GeneratorPool::class)
  122. ->disableOriginalConstructor()->getMock();
  123. $this->generatorPoolMock->expects($this->any())
  124. ->method('getGenerator')
  125. ->will(
  126. $this->returnValueMap([
  127. [\Magento\Framework\View\Layout\Generator\Block::TYPE, $this->generatorBlockMock],
  128. [\Magento\Framework\View\Layout\Generator\Container::TYPE, $this->generatorContainerMock],
  129. ])
  130. );
  131. $this->readerContextFactoryMock = $this->getMockBuilder(
  132. \Magento\Framework\View\Layout\Reader\ContextFactory::class
  133. )->disableOriginalConstructor()->getMock();
  134. $this->pageConfigStructure = $this->getMockBuilder(\Magento\Framework\View\Page\Config\Structure::class)
  135. ->setMethods(['__toArray', 'populateWithArray'])
  136. ->getMock();
  137. $this->layoutScheduledSructure = $this->getMockBuilder(\Magento\Framework\View\Layout\ScheduledStructure::class)
  138. ->setMethods(['__toArray', 'populateWithArray'])
  139. ->getMock();
  140. $this->readerContextMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Reader\Context::class)
  141. ->setMethods(['getPageConfigStructure', 'getScheduledStructure'])
  142. ->disableOriginalConstructor()
  143. ->getMock();
  144. $this->readerContextMock->expects($this->any())->method('getPageConfigStructure')
  145. ->willReturn($this->pageConfigStructure);
  146. $this->readerContextMock->expects($this->any())->method('getScheduledStructure')
  147. ->willReturn($this->layoutScheduledSructure);
  148. $this->generatorContextFactoryMock = $this->getMockBuilder(
  149. \Magento\Framework\View\Layout\Generator\ContextFactory::class
  150. )
  151. ->disableOriginalConstructor()
  152. ->getMock();
  153. $this->appStateMock = $this->getMockBuilder(\Magento\Framework\App\State::class)
  154. ->disableOriginalConstructor()
  155. ->getMock();
  156. $this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class)
  157. ->getMock();
  158. $this->serializer = $this->createMock(\Magento\Framework\Serialize\SerializerInterface::class);
  159. $this->serializer->expects($this->any())->method('serialize')
  160. ->willReturnCallback(function ($value) {
  161. return json_encode($value);
  162. });
  163. $this->serializer->expects($this->any())->method('unserialize')
  164. ->willReturnCallback(function ($value) {
  165. return json_decode($value, true);
  166. });
  167. $this->model = new \Magento\Framework\View\Layout(
  168. $this->processorFactoryMock,
  169. $this->eventManagerMock,
  170. $this->structureMock,
  171. $this->messageManagerMock,
  172. $this->themeResolverMock,
  173. $this->readerPoolMock,
  174. $this->generatorPoolMock,
  175. $this->cacheMock,
  176. $this->readerContextFactoryMock,
  177. $this->generatorContextFactoryMock,
  178. $this->appStateMock,
  179. $this->loggerMock,
  180. true,
  181. $this->serializer
  182. );
  183. }
  184. public function testCreateBlockSuccess()
  185. {
  186. $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class)
  187. ->disableOriginalConstructor()
  188. ->getMockForAbstractClass();
  189. $this->structureMock->expects($this->once())
  190. ->method('createStructuralElement')
  191. ->with(
  192. 'blockname',
  193. \Magento\Framework\View\Layout\Element::TYPE_BLOCK,
  194. \Magento\Framework\View\Element\AbstractBlock::class
  195. )->willReturn('blockname');
  196. $this->generatorBlockMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
  197. $this->model->createBlock(\Magento\Framework\View\Element\AbstractBlock::class, 'blockname', []);
  198. $this->assertInstanceOf(
  199. \Magento\Framework\View\Element\AbstractBlock::class,
  200. $this->model->getBlock('blockname')
  201. );
  202. $this->assertFalse($this->model->getBlock('not_exist'));
  203. }
  204. public function testGetUpdate()
  205. {
  206. $themeMock = $this->getMockForAbstractClass(\Magento\Framework\View\Design\ThemeInterface::class);
  207. $this->themeResolverMock->expects($this->once())
  208. ->method('get')
  209. ->will($this->returnValue($themeMock));
  210. $this->processorFactoryMock->expects($this->once())
  211. ->method('create')
  212. ->with(['theme' => $themeMock])
  213. ->will($this->returnValue($this->processorMock));
  214. $this->assertEquals($this->processorMock, $this->model->getUpdate());
  215. $this->assertEquals($this->processorMock, $this->model->getUpdate());
  216. }
  217. public function testGenerateXml()
  218. {
  219. $themeMock = $this->getMockForAbstractClass(\Magento\Framework\View\Design\ThemeInterface::class);
  220. $this->themeResolverMock->expects($this->once())
  221. ->method('get')
  222. ->will($this->returnValue($themeMock));
  223. $this->processorFactoryMock->expects($this->once())
  224. ->method('create')
  225. ->with(['theme' => $themeMock])
  226. ->will($this->returnValue($this->processorMock));
  227. $xmlString = '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
  228. . '<some_update>123</some_update></layout>';
  229. $xml = simplexml_load_string($xmlString, \Magento\Framework\View\Layout\Element::class);
  230. $this->processorMock->expects($this->once())
  231. ->method('asSimplexml')
  232. ->will($this->returnValue($xml));
  233. $this->structureMock->expects($this->once())
  234. ->method('importElements')
  235. ->with($this->equalTo([]))
  236. ->will($this->returnSelf());
  237. $this->assertSame($this->model, $this->model->generateXml());
  238. $this->assertSame('<some_update>123</some_update>', $this->model->getNode('some_update')->asXML());
  239. }
  240. public function testGetChildBlock()
  241. {
  242. $customBlockName = 'custom_block';
  243. $customBlockParentName = 'custom_block_parent';
  244. $customBlockAlias = 'custom_block_alias';
  245. $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\Template::class)
  246. ->disableOriginalConstructor()
  247. ->getMock();
  248. $this->structureMock->expects($this->once())
  249. ->method('getChildId')
  250. ->with($customBlockParentName, $customBlockAlias)
  251. ->willReturn($customBlockName);
  252. $this->structureMock->expects($this->once())
  253. ->method('hasElement')
  254. ->with($customBlockName)
  255. ->willReturn(true);
  256. $this->structureMock->expects($this->once())
  257. ->method('getAttribute')
  258. ->with($customBlockName, 'type')
  259. ->willReturn(\Magento\Framework\View\Layout\Element::TYPE_BLOCK);
  260. $this->model->setBlock($customBlockName, $blockMock);
  261. $this->assertInstanceOf(
  262. \Magento\Framework\View\Element\AbstractBlock::class,
  263. $this->model->getChildBlock($customBlockParentName, $customBlockAlias)
  264. );
  265. }
  266. public function testGetChildNonExistBlock()
  267. {
  268. $this->structureMock->expects($this->once())
  269. ->method('getChildId')
  270. ->with('non_exist_parent', 'non_exist_alias')
  271. ->willReturn(false);
  272. $this->assertFalse($this->model->getChildBlock('non_exist_parent', 'non_exist_alias'));
  273. }
  274. public function testSetChild()
  275. {
  276. $elementName = 'child';
  277. $parentName = 'parent';
  278. $alias = 'some_alias';
  279. $this->structureMock->expects($this->once())
  280. ->method('setAsChild')
  281. ->with($this->equalTo($elementName), $this->equalTo($parentName), $this->equalTo($alias))
  282. ->will($this->returnSelf());
  283. $this->assertSame($this->model, $this->model->setChild($parentName, $elementName, $alias));
  284. }
  285. public function testUnsetChild()
  286. {
  287. $parentName = 'parent';
  288. $alias = 'some_alias';
  289. $this->structureMock->expects($this->once())
  290. ->method('unsetChild')
  291. ->with($this->equalTo($parentName), $this->equalTo($alias))
  292. ->will($this->returnSelf());
  293. $this->assertSame($this->model, $this->model->unsetChild($parentName, $alias));
  294. }
  295. public function testGetChildNames()
  296. {
  297. $parentName = 'parent';
  298. $childrenArray = ['key1' => 'value1', 'key2' => 'value2'];
  299. $this->structureMock->expects($this->once())
  300. ->method('getChildren')
  301. ->with($this->equalTo($parentName))
  302. ->will($this->returnValue($childrenArray));
  303. $this->assertSame(['key1', 'key2'], $this->model->getChildNames($parentName));
  304. }
  305. public function testGetChildBlocks()
  306. {
  307. $parentName = 'parent';
  308. $childrenArray = ['block_name' => 'value1'];
  309. $this->structureMock->expects($this->once())
  310. ->method('getChildren')
  311. ->with($this->equalTo($parentName))
  312. ->will($this->returnValue($childrenArray));
  313. $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class)
  314. ->disableOriginalConstructor()
  315. ->getMockForAbstractClass();
  316. $this->structureMock->expects($this->once())
  317. ->method('createStructuralElement')
  318. ->with(
  319. 'block_name',
  320. \Magento\Framework\View\Layout\Element::TYPE_BLOCK,
  321. \Magento\Framework\View\Element\AbstractBlock::class
  322. )->willReturn('block_name');
  323. $this->generatorBlockMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
  324. $this->assertSame(
  325. $blockMock,
  326. $this->model->createBlock(\Magento\Framework\View\Element\AbstractBlock::class, 'block_name', [])
  327. );
  328. $this->assertSame(['value1' => $blockMock], $this->model->getChildBlocks($parentName));
  329. }
  330. public function testGetChildName()
  331. {
  332. $parentName = 'parent';
  333. $alias = 'some_alias';
  334. $this->structureMock->expects($this->once())
  335. ->method('getChildId')
  336. ->with($this->equalTo($parentName), $this->equalTo($alias))
  337. ->will($this->returnValue('1'));
  338. $this->assertSame('1', $this->model->getChildName($parentName, $alias));
  339. }
  340. public function testAddToParentGroup()
  341. {
  342. $blockName = 'block_name';
  343. $parentGroup = 'parent_group';
  344. $this->structureMock->expects($this->once())
  345. ->method('addToParentGroup')
  346. ->with($this->equalTo($blockName), $this->equalTo($parentGroup))
  347. ->will($this->returnSelf());
  348. $this->assertSame($this->structureMock, $this->model->addToParentGroup($blockName, $parentGroup));
  349. }
  350. public function testGetGroupChildNames()
  351. {
  352. $blockName = 'block_name';
  353. $groupName = 'group_name';
  354. $this->structureMock->expects($this->once())
  355. ->method('getGroupChildNames')
  356. ->with($this->equalTo($blockName), $this->equalTo($groupName))
  357. ->will($this->returnSelf());
  358. $this->assertSame($this->structureMock, $this->model->getGroupChildNames($blockName, $groupName));
  359. }
  360. public function testHasElement()
  361. {
  362. $elementName = 'name';
  363. $this->structureMock->expects($this->once())
  364. ->method('hasElement')
  365. ->with($this->equalTo($elementName))
  366. ->will($this->returnValue(true));
  367. $this->assertTrue($this->model->hasElement($elementName));
  368. }
  369. public function testGetElementProperty()
  370. {
  371. $elementName = 'name';
  372. $elementAttr = 'attribute';
  373. $result = 'result';
  374. $this->structureMock->expects($this->once())
  375. ->method('getAttribute')
  376. ->with($this->equalTo($elementName), $this->equalTo($elementAttr))
  377. ->will($this->returnValue($result));
  378. $this->assertSame($result, $this->model->getElementProperty($elementName, $elementAttr));
  379. }
  380. /**
  381. * @param bool $hasElement
  382. * @param string $attribute
  383. * @param bool $result
  384. * @dataProvider isContainerDataProvider
  385. */
  386. public function testIsContainer($hasElement, $attribute, $result)
  387. {
  388. $elementName = 'element_name';
  389. $this->structureMock->expects($this->once())
  390. ->method('hasElement')
  391. ->with($this->equalTo($elementName))
  392. ->will($this->returnValue($hasElement));
  393. if ($hasElement) {
  394. $this->structureMock->expects($this->once())
  395. ->method('getAttribute')
  396. ->with($this->equalTo($elementName), $this->equalTo('type'))
  397. ->will($this->returnValue($attribute));
  398. }
  399. $this->assertSame($result, $this->model->isContainer($elementName));
  400. }
  401. /**
  402. * @return array
  403. */
  404. public function isContainerDataProvider()
  405. {
  406. return [
  407. [false, '', false],
  408. [true, 'container', true],
  409. [true, 'block', false],
  410. [true, 'something', false],
  411. ];
  412. }
  413. /**
  414. * @param bool $parentName
  415. * @param array $containerConfig
  416. * @param bool $result
  417. * @dataProvider isManipulationAllowedDataProvider
  418. */
  419. public function testIsManipulationAllowed($parentName, $containerConfig, $result)
  420. {
  421. $elementName = 'element_name';
  422. $this->structureMock->expects($this->once())
  423. ->method('getParentId')
  424. ->with($this->equalTo($elementName))
  425. ->will($this->returnValue($parentName));
  426. if ($parentName) {
  427. $this->structureMock->expects($this->once())
  428. ->method('hasElement')
  429. ->with($this->equalTo($parentName))
  430. ->will($this->returnValue($containerConfig['has_element']));
  431. if ($containerConfig['has_element']) {
  432. $this->structureMock->expects($this->once())
  433. ->method('getAttribute')
  434. ->with($this->equalTo($parentName), $this->equalTo('type'))
  435. ->will($this->returnValue($containerConfig['attribute']));
  436. }
  437. }
  438. $this->assertSame($result, $this->model->isManipulationAllowed($elementName));
  439. }
  440. /**
  441. * @return array
  442. */
  443. public function isManipulationAllowedDataProvider()
  444. {
  445. return [
  446. ['parent', ['has_element' => true, 'attribute' => 'container'], true],
  447. ['parent', ['has_element' => true, 'attribute' => 'block'], false],
  448. [false, [], false],
  449. ];
  450. }
  451. /**
  452. * @covers \Magento\Framework\View\Layout::setBlock
  453. * @covers \Magento\Framework\View\Layout::getAllBlocks
  454. * @covers \Magento\Framework\View\Layout::unsetElement
  455. */
  456. public function testSetGetBlock()
  457. {
  458. $blockName = 'some_name';
  459. $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class)
  460. ->disableOriginalConstructor()
  461. ->getMockForAbstractClass();
  462. $this->assertSame($this->model, $this->model->setBlock($blockName, $blockMock));
  463. $this->assertSame([$blockName => $blockMock], $this->model->getAllBlocks());
  464. $this->structureMock->expects($this->once())
  465. ->method('unsetElement')
  466. ->with($this->equalTo($blockName))
  467. ->will($this->returnSelf());
  468. $this->assertSame($this->model, $this->model->unsetElement($blockName));
  469. $this->assertSame([], $this->model->getAllBlocks());
  470. }
  471. public function testRenameElement()
  472. {
  473. $oldName = 'old_name';
  474. $newName = 'new_name';
  475. $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\AbstractBlock::class)
  476. ->disableOriginalConstructor()
  477. ->getMockForAbstractClass();
  478. $this->structureMock->expects($this->once())
  479. ->method('renameElement')
  480. ->with($this->equalTo($oldName), $this->equalTo($newName))
  481. ->will($this->returnSelf());
  482. $this->assertSame($this->model, $this->model->setBlock($oldName, $blockMock));
  483. $this->assertSame($this->model, $this->model->renameElement($oldName, $newName));
  484. $this->assertSame([$newName => $blockMock], $this->model->getAllBlocks());
  485. }
  486. public function testGetParentName()
  487. {
  488. $childName = 'child_name';
  489. $parentId = 'parent_id';
  490. $this->structureMock->expects($this->once())
  491. ->method('getParentId')
  492. ->with($this->equalTo($childName))
  493. ->will($this->returnValue($parentId));
  494. $this->assertSame($parentId, $this->model->getParentName($childName));
  495. }
  496. public function testGetElementAlias()
  497. {
  498. $name = 'child_name';
  499. $parentId = 'parent_id';
  500. $alias = 'alias';
  501. $this->structureMock->expects($this->once())
  502. ->method('getParentId')
  503. ->with($this->equalTo($name))
  504. ->will($this->returnValue($parentId));
  505. $this->structureMock->expects($this->once())
  506. ->method('getChildAlias')
  507. ->with($this->equalTo($parentId), $this->equalTo($name))
  508. ->will($this->returnValue($alias));
  509. $this->assertSame($alias, $this->model->getElementAlias($name));
  510. }
  511. public function testAddRemoveOutputElement()
  512. {
  513. $this->assertSame($this->model, $this->model->addOutputElement('name'));
  514. $this->assertSame($this->model, $this->model->removeOutputElement('name'));
  515. }
  516. public function testIsPrivate()
  517. {
  518. $this->assertFalse($this->model->isPrivate());
  519. $this->assertSame($this->model, $this->model->setIsPrivate(true));
  520. $this->assertTrue($this->model->isPrivate());
  521. }
  522. /**
  523. * @param array $type
  524. * @param array $blockInstance
  525. * @dataProvider getBlockSingletonDataProvider
  526. */
  527. public function testGetBlockSingleton($type, $blockInstance, $isAbstract)
  528. {
  529. $blockMock = $this->createMock($blockInstance);
  530. $this->generatorBlockMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
  531. if ($isAbstract) {
  532. $blockMock->expects($this->any())
  533. ->method('setLayout')
  534. ->with($this->equalTo($this->model))
  535. ->will($this->returnSelf());
  536. }
  537. $this->assertInstanceOf($blockInstance, $this->model->getBlockSingleton($type));
  538. // singleton test
  539. $this->assertInstanceOf($blockInstance, $this->model->getBlockSingleton($type));
  540. }
  541. /**
  542. * @return array
  543. */
  544. public function getBlockSingletonDataProvider()
  545. {
  546. return [
  547. [
  548. 'some_type', \Magento\Framework\View\Element\Template::class,
  549. true,
  550. ],
  551. ];
  552. }
  553. /**
  554. * @param array $rendererData
  555. * @param array $getData
  556. * @param bool $result
  557. * @dataProvider getRendererOptionsDataProvider
  558. */
  559. public function testAddGetRendererOptions($rendererData, $getData, $result)
  560. {
  561. $this->assertSame(
  562. $this->model,
  563. $this->model->addAdjustableRenderer(
  564. $rendererData['namespace'],
  565. $rendererData['static_type'],
  566. $rendererData['dynamic_type'],
  567. $rendererData['type'],
  568. $rendererData['template'],
  569. $rendererData['data']
  570. )
  571. );
  572. $this->assertSame(
  573. $result,
  574. $this->model->getRendererOptions($getData['namespace'], $getData['static_type'], $getData['dynamic_type'])
  575. );
  576. }
  577. /**
  578. * @return array
  579. */
  580. public function getRendererOptionsDataProvider()
  581. {
  582. $rendererData = [
  583. 'namespace' => 'namespace_value',
  584. 'static_type' => 'static_type_value',
  585. 'dynamic_type' => 'dynamic_type_value',
  586. 'type' => 'type_value',
  587. 'template' => 'template.phtml',
  588. 'data' => ['some' => 'data'],
  589. ];
  590. return [
  591. 'wrong namespace' => [
  592. $rendererData,
  593. [
  594. 'namespace' => 'wrong namespace',
  595. 'static_type' => 'static_type_value',
  596. 'dynamic_type' => 'dynamic_type_value',
  597. ],
  598. null,
  599. ],
  600. 'wrong static type' => [
  601. $rendererData,
  602. [
  603. 'namespace' => 'namespace_value',
  604. 'static_type' => 'wrong static type',
  605. 'dynamic_type' => 'dynamic_type_value',
  606. ],
  607. null,
  608. ],
  609. 'wrong dynamic type' => [
  610. $rendererData,
  611. [
  612. 'namespace' => 'namespace_value',
  613. 'static_type' => 'static_type_value',
  614. 'dynamic_type' => 'wrong dynamic type',
  615. ],
  616. null,
  617. ],
  618. 'set and get test' => [
  619. $rendererData,
  620. [
  621. 'namespace' => 'namespace_value',
  622. 'static_type' => 'static_type_value',
  623. 'dynamic_type' => 'dynamic_type_value',
  624. ],
  625. [
  626. 'type' => 'type_value',
  627. 'template' => 'template.phtml',
  628. 'data' => ['some' => 'data'],
  629. ],
  630. ],
  631. ];
  632. }
  633. /**
  634. * @param string $xmlString
  635. * @param bool $result
  636. * @dataProvider isCacheableDataProvider
  637. */
  638. public function testIsCacheable($xmlString, $result)
  639. {
  640. $xml = simplexml_load_string($xmlString, \Magento\Framework\View\Layout\Element::class);
  641. $this->assertSame($this->model, $this->model->setXml($xml));
  642. $this->assertSame($result, $this->model->isCacheable());
  643. }
  644. /**
  645. * @return array
  646. */
  647. public function isCacheableDataProvider()
  648. {
  649. return [
  650. [
  651. '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
  652. . '<block></block></layout>',
  653. true,
  654. ],
  655. [
  656. '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
  657. . '<block cacheable="false"></block></layout>',
  658. false
  659. ],
  660. ];
  661. }
  662. public function testGenerateElementsWithoutCache()
  663. {
  664. $this->readerContextFactoryMock->expects($this->once())
  665. ->method('create')
  666. ->willReturn($this->readerContextMock);
  667. $layoutCacheId = 'layout_cache_id';
  668. $handles = ['default', 'another'];
  669. /** @var \Magento\Framework\View\Layout\Element $xml */
  670. $xml = simplexml_load_string('<layout/>', \Magento\Framework\View\Layout\Element::class);
  671. $this->model->setXml($xml);
  672. $themeMock = $this->getMockForAbstractClass(\Magento\Framework\View\Design\ThemeInterface::class);
  673. $this->themeResolverMock->expects($this->once())
  674. ->method('get')
  675. ->willReturn($themeMock);
  676. $this->processorFactoryMock->expects($this->once())
  677. ->method('create')
  678. ->with(['theme' => $themeMock])
  679. ->willReturn($this->processorMock);
  680. $this->processorMock->expects($this->once())
  681. ->method('getCacheId')
  682. ->willReturn($layoutCacheId);
  683. $this->processorMock->expects($this->once())
  684. ->method('getHandles')
  685. ->willReturn($handles);
  686. $this->cacheMock->expects($this->once())
  687. ->method('load')
  688. ->with('structure_' . $layoutCacheId)
  689. ->willReturn(false);
  690. $this->readerPoolMock->expects($this->once())
  691. ->method('interpret')
  692. ->with($this->readerContextMock, $xml)
  693. ->willReturnSelf();
  694. $pageConfigStructureData = [
  695. 'field_1' => 123,
  696. 'field_2' => 'text',
  697. 'field_3' => [
  698. 'field_3_1' => '1244',
  699. 'field_3_2' => null,
  700. 'field_3_3' => false,
  701. ]
  702. ];
  703. $this->pageConfigStructure->expects($this->any())->method('__toArray')
  704. ->willReturn($pageConfigStructureData);
  705. $layoutScheduledStructureData = [
  706. 'field_1' => 1283,
  707. 'field_2' => 'text_qwertyuiop[]asdfghjkl;'
  708. ];
  709. $this->layoutScheduledSructure->expects($this->any())->method('__toArray')
  710. ->willReturn($layoutScheduledStructureData);
  711. $data = [
  712. 'pageConfigStructure' => $pageConfigStructureData,
  713. 'scheduledStructure' => $layoutScheduledStructureData
  714. ];
  715. $this->cacheMock->expects($this->once())
  716. ->method('save')
  717. ->with(json_encode($data), 'structure_' . $layoutCacheId, $handles)
  718. ->willReturn(true);
  719. $generatorContextMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Generator\Context::class)
  720. ->disableOriginalConstructor()
  721. ->getMock();
  722. $this->generatorContextFactoryMock->expects($this->once())
  723. ->method('create')
  724. ->with(['structure' => $this->structureMock, 'layout' => $this->model])
  725. ->willReturn($generatorContextMock);
  726. $this->generatorPoolMock->expects($this->once())
  727. ->method('process')
  728. ->with($this->readerContextMock, $generatorContextMock)
  729. ->willReturn(true);
  730. $elements = [
  731. 'name_1' => ['type' => '', 'parent' => null],
  732. 'name_2' => ['type' => \Magento\Framework\View\Layout\Element::TYPE_CONTAINER, 'parent' => null],
  733. 'name_3' => ['type' => '', 'parent' => 'parent'],
  734. 'name_4' => ['type' => \Magento\Framework\View\Layout\Element::TYPE_CONTAINER, 'parent' => 'parent'],
  735. ];
  736. $this->structureMock->expects($this->once())
  737. ->method('exportElements')
  738. ->willReturn($elements);
  739. $this->model->generateElements();
  740. }
  741. public function testGenerateElementsWithCache()
  742. {
  743. $layoutCacheId = 'layout_cache_id';
  744. /** @var \Magento\Framework\View\Layout\Element $xml */
  745. $xml = simplexml_load_string('<layout/>', \Magento\Framework\View\Layout\Element::class);
  746. $this->model->setXml($xml);
  747. $this->readerContextFactoryMock->expects($this->once())
  748. ->method('create')
  749. ->willReturn($this->readerContextMock);
  750. $themeMock = $this->getMockForAbstractClass(\Magento\Framework\View\Design\ThemeInterface::class);
  751. $this->themeResolverMock->expects($this->once())
  752. ->method('get')
  753. ->willReturn($themeMock);
  754. $this->processorFactoryMock->expects($this->once())
  755. ->method('create')
  756. ->with(['theme' => $themeMock])
  757. ->willReturn($this->processorMock);
  758. $this->processorMock->expects($this->once())
  759. ->method('getCacheId')
  760. ->willReturn($layoutCacheId);
  761. $pageConfigStructureData = [
  762. 'field_1' => 123,
  763. 'field_2' => 'text',
  764. 'field_3' => [
  765. 'field_3_1' => '1244',
  766. 'field_3_2' => null,
  767. 'field_3_3' => false,
  768. ]
  769. ];
  770. $this->pageConfigStructure->expects($this->once())->method('populateWithArray')
  771. ->with($pageConfigStructureData);
  772. $layoutScheduledStructureData = [
  773. 'field_1' => 1283,
  774. 'field_2' => 'text_qwertyuiop[]asdfghjkl;'
  775. ];
  776. $this->layoutScheduledSructure->expects($this->once())->method('populateWithArray')
  777. ->with($layoutScheduledStructureData);
  778. $data = [
  779. 'pageConfigStructure' => $pageConfigStructureData,
  780. 'scheduledStructure' => $layoutScheduledStructureData
  781. ];
  782. $this->cacheMock->expects($this->once())
  783. ->method('load')
  784. ->with('structure_' . $layoutCacheId)
  785. ->willReturn(json_encode($data));
  786. $this->readerPoolMock->expects($this->never())
  787. ->method('interpret');
  788. $this->cacheMock->expects($this->never())
  789. ->method('save');
  790. $generatorContextMock = $this->getMockBuilder(\Magento\Framework\View\Layout\Generator\Context::class)
  791. ->disableOriginalConstructor()
  792. ->getMock();
  793. $this->generatorContextFactoryMock->expects($this->once())
  794. ->method('create')
  795. ->with(['structure' => $this->structureMock, 'layout' => $this->model])
  796. ->willReturn($generatorContextMock);
  797. $this->generatorPoolMock->expects($this->once())
  798. ->method('process')
  799. ->with($this->readerContextMock, $generatorContextMock)
  800. ->willReturn(true);
  801. $elements = [
  802. 'name_1' => ['type' => '', 'parent' => null],
  803. 'name_2' => ['type' => \Magento\Framework\View\Layout\Element::TYPE_CONTAINER, 'parent' => null],
  804. 'name_3' => ['type' => '', 'parent' => 'parent'],
  805. 'name_4' => ['type' => \Magento\Framework\View\Layout\Element::TYPE_CONTAINER, 'parent' => 'parent'],
  806. ];
  807. $this->structureMock->expects($this->once())
  808. ->method('exportElements')
  809. ->willReturn($elements);
  810. $this->model->generateElements();
  811. }
  812. public function testGetXml()
  813. {
  814. $xml = '<layout/>';
  815. $this->assertSame($xml, \Magento\Framework\View\Layout::LAYOUT_NODE);
  816. }
  817. /**
  818. * @param mixed $displayValue
  819. * @dataProvider renderElementDisplayDataProvider
  820. */
  821. public function testRenderElementDisplay($displayValue)
  822. {
  823. $name = 'test_container';
  824. $child = 'child_block';
  825. $children = [$child => true];
  826. $blockHtml = '<html/>';
  827. $this->structureMock->expects($this->atLeastOnce())
  828. ->method('getAttribute')
  829. ->willReturnMap(
  830. [
  831. [$name, 'display', $displayValue],
  832. [$child, 'display', $displayValue],
  833. [$child, 'type', \Magento\Framework\View\Layout\Element::TYPE_BLOCK]
  834. ]
  835. );
  836. $this->structureMock->expects($this->atLeastOnce())->method('hasElement')
  837. ->willReturnMap(
  838. [
  839. [$child, true]
  840. ]
  841. );
  842. $this->structureMock->expects($this->once())
  843. ->method('getChildren')
  844. ->with($name)
  845. ->willReturn($children);
  846. $block = $this->createMock(\Magento\Framework\View\Element\AbstractBlock::class);
  847. $block->expects($this->once())->method('toHtml')->willReturn($blockHtml);
  848. $renderingOutput = new \Magento\Framework\DataObject();
  849. $renderingOutput->setData('output', $blockHtml);
  850. $this->eventManagerMock->expects($this->at(0))
  851. ->method('dispatch')
  852. ->with(
  853. 'core_layout_render_element',
  854. ['element_name' => $child, 'layout' => $this->model, 'transport' => $renderingOutput]
  855. );
  856. $this->eventManagerMock->expects($this->at(1))
  857. ->method('dispatch')
  858. ->with(
  859. 'core_layout_render_element',
  860. ['element_name' => $name, 'layout' => $this->model, 'transport' => $renderingOutput]
  861. );
  862. $this->model->setBlock($child, $block);
  863. $this->assertEquals($blockHtml, $this->model->renderElement($name, false));
  864. }
  865. /**
  866. * @param mixed $displayValue
  867. * @dataProvider renderElementDoNotDisplayDataProvider
  868. */
  869. public function testRenderElementDoNotDisplay($displayValue)
  870. {
  871. $displayValue = 'false';
  872. $name = 'test_container';
  873. $blockHtml = '';
  874. $this->structureMock->expects($this->atLeastOnce())
  875. ->method('getAttribute')
  876. ->willReturnMap([[$name, 'display', $displayValue]]);
  877. $this->assertEquals($blockHtml, $this->model->renderElement($name, false));
  878. }
  879. /**
  880. * @return array
  881. */
  882. public function renderElementDoNotDisplayDataProvider()
  883. {
  884. return [
  885. ['false'],
  886. ['0'],
  887. [0]
  888. ];
  889. }
  890. /**
  891. * @return array
  892. */
  893. public function renderElementDisplayDataProvider()
  894. {
  895. return [
  896. [true],
  897. ['1'],
  898. [1],
  899. ['true'],
  900. [false],
  901. [null]
  902. ];
  903. }
  904. }