You are here

public function AckMenuAccessTest::testAckMenuUI in Access Control Kit 7

Test the menu management UI.

File

ack_menu/ack_menu.test, line 208
Tests for the ACK menu module.

Class

AckMenuAccessTest
Tests the menu access functions.

Code

public function testAckMenuUI() {

  // Check that administrators are notified when no schemes are available.
  $this
    ->clickLink(t('Manage menu links'));
  $this
    ->assertText(t('No access schemes have been configured to manage menu links.'));
  $this
    ->clickLink(t('access scheme administration page'));
  $this
    ->assertLink(t('Add access scheme'));

  // Finish building the test environment.
  $this
    ->setUpMenu();

  // Verify that non-integer schemes cannot use the menu link handler.
  $edit = array(
    'name' => $this
      ->randomName(),
    'machine_name' => drupal_strtolower($this
      ->randomName()),
    'roles[' . $this->ackRole->rid . ']' => TRUE,
  );
  $this
    ->drupalPost('admin/structure/access/add/boolean', $edit, 'Save access scheme and continue');
  $this
    ->assertNoFieldByName('handlers[menu_link][handler]');
  $this
    ->assertText(t('No object access handlers are available to manage Menu link objects in a Boolean scheme.'));
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertFieldByName('AckMenuMap[' . $this->schemeMachineName . ']', '', 'Link can be mapped to an integer scheme.');
  $this
    ->assertNoFieldByName('AckMenuMap[' . $edit['machine_name'] . ']', '', 'Link cannot be mapped to a boolean scheme.');
  $ack_menu_url = 'ack_menu/manage/' . $this->schemeMachineName . '/';
  $ack_link_url = 'admin/structure/menu/item/';

  // Test as the scheme menu admin.
  $this
    ->clickLink(t('Manage menu links'));

  // A scheme menu admin should see all realms.
  $this
    ->assertLinkByHref($ack_menu_url . '1', 0, 'The user 1 realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackAdmin->uid, 0, 'The admin user realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackUser->uid, 0, 'The ACK user realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->noAccessUser->uid, 0, 'The no access user realm is listed.');

  // Test a realm with no mappings.
  $this
    ->drupalGet($ack_menu_url . '1');
  $this
    ->assertTitle(t('Manage @realm menu links', array(
    '@realm' => 'placeholder-for-uid-1',
  )) . ' | Drupal');
  $this
    ->assertText(t('There are no menu links yet for @realm.', array(
    '@realm' => 'placeholder-for-uid-1',
  )));
  $this
    ->assertLink(t('Add a link'));
  $this
    ->assertNoLink(t('Edit the parent link'));
  $edit = array();
  for ($i = 0; $i < 2; $i++) {
    $this
      ->clickLink(t('Add @realm menu link', array(
      '@realm' => 'placeholder-for-uid-1',
    )));
    $selector = $this
      ->xpath('//select[@name=:name and @disabled="disabled"]', array(
      ':name' => 'AckMenuMap[' . $this->schemeMachineName . ']',
    ));
    $this
      ->assertTrue($selector, 'The mapping element is disabled.');
    $this
      ->assertOptionSelected('edit-ackmenumap-' . $this->schemeMachineName, 1, 'The realm mapping is selected.');
    $this
      ->assertOptionSelected('edit-parent', 'navigation:0', 'The parent menu is selected.');
    $this
      ->assertFieldByXPath('//option[@value="navigation:' . $this->items['mapped top link']['mlid'] . '"]', TRUE, 'Links in managed menus from other realms are not filtered.');
    $this
      ->assertNoFieldByXPath('//option[@value="main-menu:0"]', TRUE, 'Unmanaged menus are not available as parent options.');
    $edit[$i] = array(
      'link_title' => $this
        ->randomName(),
      'link_path' => 'node',
    );
    $this
      ->drupalPost(NULL, $edit[$i], 'Save');
    $this
      ->assertLink(t('Edit the parent link'), $i);
    if (!$i) {

      // With only one link, the parent link header should not be shown.
      $this
        ->assertNoRaw('<legend><span class="fieldset-legend"><a href="' . url('node') . '" title="">' . $edit[$i]['link_title'] . '</a></span></legend>', 'Parent link header is not displayed when only one parent is present.');
    }
    else {

      // With more than one, we need a header for each.
      $this
        ->assertRaw('<legend><span class="fieldset-legend"><a href="' . url('node') . '" title="">' . $edit[$i]['link_title'] . '</a></span></legend>', 'Parent link headers are displayed when there are two parents available.');
    }
  }

  // Make sure both headers are present.
  $this
    ->assertRaw('<legend><span class="fieldset-legend"><a href="' . url('node') . '" title="">' . $edit[0]['link_title'] . '</a></span></legend>');

  // Check access to menu items.
  $this
    ->clickLink(t('Edit the parent link'));
  $this
    ->assertText(t('Edit menu link'), 'The link can be edited.');
  $selector = $this
    ->xpath('//select[@name=:name and @disabled="disabled"]', array(
    ':name' => 'AckMenuMap[' . $this->schemeMachineName . ']',
  ));
  $this
    ->assertFalse($selector, 'The mapping can be changed.');
  $this
    ->assertOptionSelected('edit-ackmenumap-' . $this->schemeMachineName, 1, 'The realm mapping is selected.');
  $this
    ->drupalPost(NULL, array(), 'Delete');
  $this
    ->assertText(t('Are you sure you want to delete the custom menu link'), 'The link can be deleted.');

  // Check the access callbacks.
  $this
    ->drupalGet($ack_menu_url . 'a');
  $this
    ->assertResponse(403, 'Access is denied to an invalid realm.');
  $this
    ->drupalGet('admin/structure/menu/settings');
  $this
    ->assertResponse(403, 'Access is denied to the menu settings page.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu');
  $this
    ->assertResponse(403, 'Access is denied to an unmanaged menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to an unmanaged menu.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation');
  $this
    ->assertResponse(200, 'Access is granted to a managed menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertResponse(200, 'Access is granted to add a link to a managed menu.');
  $this
    ->drupalGet('admin/structure/menu');
  $this
    ->assertResponse(200, 'Access is granted to the menu admin page.');

  // Check that the menu overview page is properly filtered.
  $this
    ->assertNoLinkByHref('admin/structure/menu/manage/main-menu');
  $this
    ->assertNoLinkByHref('admin/structure/menu/manage/management');
  $this
    ->assertLinkByHref('admin/structure/menu/manage/navigation');
  $this
    ->assertNoLinkByHref('admin/structure/menu/manage/user-menu');
  $this
    ->assertNoLinkByHref('admin/structure/menu/settings');

  // Test as the test user, without an access grant.
  $this
    ->drupalLogin($this->ackUser);
  $this
    ->clickLink(t('Manage menu links'));

  // Without a grant, the menu manager should be empty.
  $this
    ->assertNoLinkByHref($ack_menu_url, 'No realms are listed.');
  $this
    ->assertText(t('You have not been granted access to any menu trees.'));

  // Check the access callbacks.
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid);
  $this
    ->assertResponse(403, 'Access is denied to a menu tree.');
  $this
    ->drupalGet($ack_menu_url . 'a');
  $this
    ->assertResponse(403, 'Access is denied to an invalid realm.');
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid . '/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit an unmapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete an unmapped link.');
  $this
    ->drupalGet('admin/structure/menu');
  $this
    ->assertResponse(403, 'Access is denied to the menu admin page.');
  $this
    ->drupalGet('admin/structure/menu/settings');
  $this
    ->assertResponse(403, 'Access is denied to the menu settings page.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu');
  $this
    ->assertResponse(403, 'Access is denied to an unmanaged menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to an unmanaged menu.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation');
  $this
    ->assertResponse(403, 'Access is denied to a managed menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to a managed menu.');

  // Grant access to the test user.
  $this
    ->drupalLogin($this->ackAdmin);
  $field = 'ack_' . $this->schemeMachineName . '[und]';
  $edit = array(
    'user' => $this->ackUser->name,
    'role' => $this->ackRole->rid,
    $field . '[' . $this->ackUser->uid . ']' => TRUE,
    $field . '[' . $this->ackAdmin->uid . ']' => TRUE,
    $field . '[' . $this->menuAdmin->uid . ']' => TRUE,
  );
  $this
    ->drupalPost('admin/access/add/' . $this->schemeMachineName, $edit, 'Save');

  // Retest as the test user.
  $this
    ->drupalLogin($this->ackUser);
  $this
    ->clickLink(t('Manage menu links'));

  // With a grant, the menu manager should only list the assigned realms.
  $this
    ->assertNoLinkByHref($ack_menu_url . '1', 'The user 1 realm is not listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackAdmin->uid, 0, 'The admin user realm is listed: ' . $this->ackAdmin->name);
  $this
    ->assertNoLinkByHref($ack_menu_url . $this->menuAdmin->uid, 'The global admin user realm is not listed: ' . $this->menuAdmin->name);
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackUser->uid, 0, 'The ACK user realm is listed: ' . $this->ackUser->name);
  $this
    ->assertNoLinkByHref($ack_menu_url . $this->noAccessUser->uid, 'The no access user realm is not listed: ' . $this->noAccessUser->name);

  // Check the access callbacks.
  $this
    ->drupalGet($ack_menu_url . $this->menuAdmin->uid);
  $this
    ->assertResponse(403, 'Access is denied to a realm menu tree with no mapped links.');
  $this
    ->drupalGet($ack_menu_url . $this->noAccessUser->uid);
  $this
    ->assertResponse(403, 'Access is denied to the no access menu tree.');
  $this
    ->drupalGet($ack_menu_url . 'a');
  $this
    ->assertResponse(403, 'Access is denied to an invalid realm.');
  $this
    ->drupalGet($ack_menu_url . $this->noAccessUser->uid . '/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to the no access realm.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access top link']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit the top link in the no access realm.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access child link']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit a link in the no access realm that is a child of an accessible link.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access grandchild link']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit a link in the no access realm that is a grandchild of an accessible link.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access top link']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete the top link in the no access realm.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access child link']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete a link in the no access realm that is a child of an accessible link.');
  $this
    ->drupalGet($ack_link_url . $this->items['no access grandchild link']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete a link in the no access realm that is a grandchild of an accessible link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit an unmapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete an unmapped link.');
  $this
    ->drupalGet('admin/structure/menu');
  $this
    ->assertResponse(403, 'Access is denied to the menu admin page.');
  $this
    ->drupalGet('admin/structure/menu/settings');
  $this
    ->assertResponse(403, 'Access is denied to the menu settings page.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu');
  $this
    ->assertResponse(403, 'Access is denied to an unmanaged menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to an unmanaged menu.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation');
  $this
    ->assertResponse(403, 'Access is denied to a managed menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to a managed menu.');

  // Put the links we'll be testing into a more easily referenced format.
  // The parent link for the user's realm.
  $parent = new stdClass();
  $parent->mlid = $this->items['mapped top link']['mlid'];
  $parent->plid = $this->items['mapped top link']['plid'];
  $parent->title = $this->items['mapped top link']['title'];
  $parent->field_name = $parent->plid . '[subtree][mlid:' . $parent->mlid . ']';
  $parent->edit = $ack_link_url . $parent->mlid . '/edit';
  $parent->delete = $ack_link_url . $parent->mlid . '/delete';

  // A normal child link of $parent.
  $child = new stdClass();
  $child->mlid = $this->items['not mapped child link']['mlid'];
  $child->title = $this->items['not mapped child link']['title'];
  $child->field_name = $parent->mlid . '[subtree][mlid:' . $child->mlid . ']';
  $child->edit = $ack_link_url . $child->mlid . '/edit';
  $child->delete = $ack_link_url . $child->mlid . '/delete';

  // A child link of $parent explicitly mapped to an accessible foreign realm.
  $foreign_child = new stdClass();
  $foreign_child->mlid = $this->items['mapped child link']['mlid'];
  $foreign_child->title = $this->items['mapped child link']['title'];
  $foreign_child->field_name = $parent->mlid . '[subtree][mlid:' . $foreign_child->mlid . ']';
  $foreign_child->field_id = 'edit-' . $parent->mlid . '-subtree-mlid' . $foreign_child->mlid;
  $foreign_child->edit = $ack_link_url . $foreign_child->mlid . '/edit';
  $foreign_child->delete = $ack_link_url . $foreign_child->mlid . '/delete';

  // A child link of $parent explicitly mapped to an inaccessible realm.
  $no_access_child = new stdClass();
  $no_access_child->mlid = $this->items['no access child link']['mlid'];
  $no_access_child->title = $this->items['no access child link']['title'];
  $no_access_child->field_name = $parent->mlid . '[subtree][mlid:' . $no_access_child->mlid . ']';
  $no_access_child->edit = $ack_link_url . $no_access_child->mlid . '/edit';
  $no_access_child->delete = $ack_link_url . $no_access_child->mlid . '/delete';

  // A child link of $no_access_child.
  $no_access_grandchild = new stdClass();
  $no_access_grandchild->mlid = $this->items['no access grandchild link']['mlid'];
  $no_access_grandchild->title = $this->items['no access grandchild link']['title'];
  $no_access_grandchild->field_name = $no_access_child->mlid . '[subtree][mlid:' . $no_access_grandchild->mlid . ']';

  // Test the subtree for a realm with a top-level mapping.
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid);

  // The parent link.
  $this
    ->assertNoFieldByName($parent->field_name . '[plid]', $parent->plid, 'The parent link does not appear in the subtree: ' . $parent->title);
  $this
    ->assertLinkByHref($parent->edit, 0, 'The parent link shows the edit operation.');
  $this
    ->assertNoLinkByHref($parent->delete, 'The parent link does not show the delete operation.');

  // The normal child link.
  $this
    ->assertFieldByName($child->field_name . '[plid]', $parent->mlid, 'The child link appears in the subtree: ' . $child->title);
  $this
    ->assertLinkByHref($child->edit, 0, 'The child link shows the edit operation.');
  $this
    ->assertLinkByHref($child->delete, 0, 'The child link shows the delete operation.');

  // The accessible foreign child link.
  $this
    ->assertFieldByName($foreign_child->field_name . '[plid]', $parent->mlid, 'The foreign child link appears in the subtree: ' . $foreign_child->title);
  $this
    ->assertLinkByHref($foreign_child->edit, 0, 'The foreign child link shows the edit operation.');
  $this
    ->assertLinkByHref($foreign_child->delete, 0, 'The foreign child link shows the delete operation.');
  $this
    ->assertFieldChecked($foreign_child->field_id . '-hidden', 'The foreign child link is enabled.');

  // The inaccessible foreign child link.
  $this
    ->assertFieldByName($no_access_child->field_name . '[plid]', $parent->mlid, 'The inaccessible child link appears in the subtree: ' . $no_access_child->title);
  $this
    ->assertNoLinkByHref($no_access_child->edit, 'The inaccessible child link does not show the edit operation.');
  $this
    ->assertNoLinkByHref($no_access_child->delete, 'The inaccessible child link does not show the delete operation.');

  // The inaccessible grandchild link.
  $this
    ->assertNoFieldByName($no_access_grandchild->field_name . '[plid]', $parent->mlid, 'The inaccessible grandchild link does not appear in the subtree: ' . $no_access_grandchild->title);
  $this
    ->assertNoLink($no_access_grandchild->title);

  // Test editing a link.
  $edit = array(
    $foreign_child->field_name . '[hidden]' => FALSE,
  );
  $this
    ->drupalPost(NULL, $edit, 'Save configuration');
  $this
    ->assertNoFieldChecked($foreign_child->field_id . '-hidden', 'The foreign child link is disabled: ' . $foreign_child->title);

  // Add a link to the realm.
  $this
    ->clickLink(t('Add @realm menu link', array(
    '@realm' => $this->ackUser->name,
  )));
  $this
    ->assertOptionSelected('edit-parent', 'navigation:' . $parent->mlid, 'The parent link is selected: ' . $parent->title);
  $this
    ->assertFieldByXPath('//option[@value="navigation:' . $child->mlid . '"]', TRUE, 'The child link is an option: ' . $child->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:' . $foreign_child->mlid . '"]', TRUE, 'The foreign child link is not an option: ' . $foreign_child->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:' . $no_access_child->mlid . '"]', TRUE, 'The inaccessible child link is not an option: ' . $no_access_child->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:' . $no_access_grandchild->mlid . '"]', TRUE, 'The inaccessible grandchild link is not an option: ' . $no_access_grandchild->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:0"]', TRUE, 'The parent menu options were filtered.');
  $this
    ->assertNoFieldByXPath('//option[@value="main-menu:0"]', TRUE, 'Unmanaged menus are not available as parent options.');
  $edit = array(
    'link_title' => $this
      ->randomName(),
    'link_path' => 'node',
    'parent' => 'navigation:' . $child->mlid,
  );
  $this
    ->drupalPost(NULL, $edit, 'Save');
  $this
    ->assertText(t('Your configuration has been saved.'));
  $this
    ->assertLink($edit['link_title'], 0, 'The ACK user can create a link.');

  // A few more links for the next set of tests.
  // The parent link of the inaccessible realm.
  $no_access = new stdClass();
  $no_access->mlid = $this->items['no access top link']['mlid'];
  $no_access->title = $this->items['no access top link']['title'];
  $no_access->edit = $ack_link_url . $no_access->mlid . '/edit';
  $no_access->delete = $ack_link_url . $no_access->mlid . '/delete';

  // A link mapped to this realm, but a child of an inaccessible link.
  $child_of_no_access = new stdClass();
  $child_of_no_access->mlid = $this->items['mapped child link with no access parent']['mlid'];
  $child_of_no_access->title = $this->items['mapped child link with no access parent']['title'];
  $child_of_no_access->field_name = $no_access->mlid . '[subtree][mlid:' . $child_of_no_access->mlid . ']';
  $child_of_no_access->edit = $ack_link_url . $child_of_no_access->mlid . '/edit';
  $child_of_no_access->delete = $ack_link_url . $child_of_no_access->mlid . '/delete';

  // Edit the accessible foreign child link.
  $options = array(
    'query' => array(
      'destination' => $ack_menu_url . $this->ackUser->uid,
    ),
  );
  $this
    ->drupalGet($foreign_child->edit, $options);
  $this
    ->assertOptionSelected('edit-parent', 'navigation:' . $parent->mlid, 'The parent link is selected: ' . $parent->title);
  $this
    ->assertNoOptionSelected('edit-parent', 'navigation:' . $child_of_no_access->mlid, 'The other potential parent option is available, but not selected: ' . $child_of_no_access->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:' . $no_access->mlid . '"]', TRUE, 'The "no access" realm parent link is not available as a parent option: ' . $no_access->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:0"]', TRUE, 'The parent menu options were filtered.');
  $this
    ->assertNoFieldByXPath('//option[@value="main-menu:0"]', TRUE, 'Unmanaged menus are not available as parent options.');
  $selector = $this
    ->xpath('//select[@name=:name and @disabled="disabled"]', array(
    ':name' => 'weight',
  ));
  $this
    ->assertFalse($selector, 'The weight element is not disabled.');
  $this
    ->drupalPost(NULL, array(
    'enabled' => TRUE,
  ), 'Save');
  $this
    ->assertText(t('Your configuration has been saved.'));
  $this
    ->assertFieldChecked($foreign_child->field_id . '-hidden', 'The ACK user can edit a link.');

  // Test the subtrees for a realm with child-level mappings.
  $this
    ->drupalGet($ack_menu_url . $this->ackAdmin->uid);
  $this
    ->assertNoLinkByHref($no_access->edit, 'The "no access" realm parent link is not listed.');
  $this
    ->assertNoFieldByName($foreign_child->field_name . '[plid]', $parent->mlid, 'The link with the accessible parent does not appear in the subtree: ' . $foreign_child->title);
  $this
    ->assertLink($foreign_child->title);
  $this
    ->assertLinkByHref($foreign_child->edit, 0, 'The link with the accessible parent shows the edit operation.');
  $this
    ->assertNoLinkByHref($foreign_child->delete, 'The link with the accessible parent does not show the delete operation.');
  $this
    ->assertNoFieldByName($child_of_no_access->field_name . '[plid]', $no_access->mlid, 'The link with the inaccessible parent does not appear in a subtree for its parent: ' . $child_of_no_access->title);
  $this
    ->assertNoFieldByName($foreign_child->mlid . '[subtree][mlid:' . $child_of_no_access->mlid . ']' . '[plid]', $no_access->mlid, 'The link with the inaccessible parent does not appear in a subtree for the link with the accessible parent: ' . $child_of_no_access->title);
  $this
    ->assertLink($child_of_no_access->title);
  $this
    ->assertLinkByHref($child_of_no_access->edit, 0, 'The link with the inaccessible parent shows the edit operation.');
  $this
    ->assertNoLinkByHref($child_of_no_access->delete, 'The link with the inaccessible parent does not show the delete operation.');

  // Delete the link with the accessible parent.
  $options = array(
    'query' => array(
      'destination' => $ack_menu_url . $this->ackAdmin->uid,
    ),
  );
  $this
    ->drupalPost($foreign_child->delete, array(), 'Confirm', $options);
  $this
    ->assertText(t('The menu link @title has been deleted.', array(
    '@title' => $foreign_child->title,
  )));
  $this
    ->assertNoLinkByHref($foreign_child->edit, 'The ACK user can delete a link.');
  $this
    ->assertLinkByHref($child_of_no_access->edit, 0, 'The link with the inaccessible parent is still available.');

  // Test editing an item with an inaccessible parent.
  $this
    ->clickLink(t('Edit the parent link'));
  $this
    ->assertFieldByName('link_title', $child_of_no_access->title);
  $this
    ->assertOptionSelected('edit-parent', 'navigation:' . $no_access->mlid, 'The parent is selected: ' . $no_access->title);
  $this
    ->assertNoFieldByXPath('//option[@value="navigation:' . $parent->mlid . '"]', TRUE, 'The parent link options were filtered.');
  $selector = $this
    ->xpath('//select[@name=:name and @disabled="disabled"]', array(
    ':name' => 'weight',
  ));
  $this
    ->assertTrue($selector, 'The weight element is disabled.');

  // Test as a user with no menu-related access.
  $this
    ->drupalLogin($this->noAccessUser);
  $this
    ->assertNoLink(t('Manage menu links'));

  // Check the access callbacks.
  $this
    ->drupalGet('ack_menu');
  $this
    ->assertResponse(403, 'Access is denied to the menu manager.');
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid);
  $this
    ->assertResponse(403, 'Access is denied to a menu tree.');
  $this
    ->drupalGet($ack_menu_url . 'a');
  $this
    ->assertResponse(403, 'Access is denied to an invalid realm.');
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid . '/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/edit');
  $this
    ->assertResponse(403, 'Access is denied to edit an unmapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/delete');
  $this
    ->assertResponse(403, 'Access is denied to delete an unmapped link.');
  $this
    ->drupalGet('admin/structure/menu');
  $this
    ->assertResponse(403, 'Access is denied to the menu admin page.');
  $this
    ->drupalGet('admin/structure/menu/settings');
  $this
    ->assertResponse(403, 'Access is denied to the menu settings page.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu');
  $this
    ->assertResponse(403, 'Access is denied to an unmanaged menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to an unmanaged menu.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation');
  $this
    ->assertResponse(403, 'Access is denied to a managed menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertResponse(403, 'Access is denied to add a link to a managed menu.');

  // Test as the menu administrator.
  $this
    ->drupalLogin($this->menuAdmin);
  $this
    ->clickLink(t('Manage menu links'));

  // A menu admin should see all realms.
  $this
    ->assertLinkByHref($ack_menu_url . '1', 0, 'The user 1 realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackAdmin->uid, 0, 'The admin user realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->ackUser->uid, 0, 'The ACK user realm is listed.');
  $this
    ->assertLinkByHref($ack_menu_url . $this->noAccessUser->uid, 0, 'The no access user realm is listed.');

  // Check the access callbacks.
  $this
    ->assertResponse(200, 'Access is granted to the menu manager.');
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid);
  $this
    ->assertResponse(200, 'Access is granted to a menu tree.');
  $this
    ->drupalGet($ack_menu_url . 'a');
  $this
    ->assertResponse(403, 'Access is denied to an invalid realm.');
  $this
    ->drupalGet($ack_menu_url . $this->ackUser->uid . '/add');
  $this
    ->assertResponse(200, 'Access is granted to add a link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/edit');
  $this
    ->assertResponse(200, 'Access is granted to edit a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['mapped top link']['mlid'] . '/delete');
  $this
    ->assertResponse(200, 'Access is granted to delete a mapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/edit');
  $this
    ->assertResponse(200, 'Access is granted to edit an unmapped link.');
  $this
    ->drupalGet($ack_link_url . $this->items['not mapped']['mlid'] . '/delete');
  $this
    ->assertResponse(200, 'Access is granted to delete an unmapped link.');
  $this
    ->drupalGet('admin/structure/menu/settings');
  $this
    ->assertResponse(200, 'Access is granted to the menu settings page.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu');
  $this
    ->assertResponse(200, 'Access is granted to an unmanaged menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/main-menu/add');
  $this
    ->assertResponse(200, 'Access is granted to add a link to an unmanaged menu.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation');
  $this
    ->assertResponse(200, 'Access is granted to a managed menu list.');
  $this
    ->drupalGet('admin/structure/menu/manage/navigation/add');
  $this
    ->assertResponse(200, 'Access is granted to add a link to a managed menu.');
  $this
    ->drupalGet('admin/structure/menu');
  $this
    ->assertResponse(200, 'Access is granted to the menu admin page.');

  // Check that the menu overview page is not filtered.
  $this
    ->assertLinkByHref('admin/structure/menu/manage/main-menu');
  $this
    ->assertLinkByHref('admin/structure/menu/manage/management');
  $this
    ->assertLinkByHref('admin/structure/menu/manage/navigation');
  $this
    ->assertLinkByHref('admin/structure/menu/manage/user-menu');
  $this
    ->assertLinkByHref('admin/structure/menu/settings');

  // Check the permission descriptions.
  $this
    ->drupalGet('admin/people/permissions');
  $this
    ->assertText(t('Manage the links in the following access scheme-controlled menus: @menus.', array(
    '@menus' => 'Navigation',
  )), 'Permissions page lists manageable menus.');
  $scheme = access_scheme_machine_name_load($this->schemeMachineName);
  $this
    ->assertText(t('This permission only applies to the following access schemes: @schemes.', array(
    '@schemes' => $scheme->name,
  )), 'Permissions page lists applicable schemes.');
}