MinifierTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Asset;
  7. use Magento\Deploy\Console\ConsoleLogger;
  8. use Magento\Framework\App\Filesystem\DirectoryList;
  9. use Magento\TestFramework\Helper\Bootstrap;
  10. use Magento\Framework\App\State as AppState;
  11. use Magento\Deploy\Console\DeployStaticOptions as Options;
  12. use Magento\Deploy\Strategy\DeployStrategyFactory;
  13. /**
  14. * Tests for minifier
  15. *
  16. * @magentoComponentsDir Magento/Framework/View/_files/static/theme
  17. * @magentoDbIsolation enabled
  18. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  19. */
  20. class MinifierTest extends \PHPUnit\Framework\TestCase
  21. {
  22. /**
  23. * @var \Magento\Framework\Filesystem\Directory\WriteInterface
  24. */
  25. private $staticDir;
  26. /**
  27. * @var \Magento\TestFramework\ObjectManager
  28. */
  29. protected $objectManager;
  30. /**
  31. * @var string
  32. */
  33. private $origMode;
  34. /**
  35. * {@inheritDoc}
  36. */
  37. protected function setUp()
  38. {
  39. parent::setUp();
  40. $this->objectManager = Bootstrap::getInstance()->getObjectManager();
  41. /** @var \Magento\Theme\Model\Theme\Registration $registration */
  42. $registration = $this->objectManager->get(
  43. \Magento\Theme\Model\Theme\Registration::class
  44. );
  45. $registration->register();
  46. /** @var \Magento\TestFramework\App\State $appState */
  47. $appState = $this->objectManager->get(\Magento\TestFramework\App\State::class);
  48. $this->origMode = $appState->getMode();
  49. $appState->setMode(AppState::MODE_DEFAULT);
  50. /** @var \Magento\Framework\Filesystem $filesystem */
  51. $filesystem = Bootstrap::getObjectManager()->get(\Magento\Framework\Filesystem::class);
  52. $this->staticDir = $filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
  53. }
  54. /**
  55. * {@inheritDoc}
  56. */
  57. protected function tearDown()
  58. {
  59. /** @var \Magento\TestFramework\App\State $appState */
  60. $appState = $this->objectManager->get(\Magento\TestFramework\App\State::class);
  61. $appState->setMode($this->origMode);
  62. if ($this->staticDir->isExist('frontend/FrameworkViewMinifier')) {
  63. $this->staticDir->delete('frontend/FrameworkViewMinifier');
  64. }
  65. parent::tearDown();
  66. }
  67. /**
  68. * CSS Minifier library test
  69. *
  70. * When fails on library update or minification handler replacement:
  71. * 1 - minify `_files/static/css/styles.css` with new library manually
  72. * 2 - use DIFF tools to see difference between new minified CSS and old minified one
  73. * 3 - ensure that all differences are acceptable
  74. * 4 - ensure that new minified CSS is fully workable in all supported browsers
  75. * 5 - replace `_files/static/css/styles.magento.min.css` with new minified css
  76. */
  77. public function testCSSminLibrary()
  78. {
  79. /** @var \Magento\Framework\Code\Minifier\AdapterInterface $adapter */
  80. $adapter = $this->objectManager->get('cssMinificationAdapter');
  81. $this->assertEquals(
  82. file_get_contents(dirname(__DIR__) . '/_files/static/expected/styles.magento.min.css'),
  83. $adapter->minify(file_get_contents(dirname(__DIR__) . '/_files/static/theme/web/css/styles.css')),
  84. 'Minified CSS differs from initial minified CSS snapshot. '
  85. . 'Ensure that new CSS is fully valid for all supported browsers '
  86. . 'and replace old minified snapshot with new one.'
  87. );
  88. }
  89. /**
  90. * Test JS minification library
  91. *
  92. * @return void
  93. */
  94. public function testJshrinkLibrary()
  95. {
  96. /** @var \Magento\Framework\Code\Minifier\AdapterInterface $adapter */
  97. $adapter = $this->objectManager->get('jsMinificationAdapter');
  98. $this->assertEquals(
  99. file_get_contents(dirname(__DIR__) . '/_files/static/expected/test.min.js'),
  100. $adapter->minify(file_get_contents(dirname(__DIR__) . '/_files/static/theme/web/js/test.js')),
  101. 'Minified JS differs from initial minified JS snapshot. '
  102. . 'Ensure that new JS is fully valid for all supported browsers '
  103. . 'and replace old minified snapshot with new one.'
  104. );
  105. }
  106. /**
  107. * Test CSS minification
  108. *
  109. * @param string $requestedUri
  110. * @param callable $assertionCallback
  111. * @throws \Magento\Framework\Exception\LocalizedException
  112. */
  113. protected function _testCssMinification($requestedUri, $assertionCallback)
  114. {
  115. /** @var \Magento\Framework\App\Request\Http $request */
  116. $request = $this->objectManager->get(\Magento\Framework\App\Request\Http::class);
  117. $request->setRequestUri($requestedUri);
  118. $request->setParam('resource', $requestedUri);
  119. $response = $this->getMockBuilder(\Magento\Framework\App\Response\FileInterface::class)
  120. ->setMethods(['setFilePath'])
  121. ->getMockForAbstractClass();
  122. $response
  123. ->expects($this->any())
  124. ->method('setFilePath')
  125. ->will($this->returnCallback($assertionCallback));
  126. /** @var \Magento\Framework\App\StaticResource $staticResourceApp */
  127. $staticResourceApp = $this->objectManager->create(
  128. \Magento\Framework\App\StaticResource::class,
  129. ['response' => $response]
  130. );
  131. $staticResourceApp->launch();
  132. }
  133. /**
  134. * @magentoConfigFixture current_store dev/css/minify_files 0
  135. * @magentoAppIsolation enabled
  136. */
  137. public function testCssMinificationOff()
  138. {
  139. $this->_testCssMinification(
  140. '/frontend/FrameworkViewMinifier/default/en_US/css/styles.css',
  141. function ($path) {
  142. $content = file_get_contents($path);
  143. $this->assertNotEmpty($content);
  144. $this->assertContains('FrameworkViewMinifier/frontend', $content);
  145. $this->assertNotEquals(
  146. file_get_contents(
  147. dirname(__DIR__)
  148. . '/_files/static/expected/styles.magento.min.css'
  149. ),
  150. $content,
  151. 'CSS is minified when minification turned off'
  152. );
  153. }
  154. );
  155. }
  156. /**
  157. * @magentoConfigFixture current_store dev/css/minify_files 1
  158. */
  159. public function testCssMinification()
  160. {
  161. $this->_testCssMinification(
  162. '/frontend/FrameworkViewMinifier/default/en_US/css/styles.min.css',
  163. function ($path) {
  164. $this->assertEquals(
  165. file_get_contents(
  166. dirname(__DIR__)
  167. . '/_files/static/expected/styles.magento.min.css'
  168. ),
  169. file_get_contents($path),
  170. 'Minified files are not equal or minification did not work for requested CSS'
  171. );
  172. }
  173. );
  174. }
  175. /**
  176. * @magentoConfigFixture current_store dev/css/minify_files 1
  177. */
  178. public function testCssMinificationForMinifiedFiles()
  179. {
  180. $this->_testCssMinification(
  181. '/frontend/FrameworkViewMinifier/default/en_US/css/preminified-styles.min.css',
  182. function ($path) {
  183. $content = file_get_contents($path);
  184. $this->assertNotEmpty($content);
  185. $this->assertContains('Magento/backend', $content);
  186. $this->assertContains('semi-minified file', $content);
  187. }
  188. );
  189. }
  190. /**
  191. * @magentoConfigFixture current_store dev/css/minify_files 1
  192. */
  193. public function testDeploymentWithMinifierEnabled()
  194. {
  195. $staticPath = $this->staticDir->getAbsolutePath();
  196. $fileToBePublished = $staticPath . '/frontend/FrameworkViewMinifier/default/en_US/css/styles.min.css';
  197. $fileToTestPublishing = dirname(__DIR__) . '/_files/static/theme/web/css/styles.css';
  198. $omFactory = $this->createPartialMock(\Magento\Framework\App\ObjectManagerFactory::class, ['create']);
  199. $omFactory->expects($this->any())
  200. ->method('create')
  201. ->will($this->returnValue($this->objectManager));
  202. $filesUtil = $this->createMock(\Magento\Framework\App\Utility\Files::class);
  203. $filesUtil->expects($this->any())
  204. ->method('getStaticLibraryFiles')
  205. ->will($this->returnValue([]));
  206. $filesUtil->expects($this->any())
  207. ->method('getPhtmlFiles')
  208. ->will($this->returnValue([]));
  209. $filesUtil->expects($this->any())
  210. ->method('getStaticPreProcessingFiles')
  211. ->will($this->returnValue(
  212. [
  213. ['frontend', 'FrameworkViewMinifier/default', '', '', 'css/styles.css', $fileToTestPublishing]
  214. ]
  215. ));
  216. $this->objectManager->addSharedInstance($filesUtil, \Magento\Framework\App\Utility\Files::class);
  217. $output = $this->objectManager->create(
  218. \Symfony\Component\Console\Output\ConsoleOutput::class
  219. );
  220. $logger = $this->objectManager->create(
  221. ConsoleLogger::class,
  222. ['output' => $output]
  223. );
  224. $versionStorage = $this->createPartialMock(
  225. \Magento\Framework\App\View\Deployment\Version\StorageInterface::class,
  226. ['save', 'load']
  227. );
  228. /** @var \Magento\Deploy\Service\DeployStaticContent $deployService */
  229. $deployService = $this->objectManager->create(
  230. \Magento\Deploy\Service\DeployStaticContent::class,
  231. [
  232. 'objectManager' => $this->objectManager,
  233. 'logger' => $logger,
  234. 'versionStorage' => $versionStorage,
  235. ]
  236. );
  237. $deployService->deploy(
  238. [
  239. Options::DRY_RUN => false,
  240. Options::NO_JAVASCRIPT => true,
  241. Options::NO_CSS => false,
  242. Options::NO_LESS => false,
  243. Options::NO_IMAGES => true,
  244. Options::NO_FONTS => true,
  245. Options::NO_HTML => true,
  246. Options::NO_MISC => true,
  247. Options::NO_HTML_MINIFY => true,
  248. Options::AREA => ['frontend'],
  249. Options::EXCLUDE_AREA => ['none'],
  250. Options::THEME => ['FrameworkViewMinifier/default'],
  251. Options::EXCLUDE_THEME => ['none'],
  252. Options::LANGUAGE => ['en_US'],
  253. Options::EXCLUDE_LANGUAGE => ['none'],
  254. Options::JOBS_AMOUNT => 0,
  255. Options::SYMLINK_LOCALE => false,
  256. Options::STRATEGY => DeployStrategyFactory::DEPLOY_STRATEGY_QUICK
  257. ]
  258. );
  259. $this->assertFileExists($fileToBePublished);
  260. $this->assertEquals(
  261. file_get_contents(dirname(__DIR__) . '/_files/static/expected/styles.magento.min.css'),
  262. file_get_contents($fileToBePublished),
  263. 'Minified file is not equal or minification did not work for deployed CSS'
  264. );
  265. }
  266. }