DevelToolbarTest.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. namespace Drupal\Tests\devel\Functional;
  3. use Drupal\Core\Menu\MenuTreeParameters;
  4. use Drupal\Tests\BrowserTestBase;
  5. /**
  6. * Tests devel toolbar module functionality.
  7. *
  8. * @group devel
  9. */
  10. class DevelToolbarTest extends BrowserTestBase {
  11. /**
  12. * {@inheritdoc}
  13. */
  14. public static $modules = ['devel', 'toolbar', 'block'];
  15. /**
  16. * The user for tests.
  17. *
  18. * @var \Drupal\user\UserInterface
  19. */
  20. protected $toolbarUser;
  21. /**
  22. * The user for tests.
  23. *
  24. * @var \Drupal\user\UserInterface
  25. */
  26. protected $develUser;
  27. /**
  28. * The dafault toolbar items.
  29. *
  30. * @var array
  31. */
  32. protected $defaultToolbarItems = [
  33. 'devel.cache_clear',
  34. 'devel.container_info.service',
  35. 'devel.admin_settings_link',
  36. 'devel.menu_rebuild',
  37. 'devel.reinstall',
  38. 'devel.route_info',
  39. 'devel.run_cron',
  40. ];
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function setUp() {
  45. parent::setUp();
  46. $this->drupalPlaceBlock('local_tasks_block');
  47. $this->drupalPlaceBlock('page_title_block');
  48. $this->develUser = $this->drupalCreateUser([
  49. 'administer site configuration',
  50. 'access devel information',
  51. 'access toolbar',
  52. ]);
  53. $this->toolbarUser = $this->drupalCreateUser([
  54. 'access toolbar',
  55. ]);
  56. }
  57. /**
  58. * Tests configuration form.
  59. */
  60. public function testConfigurationForm() {
  61. // Ensures that the page is accessible ony to users with the adequate
  62. // permissions.
  63. $this->drupalGet('admin/config/development/devel/toolbar');
  64. $this->assertSession()->statusCodeEquals(403);
  65. // Ensures that the config page is accessible for users with the adequate
  66. // permissions and exists the Devel toolbar local task.
  67. $this->drupalLogin($this->develUser);
  68. $this->drupalGet('admin/config/development/devel/toolbar');
  69. $this->assertSession()->statusCodeEquals(200);
  70. $this->assertSession()->elementExists('css', '.tabs .primary a:contains("Toolbar Settings")');
  71. $this->assertSession()->pageTextContains('Devel Toolbar Settings');
  72. // Ensures and that all devel menu links are listed in the configuration
  73. // page.
  74. foreach ($this->getMenuLinkInfos() as $link) {
  75. $this->assertSession()->fieldExists(sprintf('toolbar_items[%s]', $link['id']));
  76. }
  77. // Ensures and that the default configuration items are selected by
  78. // default.
  79. foreach ($this->defaultToolbarItems as $item) {
  80. $this->assertSession()->checkboxChecked(sprintf('toolbar_items[%s]', $item));
  81. }
  82. // Ensures that the configuration save works as expected.
  83. $edit = [
  84. 'toolbar_items[devel.event_info]' => 'devel.event_info',
  85. 'toolbar_items[devel.theme_registry]' => 'devel.theme_registry',
  86. ];
  87. $this->drupalPostForm('admin/config/development/devel/toolbar', $edit, t('Save configuration'));
  88. $this->assertSession()->pageTextContains('The configuration options have been saved.');
  89. $expected_items = array_merge($this->defaultToolbarItems, ['devel.event_info', 'devel.theme_registry']);
  90. sort($expected_items);
  91. $config_items = \Drupal::config('devel.toolbar.settings')->get('toolbar_items');
  92. sort($config_items);
  93. $this->assertEquals($expected_items, $config_items);
  94. }
  95. /**
  96. * Tests cache metadata headers.
  97. */
  98. public function testCacheHeaders() {
  99. // Disable user toolbar tab so we can test properly if the devel toolbar
  100. // implementation interferes with the page cacheability.
  101. \Drupal::service('module_installer')->install(['toolbar_disable_user_toolbar']);
  102. // The menu is not loaded for users without the adequate permission,
  103. // so no cache tags for configuration are added.
  104. $this->drupalLogin($this->toolbarUser);
  105. $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
  106. $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
  107. // Make sure that the configuration cache tags are present for users with
  108. // the adequate permission.
  109. $this->drupalLogin($this->develUser);
  110. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
  111. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
  112. // The Devel toolbar implementation should not interfere with the page
  113. // cacheability, so you expect a MISS value in the X-Drupal-Dynamic-Cache
  114. // header the first time.
  115. $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'MISS');
  116. // Triggers a page reload and verify that the page is served from the
  117. // cache.
  118. $this->drupalGet('');
  119. $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'HIT');
  120. }
  121. /**
  122. * Tests toolbar integration.
  123. */
  124. public function testToolbarIntegration() {
  125. $library_css_url = 'devel/css/devel.toolbar.css';
  126. $toolbar_selector = '#toolbar-bar .toolbar-tab';
  127. $toolbar_tab_selector = '#toolbar-bar .toolbar-tab a.toolbar-icon-devel';
  128. $toolbar_tray_selector = '#toolbar-bar .toolbar-tab #toolbar-item-devel-tray';
  129. // Ensures that devel toolbar item is accessible only for user with the
  130. // adequate permissions.
  131. $this->drupalGet('');
  132. $this->assertSession()->responseNotContains($library_css_url);
  133. $this->assertSession()->elementNotExists('css', $toolbar_selector);
  134. $this->assertSession()->elementNotExists('css', $toolbar_tab_selector);
  135. $this->drupalLogin($this->toolbarUser);
  136. $this->assertSession()->responseNotContains($library_css_url);
  137. $this->assertSession()->elementExists('css', $toolbar_selector);
  138. $this->assertSession()->elementNotExists('css', $toolbar_tab_selector);
  139. $this->drupalLogin($this->develUser);
  140. $this->assertSession()->responseContains($library_css_url);
  141. $this->assertSession()->elementExists('css', $toolbar_selector);
  142. $this->assertSession()->elementExists('css', $toolbar_tab_selector);
  143. $this->assertSession()->elementTextContains('css', $toolbar_tab_selector, 'Devel');
  144. // Ensures that the configure link in the toolbar is present and point to
  145. // the correct page.
  146. $this->clickLink('Configure');
  147. $this->assertSession()->addressEquals('admin/config/development/devel/toolbar');
  148. // Ensures that the toolbar tray contains the all the menu links. To the
  149. // links not marked as always visible will be assigned a css class that
  150. // allow to hide they when the toolbar has horizontal orientation.
  151. $this->drupalGet('');
  152. $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
  153. $devel_menu_items = $this->getMenuLinkInfos();
  154. $toolbar_items = $toolbar_tray->findAll('css', 'ul.toolbar-menu a');
  155. $this->assertCount(count($devel_menu_items), $toolbar_items);
  156. foreach ($devel_menu_items as $link) {
  157. $item_selector = sprintf('ul.toolbar-menu a:contains("%s")', $link['title']);
  158. $item = $this->assertSession()->elementExists('css', $item_selector, $toolbar_tray);
  159. // TODO: find a more correct way to test link url.
  160. $this->assertContains(strtok($link['url'], '?'), $item->getAttribute('href'));
  161. $not_visible = !in_array($link['id'], $this->defaultToolbarItems);
  162. $this->assertTrue($not_visible === $item->hasClass('toolbar-horizontal-item-hidden'));
  163. }
  164. // Ensures that changing the toolbar settings configuration the changes are
  165. // immediately visible.
  166. $saved_items = $this->config('devel.toolbar.settings')->get('toolbar_items');
  167. $saved_items[] = 'devel.event_info';
  168. $this->config('devel.toolbar.settings')
  169. ->set('toolbar_items', $saved_items)
  170. ->save();
  171. $this->drupalGet('');
  172. $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
  173. $item = $this->assertSession()->elementExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray);
  174. $this->assertFalse($item->hasClass('toolbar-horizontal-item-hidden'));
  175. // Ensures that disabling a menu link it will not more shown in the toolbar
  176. // and that the changes are immediately visible.
  177. $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
  178. $menu_link_manager->updateDefinition('devel.event_info', ['enabled' => FALSE]);
  179. $this->drupalGet('');
  180. $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector);
  181. $this->assertSession()->elementNotExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray);
  182. }
  183. /**
  184. * Tests devel when toolbar module is not installed.
  185. */
  186. public function testToolbarModuleNotInstalled() {
  187. // Ensures that when toolbar module is not installed all works properly.
  188. \Drupal::service('module_installer')->uninstall(['toolbar']);
  189. $this->drupalLogin($this->develUser);
  190. // Toolbar settings page should respond with 404.
  191. $this->drupalGet('admin/config/development/devel/toolbar');
  192. $this->assertSession()->statusCodeEquals(404);
  193. // Primary local task should not contains toolbar tab.
  194. $this->drupalGet('admin/config/development/devel');
  195. $this->assertSession()->statusCodeEquals(200);
  196. $this->assertSession()->elementNotExists('css', '.tabs .primary a:contains("Toolbar Settings")');
  197. // Toolbar setting config and devel menu cache tags sholud not present.
  198. $this->drupalGet('');
  199. $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings');
  200. $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel');
  201. }
  202. /**
  203. * Helper function for retrieve the menu link informations.
  204. *
  205. * @return array
  206. * An array containing the menu link informations.
  207. */
  208. protected function getMenuLinkInfos() {
  209. $parameters = new MenuTreeParameters();
  210. $parameters->onlyEnabledLinks()->setTopLevelOnly();
  211. $tree = \Drupal::menuTree()->load('devel', $parameters);
  212. $links = [];
  213. foreach ($tree as $element) {
  214. $links[] = [
  215. 'id' => $element->link->getPluginId(),
  216. 'title' => $element->link->getTitle(),
  217. 'url' => $element->link->getUrlObject()->toString(),
  218. ];
  219. }
  220. return $links;
  221. }
  222. }