3 namespace Drupal\Tests\devel\Functional;
5 use Drupal\Core\Menu\MenuTreeParameters;
6 use Drupal\Tests\BrowserTestBase;
9 * Tests devel toolbar module functionality.
13 class DevelToolbarTest extends BrowserTestBase {
18 public static $modules = ['devel', 'toolbar', 'block'];
23 * @var \Drupal\user\UserInterface
25 protected $toolbarUser;
30 * @var \Drupal\user\UserInterface
35 * The dafault toolbar items.
39 protected $defaultToolbarItems = [
41 'devel.container_info.service',
42 'devel.admin_settings_link',
53 public function setUp() {
56 $this->drupalPlaceBlock('local_tasks_block');
57 $this->drupalPlaceBlock('page_title_block');
59 $this->develUser = $this->drupalCreateUser([
60 'administer site configuration',
61 'access devel information',
65 $this->toolbarUser = $this->drupalCreateUser([
71 * Tests configuration form.
73 public function testConfigurationForm() {
74 // Ensures that the page is accessible ony to users with the adequate
76 $this->drupalGet('admin/config/development/devel/toolbar');
77 $this->assertSession()->statusCodeEquals(403);
79 // Ensures that the config page is accessible for users with the adequate
80 // permissions and exists the Devel toolbar local task.
81 $this->drupalLogin($this->develUser);
82 $this->drupalGet('admin/config/development/devel/toolbar');
83 $this->assertSession()->statusCodeEquals(200);
84 $this->assertSession()->elementExists('css', '.tabs .primary a:contains("Toolbar Settings")');
85 $this->assertSession()->pageTextContains('Devel Toolbar Settings');
87 // Ensures and that all devel menu links are listed in the configuration
89 foreach ($this->getMenuLinkInfos() as $link) {
90 $this->assertSession()->fieldExists(sprintf('toolbar_items[%s]', $link['id']));
93 // Ensures and that the default configuration items are selected by
95 foreach ($this->defaultToolbarItems as $item) {
96 $this->assertSession()->checkboxChecked(sprintf('toolbar_items[%s]', $item));
99 // Ensures that the configuration save works as expected.
101 'toolbar_items[devel.event_info]' => 'devel.event_info',
102 'toolbar_items[devel.theme_registry]' => 'devel.theme_registry',
104 $this->drupalPostForm('admin/config/development/devel/toolbar', $edit, t('Save configuration'));
105 $this->assertSession()->pageTextContains('The configuration options have been saved.');
107 $expected_items = array_merge($this->defaultToolbarItems, ['devel.event_info', 'devel.theme_registry']);
108 sort($expected_items);
109 $config_items = \Drupal::config('devel.toolbar.settings')->get('toolbar_items');
112 $this->assertEquals($expected_items, $config_items);
116 * Tests cache metadata headers.
118 public function testCacheHeaders() {
119 // Disable user toolbar tab so we can test properly if the devel toolbar
120 // implementation interferes with the page cacheability.
121 \Drupal::service('module_installer')->install(['toolbar_disable_user_toolbar']);
123 // The menu is not loaded for users without the adequate permission,
124 // so no cache tags for configuration are added.
125 $this->drupalLogin($this->toolbarUser);
126 $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
127 $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
129 // Make sure that the configuration cache tags are present for users with
130 // the adequate permission.
131 $this->drupalLogin($this->develUser);
132 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
133 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
135 // The Devel toolbar implementation should not interfere with the page
136 // cacheability, so you expect a MISS value in the X-Drupal-Dynamic-Cache
137 // header the first time.
138 $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'MISS');
140 // Triggers a page reload and verify that the page is served from the
142 $this->drupalGet('');
143 $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'HIT');
147 * Tests toolbar integration.
149 public function testToolbarIntegration() {
150 $library_css_url = 'devel/css/devel.toolbar.css';
151 $toolbar_selector = '#toolbar-bar .toolbar-tab';
152 $toolbar_tab_selector = '#toolbar-bar .toolbar-tab a.toolbar-icon-devel';
153 $toolbar_tray_selector = '#toolbar-bar .toolbar-tab #toolbar-item-devel-tray';
155 // Ensures that devel toolbar item is accessible only for user with the
156 // adequate permissions.
157 $this->drupalGet('');
158 $this->assertSession()->responseNotContains($library_css_url);
159 $this->assertSession()->elementNotExists('css', $toolbar_selector);
160 $this->assertSession()->elementNotExists('css', $toolbar_tab_selector);
162 $this->drupalLogin($this->toolbarUser);
163 $this->assertSession()->responseNotContains($library_css_url);
164 $this->assertSession()->elementExists('css', $toolbar_selector);
165 $this->assertSession()->elementNotExists('css', $toolbar_tab_selector);
167 $this->drupalLogin($this->develUser);
168 $this->assertSession()->responseContains($library_css_url);
169 $this->assertSession()->elementExists('css', $toolbar_selector);
170 $this->assertSession()->elementExists('css', $toolbar_tab_selector);
171 $this->assertSession()->elementTextContains('css', $toolbar_tab_selector, 'Devel');
173 // Ensures that the configure link in the toolbar is present and point to
175 $this->clickLink('Configure');
176 $this->assertSession()->addressEquals('admin/config/development/devel/toolbar');
178 // Ensures that the toolbar tray contains the all the menu links. To the
179 // links not marked as always visible will be assigned a css class that
180 // allow to hide they when the toolbar has horizontal orientation.
181 $this->drupalGet('');
182 $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
184 $devel_menu_items = $this->getMenuLinkInfos();
185 $toolbar_items = $toolbar_tray->findAll('css', 'ul.menu a');
186 $this->assertCount(count($devel_menu_items), $toolbar_items);
188 foreach ($devel_menu_items as $link) {
189 $item_selector = sprintf('ul.menu a:contains("%s")', $link['title']);
190 $item = $this->assertSession()->elementExists('css', $item_selector, $toolbar_tray);
191 // TODO: find a more correct way to test link url.
192 $this->assertContains(strtok($link['url'], '?'), $item->getAttribute('href'));
194 $not_visible = !in_array($link['id'], $this->defaultToolbarItems);
195 $this->assertTrue($not_visible === $item->hasClass('toolbar-horizontal-item-hidden'));
198 // Ensures that changing the toolbar settings configuration the changes are
199 // immediately visible.
200 $saved_items = $this->config('devel.toolbar.settings')->get('toolbar_items');
201 $saved_items[] = 'devel.event_info';
203 $this->config('devel.toolbar.settings')
204 ->set('toolbar_items', $saved_items)
207 $this->drupalGet('');
208 $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
209 $item = $this->assertSession()->elementExists('css', sprintf('ul.menu a:contains("%s")', 'Events Info'), $toolbar_tray);
210 $this->assertFalse($item->hasClass('toolbar-horizontal-item-hidden'));
212 // Ensures that disabling a menu link it will not more shown in the toolbar
213 // and that the changes are immediately visible.
214 $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
215 $menu_link_manager->updateDefinition('devel.event_info', ['enabled' => FALSE]);
217 $this->drupalGet('');
218 $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
219 $this->assertSession()->elementNotExists('css', sprintf('ul.menu a:contains("%s")', 'Events Info'), $toolbar_tray);
223 * Tests devel when toolbar module is not installed.
225 public function testToolbarModuleNotInstalled() {
226 // Ensures that when toolbar module is not installed all works properly.
227 \Drupal::service('module_installer')->uninstall(['toolbar']);
229 $this->drupalLogin($this->develUser);
231 // Toolbar settings page should respond with 404.
232 $this->drupalGet('admin/config/development/devel/toolbar');
233 $this->assertSession()->statusCodeEquals(404);
235 // Primary local task should not contains toolbar tab.
236 $this->drupalGet('admin/config/development/devel');
237 $this->assertSession()->statusCodeEquals(200);
238 $this->assertSession()->elementNotExists('css', '.tabs .primary a:contains("Toolbar Settings")');
240 // Toolbar setting config and devel menu cache tags sholud not present.
241 $this->drupalGet('');
242 $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
243 $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
247 * Helper function for retrieve the menu link informations.
250 * An array containing the menu link informations.
252 protected function getMenuLinkInfos() {
253 $parameters = new MenuTreeParameters();
254 $parameters->onlyEnabledLinks()->setTopLevelOnly();
255 $tree = \Drupal::menuTree()->load('devel', $parameters);
258 foreach ($tree as $element) {
260 'id' => $element->link->getPluginId(),
261 'title' => $element->link->getTitle(),
262 'url' => $element->link->getUrlObject()->toString(),