123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\View\Layout;
- use Magento\Framework\App\State;
- use Magento\Framework\Phrase;
- use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
- /**
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class MergeTest extends \PHPUnit\Framework\TestCase
- {
- /**
- * Fixture XML instruction(s) to be used in tests
- */
- // @codingStandardsIgnoreStart
- const FIXTURE_LAYOUT_XML = '<block class="Magento\Framework\View\Element\Template" template="Magento_Framework::fixture_template_one.phtml"/>';
- // @codingStandardsIgnoreEnd
- /**
- * @var \Magento\Framework\View\Model\Layout\Merge
- */
- protected $_model;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_resource;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_appState;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_cache;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_theme;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $scope;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_logger;
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $_layoutValidator;
- /**
- * @var \Magento\Framework\View\Page\Config|\PHPUnit_Framework_MockObject_MockObject
- */
- protected $pageConfig;
- /**
- * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
- */
- protected $layoutCacheKeyMock;
- protected function setUp()
- {
- $files = [];
- foreach (glob(__DIR__ . '/_mergeFiles/layout/*.xml') as $filename) {
- $files[] = new \Magento\Framework\View\File($filename, 'Magento_Widget');
- }
- $fileSource = $this->getMockForAbstractClass(\Magento\Framework\View\File\CollectorInterface::class);
- $fileSource->expects($this->any())->method('getFiles')->will($this->returnValue($files));
- $pageLayoutFileSource = $this->getMockForAbstractClass(\Magento\Framework\View\File\CollectorInterface::class);
- $pageLayoutFileSource->expects($this->any())->method('getFiles')->willReturn([]);
- $design = $this->getMockForAbstractClass(\Magento\Framework\View\DesignInterface::class);
- $this->scope = $this->createMock(\Magento\Framework\Url\ScopeInterface::class);
- $this->scope->expects($this->any())->method('getId')->will($this->returnValue(20));
- $scopeResolver = $this->getMockForAbstractClass(\Magento\Framework\Url\ScopeResolverInterface::class);
- $scopeResolver->expects($this->once())->method('getScope')->with(null)->will($this->returnValue($this->scope));
- $this->_resource = $this->createMock(\Magento\Widget\Model\ResourceModel\Layout\Update::class);
- $this->_appState = $this->createMock(\Magento\Framework\App\State::class);
- $this->_logger = $this->createMock(\Psr\Log\LoggerInterface::class);
- $this->_layoutValidator = $this->createMock(\Magento\Framework\View\Model\Layout\Update\Validator::class);
- $this->_cache = $this->getMockForAbstractClass(\Magento\Framework\Cache\FrontendInterface::class);
- $this->_theme = $this->createMock(\Magento\Theme\Model\Theme::class);
- $this->_theme->expects($this->any())->method('isPhysical')->will($this->returnValue(true));
- $this->_theme->expects($this->any())->method('getArea')->will($this->returnValue('area'));
- $this->_theme->expects($this->any())->method('getId')->will($this->returnValue(100));
- $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
- $this->pageConfig = $this->getMockBuilder(\Magento\Framework\View\Page\Config::class)
- ->disableOriginalConstructor()
- ->getMock();
- $readFactory = $this->createMock(\Magento\Framework\Filesystem\File\ReadFactory::class);
- $fileReader = $this->createMock(\Magento\Framework\Filesystem\File\Read::class);
- $readFactory->expects($this->any())->method('create')->willReturn($fileReader);
- $fileDriver = $objectHelper->getObject(\Magento\Framework\Filesystem\Driver\File::class);
- $fileReader->expects($this->any())->method('readAll')->will(
- $this->returnCallback(
- function ($filename) use ($fileDriver) {
- return $fileDriver->fileGetContents(__DIR__ . '/_mergeFiles/layout/' . $filename);
- }
- )
- );
- $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class);
- $this->layoutCacheKeyMock->expects($this->any())
- ->method('getCacheKeys')
- ->willReturn([]);
- $this->_model = $objectHelper->getObject(
- \Magento\Framework\View\Model\Layout\Merge::class,
- [
- 'design' => $design,
- 'scopeResolver' => $scopeResolver,
- 'fileSource' => $fileSource,
- 'pageLayoutFileSource' => $pageLayoutFileSource,
- 'resource' => $this->_resource,
- 'appState' => $this->_appState,
- 'cache' => $this->_cache,
- 'theme' => $this->_theme,
- 'validator' => $this->_layoutValidator,
- 'logger' => $this->_logger,
- 'readFactory' => $readFactory,
- 'pageConfig' => $this->pageConfig,
- 'layoutCacheKey' => $this->layoutCacheKeyMock,
- ]
- );
- }
- public function testAddUpdate()
- {
- $this->assertEmpty($this->_model->asArray());
- $this->assertEmpty($this->_model->asString());
- $this->_model->addUpdate('test');
- $this->assertEquals(['test'], $this->_model->asArray());
- $this->assertEquals('test', $this->_model->asString());
- }
- public function testAddHandle()
- {
- $this->assertEmpty($this->_model->getHandles());
- $this->_model->addHandle('test');
- $this->assertEquals(['test'], $this->_model->getHandles());
- }
- public function testRemoveHandle()
- {
- $this->_model->addHandle('test');
- $this->_model->removeHandle('test');
- $this->assertEmpty($this->_model->getHandles());
- }
- public function testAddPageHandles()
- {
- /* add a non-page handle to verify that it won't be affected during page handles manipulation */
- $nonPageHandles = ['non_page_handle'];
- $this->_model->addHandle($nonPageHandles);
- $this->assertFalse($this->_model->addPageHandles(['non_existing_handle']));
- $this->assertEmpty($this->_model->getPageHandles());
- $this->assertEquals($nonPageHandles, $this->_model->getHandles());
- /* test that only the first existing handle is taken into account */
- $handlesToTry = [
- 'default',
- 'catalog_category_default',
- 'catalog_product_view',
- 'catalog_product_view_type_simple',
- ];
- $expectedPageHandles = [
- 'default',
- 'catalog_category_default',
- 'catalog_product_view',
- 'catalog_product_view_type_simple',
- ];
- $this->assertTrue($this->_model->addPageHandles($handlesToTry));
- $this->assertEquals($expectedPageHandles, $this->_model->getPageHandles());
- $this->assertEquals(array_merge($nonPageHandles, $expectedPageHandles), $this->_model->getHandles());
- /* test that new handles override the previous ones */
- $expectedPageHandles = ['default', 'checkout_index_index'];
- $this->_model->removeHandle('catalog_category_default');
- $this->_model->removeHandle('catalog_product_view');
- $this->_model->removeHandle('catalog_product_view_type_simple');
- $this->assertTrue($this->_model->addPageHandles(['default', 'checkout_index_index']));
- $this->assertEquals($expectedPageHandles, $this->_model->getPageHandles());
- $this->assertEquals(array_merge($nonPageHandles, $expectedPageHandles), $this->_model->getHandles());
- }
- /**
- * @dataProvider pageHandleExistsDataProvider
- */
- public function testPageHandleExists($inputPageHandle, $expectedResult)
- {
- $this->assertSame($expectedResult, $this->_model->pageHandleExists($inputPageHandle));
- }
- public function pageHandleExistsDataProvider()
- {
- return [
- 'non-existing handle' => ['non_existing_handle', false],
- 'existing page type' => ['default', true],
- ];
- }
- public function testLoadFileSystem()
- {
- $handles = ['fixture_handle_one', 'fixture_handle_two'];
- $this->assertEmpty($this->_model->getHandles());
- $this->assertEmpty($this->_model->asString());
- $this->_model->load($handles);
- $this->assertEquals($handles, $this->_model->getHandles());
- $expectedResult = '
- <root>
- <body>
- <block class="Magento\Framework\View\Element\Template"
- template="Magento_Framework::fixture_template_one.phtml"/>
- </body>
- <body>
- <block class="Magento\Framework\View\Element\Template"
- template="Magento_Framework::fixture_template_two.phtml"/>
- </body>
- </root>
- ';
- $actualResult = '<root>' . $this->_model->asString() . '</root>';
- $this->assertXmlStringEqualsXmlString($expectedResult, $actualResult);
- }
- public function testLoadFileSystemWithPageLayout()
- {
- $handles = ['fixture_handle_with_page_layout'];
- $expectedHandles = ['fixture_handle_with_page_layout'];
- $expectedResult = '
- <root>
- <body>
- <referenceContainer name="main.container">
- <block class="Magento\Framework\View\Element\Template"
- template="Magento_Framework::fixture_template_one.phtml"/>
- </referenceContainer>
- </body>
- </root>
- ';
- $this->assertEmpty($this->_model->getHandles());
- $this->assertEmpty($this->_model->asString());
- $this->_model->load($handles);
- $this->assertEquals($expectedHandles, $this->_model->getHandles());
- $actualResult = '<root>' . $this->_model->asString() . '</root>';
- $this->assertXmlStringEqualsXmlString($expectedResult, $actualResult);
- $this->assertEquals('fixture_handle_page_layout', $this->_model->getPageLayout());
- }
- public function testLoadCache()
- {
- $this->_cache->expects($this->at(0))->method('load')
- ->with('LAYOUT_area_STORE20_100c6a4ccd050e33acef0553f24ef399961')
- ->will($this->returnValue(self::FIXTURE_LAYOUT_XML));
- $this->assertEmpty($this->_model->getHandles());
- $this->assertEmpty($this->_model->asString());
- $handles = ['fixture_handle_one', 'fixture_handle_two'];
- $this->_model->load($handles);
- $this->assertEquals($handles, $this->_model->getHandles());
- $this->assertEquals(self::FIXTURE_LAYOUT_XML, $this->_model->asString());
- }
- public function testLoadDbApp()
- {
- $this->_resource->expects(
- $this->any()
- )->method(
- 'fetchUpdatesByHandle'
- )->with(
- 'fixture_handle',
- $this->_theme,
- $this->scope
- )->will(
- $this->returnValue(self::FIXTURE_LAYOUT_XML)
- );
- $this->assertEmpty($this->_model->getHandles());
- $this->assertEmpty($this->_model->asString());
- $handles = ['fixture_handle_one'];
- $this->_model->load($handles);
- $this->assertEquals($handles, $this->_model->getHandles());
- $this->assertXmlStringEqualsXmlString(
- '<body>' . self::FIXTURE_LAYOUT_XML . '</body>',
- $this->_model->asString()
- );
- }
- public function testGetFileLayoutUpdatesXml()
- {
- $errorString = "Theme layout update file '" . __DIR__ . "/_mergeFiles/layout/file_wrong.xml' is not valid.";
- $this->_logger->expects($this->atLeastOnce())->method('info')
- ->with($this->stringStartsWith($errorString));
- $actualXml = $this->_model->getFileLayoutUpdatesXml();
- $this->assertXmlStringEqualsXmlFile(__DIR__ . '/_mergeFiles/merged.xml', $actualXml->asNiceXml());
- }
- public function testGetContainers()
- {
- $this->_model->addPageHandles(['default']);
- $this->_model->addPageHandles(['catalog_product_view']);
- $this->_model->addPageHandles(['catalog_product_view_type_configurable']);
- $this->_model->load();
- $expected = [
- 'content' => 'Main Content Area',
- 'product.info.extrahint' => 'Product View Extra Hint',
- 'product.info.configurable.extra' => 'Configurable Product Extra Info',
- ];
- $this->assertEquals($expected, $this->_model->getContainers());
- }
- public function testGetAllDesignAbstractions()
- {
- $expected = [
- 'customer_account' => [
- 'name' => 'customer_account',
- 'label' => new Phrase('Customer My Account (All Pages)'),
- 'design_abstraction' => 'custom',
- ],
- 'page_empty' => [
- 'name' => 'page_empty',
- 'label' => new Phrase('All Empty Layout Pages'),
- 'design_abstraction' => 'page_layout',
- ],
- ];
- $this->assertEquals($expected, $this->_model->getAllDesignAbstractions());
- }
- public function testIsPageLayoutDesignAbstractions()
- {
- $expected = [
- 'customer_account' => [
- 'name' => 'customer_account',
- 'label' => 'Customer My Account (All Pages)',
- 'design_abstraction' => 'custom',
- ],
- 'page_empty' => [
- 'name' => 'page_empty',
- 'label' => 'All Empty Layout Pages',
- 'design_abstraction' => 'page_layout',
- ],
- 'empty_data' => [],
- ];
- $this->assertTrue($this->_model->isPageLayoutDesignAbstraction($expected['page_empty']));
- $this->assertFalse($this->_model->isPageLayoutDesignAbstraction($expected['customer_account']));
- $this->assertFalse($this->_model->isPageLayoutDesignAbstraction($expected['empty_data']));
- }
- public function testIsCustomDesignAbstractions()
- {
- $expected = [
- 'customer_account' => [
- 'name' => 'customer_account',
- 'label' => 'Customer My Account (All Pages)',
- 'design_abstraction' => 'custom',
- ],
- 'page_empty' => [
- 'name' => 'page_empty',
- 'label' => 'All Empty Layout Pages',
- 'design_abstraction' => 'page_layout',
- ],
- 'empty_data' => [],
- ];
- $this->assertTrue($this->_model->isCustomerDesignAbstraction($expected['customer_account']));
- $this->assertFalse($this->_model->isCustomerDesignAbstraction($expected['page_empty']));
- $this->assertFalse($this->_model->isCustomerDesignAbstraction($expected['empty_data']));
- }
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- * @expectedExceptionMessage Invalid layout update handle
- */
- public function testLoadWithInvalidArgumentThrowsException()
- {
- $this->_model->load(123);
- }
- /**
- * Test loading invalid layout
- *
- * @expectedException \Exception
- * @expectedExceptionMessage Layout is invalid.
- */
- public function testLoadWithInvalidLayout()
- {
- $this->_model->addPageHandles(['default']);
- $this->_appState->expects($this->once())->method('getMode')->willReturn(State::MODE_DEVELOPER);
- $this->_layoutValidator->expects($this->any())
- ->method('getMessages')
- ->willReturn(['testMessage1', 'testMessage2']);
- $this->_layoutValidator->expects($this->any())
- ->method('isValid')
- ->willThrowException(new \Exception('Layout is invalid.'));
- $suffix = md5(implode('|', $this->_model->getHandles()));
- $cacheId = "LAYOUT_{$this->_theme->getArea()}_STORE{$this->scope->getId()}_{$this->_theme->getId()}{$suffix}";
- $messages = $this->_layoutValidator->getMessages();
- // Testing error message is logged with logger
- $this->_logger->expects($this->once())->method('info')
- ->with(
- 'Cache file with merged layout: ' . $cacheId . ' and handles default' . ': ' . array_shift($messages)
- );
- $this->_model->load();
- }
- /**
- * @expectedException \Magento\Framework\Config\Dom\ValidationException
- * @expectedExceptionMessageRegExp /_mergeFiles\/layout\/file_wrong\.xml\' is not valid/
- */
- public function testLayoutUpdateFileIsNotValid()
- {
- $this->_appState->expects($this->once())->method('getMode')->willReturn(State::MODE_DEVELOPER);
- $this->_model->addPageHandles(['default']);
- }
- }
|