319 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
<?php
 | 
						|
/**
 | 
						|
 * Copyright © Magento, Inc. All rights reserved.
 | 
						|
 * See COPYING.txt for license details.
 | 
						|
 */
 | 
						|
namespace Magento\Deploy;
 | 
						|
 | 
						|
use Magento\Deploy\Package\Processor\PreProcessor\Less;
 | 
						|
use Magento\Deploy\Service\DeployStaticContent;
 | 
						|
use Magento\Deploy\Strategy\DeployStrategyFactory;
 | 
						|
use Magento\Framework\App\State;
 | 
						|
use Magento\TestFramework\Helper\Bootstrap;
 | 
						|
use Magento\Framework\App\Filesystem\DirectoryList;
 | 
						|
use Magento\Framework\Filesystem;
 | 
						|
use Magento\Framework\Filesystem\Directory\ReadInterface;
 | 
						|
use Magento\Deploy\Console\DeployStaticOptions as Options;
 | 
						|
use Magento\Framework\Config\View;
 | 
						|
use Magento\Deploy\Config\BundleConfig;
 | 
						|
use Magento\Framework\Filesystem\Directory\WriteInterface;
 | 
						|
 | 
						|
/**
 | 
						|
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 | 
						|
 */
 | 
						|
class DeployTest extends \PHPUnit\Framework\TestCase
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @var Filesystem
 | 
						|
     */
 | 
						|
    private $filesystem;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var WriteInterface
 | 
						|
     */
 | 
						|
    private $staticDir;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var ReadInterface
 | 
						|
     */
 | 
						|
    private $rootDir;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var DeployStaticContent
 | 
						|
     */
 | 
						|
    private $deployService;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var View
 | 
						|
     */
 | 
						|
    private $config;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var BundleConfig
 | 
						|
     */
 | 
						|
    private $bundleConfig;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var DeployStaticContent
 | 
						|
     */
 | 
						|
    private $staticContentService;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var string
 | 
						|
     */
 | 
						|
    private $prevMode;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    private $options = [
 | 
						|
        Options::DRY_RUN => false,
 | 
						|
        Options::NO_JAVASCRIPT => false,
 | 
						|
        Options::NO_JS_BUNDLE => false,
 | 
						|
        Options::NO_CSS => false,
 | 
						|
        Options::NO_LESS => false,
 | 
						|
        Options::NO_IMAGES => false,
 | 
						|
        Options::NO_FONTS => false,
 | 
						|
        Options::NO_HTML => false,
 | 
						|
        Options::NO_MISC => false,
 | 
						|
        Options::NO_HTML_MINIFY => false,
 | 
						|
        Options::AREA => ['frontend'],
 | 
						|
        Options::EXCLUDE_AREA => ['none'],
 | 
						|
        Options::THEME => ['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3', 'Vendor/parent', 'Vendor/child'],
 | 
						|
        Options::EXCLUDE_THEME => ['none'],
 | 
						|
        Options::LANGUAGE => ['en_US', 'fr_FR', 'pl_PL'],
 | 
						|
        Options::EXCLUDE_LANGUAGE => ['none'],
 | 
						|
        Options::JOBS_AMOUNT => 0,
 | 
						|
        Options::SYMLINK_LOCALE => false,
 | 
						|
        Options::STRATEGY => DeployStrategyFactory::DEPLOY_STRATEGY_COMPACT,
 | 
						|
    ];
 | 
						|
 | 
						|
    protected function setUp(): void
 | 
						|
    {
 | 
						|
        $objectManager = Bootstrap::getObjectManager();
 | 
						|
        $this->prevMode = $objectManager->get(State::class)->getMode();
 | 
						|
        $objectManager->get(State::class)->setMode(State::MODE_PRODUCTION);
 | 
						|
 | 
						|
        $this->filesystem = $objectManager->get(Filesystem::class);
 | 
						|
        $this->staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
 | 
						|
        $this->rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT);
 | 
						|
 | 
						|
        $logger = $objectManager->get(\Psr\Log\LoggerInterface::class);
 | 
						|
        $this->deployService = $objectManager->create(
 | 
						|
            DeployStaticContent::class,
 | 
						|
            ['logger' => $logger]
 | 
						|
        );
 | 
						|
 | 
						|
        $this->bundleConfig = $objectManager->create(BundleConfig::class);
 | 
						|
        $this->config = $objectManager->create(View::class);
 | 
						|
 | 
						|
        $this->staticContentService = $objectManager->create(DeployStaticContent::class);
 | 
						|
 | 
						|
        $this->filesystem->getDirectoryWrite(DirectoryList::PUB)->delete(DirectoryList::STATIC_VIEW);
 | 
						|
        $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR)->delete(DirectoryList::TMP_MATERIALIZATION_DIR);
 | 
						|
    }
 | 
						|
 | 
						|
    protected function tearDown(): void
 | 
						|
    {
 | 
						|
        $objectManager = Bootstrap::getObjectManager();
 | 
						|
        $objectManager->get(State::class)->setMode($this->prevMode);
 | 
						|
        $this->filesystem = $objectManager->get(Filesystem::class);
 | 
						|
        $this->filesystem->getDirectoryWrite(DirectoryList::PUB)->delete(DirectoryList::STATIC_VIEW);
 | 
						|
        $this->staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
 | 
						|
        $this->staticDir->getDriver()->createDirectory($this->staticDir->getAbsolutePath());
 | 
						|
 | 
						|
        parent::tearDown();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @magentoDataFixture Magento/Deploy/_files/theme.php
 | 
						|
     */
 | 
						|
    public function testDeploy()
 | 
						|
    {
 | 
						|
        $this->deployService->deploy($this->options);
 | 
						|
 | 
						|
        $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom1/default/css/root.css'));
 | 
						|
        $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom2/default/css/root.css'));
 | 
						|
        $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom3/default/css/root.css'));
 | 
						|
        $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom3/default/css/local.css'));
 | 
						|
 | 
						|
        $this->assertFileExistsIsGenerated('requirejs-config.js');
 | 
						|
        $this->assertFileExistsIsGenerated('requirejs-map.js');
 | 
						|
        $this->assertFileExistsIsGenerated('map.json');
 | 
						|
        $this->assertFileExistsIsGenerated('js-translation.json');
 | 
						|
        $this->assertFileExistsIsGenerated('result_map.json');
 | 
						|
 | 
						|
        $actualFileContent = $this->staticDir->readFile('frontend/Magento/zoom3/default/css/root.css');
 | 
						|
        $this->assertLessPreProcessor($actualFileContent);
 | 
						|
        $this->assertCssUrlFixerPostProcessor($actualFileContent);
 | 
						|
 | 
						|
        $actualFileContent = $this->staticDir->readFile('frontend/Vendor/child/default/css/styles-m.css');
 | 
						|
        $this->assertCssFromChildTheme($actualFileContent);
 | 
						|
 | 
						|
        foreach (['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3', 'Vendor/parent', 'Vendor/child'] as $theme) {
 | 
						|
            $this->assertBundleSize($theme);
 | 
						|
            $this->assertExcluded($theme, $this->config->getExcludedFiles());
 | 
						|
            $this->assertExcluded($theme, $this->config->getExcludedDir());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert file exists in all themes and locales
 | 
						|
     *
 | 
						|
     * @param string $fileName
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertFileExistsIsGenerated($fileName)
 | 
						|
    {
 | 
						|
        foreach (['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3', 'Vendor/parent', 'Vendor/child'] as $theme) {
 | 
						|
            foreach ($this->options[Options::LANGUAGE] as $locale) {
 | 
						|
                $this->assertFileExists(
 | 
						|
                    $this->staticDir->getAbsolutePath(
 | 
						|
                        'frontend/' . $theme . '/' . $locale . '/' . $fileName
 | 
						|
                    )
 | 
						|
                );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert Less pre-processor
 | 
						|
     *
 | 
						|
     * @see Less
 | 
						|
     * @param $actualRootCssContent
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertLessPreProcessor($actualRootCssContent)
 | 
						|
    {
 | 
						|
        //_testA is included from Magento/zoom3
 | 
						|
        //_testB is included from Magento/zoom2
 | 
						|
        $this->assertStringContainsString('color:#111', $actualRootCssContent);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert CssUrlFixer post-processor
 | 
						|
     *
 | 
						|
     * @param $actualRootCssContent
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertCssUrlFixerPostProcessor($actualRootCssContent)
 | 
						|
    {
 | 
						|
        //assert CssUrlFixer fix urls
 | 
						|
        $this->assertStringContainsString(
 | 
						|
            'url("../../../../../frontend/Magento/zoom1/default/images/logo-magento-1.png")',
 | 
						|
            $actualRootCssContent
 | 
						|
        );
 | 
						|
        $this->assertStringContainsString(
 | 
						|
            'url("../../../../../frontend/Magento/zoom2/default/images/logo-magento-2.png")',
 | 
						|
            $actualRootCssContent
 | 
						|
        );
 | 
						|
        $this->assertStringContainsString(
 | 
						|
            'url("../images/logo-magento-3.png")',
 | 
						|
            $actualRootCssContent
 | 
						|
        );
 | 
						|
        //_testA is included from Magento/zoom3
 | 
						|
        //_testB is included from Magento/zoom2
 | 
						|
        $this->assertStringContainsString('color:#111', $actualRootCssContent);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert CSS from child post-processor
 | 
						|
     *
 | 
						|
     * @param $actualRootCssContent
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertCssFromChildTheme($actualRootCssContent)
 | 
						|
    {
 | 
						|
        //assert CssUrlFixer fix urls
 | 
						|
        $this->assertStringContainsString(
 | 
						|
            'super-test-class-for-easy-find',
 | 
						|
            $actualRootCssContent
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert correct bundle size according to configuration set in view.xml
 | 
						|
     *
 | 
						|
     * @param string $theme
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertBundleSize($theme)
 | 
						|
    {
 | 
						|
        $expectedSize = $this->bundleConfig->getBundleFileMaxSize('frontend', $theme);
 | 
						|
        $expectedSize *= 1.2;
 | 
						|
 | 
						|
        $iterator = $this->getDirectoryIterator("frontend/{$theme}/en_US/js/bundle");
 | 
						|
        /** @var \SplFileInfo $file */
 | 
						|
        foreach ($iterator as $file) {
 | 
						|
            if ($file->isFile()) {
 | 
						|
                $size = (int)$file->getSize() / 1024;
 | 
						|
                $this->assertLessThan($expectedSize, $size);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assert that file is excluded from view.xml
 | 
						|
     *
 | 
						|
     * @param string $theme
 | 
						|
     * @param array $excluded
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    private function assertExcluded($theme, array $excluded)
 | 
						|
    {
 | 
						|
        $iterator = $this->getDirectoryIterator("frontend/{$theme}/en_US/js/bundle");
 | 
						|
        foreach ($excluded as $pathData) {
 | 
						|
            $path = $this->splitPath($pathData);
 | 
						|
            if ($path['module'] !== null) {
 | 
						|
                $path = implode('/', $path);
 | 
						|
            } else {
 | 
						|
                $path = $path['path'];
 | 
						|
            }
 | 
						|
            /** @var \SplFileInfo $file */
 | 
						|
            foreach ($iterator as $file) {
 | 
						|
                if ($file->isFile()) {
 | 
						|
                    $bundleContent = $this->staticDir->readFile(
 | 
						|
                        $this->staticDir->getRelativePath($file->getPathname())
 | 
						|
                    );
 | 
						|
                    $this->assertStringNotContainsString('"' . $path . '":"', $bundleContent);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $path
 | 
						|
     * @return \RecursiveIteratorIterator
 | 
						|
     */
 | 
						|
    private function getDirectoryIterator($path)
 | 
						|
    {
 | 
						|
        $dirIterator = new \RecursiveDirectoryIterator(
 | 
						|
            $this->staticDir->getAbsolutePath($path),
 | 
						|
            \FilesystemIterator::SKIP_DOTS
 | 
						|
        );
 | 
						|
        return new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get excluded module and path from complex string
 | 
						|
     *
 | 
						|
     * @param string $path
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    private function splitPath($path)
 | 
						|
    {
 | 
						|
        if (strpos($path, '::') !== false) {
 | 
						|
            list($module, $path) = explode('::', $path);
 | 
						|
            return [
 | 
						|
                'module' => $module != 'Lib' ? $module : null,
 | 
						|
                'path' => $path,
 | 
						|
            ];
 | 
						|
        } else {
 | 
						|
            return [
 | 
						|
                'module' => null,
 | 
						|
                'path' => $path,
 | 
						|
            ];
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |