Newer
Older
<?php
// $Id$
/**
* @file
* Tests file for the menu module.
*/
class MenuTestCase extends DrupalWebTestCase {
protected $big_user;
protected $std_user;
protected $menu;
protected $items;
Angie Byron
committed
public static function getInfo() {
return array(
'name' => 'Menu link creation/deletion',
'description' => 'Add a custom menu, add menu links to the custom menu and Navigation menu, check their data, and delete them using the menu module UI.',
'group' => 'Menu'
);
}
function setUp() {
parent::setUp('menu');
// Create users.
$this->big_user = $this->drupalCreateUser(array('access administration pages', 'administer blocks', 'administer menu', 'create article content'));
$this->std_user = $this->drupalCreateUser(array());
}
/**
* Login users, add menus and menu links, and test menu functionality through the admin and user interfaces.
*/
function testMenu() {
// Login the user.
$this->drupalLogin($this->big_user);
$this->items = array();
// Do standard menu tests.
$this->doStandardMenuTests();
// Do custom menu tests.
$this->doCustomMenuTests();
// Do standard user tests.
// Login the user.
$this->drupalLogin($this->std_user);
$this->verifyAccess(403);
foreach ($this->items as $item) {
$node = node_load(substr($item['link_path'], 5)); // Paths were set as 'node/$nid'.
$this->verifyMenuLink($item, $node);
}
// Login the user.
$this->drupalLogin($this->big_user);
// Delete menu links.
foreach ($this->items as $item) {
$this->deleteMenuLink($item);
}
// Delete custom menu.
$this->deleteCustomMenu($this->menu);
// Modify and reset a standard menu link.
$item = $this->getStandardMenuLink();
$old_title = $item['link_title'];
$this->modifyMenuLink($item);
$item = menu_link_load($item['mlid']);
// Verify that a change to the description is saved.
$description = $this->randomName(16);
$item['options']['attributes']['title'] = $description;
menu_link_save($item);
$saved_item = menu_link_load($item['mlid']);
$this->assertEqual($description, $saved_item['options']['attributes']['title'], t('Saving an existing link updates the description (title attribute)'));
$this->resetMenuLink($item, $old_title);
}
/**
* Test standard menu functionality using navigation menu.
*
*/
function doStandardMenuTests() {
$this->doMenuTests();
$this->addInvalidMenuLink();
}
/**
* Test custom menu functionality using navigation menu.
*
*/
function doCustomMenuTests() {
$this->menu = $this->addCustomMenu();
$this->doMenuTests($this->menu['menu_name']);
$this->addInvalidMenuLink($this->menu['menu_name']);
$this->addCustomMenuCRUD();
}
/**
* Add custom menu using CRUD functions.
*/
function addCustomMenuCRUD() {
// Add a new custom menu.
Dries Buytaert
committed
$menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
$title = $this->randomName(16);
$menu = array(
'menu_name' => $menu_name,
'title' => $title,
'description' => 'Description text',
);
menu_save($menu);
// Assert the new menu.
$this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
$this->assertText($title, t('Custom menu was added.'));
// Edit the menu.
$new_title = $this->randomName(16);
$menu['title'] = $new_title;
menu_save($menu);
$this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
$this->assertText($new_title, t('Custom menu was edited.'));
}
/**
* Add custom menu.
*/
function addCustomMenu() {
// Add custom menu.
// Try adding a menu using a menu_name that is too long.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/add');
Dries Buytaert
committed
$menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1);
$title = $this->randomName(16);
$edit = array(
'menu_name' => $menu_name,
'description' => '',
'title' => $title,
);
Dries Buytaert
committed
$this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
// Verify that using a menu_name that is too long results in a validation message.
$this->assertText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
// Change the menu_name so it no longer exceeds the maximum length.
Dries Buytaert
committed
$menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
$edit['menu_name'] = $menu_name;
Dries Buytaert
committed
$this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
// Verify that no validation error is given for menu_name length.
$this->assertNoText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
// Unlike most other modules, there is no confirmation message displayed.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu');
$this->assertText($title, 'Menu created');
// Enable the custom menu block.
$menu_name = 'menu-' . $menu_name; // Drupal prepends the name with 'menu-'.
$edit = array();
Angie Byron
committed
$edit['menu_' . $menu_name . '[region]'] = 'sidebar_first';
Dries Buytaert
committed
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
$this->assertResponse(200);
$this->assertText(t('The block settings have been updated.'), t('Custom menu block was enabled'));
return menu_load($menu_name);
}
/**
* Delete custom menu.
*
* @param string $menu_name Custom menu name.
*/
function deleteCustomMenu($menu) {
$menu_name = $this->menu['menu_name'];
$title = $this->menu['title'];
// Delete custom menu.
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/manage/$menu_name/delete", array(), t('Delete'));
$this->assertResponse(200);
$this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $title)), t('Custom menu was deleted'));
$this->assertFalse(menu_load($menu_name), 'Custom menu was deleted');
// Test if all menu links associated to the menu were removed from database.
$result = db_query("SELECT menu_name FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu_name))->fetchField();
Angie Byron
committed
$this->assertFalse($result, t('All menu links associated to the custom menu were deleted.'));
}
/**
* Test menu functionality using navigation menu.
*
*/
function doMenuTests($menu_name = 'navigation') {
// Add nodes to use as links for menu links.
Dries Buytaert
committed
$node1 = $this->drupalCreateNode(array('type' => 'article'));
$node2 = $this->drupalCreateNode(array('type' => 'article'));
// Add menu links.
$item1 = $this->addMenuLink(0, 'node/' . $node1->nid, $menu_name);
$item2 = $this->addMenuLink($item1['mlid'], 'node/' . $node2->nid, $menu_name);
// Verify menu links.
$this->verifyMenuLink($item1, $node1);
$this->verifyMenuLink($item2, $node2, $item1, $node1);
// Modify menu links.
$this->modifyMenuLink($item1);
$this->modifyMenuLink($item2);
// Toggle menu links.
$this->toggleMenuLink($item1);
$this->toggleMenuLink($item2);
// Enable a link via the overview form.
$this->disableMenuLink($item1);
$edit = array();
// Note in the UI the 'mlid:x[hidden]' form element maps to enabled, or
// NOT hidden.
$edit['mlid:' . $item1['mlid'] . '[hidden]'] = TRUE;
Dries Buytaert
committed
$this->drupalPost('admin/structure/menu/manage/' . $item1['menu_name'], $edit, t('Save configuration'));
// Verify in the database.
Dries Buytaert
committed
$hidden = db_query("SELECT hidden FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item1['mlid']))->fetchField();
$this->assertEqual($hidden, 0, t('Link is not hidden in the database table when enabled via the overview form'));
// Save menu links for later tests.
$this->items[] = $item1;
$this->items[] = $item2;
}
Dries Buytaert
committed
/**
* Add and remove a menu link with a query string and fragment.
*/
function testMenuQueryAndFragment() {
$this->drupalLogin($this->big_user);
// Make a path with query and fragment on.
$path = 'node?arg1=value1&arg2=value2';
$item = $this->addMenuLink(0, $path);
$this->drupalGet('admin/structure/menu/item/' . $item['mlid'] . '/edit');
$this->assertFieldByName('link_path', $path, t('Path is found with both query and fragment.'));
// Now change the path to something without query and fragment.
$path = 'node';
$this->drupalPost('admin/structure/menu/item/' . $item['mlid'] . '/edit', array('link_path' => $path), t('Save'));
$this->drupalGet('admin/structure/menu/item/' . $item['mlid'] . '/edit');
$this->assertFieldByName('link_path', $path, t('Path no longer has query or fragment.'));
}
/**
* Add a menu link using the menu module UI.
*
* @param integer $plid Parent menu link id.
* @param string $link Link path.
* @param string $menu_name Menu name.
* @return array Menu link created.
*/
function addMenuLink($plid = 0, $link = '<front>', $menu_name = 'navigation') {
// View add menu link page.
Dries Buytaert
committed
$this->drupalGet("admin/structure/menu/manage/$menu_name/add");
$this->assertResponse(200);
$title = '!link_' . $this->randomName(16);
$edit = array(
'link_path' => $link,
'link_title' => $title,
'description' => '',
'enabled' => TRUE, // Use this to disable the menu and test.
'expanded' => TRUE, // Setting this to true should test whether it works when we do the std_user tests.
'parent' => $menu_name . ':' . $plid,
'weight' => '0',
);
// Add menu link.
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertResponse(200);
// Unlike most other modules, there is no confirmation message displayed.
$this->assertText($title, 'Menu link was added');
// Retrieve menu link.
Dries Buytaert
committed
$item = db_query("SELECT * FROM {menu_links} WHERE link_title = :title", array(':title' => $title))->fetchAssoc();
// Check the structure in the DB of the two menu links.
// In general, if $n = $item['depth'] then $item['p'. $n] == $item['mlid'] and $item['p' . ($n - 1)] == $item['plid'] (unless depth == 0).
// All $item['p' . $n] for $n > depth must be 0.
// We know link1 is at the top level, so $item1['deptj'] == 1 and $item1['plid'] == 0.
// We know that the parent of link2 is link1, so $item2['plid'] == $item1['mlid'].
// Both menu links were created in the navigation menu.
$this->assertEqual($item['menu_name'], $menu_name);
$this->assertEqual($item['plid'], $plid);
Dries Buytaert
committed
$options = unserialize($item['options']);
if (!empty($options['query'])) {
$item['link_path'] .= '?' . drupal_http_build_query($options['query']);
}
if (!empty($options['fragment'])) {
$item['link_path'] .= '#' . $options['fragment'];
}
$this->assertEqual($item['link_path'], $link);
$this->assertEqual($item['link_title'], $title);
if ($plid == 0) {
$this->assertTrue($item['depth'] == 1 && !$item['has_children'] && $item['p1'] == $item['mlid'] && $item['p2'] == 0, 'Menu link has correct data');
}
else {
$this->assertTrue($item['depth'] == 2 && !$item['has_children'] && $item['p1'] == $plid && $item['p2'] == $item['mlid'], 'Menu link has correct data');
}
return $item;
}
/**
* Attempt to add menu link with invalid path or no access permission.
*
* @param string $menu_name Menu name.
*/
function addInvalidMenuLink($menu_name = 'navigation') {
Angie Byron
committed
foreach (array('-&-', 'admin/people/permissions') as $link_path) {
$edit = array(
'link_path' => $link_path,
'link_title' => 'title',
);
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/manage/$menu_name/add", $edit, t('Save'));
$this->assertRaw(t("The path '@path' is either invalid or you do not have access to it.", array('@path' => $link_path)), 'Menu link was not created');
}
}
/**
* Verify a menu link using the menu module UI.
*
* @param array $item Menu link.
* @param object $item_node Menu link content node.
* @param array $parent Parent menu link.
* @param object $parent_node Parent menu link content node.
*/
function verifyMenuLink($item, $item_node, $parent = NULL, $parent_node = NULL) {
// View home page.
$this->drupalGet('');
$this->assertResponse(200);
// Verify parent menu link.
if (isset($parent)) {
// Verify menu link.
$title = $parent['link_title'];
$this->assertText($title, 'Parent menu link was displayed');
// Verify menu link link.
$this->clickLink($title);
$title = $parent_node->title;
$this->assertTitle(t("@title | Drupal", array('@title' => $title)), t('Parent menu link link target was correct'));
}
// Verify menu link.
$title = $item['link_title'];
$this->assertText($title, 'Menu link was displayed');
// Verify menu link link.
$this->clickLink($title);
$title = $item_node->title;
$this->assertTitle(t("@title | Drupal", array('@title' => $title)), t('Menu link link target was correct'));
}
/**
* Modify a menu link using the menu module UI.
*
* @param array &$item Menu link passed by reference.
*/
function modifyMenuLink(&$item) {
$item['link_title'] = $this->randomName(16);
$mlid = $item['mlid'];
$title = $item['link_title'];
// Edit menu link.
$edit = array();
$edit['link_title'] = $title;
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/item/$mlid/edit", $edit, t('Save'));
$this->assertResponse(200);
// Unlike most other modules, there is no confirmation message displayed.
// Verify menu link.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/manage/' . $item['menu_name']);
$this->assertText($title, 'Menu link was edited');
}
/**
* Reset a standard menu link using the menu module UI.
*
* @param array $item Menu link.
* @param string $old_title Original title for menu link.
*/
function resetMenuLink($item, $old_title) {
$mlid = $item['mlid'];
$title = $item['link_title'];
// Reset menu link.
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/item/$mlid/reset", array(), t('Reset'));
$this->assertResponse(200);
$this->assertRaw(t('The menu link was reset to its default settings.'), t('Menu link was reset'));
// Verify menu link.
$this->drupalGet('');
$this->assertNoText($title, 'Menu link was reset');
$this->assertText($old_title, 'Menu link was reset');
}
/**
* Delete a menu link using the menu module UI.
*
* @param array $item Menu link.
*/
function deleteMenuLink($item) {
$mlid = $item['mlid'];
$title = $item['link_title'];
// Delete menu link.
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/item/$mlid/delete", array(), t('Confirm'));
$this->assertResponse(200);
$this->assertRaw(t('The menu link %title has been deleted.', array('%title' => $title)), t('Menu link was deleted'));
// Verify deletion.
$this->drupalGet('');
$this->assertNoText($title, 'Menu link was deleted');
}
/**
* Alternately disable and enable a menu link.
*
* @param $item
* Menu link.
*/
function toggleMenuLink($item) {
$this->disableMenuLink($item);
// Verify menu link is absent.
$this->drupalGet('');
$this->assertNoText($item['link_title'], 'Menu link was not displayed');
$this->enableMenuLink($item);
// Verify menu link is displayed.
$this->drupalGet('');
$this->assertText($item['link_title'], 'Menu link was displayed');
}
/**
* Disable a menu link.
*
* @param $item
* Menu link.
*/
function disableMenuLink($item) {
$mlid = $item['mlid'];
$edit['enabled'] = FALSE;
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/item/$mlid/edit", $edit, t('Save'));
// Unlike most other modules, there is no confirmation message displayed.
// Verify in the database.
$hidden = db_query("SELECT hidden FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $mlid))->fetchField();
$this->assertEqual($hidden, 1, t('Link is hidden in the database table'));
}
/**
* Enable a menu link.
*
* @param $item
* Menu link.
*/
function enableMenuLink($item) {
$mlid = $item['mlid'];
$edit['enabled'] = TRUE;
Dries Buytaert
committed
$this->drupalPost("admin/structure/menu/item/$mlid/edit", $edit, t('Save'));
// Verify in the database.
Dries Buytaert
committed
$hidden = db_query("SELECT hidden FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $mlid))->fetchField();
$this->assertEqual($hidden, 0, t('Link is not hidden in the database table'));
}
/**
* Get standard menu link.
*/
private function getStandardMenuLink() {
// Retrieve menu link id of the Log out menu link, which will always be on the front page.
$mlid = db_query("SELECT mlid FROM {menu_links} WHERE module = 'system' AND router_path = 'user/logout'")->fetchField();
$this->assertTrue($mlid > 0, 'Standard menu link id was found');
// Load menu link.
// Use api function so that link is translated for rendering.
$item = menu_link_load($mlid);
$this->assertTrue((bool) $item, 'Standard menu link was loaded');
return $item;
}
/**
* Verify the logged in user has the desired access to the various menu nodes.
*
* @param integer $response HTTP response code.
*/
private function verifyAccess($response = 200) {
// View menu help node.
$this->drupalGet('admin/help/menu');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Menu'), t('Menu help was displayed'));
}
// View menu build overview node.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Menus'), t('Menu build overview node was displayed'));
}
// View navigation menu customization node.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/manage/navigation');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Navigation'), t('Navigation menu node was displayed'));
}
// View menu edit node.
$item = $this->getStandardMenuLink();
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/item/' . $item['mlid'] . '/edit');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Edit menu item'), t('Menu edit node was displayed'));
}
// View menu settings node.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/settings');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Menus'), t('Menu settings node was displayed'));
}
// View add menu node.
Dries Buytaert
committed
$this->drupalGet('admin/structure/menu/add');
$this->assertResponse($response);
if ($response == 200) {
$this->assertText(t('Menus'), t('Add menu node was displayed'));
}
}
}
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
/**
* Test menu settings for nodes.
*/
class MenuNodeTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Menu settings for nodes',
'description' => 'Add, edit, and delete a node with menu link.',
'group' => 'Menu',
);
}
function setUp() {
parent::setUp('menu');
$this->admin_user = $this->drupalCreateUser(array(
'access administration pages',
'administer content types',
'administer menu',
'create page content',
'edit any page content',
'delete any page content',
));
$this->drupalLogin($this->admin_user);
}
/**
* Test creating, editing, deleting menu links via node form widget.
*/
function testMenuNodeFormWidget() {
// Enable Navigation menu as available menu.
$edit = array(
'menu_options[navigation]' => 1,
);
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
// Change default parent item to Navigation menu, so we can assert more
// easily.
$edit = array(
'menu_parent' => 'navigation:0',
);
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
// Create a node.
$node_title = $this->randomName();
Dries Buytaert
committed
$language = LANGUAGE_NONE;
$edit = array(
"title" => $node_title,
Dries Buytaert
committed
"body[$language][0][value]" => $this->randomString(),
);
$this->drupalPost('node/add/page', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($node_title);
// Assert that there is no link for the node.
$this->drupalGet('');
$this->assertNoLink($node_title);
// Edit the node, enable the menu link setting, but skip the link title.
$edit = array(
'menu[enabled]' => 1,
);
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
// Assert that there is no link for the node.
$this->drupalGet('');
$this->assertNoLink($node_title);
// Edit the node and create a menu link.
$edit = array(
'menu[enabled]' => 1,
'menu[link_title]' => $node_title,
Angie Byron
committed
'menu[weight]' => 17,
);
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
// Assert that the link exists.
$this->drupalGet('');
$this->assertLink($node_title);
Angie Byron
committed
$this->drupalGet('node/' . $node->nid . '/edit');
$this->assertOptionSelected('edit-menu-weight', 17, t('Menu weight correct in edit form'));
// Edit the node and remove the menu link.
$edit = array(
'menu[enabled]' => FALSE,
);
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
// Assert that there is no link for the node.
$this->drupalGet('');
$this->assertNoLink($node_title);
}
}