CssOptimizerUnitTest.php 9.58 KB
Newer Older
1 2
<?php

3
namespace Drupal\Tests\Core\Asset;
4 5 6 7 8

use Drupal\Core\Asset\CssOptimizer;
use Drupal\Tests\UnitTestCase;

/**
9
 * Tests the CSS asset optimizer.
10 11 12 13 14
 *
 * @group Asset
 */
class CssOptimizerUnitTest extends UnitTestCase {

15 16 17 18 19
  /**
   * {@inheritdoc}
   */
  protected $backupGlobals = FALSE;

20 21 22 23 24 25 26
  /**
   * A CSS asset optimizer.
   *
   * @var \Drupal\Core\Asset\CssOptimizer object.
   */
  protected $optimizer;

27
  protected function setUp() {
28 29 30 31 32 33 34 35
    parent::setUp();

    $this->optimizer = new CssOptimizer();
  }

  /**
   * Provides data for the CSS asset optimizing test.
   */
36
  function providerTestOptimize() {
37
    $path = 'core/tests/Drupal/Tests/Core/Asset/css_test_files/';
38
    $absolute_path = dirname(__FILE__) . '/css_test_files/';
39 40 41
    return array(
      // File. Tests:
      // - Stripped comments and white-space.
42 43
      // - Retain white-space in selectors. (https://www.drupal.org/node/472820)
      // - Retain pseudo-selectors. (https://www.drupal.org/node/460448)
44
      array(
45 46 47 48 49 50 51 52 53 54
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.012,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_without_import.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_without_import.css',
        ),
55
        file_get_contents($absolute_path . 'css_input_without_import.css.optimized.css'),
56 57
      ),
      // File. Tests:
58
      // - Proper URLs in imported files. (https://www.drupal.org/node/265719)
59 60
      // - A background image with relative paths, which must be rewritten.
      // - The rewritten background image path must also be passed through
61
      //   file_create_url(). (https://www.drupal.org/node/1961340)
62
      // - Imported files that are external (protocol-relative URL or not)
63
      //   should not be expanded. (https://www.drupal.org/node/2014851)
64
      array(
65 66 67 68 69 70 71 72 73 74
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_with_import.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_with_import.css',
        ),
75
        str_replace('url(images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_input_with_import.css.optimized.css')),
76 77 78
      ),
      // File. Tests:
      // - Retain comment hacks.
79
      array(
80 81 82 83 84 85 86 87 88 89
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'comment_hacks.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'comment_hacks.css',
        ),
90
        file_get_contents($absolute_path . 'comment_hacks.css.optimized.css'),
91
      ),
92
      // File in subfolder. Tests:
93 94 95
      // - CSS import path is properly interpreted.
      //   (https://www.drupal.org/node/1198904)
      // - Don't adjust data URIs (https://www.drupal.org/node/2142441)
96
      array(
97
        array(
98 99 100
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
101 102
          'media' => 'all',
          'preprocess' => TRUE,
103
          'data' => $path . 'css_subfolder/css_input_with_import.css',
104
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
105
          'basename' => 'css_input_with_import.css',
106
        ),
107
        str_replace('url(../images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_subfolder/css_input_with_import.css.optimized.css')),
108
      ),
109 110 111
      // File. Tests:
      // - Any @charaset declaration at the beginning of a file should be
      //   removed without breaking subsequent CSS.
112
      array(
113
        array(
114 115
          'group' => -100,
          'type' => 'file',
116 117
          'weight' => 0.013,
          'media' => 'all',
118 119
          'preprocess' => TRUE,
          'data' => $path . 'charset_sameline.css',
120
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
121
          'basename' => 'charset_sameline.css',
122
        ),
123
        file_get_contents($absolute_path . 'charset.css.optimized.css'),
124
      ),
125
      array(
126 127 128 129 130 131
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
132
          'data' => $path . 'charset_newline.css',
133
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
134
          'basename' => 'charset_newline.css',
135
        ),
136
        file_get_contents($absolute_path . 'charset.css.optimized.css'),
137
      ),
138
      array(
139 140 141 142 143 144 145 146 147 148
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_with_bom.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_with_bom.css',
        ),
149
        '.byte-order-mark-test{content:"☃";}' . "\n",
150
      ),
151
      array(
152 153 154 155 156 157 158 159 160 161 162 163
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_with_charset.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_with_charset.css',
        ),
        '.charset-test{content:"€";}' . "\n",
      ),
164
      array(
165 166 167 168 169 170 171 172 173 174 175 176
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_with_bom_and_charset.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_with_bom_and_charset.css',
        ),
        '.byte-order-mark-charset-test{content:"☃";}' . "\n",
      ),
177
      array(
178 179 180 181 182 183 184 185 186 187 188 189
        array(
          'group' => -100,
          'type' => 'file',
          'weight' => 0.013,
          'media' => 'all',
          'preprocess' => TRUE,
          'data' => $path . 'css_input_with_utf16_bom.css',
          'browsers' => array('IE' => TRUE, '!IE' => TRUE),
          'basename' => 'css_input_with_utf16_bom.css',
        ),
        '.utf16-byte-order-mark-test{content:"☃";}' . "\n",
      ),
190 191 192 193 194 195
    );
  }

  /**
   * Tests optimizing a CSS asset group containing 'type' => 'file'.
   *
196
   * @dataProvider providerTestOptimize
197 198
   */
  function testOptimize($css_asset, $expected) {
199 200 201 202 203 204 205 206 207
    global $base_path;
    $original_base_path = $base_path;
    $base_path = '/';

    // \Drupal\Core\Asset\CssOptimizer::loadFile() relies on the current working
    // directory being the one that is used when index.php is the entry point.
    // Note: PHPUnit automatically restores the original working directory.
    chdir(realpath(__DIR__ . '/../../../../../../'));

208
    $this->assertEquals($expected, $this->optimizer->optimize($css_asset), 'Group of file CSS assets optimized correctly.');
209 210

    $base_path = $original_base_path;
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
  }

  /**
   * Tests a file CSS asset with preprocessing disabled.
   */
  function testTypeFilePreprocessingDisabled() {
    $this->setExpectedException('Exception', 'Only file CSS assets with preprocessing enabled can be optimized.');

    $css_asset = array(
      'group' => -100,
      'type' => 'file',
      'weight' => 0.012,
      'media' => 'all',
      // Preprocessing disabled.
      'preprocess' => FALSE,
      'data' => 'tests/Drupal/Tests/Core/Asset/foo.css',
      'browsers' => array('IE' => TRUE, '!IE' => TRUE),
      'basename' => 'foo.css',
    );
    $this->optimizer->optimize($css_asset);
  }

  /**
   * Tests a CSS asset with 'type' => 'external'.
   */
  function testTypeExternal() {
237
    $this->setExpectedException('Exception', 'Only file CSS assets can be optimized.');
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

    $css_asset = array(
      'group' => -100,
      // Type external.
      'type' => 'external',
      'weight' => 0.012,
      'media' => 'all',
      'preprocess' => TRUE,
      'data' => 'http://example.com/foo.js',
      'browsers' => array('IE' => TRUE, '!IE' => TRUE),
    );
    $this->optimizer->optimize($css_asset);
  }

}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

/**
 * Temporary mock for file_create_url(), until that is moved into
 * Component/Utility.
 */
if (!function_exists('Drupal\Tests\Core\Asset\file_create_url')) {
  function file_create_url($uri) {
    return 'file_create_url:' . $uri;
  }
}

/**
 * Temporary mock of file_url_transform_relative, until that is moved into
 * Component/Utility.
 */
if (!function_exists('Drupal\Tests\Core\Asset\file_url_transform_relative')) {
  function file_url_transform_relative($uri) {
    return 'file_url_transform_relative:' . $uri;
  }
}

/**
 * CssCollectionRenderer uses file_create_url() & file_url_transform_relative(),
 * which *are* available when using the Simpletest test runner, but not when
 * using the PHPUnit test runner; hence this hack.
 */
namespace Drupal\Core\Asset;

if (!function_exists('Drupal\Core\Asset\file_create_url')) {

  /**
   * Temporary mock for file_create_url(), until that is moved into
   * Component/Utility.
   */
  function file_create_url($uri) {
    return \Drupal\Tests\Core\Asset\file_create_url($uri);
  }

}
if (!function_exists('Drupal\Core\Asset\file_url_transform_relative')) {

  /**
   * Temporary mock of file_url_transform_relative, until that is moved into
   * Component/Utility.
   */
  function file_url_transform_relative($uri) {
    return \Drupal\Tests\Core\Asset\file_url_transform_relative($uri);
  }

}
if (!function_exists('Drupal\Core\Asset\file_uri_scheme')) {

  function file_uri_scheme($uri) {
    return FALSE;
  }

309
}