You are here

DevelToolbarTest.php in Devel 4.x

File

tests/src/Functional/DevelToolbarTest.php
View source
<?php

namespace Drupal\Tests\devel\Functional;

use Drupal\Core\Menu\MenuTreeParameters;

/**
 * Tests devel toolbar module functionality.
 *
 * @group devel
 */
class DevelToolbarTest extends DevelBrowserTestBase {

  /**
   * {@inheritdoc}
   */
  public static $modules = [
    'devel',
    'toolbar',
    'block',
  ];

  /**
   * The user for tests.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $toolbarUser;

  /**
   * The user for tests.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $develUser;

  /**
   * The dafault toolbar items.
   *
   * @var array
   */
  protected $defaultToolbarItems = [
    'devel.cache_clear',
    'devel.container_info.service',
    'devel.admin_settings_link',
    'devel.menu_rebuild',
    'devel.reinstall',
    'devel.route_info',
    'devel.run_cron',
  ];

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp();
    $this
      ->drupalPlaceBlock('local_tasks_block');
    $this
      ->drupalPlaceBlock('page_title_block');
    $this->develUser = $this
      ->drupalCreateUser([
      'administer site configuration',
      'access devel information',
      'access toolbar',
    ]);
    $this->toolbarUser = $this
      ->drupalCreateUser([
      'access toolbar',
    ]);
  }

  /**
   * Tests configuration form.
   */
  public function testConfigurationForm() {

    // Ensures that the page is accessible only to users with the adequate
    // permissions.
    $this
      ->drupalGet('admin/config/development/devel/toolbar');
    $this
      ->assertSession()
      ->statusCodeEquals(403);

    // Ensures that the config page is accessible for users with the adequate
    // permissions and the Devel toolbar local task and content are shown.
    $this
      ->drupalLogin($this->develUser);
    $this
      ->drupalGet('admin/config/development/devel/toolbar');
    $this
      ->assertSession()
      ->statusCodeEquals(200);
    $this
      ->assertSession()
      ->elementExists('xpath', '//h2[text()="Primary tabs"]/following-sibling::ul//a[contains(text(), "Toolbar Settings")]');
    $this
      ->assertSession()
      ->elementExists('xpath', '//fieldset[@id="edit-toolbar-items--wrapper"]');
    $this
      ->assertSession()
      ->pageTextContains('Devel Toolbar Settings');

    // Ensures and that all devel menu links are listed in the configuration
    // page.
    foreach ($this
      ->getMenuLinkInfos() as $link) {
      $this
        ->assertSession()
        ->fieldExists(sprintf('toolbar_items[%s]', $link['id']));
    }

    // Ensures and that the default configuration items are selected by
    // default.
    foreach ($this->defaultToolbarItems as $item) {
      $this
        ->assertSession()
        ->checkboxChecked(sprintf('toolbar_items[%s]', $item));
    }

    // Ensures that the configuration save works as expected.
    $edit = [
      'toolbar_items[devel.event_info]' => 'devel.event_info',
      'toolbar_items[devel.theme_registry]' => 'devel.theme_registry',
    ];
    $this
      ->drupalPostForm('admin/config/development/devel/toolbar', $edit, 'Save configuration');
    $this
      ->assertSession()
      ->pageTextContains('The configuration options have been saved.');
    $expected_items = array_merge($this->defaultToolbarItems, [
      'devel.event_info',
      'devel.theme_registry',
    ]);
    sort($expected_items);
    $config_items = \Drupal::config('devel.toolbar.settings')
      ->get('toolbar_items');
    sort($config_items);
    $this
      ->assertEquals($expected_items, $config_items);
  }

  /**
   * Tests cache metadata headers.
   */
  public function testCacheHeaders() {

    // Disable user toolbar tab so we can test properly if the devel toolbar
    // implementation interferes with the page cacheability.
    \Drupal::service('module_installer')
      ->install([
      'toolbar_disable_user_toolbar',
    ]);

    // The menu is not loaded for users without the adequate permission,
    // so no cache tags for configuration are added.
    $this
      ->drupalLogin($this->toolbarUser);
    $this
      ->assertSession()
      ->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
    $this
      ->assertSession()
      ->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');

    // Make sure that the configuration cache tags are present for users with
    // the adequate permission.
    $this
      ->drupalLogin($this->develUser);
    $this
      ->assertSession()
      ->responseHeaderContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
    $this
      ->assertSession()
      ->responseHeaderContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');

    // The Devel toolbar implementation should not interfere with the page
    // cacheability, so you expect a MISS value in the X-Drupal-Dynamic-Cache
    // header the first time.
    $this
      ->assertSession()
      ->responseHeaderContains('X-Drupal-Dynamic-Cache', 'MISS');

    // Triggers a page reload and verify that the page is served from the
    // cache.
    $this
      ->drupalGet('');
    $this
      ->assertSession()
      ->responseHeaderContains('X-Drupal-Dynamic-Cache', 'HIT');
  }

  /**
   * Tests toolbar integration.
   */
  public function testToolbarIntegration() {
    $library_css_url = 'css/devel.toolbar.css';
    $toolbar_selector = '#toolbar-bar .toolbar-tab';
    $toolbar_tab_selector = '#toolbar-bar .toolbar-tab a.toolbar-icon-devel';
    $toolbar_tray_selector = '#toolbar-bar .toolbar-tab #toolbar-item-devel-tray';

    // Ensures that devel toolbar item is accessible only for user with the
    // adequate permissions.
    $this
      ->drupalGet('');
    $this
      ->assertSession()
      ->responseNotContains($library_css_url);
    $this
      ->assertSession()
      ->elementNotExists('css', $toolbar_selector);
    $this
      ->assertSession()
      ->elementNotExists('css', $toolbar_tab_selector);
    $this
      ->drupalLogin($this->toolbarUser);
    $this
      ->assertSession()
      ->responseNotContains($library_css_url);
    $this
      ->assertSession()
      ->elementExists('css', $toolbar_selector);
    $this
      ->assertSession()
      ->elementNotExists('css', $toolbar_tab_selector);
    $this
      ->drupalLogin($this->develUser);
    $this
      ->assertSession()
      ->responseContains($library_css_url);
    $this
      ->assertSession()
      ->elementExists('css', $toolbar_selector);
    $this
      ->assertSession()
      ->elementExists('css', $toolbar_tab_selector);
    $this
      ->assertSession()
      ->elementTextContains('css', $toolbar_tab_selector, 'Devel');

    // Ensures that the configure link in the toolbar is present and point to
    // the correct page.
    $this
      ->clickLink('Configure');
    $this
      ->assertSession()
      ->addressEquals('admin/config/development/devel/toolbar');

    // Ensures that the toolbar tray contains the all the menu links. To the
    // links not marked as always visible will be assigned a css class that
    // allow to hide they when the toolbar has horizontal orientation.
    $this
      ->drupalGet('');
    $toolbar_tray = $this
      ->assertSession()
      ->elementExists('css', $toolbar_tray_selector);
    $devel_menu_items = $this
      ->getMenuLinkInfos();
    $toolbar_items = $toolbar_tray
      ->findAll('css', 'ul.toolbar-menu a');
    $this
      ->assertCount(count($devel_menu_items), $toolbar_items);
    foreach ($devel_menu_items as $link) {
      $item_selector = sprintf('ul.toolbar-menu a:contains("%s")', $link['title']);
      $item = $this
        ->assertSession()
        ->elementExists('css', $item_selector, $toolbar_tray);

      // Only test the url up to the ? as the destination and token parameters
      // will vary and are not checkable.
      $this
        ->assertEquals(strtok($link['url'], '?'), strtok($item
        ->getAttribute('href'), '?'));
      $not_visible = !in_array($link['id'], $this->defaultToolbarItems);
      $this
        ->assertTrue($not_visible === $item
        ->hasClass('toolbar-horizontal-item-hidden'));
    }

    // Ensures that changing the toolbar settings configuration the changes are
    // immediately visible.
    $saved_items = $this
      ->config('devel.toolbar.settings')
      ->get('toolbar_items');
    $saved_items[] = 'devel.event_info';
    $this
      ->config('devel.toolbar.settings')
      ->set('toolbar_items', $saved_items)
      ->save();
    $this
      ->drupalGet('');
    $toolbar_tray = $this
      ->assertSession()
      ->elementExists('css', $toolbar_tray_selector);
    $item = $this
      ->assertSession()
      ->elementExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray);
    $this
      ->assertFalse($item
      ->hasClass('toolbar-horizontal-item-hidden'));

    // Ensures that disabling a menu link it will not more shown in the toolbar
    // and that the changes are immediately visible.
    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
    $menu_link_manager
      ->updateDefinition('devel.event_info', [
      'enabled' => FALSE,
    ]);
    $this
      ->drupalGet('');
    $toolbar_tray = $this
      ->assertSession()
      ->elementExists('css', $toolbar_tray_selector);
    $this
      ->assertSession()
      ->elementNotExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray);
  }

  /**
   * Tests devel when toolbar module is not installed.
   */
  public function testToolbarModuleNotInstalled() {

    // Ensures that when toolbar module is not installed all works properly.
    \Drupal::service('module_installer')
      ->uninstall([
      'toolbar',
    ]);
    $this
      ->drupalLogin($this->develUser);

    // Toolbar settings page should respond with 404.
    $this
      ->drupalGet('admin/config/development/devel/toolbar');
    $this
      ->assertSession()
      ->statusCodeEquals(404);

    // Primary local task should not contain toolbar tab.
    $this
      ->drupalGet('admin/config/development/devel');
    $this
      ->assertSession()
      ->statusCodeEquals(200);
    $this
      ->assertSession()
      ->elementNotExists('xpath', '//a[contains(text(), "Toolbar Settings")]');

    // Toolbar setting config and devel menu cache tags sholud not present.
    $this
      ->drupalGet('');
    $this
      ->assertSession()
      ->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
    $this
      ->assertSession()
      ->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
  }

  /**
   * Helper function for retrieve the menu link informations.
   *
   * @return array
   *   An array containing the menu link informations.
   */
  protected function getMenuLinkInfos() {
    $parameters = new MenuTreeParameters();
    $parameters
      ->onlyEnabledLinks()
      ->setTopLevelOnly();
    $tree = \Drupal::menuTree()
      ->load('devel', $parameters);
    $links = [];
    foreach ($tree as $element) {
      $links[] = [
        'id' => $element->link
          ->getPluginId(),
        'title' => $element->link
          ->getTitle(),
        'url' => $element->link
          ->getUrlObject()
          ->toString(),
      ];
    }
    return $links;
  }

}

Classes

Namesort descending Description
DevelToolbarTest Tests devel toolbar module functionality.