'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(''); $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')); } }