ThemeTest.php 13.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
<?php

/**
 * @file
 * Definition of Drupal\system\Tests\System\ThemeTest.
 */

namespace Drupal\system\Tests\System;

10
use Drupal\Core\StreamWrapper\PublicStream;
11 12 13
use Drupal\simpletest\WebTestBase;

/**
14 15 16 17
 * Tests the theme interface functionality by enabling and switching themes, and
 * using an administration theme.
 *
 * @group system
18 19
 */
class ThemeTest extends WebTestBase {
20 21 22 23 24 25

  /**
   * Modules to enable.
   *
   * @var array
   */
26
  public static $modules = array('node', 'block', 'file');
27

28
  protected function setUp() {
29
    parent::setUp();
30 31 32 33 34 35 36 37 38 39 40 41

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

    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer themes', 'bypass node access', 'administer blocks'));
    $this->drupalLogin($this->admin_user);
    $this->node = $this->drupalCreateNode();
  }

  /**
   * Test the theme settings form.
   */
  function testThemeSettings() {
42 43
    // Ensure invalid theme settings form URLs return a proper 404.
    $this->drupalGet('admin/appearance/settings/bartik');
44
    $this->assertResponse(404, 'The theme settings form URL for a uninstalled theme could not be found.');
45
    $this->drupalGet('admin/appearance/settings/' . $this->randomMachineName());
46 47
    $this->assertResponse(404, 'The theme settings form URL for a non-existent theme could not be found.');

48 49
    // Specify a filesystem path to be used for the logo.
    $file = current($this->drupalGetTestFiles('image'));
50
    $file_relative = strtr($file->uri, array('public:/' => PublicStream::basePath()));
51
    $default_theme_path = 'core/themes/classy';
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

    $supported_paths = array(
      // Raw stream wrapper URI.
      $file->uri => array(
        'form' => file_uri_target($file->uri),
        'src' => file_create_url($file->uri),
      ),
      // Relative path within the public filesystem.
      file_uri_target($file->uri) => array(
        'form' => file_uri_target($file->uri),
        'src' => file_create_url($file->uri),
      ),
      // Relative path to a public file.
      $file_relative => array(
        'form' => $file_relative,
        'src' => file_create_url($file->uri),
      ),
      // Relative path to an arbitrary file.
      'core/misc/druplicon.png' => array(
        'form' => 'core/misc/druplicon.png',
        'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png',
      ),
      // Relative path to a file in a theme.
      $default_theme_path . '/logo.png' => array(
        'form' => $default_theme_path . '/logo.png',
        'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.png',
      ),
    );
    foreach ($supported_paths as $input => $expected) {
      $edit = array(
        'default_logo' => FALSE,
        'logo_path' => $input,
      );
85
      $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
      $this->assertNoText('The custom logo path is invalid.');
      $this->assertFieldByName('logo_path', $expected['form']);

      // Verify logo path examples.
      $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(
        ':item' => 'form-item-logo-path',
        ':description' => 'description',
      ));
      // Expected default values (if all else fails).
      $implicit_public_file = 'logo.png';
      $explicit_file = 'public://logo.png';
      $local_file = $default_theme_path . '/logo.png';
      // Adjust for fully qualified stream wrapper URI in public filesystem.
      if (file_uri_scheme($input) == 'public') {
        $implicit_public_file = file_uri_target($input);
        $explicit_file = $input;
102
        $local_file = strtr($input, array('public:/' => PublicStream::basePath()));
103 104 105 106 107 108 109 110 111
      }
      // Adjust for fully qualified stream wrapper URI elsewhere.
      elseif (file_uri_scheme($input) !== FALSE) {
        $explicit_file = $input;
      }
      // Adjust for relative path within public filesystem.
      elseif ($input == file_uri_target($file->uri)) {
        $implicit_public_file = $input;
        $explicit_file = 'public://' . $input;
112
        $local_file = PublicStream::basePath() . '/' . $input;
113 114 115 116 117 118 119
      }
      $this->assertEqual((string) $elements[0], $implicit_public_file);
      $this->assertEqual((string) $elements[1], $explicit_file);
      $this->assertEqual((string) $elements[2], $local_file);

      // Verify the actual 'src' attribute of the logo being output.
      $this->drupalGet('');
120 121 122 123
      $elements = $this->xpath('//header/a[@rel=:rel]/img', array(
          ':rel' => 'home',
        )
      );
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
      $this->assertEqual((string) $elements[0]['src'], $expected['src']);
    }
    $unsupported_paths = array(
      // Stream wrapper URI to non-existing file.
      'public://whatever.png',
      'private://whatever.png',
      'temporary://whatever.png',
      // Bogus stream wrapper URIs.
      'public:/whatever.png',
      '://whatever.png',
      ':whatever.png',
      'public://',
      // Relative path within the public filesystem to non-existing file.
      'whatever.png',
      // Relative path to non-existing file in public filesystem.
139
      PublicStream::basePath() . '/whatever.png',
140
      // Semi-absolute path to non-existing file in public filesystem.
141
      '/' . PublicStream::basePath() . '/whatever.png',
142 143 144 145 146 147 148 149 150 151 152 153 154
      // Relative path to arbitrary non-existing file.
      'core/misc/whatever.png',
      // Semi-absolute path to arbitrary non-existing file.
      '/core/misc/whatever.png',
      // Absolute paths to any local file (even if it exists).
      drupal_realpath($file->uri),
    );
    $this->drupalGet('admin/appearance/settings');
    foreach ($unsupported_paths as $path) {
      $edit = array(
        'default_logo' => FALSE,
        'logo_path' => $path,
      );
155
      $this->drupalPostForm(NULL, $edit, t('Save configuration'));
156 157 158 159 160 161 162 163 164
      $this->assertText('The custom logo path is invalid.');
    }

    // Upload a file to use for the logo.
    $edit = array(
      'default_logo' => FALSE,
      'logo_path' => '',
      'files[logo_upload]' => drupal_realpath($file->uri),
    );
165
    $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
166 167 168 169 170

    $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
    $uploaded_filename = 'public://' . $fields[0]['value'];

    $this->drupalGet('');
171 172 173 174
    $elements = $this->xpath('//header/a[@rel=:rel]/img', array(
        ':rel' => 'home',
      )
    );
175 176 177 178 179 180 181
    $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
  }

  /**
   * Test the administration theme functionality.
   */
  function testAdministrationTheme() {
182
    $this->container->get('theme_handler')->install(array('seven'));
183

184
    // Install an administration theme and show it on the node admin pages.
185 186
    $edit = array(
      'admin_theme' => 'seven',
187
      'use_admin_theme' => TRUE,
188
    );
189
    $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
190 191

    $this->drupalGet('admin/config');
192
    $this->assertRaw('core/themes/seven', 'Administration theme used on an administration page.');
193

194
    $this->drupalGet('node/' . $this->node->id());
195
    $this->assertRaw('core/themes/classy', 'Site default theme used on node page.');
196 197

    $this->drupalGet('node/add');
198
    $this->assertRaw('core/themes/seven', 'Administration theme used on the add content page.');
199

200
    $this->drupalGet('node/' . $this->node->id() . '/edit');
201
    $this->assertRaw('core/themes/seven', 'Administration theme used on the edit content page.');
202 203 204

    // Disable the admin theme on the node admin pages.
    $edit = array(
205
      'use_admin_theme' => FALSE,
206
    );
207
    $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
208 209

    $this->drupalGet('admin/config');
210
    $this->assertRaw('core/themes/seven', 'Administration theme used on an administration page.');
211

212 213 214 215 216 217 218 219
    // Ensure that the admin theme is also visible on the 403 page.
    $normal_user = $this->drupalCreateUser(['view the administration theme']);
    $this->drupalLogin($normal_user);
    $this->drupalGet('admin/config');
    $this->assertResponse(403);
    $this->assertRaw('core/themes/seven', 'Administration theme used on an administration page.');
    $this->drupalLogin($this->admin_user);

220
    $this->drupalGet('node/add');
221
    $this->assertRaw('core/themes/classy', 'Site default theme used on the add content page.');
222 223 224 225

    // Reset to the default theme settings.
    $edit = array(
      'admin_theme' => '0',
226
      'use_admin_theme' => FALSE,
227
    );
228
    $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
229 230

    $this->drupalGet('admin');
231
    $this->assertRaw('core/themes/classy', 'Site default theme used on administration page.');
232 233

    $this->drupalGet('node/add');
234
    $this->assertRaw('core/themes/classy', 'Site default theme used on the add content page.');
235 236 237 238 239 240
  }

  /**
   * Test switching the default theme.
   */
  function testSwitchDefaultTheme() {
241 242
    // Install Bartik and set it as the default theme.
    \Drupal::service('theme_handler')->install(array('bartik'));
243
    $this->drupalGet('admin/appearance');
244
    $this->clickLink(t('Set as default'));
245
    $this->assertEqual($this->config('system.theme')->get('default'), 'bartik');
246 247 248

    // Test the default theme on the secondary links (blocks admin page).
    $this->drupalGet('admin/structure/block');
249
    $this->assertText('Bartik(' . t('active tab') . ')', 'Default local task on blocks admin page is the default theme.');
250 251
    // Switch back to Stark and test again to test that the menu cache is cleared.
    $this->drupalGet('admin/appearance');
252 253
    // Classy is the first 'Set as default' link.
    $this->clickLink(t('Set as default'), 0);
254
    $this->drupalGet('admin/structure/block');
255
    $this->assertText('Classy(' . t('active tab') . ')', 'Default local task on blocks admin page has changed.');
256
  }
257 258

  /**
259
   * Test themes can't be installed when the base theme or engine is missing.
260 261
   */
  function testInvalidTheme() {
262
    // theme_page_test_system_info_alter() un-hides all hidden themes.
263
    $this->container->get('module_installer')->install(array('theme_page_test'));
264 265
    // Clear the system_list() and theme listing cache to pick up the change.
    $this->container->get('theme_handler')->reset();
266
    $this->drupalGet('admin/appearance');
267 268
    $this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')));
    $this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')));
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 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

  /**
   * Test uninstalling of themes works.
   */
  function testUninstallingThemes() {
    // Install Bartik and set it as the default theme.
    \Drupal::service('theme_handler')->install(array('bartik'));
    // Set up seven as the admin theme.
    \Drupal::service('theme_handler')->install(array('seven'));
    $edit = array(
      'admin_theme' => 'seven',
      'use_admin_theme' => TRUE,
    );
    $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
    $this->drupalGet('admin/appearance');
    $this->clickLink(t('Set as default'));

    // Check that seven cannot be uninstalled as it is the admin theme.
    $this->assertNoRaw('Uninstall Seven theme', 'A link to uninstall the Seven theme does not appear on the theme settings page.');
    // Check that bartik cannot be uninstalled as it is the default theme.
    $this->assertNoRaw('Uninstall Bartik theme', 'A link to uninstall the Bartik theme does not appear on the theme settings page.');
    // Check that the classy theme cannot be uninstalled as it is a base theme
    // of seven and bartik.
    $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');

    // Install Stark and set it as the default theme.
    \Drupal::service('theme_handler')->install(array('stark'));

    $edit = array(
      'admin_theme' => 'stark',
      'use_admin_theme' => TRUE,
    );
    $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));

    // Check that seven can be uninstalled now.
    $this->assertRaw('Uninstall Seven theme', 'A link to uninstall the Seven theme does appear on the theme settings page.');
    // Check that the classy theme still cannot be uninstalled as it is a
    // base theme of bartik.
    $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');

    // Change the default theme to stark, stark is third in the list.
    $this->clickLink(t('Set as default'), 2);

    // Check that bartik can be uninstalled now.
    $this->assertRaw('Uninstall Bartik theme', 'A link to uninstall the Bartik theme does appear on the theme settings page.');

    // Check that the classy theme still can't be uninstalled as neither of it's
    // base themes have been.
    $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');

    // Uninstall each of the three themes starting with Bartik.
    $this->clickLink(t('Uninstall'));
    $this->assertRaw('The <em class="placeholder">Bartik</em> theme has been uninstalled');
    // Seven is the second in the list.
    $this->clickLink(t('Uninstall'));
    $this->assertRaw('The <em class="placeholder">Seven</em> theme has been uninstalled');
    // Now uninstall classy.
    $this->clickLink(t('Uninstall'));
    $this->assertRaw('The <em class="placeholder">Classy</em> theme has been uninstalled');
  }
330
}