DeployTest.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Deploy;
  7. use Magento\Deploy\Package\Processor\PreProcessor\Less;
  8. use Magento\Deploy\Service\DeployStaticContent;
  9. use Magento\Deploy\Strategy\DeployStrategyFactory;
  10. use Magento\Framework\App\State;
  11. use Magento\TestFramework\Helper\Bootstrap;
  12. use Magento\Framework\App\Filesystem\DirectoryList;
  13. use Magento\Framework\Filesystem;
  14. use Magento\Framework\Filesystem\Directory\ReadInterface;
  15. use Magento\Deploy\Console\DeployStaticOptions as Options;
  16. use Magento\Framework\Config\View;
  17. use Magento\Deploy\Config\BundleConfig;
  18. use Magento\Framework\Filesystem\Directory\WriteInterface;
  19. /**
  20. * Class DeployTest
  21. *
  22. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  23. */
  24. class DeployTest extends \PHPUnit\Framework\TestCase
  25. {
  26. /**
  27. * @var Filesystem
  28. */
  29. private $filesystem;
  30. /**
  31. * @var WriteInterface
  32. */
  33. private $staticDir;
  34. /**
  35. * @var ReadInterface
  36. */
  37. private $rootDir;
  38. /**
  39. * @var DeployStaticContent
  40. */
  41. private $deployService;
  42. /**
  43. * @var View
  44. */
  45. private $config;
  46. /**
  47. * @var BundleConfig
  48. */
  49. private $bundleConfig;
  50. /**
  51. * @var DeployStaticContent
  52. */
  53. private $staticContentService;
  54. /**
  55. * @var string
  56. */
  57. private $prevMode;
  58. /**
  59. * @var array
  60. */
  61. private $options = [
  62. Options::DRY_RUN => false,
  63. Options::NO_JAVASCRIPT => false,
  64. Options::NO_CSS => false,
  65. Options::NO_LESS => false,
  66. Options::NO_IMAGES => false,
  67. Options::NO_FONTS => false,
  68. Options::NO_HTML => false,
  69. Options::NO_MISC => false,
  70. Options::NO_HTML_MINIFY => false,
  71. Options::AREA => ['frontend'],
  72. Options::EXCLUDE_AREA => ['none'],
  73. Options::THEME => ['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3'],
  74. Options::EXCLUDE_THEME => ['none'],
  75. Options::LANGUAGE => ['en_US', 'fr_FR', 'pl_PL'],
  76. Options::EXCLUDE_LANGUAGE => ['none'],
  77. Options::JOBS_AMOUNT => 0,
  78. Options::SYMLINK_LOCALE => false,
  79. Options::STRATEGY => DeployStrategyFactory::DEPLOY_STRATEGY_COMPACT,
  80. ];
  81. protected function setUp()
  82. {
  83. $objectManager = Bootstrap::getObjectManager();
  84. $this->prevMode = $objectManager->get(State::class)->getMode();
  85. $objectManager->get(State::class)->setMode(State::MODE_PRODUCTION);
  86. $this->filesystem = $objectManager->get(Filesystem::class);
  87. $this->staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
  88. $this->rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT);
  89. $logger = $objectManager->get(\Psr\Log\LoggerInterface::class);
  90. $this->deployService = $objectManager->create(DeployStaticContent::class, [
  91. 'logger' => $logger
  92. ]);
  93. $this->bundleConfig = $objectManager->create(BundleConfig::class);
  94. $this->config = $objectManager->create(View::class);
  95. $this->staticContentService = $objectManager->create(DeployStaticContent::class);
  96. $this->filesystem->getDirectoryWrite(DirectoryList::PUB)->delete(DirectoryList::STATIC_VIEW);
  97. $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR)->delete(DirectoryList::TMP_MATERIALIZATION_DIR);
  98. }
  99. protected function tearDown()
  100. {
  101. $objectManager = Bootstrap::getObjectManager();
  102. $objectManager->get(State::class)->setMode($this->prevMode);
  103. $this->filesystem = $objectManager->get(Filesystem::class);
  104. $this->filesystem->getDirectoryWrite(DirectoryList::PUB)->delete(DirectoryList::STATIC_VIEW);
  105. $this->staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
  106. $this->staticDir->getDriver()->createDirectory($this->staticDir->getAbsolutePath());
  107. parent::tearDown();
  108. }
  109. /**
  110. * @magentoDataFixture Magento/Deploy/_files/theme.php
  111. */
  112. public function testDeploy()
  113. {
  114. $this->deployService->deploy($this->options);
  115. $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom1/default/css/root.css'));
  116. $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom2/default/css/root.css'));
  117. $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom3/default/css/root.css'));
  118. $this->assertFileExists($this->staticDir->getAbsolutePath('frontend/Magento/zoom3/default/css/local.css'));
  119. $this->assertFileExistsIsGenerated('requirejs-config.js');
  120. $this->assertFileExistsIsGenerated('requirejs-map.js');
  121. $this->assertFileExistsIsGenerated('map.json');
  122. $this->assertFileExistsIsGenerated('js-translation.json');
  123. $this->assertFileExistsIsGenerated('result_map.json');
  124. $actualFileContent = $this->staticDir->readFile('frontend/Magento/zoom3/default/css/root.css');
  125. $this->assertLessPreProcessor($actualFileContent);
  126. $this->assertCssUrlFixerPostProcessor($actualFileContent);
  127. foreach (['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3'] as $theme) {
  128. $this->assertBundleSize($theme);
  129. $this->assertExcluded($theme, $this->config->getExcludedFiles());
  130. $this->assertExcluded($theme, $this->config->getExcludedDir());
  131. }
  132. }
  133. /**
  134. * Assert file exists in all themes and locales
  135. *
  136. * @param string $fileName
  137. * @return void
  138. */
  139. private function assertFileExistsIsGenerated($fileName)
  140. {
  141. foreach (['Magento/zoom1', 'Magento/zoom2', 'Magento/zoom3'] as $theme) {
  142. foreach ($this->options[Options::LANGUAGE] as $locale) {
  143. $this->assertFileExists(
  144. $this->staticDir->getAbsolutePath(
  145. 'frontend/' . $theme . '/' . $locale . '/' . $fileName
  146. )
  147. );
  148. }
  149. }
  150. }
  151. /**
  152. * Assert Less pre-processor
  153. *
  154. * @see Less
  155. * @param $actualRootCssContent
  156. * @return void
  157. */
  158. private function assertLessPreProcessor($actualRootCssContent)
  159. {
  160. //_testA is included from Magento/zoom3
  161. //_testB is included from Magento/zoom2
  162. $this->assertContains('color:#111', $actualRootCssContent);
  163. }
  164. /**
  165. * Assert CssUrlFixer post-processor
  166. *
  167. * @param $actualRootCssContent
  168. * @return void
  169. */
  170. private function assertCssUrlFixerPostProcessor($actualRootCssContent)
  171. {
  172. //assert CssUrlFixer fix urls
  173. $this->assertContains(
  174. 'url("../../../../../frontend/Magento/zoom1/default/images/logo-magento-1.png")',
  175. $actualRootCssContent
  176. );
  177. $this->assertContains(
  178. 'url("../../../../../frontend/Magento/zoom2/default/images/logo-magento-2.png")',
  179. $actualRootCssContent
  180. );
  181. $this->assertContains(
  182. 'url("../images/logo-magento-3.png")',
  183. $actualRootCssContent
  184. );
  185. //_testA is included from Magento/zoom3
  186. //_testB is included from Magento/zoom2
  187. $this->assertContains('color:#111', $actualRootCssContent);
  188. }
  189. /**
  190. * Assert correct bundle size according to configuration set in view.xml
  191. *
  192. * @param string $theme
  193. * @return void
  194. */
  195. private function assertBundleSize($theme)
  196. {
  197. $expectedSize = $this->bundleConfig->getBundleFileMaxSize('frontend', $theme);
  198. $expectedSize *= 1.15;
  199. $iterator = $this->getDirectoryIterator("frontend/{$theme}/en_US/js/bundle");
  200. /** @var \SplFileInfo $file */
  201. foreach ($iterator as $file) {
  202. if ($file->isFile()) {
  203. $size = (int)$file->getSize() / 1024;
  204. $this->assertLessThan($expectedSize, $size);
  205. }
  206. }
  207. }
  208. /**
  209. * Assert that file is excluded from view.xml
  210. *
  211. * @param string $theme
  212. * @param array $excluded
  213. * @return void
  214. */
  215. private function assertExcluded($theme, array $excluded)
  216. {
  217. $iterator = $this->getDirectoryIterator("frontend/{$theme}/en_US/js/bundle");
  218. foreach ($excluded as $pathData) {
  219. $path = $this->splitPath($pathData);
  220. if ($path['module'] !== null) {
  221. $path = implode('/', $path);
  222. } else {
  223. $path = $path['path'];
  224. }
  225. /** @var \SplFileInfo $file */
  226. foreach ($iterator as $file) {
  227. if ($file->isFile()) {
  228. $bundleContent = $this->staticDir->readFile(
  229. $this->staticDir->getRelativePath($file->getPathname())
  230. );
  231. $this->assertNotContains('"' . $path . '":"', $bundleContent);
  232. }
  233. }
  234. }
  235. }
  236. /**
  237. * @param string $path
  238. * @return \RecursiveIteratorIterator
  239. */
  240. private function getDirectoryIterator($path)
  241. {
  242. $dirIterator = new \RecursiveDirectoryIterator(
  243. $this->staticDir->getAbsolutePath($path),
  244. \FilesystemIterator::SKIP_DOTS
  245. );
  246. return new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
  247. }
  248. /**
  249. * Get excluded module and path from complex string
  250. *
  251. * @param string $path
  252. * @return array
  253. */
  254. private function splitPath($path)
  255. {
  256. if (strpos($path, '::') !== false) {
  257. list($module, $path) = explode('::', $path);
  258. return [
  259. 'module' => $module != 'Lib' ? $module : null,
  260. 'path' => $path,
  261. ];
  262. } else {
  263. return [
  264. 'module' => null,
  265. 'path' => $path,
  266. ];
  267. }
  268. }
  269. }