You are here

menu.test in SimpleTest 7

Provides SimpleTests for menu.inc.

File

tests/menu.test
View source
<?php

/**
 * @file
 * Provides SimpleTests for menu.inc.
 */
class MenuIncTestCase extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Hook menu tests',
      'description' => 'Test menu hook functionality.',
      'group' => 'Menu',
    );
  }
  function setUp() {

    // Enable dummy module that implements hook_menu.
    parent::setUp('menu_test');

    // Make the tests below more robust by explicitly setting the default theme
    // and administrative theme that they expect.
    variable_set('theme_default', 'garland');
    variable_set('admin_theme', 'seven');
  }

  /**
   * Test title callback set to FALSE.
   */
  function testTitleCallbackFalse() {
    $this
      ->drupalGet('node');
    $this
      ->assertText('A title with @placeholder', t('Raw text found on the page'));
    $this
      ->assertNoText(t('A title with @placeholder', array(
      '@placeholder' => 'some other text',
    )), t('Text with placeholder substitutions not found.'));
  }

  /**
   * Test the theme callback when it is set to use an administrative theme.
   */
  function testThemeCallbackAdministrative() {
    $this
      ->drupalGet('menu-test/theme-callback/use-admin-theme');
    $this
      ->assertText('Requested theme: seven. Actual theme: seven.', t('The administrative theme can be correctly set in a theme callback.'));
    $this
      ->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page."));
  }

  /**
   * Test that the theme callback is properly inherited.
   */
  function testThemeCallbackInheritance() {
    $this
      ->drupalGet('menu-test/theme-callback/use-admin-theme/inheritance');
    $this
      ->assertText('Requested theme: seven. Actual theme: seven. Theme callback inheritance is being tested.', t('Theme callback inheritance correctly uses the administrative theme.'));
    $this
      ->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page."));
  }

  /**
   * Test the theme callback when the site is in maintenance mode.
   */
  function testThemeCallbackMaintenanceMode() {
    variable_set('maintenance_mode', TRUE);

    // For a regular user, the fact that the site is in maintenance mode means
    // we expect the theme callback system to be bypassed entirely.
    $this
      ->drupalGet('menu-test/theme-callback/use-admin-theme');
    $this
      ->assertRaw('minnelli/minnelli.css', t("The maintenance theme's CSS appears on the page."));

    // An administrator, however, should continue to see the requested theme.
    $admin_user = $this
      ->drupalCreateUser(array(
      'access site in maintenance mode',
    ));
    $this
      ->drupalLogin($admin_user);
    $this
      ->drupalGet('menu-test/theme-callback/use-admin-theme');
    $this
      ->assertText('Requested theme: seven. Actual theme: seven.', t('The theme callback system is correctly triggered for an administrator when the site is in maintenance mode.'));
    $this
      ->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page."));
  }

  /**
   * Test the theme callback when it is set to use an optional theme.
   */
  function testThemeCallbackOptionalTheme() {

    // Request a theme that is not enabled.
    $this
      ->drupalGet('menu-test/theme-callback/use-stark-theme');
    $this
      ->assertText('Requested theme: stark. Actual theme: garland.', t('The theme callback system falls back on the default theme when a theme that is not enabled is requested.'));
    $this
      ->assertRaw('garland/style.css', t("The default theme's CSS appears on the page."));

    // Now enable the theme and request it again.
    $admin_user = $this
      ->drupalCreateUser(array(
      'administer site configuration',
    ));
    $this
      ->drupalLogin($admin_user);
    $this
      ->drupalPost('admin/appearance', array(
      'status[stark]' => 1,
    ), t('Save configuration'));
    $this
      ->drupalLogout();
    $this
      ->drupalGet('menu-test/theme-callback/use-stark-theme');
    $this
      ->assertText('Requested theme: stark. Actual theme: stark.', t('The theme callback system uses an optional theme once it has been enabled.'));
    $this
      ->assertRaw('stark/layout.css', t("The optional theme's CSS appears on the page."));
  }

  /**
   * Test the theme callback when it is set to use a theme that does not exist.
   */
  function testThemeCallbackFakeTheme() {
    $this
      ->drupalGet('menu-test/theme-callback/use-fake-theme');
    $this
      ->assertText('Requested theme: fake_theme. Actual theme: garland.', t('The theme callback system falls back on the default theme when a theme that does not exist is requested.'));
    $this
      ->assertRaw('garland/style.css', t("The default theme's CSS appears on the page."));
  }

  /**
   * Test the theme callback when no theme is requested.
   */
  function testThemeCallbackNoThemeRequested() {
    $this
      ->drupalGet('menu-test/theme-callback/no-theme-requested');
    $this
      ->assertText('Requested theme: NONE. Actual theme: garland.', t('The theme callback system falls back on the default theme when no theme is requested.'));
    $this
      ->assertRaw('garland/style.css', t("The default theme's CSS appears on the page."));
  }

  /**
   * Tests for menu_link_maintain().
   */
  function testMenuLinkMaintain() {
    $admin_user = $this
      ->drupalCreateUser(array(
      'administer site configuration',
    ));
    $this
      ->drupalLogin($admin_user);

    // Create three menu items.
    menu_link_maintain('menu_test', 'insert', 'menu_test_maintain/1', 'Menu link #1');
    menu_link_maintain('menu_test', 'insert', 'menu_test_maintain/1', 'Menu link #1-1');
    menu_link_maintain('menu_test', 'insert', 'menu_test_maintain/2', 'Menu link #2');

    // Move second link to the main-menu, to test caching later on.
    db_update('menu_links')
      ->fields(array(
      'menu_name' => 'main-menu',
    ))
      ->condition('link_title', 'Menu link #1-1')
      ->condition('customized', 0)
      ->condition('module', 'menu_test')
      ->execute();
    menu_cache_clear('main-menu');

    // Load front page.
    $this
      ->drupalGet('node');
    $this
      ->assertLink(t('Menu link #1'), 0, 'Found menu link #1');
    $this
      ->assertLink(t('Menu link #1-1'), 0, 'Found menu link #1-1');
    $this
      ->assertLink(t('Menu link #2'), 0, 'Found menu link #2');

    // Rename all links for the given path.
    menu_link_maintain('menu_test', 'update', 'menu_test_maintain/1', 'Menu link updated');

    // Load a different page to be sure that we have up to date information.
    $this
      ->drupalGet('menu_test_maintain/1');
    $this
      ->assertLink(t('Menu link updated'), 0, t('Found updated menu link'));
    $this
      ->assertNoLink(t('Menu link #1'), 0, t('Not found menu link #1'));
    $this
      ->assertNoLink(t('Menu link #1'), 0, t('Not found menu link #1-1'));
    $this
      ->assertLink(t('Menu link #2'), 0, t('Found menu link #2'));

    // Delete all links for the given path.
    menu_link_maintain('menu_test', 'delete', 'menu_test_maintain/1', '');

    // Load a different page to be sure that we have up to date information.
    $this
      ->drupalGet('menu_test_maintain/2');
    $this
      ->assertNoLink(t('Menu link updated'), 0, t('Not found deleted menu link'));
    $this
      ->assertNoLink(t('Menu link #1'), 0, t('Not found menu link #1'));
    $this
      ->assertNoLink(t('Menu link #1'), 0, t('Not found menu link #1-1'));
    $this
      ->assertLink(t('Menu link #2'), 0, t('Found menu link #2'));
  }

  /**
   * Test menu_get_names().
   */
  function testMenuGetNames() {

    // Create three menu items.
    for ($i = 0; $i < 3; $i++) {
      $menu_link = array(
        'link_title' => 'Menu link #' . $i,
        'link_path' => 'menu_test/' . $i,
        'module' => 'menu_test',
        'menu_name' => 'menu_test_' . $i,
      );
      menu_link_save($menu_link);
    }
    drupal_static_reset('menu_get_names');

    // Verify that the menu names are correctly reported by menu_get_names().
    $menu_names = menu_get_names();
    $this
      ->pass(implode(' | ', $menu_names));
    for ($i = 0; $i < 3; $i++) {
      $this
        ->assertTrue(in_array('menu_test_' . $i, $menu_names), t('Expected menu name %expected is returned.', array(
        '%expected' => 'menu_test_' . $i,
      )));
    }
  }

  /**
   * Tests for menu_name parameter for hook_menu().
   */
  function testMenuName() {
    $admin_user = $this
      ->drupalCreateUser(array(
      'administer site configuration',
    ));
    $this
      ->drupalLogin($admin_user);
    $sql = "SELECT menu_name FROM {menu_links} WHERE router_path = 'menu_name_test'";
    $name = db_query($sql)
      ->fetchField();
    $this
      ->assertEqual($name, 'original', t('Menu name is "original".'));

    // Change the menu_name parameter in menu_test.module, then force a menu
    // rebuild.
    menu_test_menu_name('changed');
    menu_rebuild();
    $sql = "SELECT menu_name FROM {menu_links} WHERE router_path = 'menu_name_test'";
    $name = db_query($sql)
      ->fetchField();
    $this
      ->assertEqual($name, 'changed', t('Menu name was successfully changed after rebuild.'));
  }

  /**
   * Tests for menu hiearchy.
   */
  function testMenuHiearchy() {
    $parent_link = db_query('SELECT * FROM {menu_links} WHERE link_path = :link_path', array(
      ':link_path' => 'menu-test/hierarchy/parent',
    ))
      ->fetchAssoc();
    $child_link = db_query('SELECT * FROM {menu_links} WHERE link_path = :link_path', array(
      ':link_path' => 'menu-test/hierarchy/parent/child',
    ))
      ->fetchAssoc();
    $unattached_child_link = db_query('SELECT * FROM {menu_links} WHERE link_path = :link_path', array(
      ':link_path' => 'menu-test/hierarchy/parent/child2/child',
    ))
      ->fetchAssoc();
    $this
      ->assertEqual($child_link['plid'], $parent_link['mlid'], t('The parent of a directly attached child is correct.'));
    $this
      ->assertEqual($unattached_child_link['plid'], $parent_link['mlid'], t('The parent of a non-directly attached child is correct.'));
  }

  /**
   * Test menu_set_item().
   */
  function testMenuSetItem() {
    $item = menu_get_item('node');
    $this
      ->assertEqual($item['path'], 'node', t("Path from menu_get_item('node') is equal to 'node'"), 'menu');

    // Modify the path for the item then save it.
    $item['path'] = 'node_test';
    $item['href'] = 'node_test';
    menu_set_item('node', $item);
    $compare_item = menu_get_item('node');
    $this
      ->assertEqual($compare_item, $item, t('Modified menu item is equal to newly retrieved menu item.'), 'menu');
  }

  /**
   * Test menu maintainance hooks.
   */
  function testMenuItemHooks() {

    // Create an item.
    menu_link_maintain('menu_test', 'insert', 'menu_test_maintain/4', 'Menu link #4');
    $this
      ->assertEqual(menu_test_static_variable(), 'insert', t('hook_menu_link_insert() fired correctly'));

    // Update the item.
    menu_link_maintain('menu_test', 'update', 'menu_test_maintain/4', 'Menu link updated');
    $this
      ->assertEqual(menu_test_static_variable(), 'update', t('hook_menu_link_update() fired correctly'));

    // Delete the item.
    menu_link_maintain('menu_test', 'delete', 'menu_test_maintain/4', '');
    $this
      ->assertEqual(menu_test_static_variable(), 'delete', t('hook_menu_link_delete() fired correctly'));
  }

}

/**
 * Tests rebuilding the menu by setting 'menu_rebuild_needed.'
 */
class MenuRebuildTestCase extends DrupalWebTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Menu rebuild test',
      'description' => 'Test rebuilding of menu.',
      'group' => 'Menu',
    );
  }

  /**
   * Test if the 'menu_rebuild_needed' variable triggers a menu_rebuild() call.
   */
  function testMenuRebuildByVariable() {

    // Check if 'admin' path exists.
    $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(
      ':path' => 'admin',
    ))
      ->fetchField();
    $this
      ->assertEqual($admin_exists, 'admin', t("The path 'admin/' exists prior to deleting."));

    // Delete the path item 'admin', and test that the path doesn't exist in the database.
    $delete = db_delete('menu_router')
      ->condition('path', 'admin')
      ->execute();
    $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(
      ':path' => 'admin',
    ))
      ->fetchField();
    $this
      ->assertFalse($admin_exists, t("The path 'admin/' has been deleted and doesn't exist in the database."));

    // Now we enable the rebuild variable and trigger menu_execute_active_handler()
    // to rebuild the menu item. Now 'admin' should exist.
    variable_set('menu_rebuild_needed', TRUE);

    // menu_execute_active_handler() should trigger the rebuild.
    $this
      ->drupalGet('<front>');
    $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(
      ':path' => 'admin',
    ))
      ->fetchField();
    $this
      ->assertEqual($admin_exists, 'admin', t("The menu has been rebuilt, the path 'admin' now exists again."));
  }

}

/**
 * Menu tree data related tests.
 */
class MenuTreeDataTestCase extends DrupalUnitTestCase {

  /**
   * Dummy link structure acceptable for menu_tree_data().
   */
  var $links = array(
    1 => array(
      'mlid' => 1,
      'depth' => 1,
    ),
    2 => array(
      'mlid' => 2,
      'depth' => 1,
    ),
    3 => array(
      'mlid' => 3,
      'depth' => 2,
    ),
    4 => array(
      'mlid' => 4,
      'depth' => 3,
    ),
    5 => array(
      'mlid' => 5,
      'depth' => 1,
    ),
  );
  public static function getInfo() {
    return array(
      'name' => 'Menu tree generation',
      'description' => 'Tests recursive menu tree generation functions.',
      'group' => 'Menu',
    );
  }

  /**
   * Validate the generation of a proper menu tree hierarchy.
   */
  function testMenuTreeData() {
    $tree = menu_tree_data($this->links);

    // Validate that parent items #1, #2, and #5 exist on the root level.
    $this
      ->assertSameLink($this->links[1], $tree[1]['link'], t('Parent item #1 exists.'));
    $this
      ->assertSameLink($this->links[2], $tree[2]['link'], t('Parent item #2 exists.'));
    $this
      ->assertSameLink($this->links[5], $tree[5]['link'], t('Parent item #5 exists.'));

    // Validate that child item #4 exists at the correct location in the hierarchy.
    $this
      ->assertSameLink($this->links[4], $tree[2]['below'][3]['below'][4]['link'], t('Child item #4 exists in the hierarchy.'));
  }

  /**
   * Check that two menu links are the same by comparing the mlid.
   *
   * @param $link1
   *   A menu link item.
   * @param $link2
   *   A menu link item.
   * @param $message
   *   The message to display along with the assertion.
   * @return
   *   TRUE if the assertion succeeded, FALSE otherwise.
   */
  protected function assertSameLink($link1, $link2, $message = '') {
    return $this
      ->assert($link1['mlid'] == $link2['mlid'], $message ? $message : t('First link is identical to second link'));
  }

}

Classes

Namesort descending Description
MenuIncTestCase @file Provides SimpleTests for menu.inc.
MenuRebuildTestCase Tests rebuilding the menu by setting 'menu_rebuild_needed.'
MenuTreeDataTestCase Menu tree data related tests.