block.test 22.3 KB
Newer Older
1 2 3
<?php
// $Id$

4 5 6 7 8
/**
 * @file
 * Tests for the block module
 */

9
class BlockTestCase extends DrupalWebTestCase {
10 11
  protected $regions;

12
  public static function getInfo() {
13
    return array(
14 15 16
      'name' => 'Block functionality',
      'description' => 'Add, edit and delete custom block. Configure and move a module-defined block.',
      'group' => 'Block',
17 18 19 20 21 22
    );
  }

  function setUp() {
    parent::setUp();

23 24 25
    // Create and log in an administrative user having access to the Full HTML
    // text format.
    $full_html_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject();
26 27
    $admin_user = $this->drupalCreateUser(array(
      'administer blocks',
28
      filter_permission_name($full_html_format),
29 30
      'access administration pages',
    ));
31
    $this->drupalLogin($admin_user);
32

33
    // Define the existing regions
34
    $this->regions = array();
35 36 37 38
    $this->regions[] = array('name' => 'header', 'class' => 'region region-header clearfix');
    $this->regions[] = array('name' => 'sidebar_first');
    $this->regions[] = array('name' => 'content');
    $this->regions[] = array('name' => 'sidebar_second');
39
    $this->regions[] = array('name' => 'footer');
40 41 42
  }

  /**
43
   * Test creating custom block, moving it to a specific region and then deleting it.
44
   */
45
  function testCustomBlock() {
46 47 48 49 50 51
    // Confirm that the add block link appears on block overview pages.
    $this->drupalGet('admin/structure/block');
    $this->assertRaw(l('Add block', 'admin/structure/block/add'), t('Add block link is present on block overview page for default theme.'));
    $this->drupalGet('admin/structure/block/list/seven');
    $this->assertRaw(l('Add block', 'admin/structure/block/list/seven/add'), t('Add block link is present on block overview page for non-default theme.'));

52 53 54 55 56 57 58 59
    // Confirm that hidden regions are not shown as options for block placement
    // when adding a new block.
    theme_enable(array('stark'));
    $themes = list_themes();
    $this->drupalGet('admin/structure/block/add');
    foreach ($themes as $key => $theme) {
      if ($theme->status) {
        foreach ($theme->info['regions_hidden'] as $hidden_region) {
60
          $elements = $this->xpath('//select[@id=:id]//option[@value=:value]', array(':id' => 'edit-regions-' . $key, ':value' => $hidden_region));
61 62 63 64 65
          $this->assertFalse(isset($elements[0]), t('The hidden region @region is not available for @theme.', array('@region' => $hidden_region, '@theme' => $key)));
        }
      }
    }

66 67 68 69
    // Add a new custom block by filling out the input form on the admin/structure/block/add page.
    $custom_block = array();
    $custom_block['info'] = $this->randomName(8);
    $custom_block['title'] = $this->randomName(8);
70
    $custom_block['body[value]'] = $this->randomName(32);
71
    $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
72

73 74 75
    // Confirm that the custom block has been created, and then query the created bid.
    $this->assertText(t('The block has been created.'), t('Custom block successfully created.'));
    $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
76

77 78
    // Check to see if the custom block was created by checking that it's in the database..
    $this->assertNotNull($bid, t('Custom block found in database'));
79

80
    // Check if the block can be moved to all availble regions.
81 82
    $custom_block['module'] = 'block';
    $custom_block['delta'] = $bid;
83
    foreach ($this->regions as $region) {
84
      $this->moveBlockToRegion($custom_block, $region);
85
    }
86

87
    // Verify presence of configure and delete links for custom block.
88
    $this->drupalGet('admin/structure/block');
89 90 91
    $this->assertRaw(l(t('configure'), 'admin/structure/block/manage/block/' . $bid . '/configure'), t('Custom block configure link found.'));
    $this->assertRaw(l(t('delete'), 'admin/structure/block/manage/block/' . $bid . '/delete'), t('Custom block delete link found.'));

92 93 94 95 96
    // Set visibility only for authenticated users, to verify delete functionality.
    $edit = array();
    $edit['roles[2]'] = TRUE;
    $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', $edit, t('Save block'));

97
    // Delete the created custom block & verify that it's been deleted and no longer appearing on the page.
98
    $this->clickLink(t('delete'));
99
    $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
100 101
    $this->assertRaw(t('The block %title has been removed.', array('%title' => $custom_block['info'])), t('Custom block successfully deleted.'));
    $this->assertNoText(t($custom_block['title']), t('Custom block no longer appears on page.'));
102 103
    $count = db_query("SELECT 1 FROM {block_role} WHERE module = :module AND delta = :delta", array(':module' => $custom_block['module'], ':delta' => $custom_block['delta']))->fetchField();
    $this->assertFalse($count, t('Table block_role being cleaned.'));
104 105
  }

106
  /**
107
   * Test creating custom block using Full HTML.
108
   */
109 110 111 112 113
  function testCustomBlockFormat() {
    // Add a new custom block by filling out the input form on the admin/structure/block/add page.
    $custom_block = array();
    $custom_block['info'] = $this->randomName(8);
    $custom_block['title'] = $this->randomName(8);
114
    $custom_block['body[value]'] = '<h1>Full HTML</h1>';
115
    $full_html_format_id = db_query_range('SELECT format FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchField();
116
    $custom_block['body[format]'] = $full_html_format_id;
117 118 119 120
    $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));

    // Set the created custom block to a specific region.
    $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
121
    $edit = array();
122
    $edit['block_' . $bid . '[region]'] = $this->regions[1]['name'];
123
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
124

125
    // Confirm that the custom block is being displayed using configured text format.
126
    $this->drupalGet('node');
127
    $this->assertRaw('<h1>Full HTML</h1>', t('Custom block successfully being displayed using Full HTML.'));
128 129 130 131 132

    // Confirm that a user without access to Full HTML can not see the body field,
    // but can still submit the form without errors.
    $block_admin = $this->drupalCreateUser(array('administer blocks'));
    $this->drupalLogin($block_admin);
133
    $this->drupalGet('admin/structure/block/manage/block/' . $bid . '/configure');
134
    $this->assertNoText(t('Block body'));
135
    $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', array(), t('Save block'));
136
    $this->assertNoText(t('Ensure that each block description is unique.'));
137

138
    // Confirm that the custom block is still being displayed using configured text format.
139
    $this->drupalGet('node');
140
    $this->assertRaw('<h1>Full HTML</h1>', t('Custom block successfully being displayed using Full HTML.'));
141 142
  }

143 144 145 146 147
  /**
   * Test block visibility.
   */
  function testBlockVisibility() {
    $block = array();
148

149 150
    // Create a random title for the block
    $title = $this->randomName(8);
151

152
    // Create the custom block
153 154 155
    $custom_block = array();
    $custom_block['info'] = $this->randomName(8);
    $custom_block['title'] = $title;
156
    $custom_block['body[value]'] = $this->randomName(32);
157
    $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
158

159
    $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
160 161 162
    $block['module'] = 'block';
    $block['delta'] = $bid;
    $block['title'] = $title;
163 164 165 166 167 168

    // Set the block to be hidden on any user path, and to be shown only to
    // authenticated users.
    $edit = array();
    $edit['pages'] = 'user*';
    $edit['roles[2]'] = TRUE;
169
    $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
170

171
    // Move block to the first sidebar.
172 173 174
    $this->moveBlockToRegion($block, $this->regions[1]);

    $this->drupalGet('');
175
    $this->assertText($title, t('Block was displayed on the front page.'));
176

177 178
    $this->drupalGet('user');
    $this->assertNoText($title, t('Block was not displayed according to block visibility rules.'));
179 180 181 182

    // Confirm that the block is not displayed to anonymous users.
    $this->drupalLogout();
    $this->drupalGet('');
183
    $this->assertNoText($title, t('Block was not displayed to anonymous users.'));
184 185
  }

186 187 188 189 190 191
  /**
   * Test configuring and moving a module-define block to specific regions.
   */
  function testBlock() {
    // Select the Navigation block to be configured and moved.
    $block = array();
192 193
    $block['module'] = 'system';
    $block['delta'] = 'management';
194 195 196
    $block['title'] = $this->randomName(8);

    // Set block title to confirm that interface works and override any custom titles.
197
    $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => $block['title']), t('Save block'));
198
    $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
199 200 201 202
    $bid = db_query("SELECT bid FROM {block} WHERE module = :module AND delta = :delta", array(
      ':module' => $block['module'],
      ':delta' => $block['delta'],
    ))->fetchField();
203 204 205 206

    // Check to see if the block was created by checking that it's in the database.
    $this->assertNotNull($bid, t('Block found in database'));

207 208 209 210
    // Check if the block can be moved to all availble regions.
    foreach ($this->regions as $region) {
      $this->moveBlockToRegion($block, $region);
    }
211 212 213

    // Set the block to the disabled region.
    $edit = array();
214
    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = '-1';
215
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
216 217 218 219 220

    // Confirm that the block was moved to the proper region.
    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
    $this->assertNoText(t($block['title']), t('Block no longer appears on page.'));

221
    // Confirm that the regions xpath is not availble
222
    $xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-block-' . $bid));
223
    $this->assertNoFieldByXPath($xpath, FALSE, t('Custom block found in no regions.'));
224

225 226
    // For convenience of developers, put the navigation block back.
    $edit = array();
227
    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = $this->regions[1]['name'];
228
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
229
    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to first sidebar region.'));
230

231
    $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => 'Navigation'), t('Save block'));
232 233
    $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
  }
234

235 236
  function moveBlockToRegion($block, $region) {
    // If an id for an region hasn't been specified, we assume it's the same as the name.
237 238
    if (!(isset($region['class']))) {
      $region['class'] = 'region region-' . str_replace('_', '-', $region['name']);
239 240 241 242 243
    }

    // Set the created block to a specific region.
    $edit = array();
    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = $region['name'];
244
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
245 246

    // Confirm that the block was moved to the proper region.
247
    $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array( '%region_name' => $region['name'])));
248 249

    // Confirm that the block is being displayed.
250
    $this->drupalGet('node');
251 252
    $this->assertText(t($block['title']), t('Block successfully being displayed on the page.'));

253
    // Confirm that the custom block was found at the proper region.
254 255 256 257
    $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
      ':region-class' => $region['class'],
      ':block-id' => 'block-' . $block['module'] . '-' . $block['delta'],
    ));
258
    $this->assertFieldByXPath($xpath, FALSE, t('Custom block found in %region_name region.', array('%region_name' => $region['name'])));
259
  }
260 261 262
}

class NonDefaultBlockAdmin extends DrupalWebTestCase {
263
  public static function getInfo() {
264
    return array(
265 266 267
      'name' => 'Non default theme admin',
      'description' => 'Check the administer page for non default theme.',
      'group' => 'Block',
268 269 270 271 272 273
    );
  }

  /**
   * Test non-default theme admin.
   */
274
  function testNonDefaultBlockAdmin() {
275
    $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
276
    $this->drupalLogin($admin_user);
277
    theme_enable(array('stark'));
278
    $this->drupalGet('admin/structure/block/list/stark');
279
  }
280
}
281

282 283 284 285 286 287
/**
 * Test blocks correctly initialized when picking a new default theme.
 */
class NewDefaultThemeBlocks extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
288 289 290
      'name' => 'New default theme blocks',
      'description' => 'Checks that the new default theme gets blocks.',
      'group' => 'Block',
291 292
    );
  }
293

294 295 296 297 298
  /**
   * Check the enabled Garland blocks are correctly copied over.
   */
  function testNewDefaultThemeBlocks() {
    // Create administrative user.
299
    $admin_user = $this->drupalCreateUser(array('administer themes'));
300 301 302
    $this->drupalLogin($admin_user);

    // Ensure no other theme's blocks are in the block table yet.
303 304
    $count = db_query_range("SELECT 1 FROM {block} WHERE theme NOT IN ('garland', 'seven')", 0, 1)->fetchField();
    $this->assertFalse($count, t('Only Garland and Seven have blocks.'));
305 306 307

    // Populate list of all blocks for matching against new theme.
    $blocks = array();
308
    $result = db_query("SELECT * FROM {block} WHERE theme = 'garland'");
309 310 311 312 313 314 315 316
    foreach ($result as $block) {
      // $block->theme and $block->bid will not match, so remove them.
      unset($block->theme, $block->bid);
      $blocks[$block->module][$block->delta] = $block;
    }

    // Turn on the Stark theme and ensure that it contains all of the blocks
    // that Garland did.
317 318
    theme_enable(array('stark'));
    variable_set('theme_default', 'stark');
319 320 321
    $result = db_query("SELECT * FROM {block} WHERE theme='stark'");
    foreach ($result as $block) {
      unset($block->theme, $block->bid);
322
      $this->assertEqual($blocks[$block->module][$block->delta], $block, t('Block %name matched', array('%name' => $block->module . '-' . $block->delta)));
323 324 325 326
    }
  }
}

327 328 329 330 331 332
/**
 * Test the block system with admin themes.
 */
class BlockAdminThemeTestCase extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
333 334 335
      'name' => 'Admin theme block admin accessibility',
      'description' => "Check whether the block administer page for a disabled theme acccessible if and only if it's the admin theme.",
      'group' => 'Block',
336 337
    );
  }
338

339 340 341 342 343
  /**
   * Check for the accessibility of the admin theme on the  block admin page.
   */
  function testAdminTheme() {
    // Create administrative user.
344
    $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
345 346 347
    $this->drupalLogin($admin_user);

    // Ensure that access to block admin page is denied when theme is disabled.
348
    $this->drupalGet('admin/structure/block/list/stark');
349 350 351 352
    $this->assertResponse(403, t('The block admin page for a disabled theme can not be accessed'));

    // Enable admin theme and confirm that tab is accessible.
    $edit['admin_theme'] = 'stark';
353
    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
354
    $this->drupalGet('admin/structure/block/list/stark');
355 356 357
    $this->assertResponse(200, t('The block admin page for the admin theme can be accessed'));
  }
}
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547

/**
 * Test block caching.
 */
class BlockCacheTestCase extends DrupalWebTestCase {
  protected $admin_user;
  protected $normal_user;
  protected $normal_user_alt;

  public static function getInfo() {
    return array(
      'name' => 'Block caching',
      'description' => 'Test block caching.',
      'group' => 'Block',
    );
  }

  function setUp() {
    parent::setUp('block_test');

    // Create an admin user, log in and enable test blocks.
    $this->admin_user = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
    $this->drupalLogin($this->admin_user);

    // Create additional users to test caching modes.
    $this->normal_user = $this->drupalCreateUser();
    $this->normal_user_alt = $this->drupalCreateUser();
    // Sync the roles, since drupalCreateUser() creates separate roles for
    // the same permission sets.
    user_save($this->normal_user_alt, array('roles' => $this->normal_user->roles));
    $this->normal_user_alt->roles = $this->normal_user->roles;

    // Enable block caching.
    variable_set('block_cache', TRUE);

    // Enable our test block.
    $edit['block_test_test_cache[region]'] = 'sidebar_first';
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
  }

  /**
   * Test DRUPAL_CACHE_PER_ROLE.
   */
  function testCachePerRole() {
    $this->setCacheMode(DRUPAL_CACHE_PER_ROLE);

    // Enable our test block. Set some content for it to display.
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);
    $this->drupalLogin($this->normal_user);
    $this->drupalGet('');
    $this->assertText($current_content, t('Block content displays.'));

    // Change the content, but the cached copy should still be served.
    $old_content = $current_content;
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);
    $this->drupalGet('');
    $this->assertText($old_content, t('Block is served from the cache.'));

    // Clear the cache and verify that the stale data is no longer there.
    cache_clear_all();
    $this->drupalGet('');
    $this->assertNoText($old_content, t('Block cache clear removes stale cache data.'));
    $this->assertText($current_content, t('Fresh block content is displayed after clearing the cache.'));

    // Test whether the cached data is served for the correct users.
    $old_content = $current_content;
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);
    $this->drupalLogout();
    $this->drupalGet('');
    $this->assertNoText($old_content, t('Anonymous user does not see content cached per-role for normal user.'));

    $this->drupalLogin($this->normal_user_alt);
    $this->drupalGet('');
    $this->assertText($old_content, t('User with the same roles sees per-role cached content.'));

    $this->drupalLogin($this->admin_user);
    $this->drupalGet('');
    $this->assertNoText($old_content, t('Admin user does not see content cached per-role for normal user.'));

    $this->drupalLogin($this->normal_user);
    $this->drupalGet('');
    $this->assertText($old_content, t('Block is served from the per-role cache.'));
  }

  /**
   * Test DRUPAL_CACHE_GLOBAL.
   */
  function testCacheGlobal() {
    $this->setCacheMode(DRUPAL_CACHE_GLOBAL);
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    $this->drupalGet('');
    $this->assertText($current_content, t('Block content displays.'));

    $old_content = $current_content;
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    $this->drupalLogout();
    $this->drupalGet('user');
    $this->assertText($old_content, t('Block content served from global cache.'));
  }

  /**
   * Test DRUPAL_NO_CACHE.
   */
  function testNoCache() {
    $this->setCacheMode(DRUPAL_NO_CACHE);
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    // If DRUPAL_NO_CACHE has no effect, the next request would be cached.
    $this->drupalGet('');
    $this->assertText($current_content, t('Block content displays.'));

    // A cached copy should not be served.
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);
    $this->drupalGet('');
    $this->assertText($current_content, t('DRUPAL_NO_CACHE prevents blocks from being cached.'));
  }

  /**
   * Test DRUPAL_CACHE_PER_USER.
   */
  function testCachePerUser() {
    $this->setCacheMode(DRUPAL_CACHE_PER_USER);
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);
    $this->drupalLogin($this->normal_user);

    $this->drupalGet('');
    $this->assertText($current_content, t('Block content displays.'));

    $old_content = $current_content;
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    $this->drupalGet('');
    $this->assertText($old_content, t('Block is served from per-user cache.'));

    $this->drupalLogin($this->normal_user_alt);
    $this->drupalGet('');
    $this->assertText($current_content, t('Per-user block cache is not served for other users.'));

    $this->drupalLogin($this->normal_user);
    $this->drupalGet('');
    $this->assertText($old_content, t('Per-user block cache is persistent.'));
  }

  /**
   * Test DRUPAL_CACHE_PER_PAGE.
   */
  function testCachePerPage() {
    $this->setCacheMode(DRUPAL_CACHE_PER_PAGE);
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    $this->drupalGet('node');
    $this->assertText($current_content, t('Block content displays on the node page.'));

    $old_content = $current_content;
    $current_content = $this->randomName();
    variable_set('block_test_content', $current_content);

    $this->drupalGet('user');
    $this->assertNoText($old_content, t('Block content cached for the node page does not show up for the user page.'));
    $this->drupalGet('node');
    $this->assertText($old_content, t('Block content cached for the node page.'));
  }

  /**
   * Private helper method to set the test block's cache mode.
   */
  private function setCacheMode($cache_mode) {
    db_update('block')
      ->fields(array('cache' => $cache_mode))
      ->condition('module', 'block_test')
      ->execute();

    $current_mode = db_query("SELECT cache FROM {block} WHERE module = 'block_test'")->fetchField();
    if ($current_mode != $cache_mode) {
      $this->fail(t('Unable to set cache mode to %mode. Current mode: %current_mode', array('%mode' => $cache_mode, '%current_mode' => $current_mode)));
    }
  }
}