CascadingStylesheetsTest.php 8.89 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<?php

/**
 * @file
 * Definition of Drupal\system\Tests\Common\CascadingStylesheetsTest.
 */

namespace Drupal\system\Tests\Common;

use Drupal\simpletest\WebTestBase;

/**
 * Tests the Drupal CSS system.
 */
class CascadingStylesheetsTest extends WebTestBase {
16 17 18 19 20 21 22 23

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = array('language', 'common_test');

24 25 26 27 28 29 30 31 32
  public static function getInfo() {
    return array(
      'name' => 'Cascading stylesheets',
      'description' => 'Tests adding various cascading stylesheets to the page.',
      'group' => 'Common',
    );
  }

  function setUp() {
33
    parent::setUp();
34 35 36 37 38
    // Reset drupal_add_css() before each test.
    drupal_static_reset('drupal_add_css');
  }

  /**
39
   * Checks that default stylesheets are empty.
40 41
   */
  function testDefault() {
42
    $this->assertEqual(array(), drupal_add_css(), 'Default CSS is empty.');
43 44 45
  }

  /**
46
   * Tests that stylesheets in module .info files are loaded.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
   */
  function testModuleInfo() {
    $this->drupalGet('');

    // Verify common_test.css in a STYLE media="all" tag.
    $elements = $this->xpath('//style[@media=:media and contains(text(), :filename)]', array(
      ':media' => 'all',
      ':filename' => 'tests/modules/common_test/common_test.css',
    ));
    $this->assertTrue(count($elements), "Stylesheet with media 'all' in module .info file found.");

    // Verify common_test.print.css in a STYLE media="print" tag.
    $elements = $this->xpath('//style[@media=:media and contains(text(), :filename)]', array(
      ':media' => 'print',
      ':filename' => 'tests/modules/common_test/common_test.print.css',
    ));
    $this->assertTrue(count($elements), "Stylesheet with media 'print' in module .info file found.");
  }

  /**
   * Tests adding a file stylesheet.
   */
  function testAddFile() {
    $path = drupal_get_path('module', 'simpletest') . '/simpletest.css';
    $css = drupal_add_css($path);
72
    $this->assertEqual($css[$path]['data'], $path, 'Adding a CSS file caches it properly.');
73 74 75 76 77 78 79 80
  }

  /**
   * Tests adding an external stylesheet.
   */
  function testAddExternal() {
    $path = 'http://example.com/style.css';
    $css = drupal_add_css($path, 'external');
81
    $this->assertEqual($css[$path]['type'], 'external', 'Adding an external CSS file caches it properly.');
82 83 84 85 86 87 88
  }

  /**
   * Makes sure that reseting the CSS empties the cache.
   */
  function testReset() {
    drupal_static_reset('drupal_add_css');
89
    $this->assertEqual(array(), drupal_add_css(), 'Resetting the CSS empties the cache.');
90 91 92 93 94 95 96 97 98
  }

  /**
   * Tests rendering the stylesheets.
   */
  function testRenderFile() {
    $css = drupal_get_path('module', 'simpletest') . '/simpletest.css';
    drupal_add_css($css);
    $styles = drupal_get_css();
99
    $this->assertTrue(strpos($styles, $css) > 0, 'Rendered CSS includes the added stylesheet.');
100 101 102
    // Verify that newlines are properly added inside style tags.
    $query_string = variable_get('css_js_query_string', '0');
    $css_processed = "<style media=\"all\">\n@import url(\"" . check_plain(file_create_url($css)) . "?" . $query_string ."\");\n</style>";
103
    $this->assertEqual(trim($styles), $css_processed, 'Rendered CSS includes newlines inside style tags for JavaScript use.');
104 105 106 107 108 109 110 111 112 113 114
  }

  /**
   * Tests rendering an external stylesheet.
   */
  function testRenderExternal() {
    $css = 'http://example.com/style.css';
    drupal_add_css($css, 'external');
    $styles = drupal_get_css();
    // Stylesheet URL may be the href of a LINK tag or in an @import statement
    // of a STYLE tag.
115
    $this->assertTrue(strpos($styles, 'href="' . $css) > 0 || strpos($styles, '@import url("' . $css . '")') > 0, 'Rendering an external CSS file.');
116 117 118 119 120 121 122 123 124 125
  }

  /**
   * Tests rendering inline stylesheets with preprocessing on.
   */
  function testRenderInlinePreprocess() {
    $css = 'body { padding: 0px; }';
    $css_preprocessed = '<style media="all">' . "\n<!--/*--><![CDATA[/*><!--*/\n" . drupal_load_stylesheet_content($css, TRUE) . "\n/*]]>*/-->\n" . '</style>';
    drupal_add_css($css, array('type' => 'inline'));
    $styles = drupal_get_css();
126
    $this->assertEqual(trim($styles), $css_preprocessed, 'Rendering preprocessed inline CSS adds it to the page.');
127 128 129 130 131 132 133 134 135
  }

  /**
   * Tests rendering inline stylesheets with preprocessing off.
   */
  function testRenderInlineNoPreprocess() {
    $css = 'body { padding: 0px; }';
    drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
    $styles = drupal_get_css();
136
    $this->assertTrue(strpos($styles, $css) > 0, 'Rendering non-preprocessed inline CSS adds it to the page.');
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  }

  /**
   * Tests rendering inline stylesheets through a full page request.
   */
  function testRenderInlineFullPage() {
    module_enable(array('php'));

    $css = 'body { font-size: 254px; }';
    // Inline CSS is minified unless 'preprocess' => FALSE is passed as a
    // drupal_add_css() option.
    $expected = 'body{font-size:254px;}';

    // Create Basic page node type.
    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));

    // Create a node, using the PHP filter that tests drupal_add_css().
    $php_format_id = 'php_code';
    $settings = array(
      'type' => 'page',
      'body' => array(
        LANGUAGE_NOT_SPECIFIED => array(
          array(
            'value' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>",
            'format' => $php_format_id,
          ),
        ),
      ),
      'promote' => 1,
    );
    $node = $this->drupalCreateNode($settings);

    // Fetch the page.
    $this->drupalGet('node/' . $node->nid);
171
    $this->assertRaw($expected, 'Inline stylesheets appear in the full page rendering.');
172 173 174
  }

  /**
175
   * Tests CSS ordering.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
   */
  function testRenderOrder() {
    // A module CSS file.
    drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
    // A few system CSS files, ordered in a strange way.
    $system_path = drupal_get_path('module', 'system');
    drupal_add_css($system_path . '/system.base.css', array('group' => CSS_SYSTEM, 'weight' => -10));
    drupal_add_css($system_path . '/system.theme.css', array('group' => CSS_SYSTEM));

    $expected = array(
      $system_path . '/system.base.css',
      $system_path . '/system.theme.css',
      drupal_get_path('module', 'simpletest') . '/simpletest.css',
    );


    $styles = drupal_get_css();
    // Stylesheet URL may be the href of a LINK tag or in an @import statement
    // of a STYLE tag.
    if (preg_match_all('/(href="|url\(")' . preg_quote($GLOBALS['base_url'] . '/', '/') . '([^?]+)\?/', $styles, $matches)) {
      $result = $matches[2];
    }
    else {
      $result = array();
    }

202
    $this->assertIdentical($result, $expected, 'The CSS files are in the expected order.');
203 204 205
  }

  /**
206
   * Tests CSS override.
207 208 209 210 211 212 213 214 215
   */
  function testRenderOverride() {
    $system = drupal_get_path('module', 'system');

    drupal_add_css($system . '/system.base.css');
    drupal_add_css($system . '/tests/system.base.css');

    // The dummy stylesheet should be the only one included.
    $styles = drupal_get_css();
216 217
    $this->assert(strpos($styles, $system . '/tests/system.base.css') !== FALSE, 'The overriding CSS file is output.');
    $this->assert(strpos($styles, $system . '/system.base.css') === FALSE, 'The overridden CSS file is not output.');
218 219 220 221 222 223

    drupal_add_css($system . '/tests/system.base.css');
    drupal_add_css($system . '/system.base.css');

    // The standard stylesheet should be the only one included.
    $styles = drupal_get_css();
224 225
    $this->assert(strpos($styles, $system . '/system.base.css') !== FALSE, 'The overriding CSS file is output.');
    $this->assert(strpos($styles, $system . '/tests/system.base.css') === FALSE, 'The overridden CSS file is not output.');
226 227 228 229 230 231 232
  }

  /**
   * Tests Locale module's CSS Alter to include RTL overrides.
   */
  function testAlter() {
    // Switch the language to a right to left language and add system.base.css.
233
    $language_interface = language(LANGUAGE_TYPE_INTERFACE);
234 235 236 237 238 239
    $language_interface->direction = LANGUAGE_RTL;
    $path = drupal_get_path('module', 'system');
    drupal_add_css($path . '/system.base.css');

    // Check to see if system.base-rtl.css was also added.
    $styles = drupal_get_css();
240
    $this->assert(strpos($styles, $path . '/system.base-rtl.css') !== FALSE, 'CSS is alterable as right to left overrides are added.');
241 242 243 244 245 246

    // Change the language back to left to right.
    $language_interface->direction = LANGUAGE_LTR;
  }

  /**
247
   * Tests that CSS query string remains intact when added to file.
248 249 250 251
   */
  function testAddCssFileWithQueryString() {
    $this->drupalGet('common-test/query-string');
    $query_string = variable_get('css_js_query_string', '0');
252 253
    $this->assertRaw(drupal_get_path('module', 'node') . '/node.admin.css?' . $query_string, 'Query string was appended correctly to css.');
    $this->assertRaw(drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&amp;arg2=value2', 'Query string not escaped on a URI.');
254 255
  }
}