PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php

https://gitlab.com/mohamed_hussein/prodt
PHP | 297 lines | 213 code | 21 blank | 63 comment | 1 complexity | 7b535df2a3ae40f766aedbe2db4ac6e6 MD5 | raw file
  1. <?php
  2. namespace Drupal\Tests\Core\Asset;
  3. use Drupal\Core\Asset\CssOptimizer;
  4. use Drupal\Core\File\FileUrlGeneratorInterface;
  5. use Drupal\Tests\UnitTestCase;
  6. /**
  7. * Tests the CSS asset optimizer.
  8. *
  9. * @group Asset
  10. */
  11. class CssOptimizerUnitTest extends UnitTestCase {
  12. /**
  13. * {@inheritdoc}
  14. */
  15. protected $backupGlobals = FALSE;
  16. /**
  17. * A CSS asset optimizer.
  18. *
  19. * @var \Drupal\Core\Asset\CssOptimizer
  20. */
  21. protected $optimizer;
  22. /**
  23. * The file URL generator mock.
  24. *
  25. * @var \Drupal\Core\File\FileUrlGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
  26. */
  27. protected $fileUrlGenerator;
  28. protected function setUp(): void {
  29. parent::setUp();
  30. $this->fileUrlGenerator = $this->createMock(FileUrlGeneratorInterface::class);
  31. $this->fileUrlGenerator->expects($this->any())
  32. ->method('generateString')
  33. ->with($this->isType('string'))
  34. ->willReturnCallback(function ($uri) {
  35. return 'generated-relative-url:' . $uri;
  36. });
  37. $this->optimizer = new CssOptimizer($this->fileUrlGenerator);
  38. }
  39. /**
  40. * Provides data for the CSS asset optimizing test.
  41. */
  42. public function providerTestOptimize() {
  43. $path = 'core/tests/Drupal/Tests/Core/Asset/css_test_files/';
  44. $absolute_path = dirname(__FILE__) . '/css_test_files/';
  45. return [
  46. // File. Tests:
  47. // - Stripped comments and white-space.
  48. // - Retain white-space in selectors. (https://www.drupal.org/node/472820)
  49. // - Retain pseudo-selectors. (https://www.drupal.org/node/460448)
  50. [
  51. [
  52. 'group' => -100,
  53. 'type' => 'file',
  54. 'weight' => 0.012,
  55. 'media' => 'all',
  56. 'preprocess' => TRUE,
  57. 'data' => $path . 'css_input_without_import.css',
  58. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  59. 'basename' => 'css_input_without_import.css',
  60. ],
  61. file_get_contents($absolute_path . 'css_input_without_import.css.optimized.css'),
  62. ],
  63. // File. Tests:
  64. // - Proper URLs in imported files. (https://www.drupal.org/node/265719)
  65. // - A background image with relative paths, which must be rewritten.
  66. // - The rewritten background image path must also be passed through
  67. // FileUrlGeneratorInterface::generate().
  68. // (https://www.drupal.org/node/1961340)
  69. // - Imported files that are external (protocol-relative URL or not)
  70. // should not be expanded. (https://www.drupal.org/node/2014851)
  71. // Potential forms of @import might also include media queries.
  72. // (https://developer.mozilla.org/en-US/docs/Web/CSS/@import)
  73. [
  74. [
  75. 'group' => -100,
  76. 'type' => 'file',
  77. 'weight' => 0.013,
  78. 'media' => 'all',
  79. 'preprocess' => TRUE,
  80. 'data' => $path . 'css_input_with_import.css',
  81. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  82. 'basename' => 'css_input_with_import.css',
  83. ],
  84. str_replace("url('import1.css')", 'url(generated-relative-url:' . $path . 'import1.css)', str_replace('url(images/icon.png)', 'url(generated-relative-url:' . $path . 'images/icon.png)', file_get_contents($absolute_path . 'css_input_with_import.css.optimized.css'))),
  85. ],
  86. // File. Tests:
  87. // - Retain comment hacks.
  88. [
  89. [
  90. 'group' => -100,
  91. 'type' => 'file',
  92. 'weight' => 0.013,
  93. 'media' => 'all',
  94. 'preprocess' => TRUE,
  95. 'data' => $path . 'comment_hacks.css',
  96. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  97. 'basename' => 'comment_hacks.css',
  98. ],
  99. file_get_contents($absolute_path . 'comment_hacks.css.optimized.css'),
  100. ],
  101. // File in subfolder. Tests:
  102. // - CSS import path is properly interpreted.
  103. // (https://www.drupal.org/node/1198904)
  104. // - Don't adjust data URIs (https://www.drupal.org/node/2142441)
  105. [
  106. [
  107. 'group' => -100,
  108. 'type' => 'file',
  109. 'weight' => 0.013,
  110. 'media' => 'all',
  111. 'preprocess' => TRUE,
  112. 'data' => $path . 'css_subfolder/css_input_with_import.css',
  113. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  114. 'basename' => 'css_input_with_import.css',
  115. ],
  116. str_replace('url(../images/icon.png)', 'url(generated-relative-url:' . $path . 'images/icon.png)', file_get_contents($absolute_path . 'css_subfolder/css_input_with_import.css.optimized.css')),
  117. ],
  118. // File. Tests:
  119. // - Any @charset declaration at the beginning of a file should be
  120. // removed without breaking subsequent CSS.
  121. [
  122. [
  123. 'group' => -100,
  124. 'type' => 'file',
  125. 'weight' => 0.013,
  126. 'media' => 'all',
  127. 'preprocess' => TRUE,
  128. 'data' => $path . 'charset_sameline.css',
  129. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  130. 'basename' => 'charset_sameline.css',
  131. ],
  132. file_get_contents($absolute_path . 'charset.css.optimized.css'),
  133. ],
  134. [
  135. [
  136. 'group' => -100,
  137. 'type' => 'file',
  138. 'weight' => 0.013,
  139. 'media' => 'all',
  140. 'preprocess' => TRUE,
  141. 'data' => $path . 'charset_newline.css',
  142. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  143. 'basename' => 'charset_newline.css',
  144. ],
  145. file_get_contents($absolute_path . 'charset.css.optimized.css'),
  146. ],
  147. [
  148. [
  149. 'group' => -100,
  150. 'type' => 'file',
  151. 'weight' => 0.013,
  152. 'media' => 'all',
  153. 'preprocess' => TRUE,
  154. 'data' => $path . 'css_input_with_bom.css',
  155. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  156. 'basename' => 'css_input_with_bom.css',
  157. ],
  158. '.byte-order-mark-test{content:"☃";}' . "\n",
  159. ],
  160. [
  161. [
  162. 'group' => -100,
  163. 'type' => 'file',
  164. 'weight' => 0.013,
  165. 'media' => 'all',
  166. 'preprocess' => TRUE,
  167. 'data' => $path . 'css_input_with_charset.css',
  168. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  169. 'basename' => 'css_input_with_charset.css',
  170. ],
  171. '.charset-test{content:"€";}' . "\n",
  172. ],
  173. [
  174. [
  175. 'group' => -100,
  176. 'type' => 'file',
  177. 'weight' => 0.013,
  178. 'media' => 'all',
  179. 'preprocess' => TRUE,
  180. 'data' => $path . 'css_input_with_bom_and_charset.css',
  181. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  182. 'basename' => 'css_input_with_bom_and_charset.css',
  183. ],
  184. '.byte-order-mark-charset-test{content:"☃";}' . "\n",
  185. ],
  186. [
  187. [
  188. 'group' => -100,
  189. 'type' => 'file',
  190. 'weight' => 0.013,
  191. 'media' => 'all',
  192. 'preprocess' => TRUE,
  193. 'data' => $path . 'css_input_with_utf16_bom.css',
  194. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  195. 'basename' => 'css_input_with_utf16_bom.css',
  196. ],
  197. '.utf16-byte-order-mark-test{content:"☃";}' . "\n",
  198. ],
  199. [
  200. [
  201. 'group' => -100,
  202. 'type' => 'file',
  203. 'weight' => 0.013,
  204. 'media' => 'all',
  205. 'preprocess' => TRUE,
  206. 'data' => $path . 'quotes.css',
  207. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  208. 'basename' => 'quotes.css',
  209. ],
  210. file_get_contents($absolute_path . 'quotes.css.optimized.css'),
  211. ],
  212. ];
  213. }
  214. /**
  215. * Tests optimizing a CSS asset group containing 'type' => 'file'.
  216. *
  217. * @dataProvider providerTestOptimize
  218. */
  219. public function testOptimize($css_asset, $expected) {
  220. global $base_path;
  221. $original_base_path = $base_path;
  222. $base_path = '/';
  223. // \Drupal\Core\Asset\CssOptimizer::loadFile() relies on the current working
  224. // directory being the one that is used when index.php is the entry point.
  225. // Note: PHPUnit automatically restores the original working directory.
  226. chdir(realpath(__DIR__ . '/../../../../../../'));
  227. $this->assertEquals($expected, $this->optimizer->optimize($css_asset), 'Group of file CSS assets optimized correctly.');
  228. $base_path = $original_base_path;
  229. }
  230. /**
  231. * Tests a file CSS asset with preprocessing disabled.
  232. */
  233. public function testTypeFilePreprocessingDisabled() {
  234. $this->expectException('Exception');
  235. $this->expectExceptionMessage('Only file CSS assets with preprocessing enabled can be optimized.');
  236. $css_asset = [
  237. 'group' => -100,
  238. 'type' => 'file',
  239. 'weight' => 0.012,
  240. 'media' => 'all',
  241. // Preprocessing disabled.
  242. 'preprocess' => FALSE,
  243. 'data' => 'tests/Drupal/Tests/Core/Asset/foo.css',
  244. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  245. 'basename' => 'foo.css',
  246. ];
  247. $this->optimizer->optimize($css_asset);
  248. }
  249. /**
  250. * Tests a CSS asset with 'type' => 'external'.
  251. */
  252. public function testTypeExternal() {
  253. $this->expectException('Exception');
  254. $this->expectExceptionMessage('Only file CSS assets can be optimized.');
  255. $css_asset = [
  256. 'group' => -100,
  257. // Type external.
  258. 'type' => 'external',
  259. 'weight' => 0.012,
  260. 'media' => 'all',
  261. 'preprocess' => TRUE,
  262. 'data' => 'http://example.com/foo.js',
  263. 'browsers' => ['IE' => TRUE, '!IE' => TRUE],
  264. ];
  265. $this->optimizer->optimize($css_asset);
  266. }
  267. }
  268. /**
  269. * CssCollectionRenderer uses file_uri_scheme() which need to be mocked.
  270. */
  271. namespace Drupal\Core\Asset;
  272. if (!function_exists('Drupal\Core\Asset\file_uri_scheme')) {
  273. function file_uri_scheme($uri) {
  274. return FALSE;
  275. }
  276. }