/modules/system/tests/src/Functional/Theme/ThemeSuggestionsAlterTest.php

https://github.com/drupal/core · PHP · 154 lines · 85 code · 22 blank · 47 comment · 0 complexity · 53d6cbf32a1bc3bf55a33722e36f9f85 MD5 · raw file

  1. <?php
  2. namespace Drupal\Tests\system\Functional\Theme;
  3. use Drupal\Component\Utility\Xss;
  4. use Drupal\Tests\BrowserTestBase;
  5. /**
  6. * Tests theme suggestion alter hooks.
  7. *
  8. * @group Theme
  9. */
  10. class ThemeSuggestionsAlterTest extends BrowserTestBase {
  11. /**
  12. * Modules to enable.
  13. *
  14. * @var array
  15. */
  16. public static $modules = ['theme_test'];
  17. /**
  18. * {@inheritdoc}
  19. */
  20. protected $defaultTheme = 'stark';
  21. protected function setUp() {
  22. parent::setUp();
  23. \Drupal::service('theme_installer')->install(['test_theme']);
  24. }
  25. /**
  26. * Tests that hooks to provide theme suggestions work.
  27. */
  28. public function testTemplateSuggestions() {
  29. $this->drupalGet('theme-test/suggestion-provided');
  30. $this->assertText('Template for testing suggestions provided by the module declaring the theme hook.');
  31. // Install test_theme, it contains a template suggested by theme_test.module
  32. // in theme_test_theme_suggestions_theme_test_suggestion_provided().
  33. $this->config('system.theme')
  34. ->set('default', 'test_theme')
  35. ->save();
  36. $this->drupalGet('theme-test/suggestion-provided');
  37. $this->assertText('Template overridden based on suggestion provided by the module declaring the theme hook.');
  38. }
  39. /**
  40. * Tests hook_theme_suggestions_alter().
  41. */
  42. public function testGeneralSuggestionsAlter() {
  43. $this->drupalGet('theme-test/general-suggestion-alter');
  44. $this->assertText('Original template for testing hook_theme_suggestions_alter().');
  45. // Install test_theme and test that themes can alter template suggestions.
  46. $this->config('system.theme')
  47. ->set('default', 'test_theme')
  48. ->save();
  49. $this->drupalGet('theme-test/general-suggestion-alter');
  50. $this->assertText('Template overridden based on new theme suggestion provided by the test_theme theme via hook_theme_suggestions_alter().');
  51. // Enable the theme_suggestions_test module to test modules implementing
  52. // suggestions alter hooks.
  53. \Drupal::service('module_installer')->install(['theme_suggestions_test']);
  54. $this->resetAll();
  55. $this->drupalGet('theme-test/general-suggestion-alter');
  56. $this->assertText('Template overridden based on new theme suggestion provided by a module via hook_theme_suggestions_alter().');
  57. }
  58. /**
  59. * Tests that theme suggestion alter hooks work for templates.
  60. */
  61. public function testTemplateSuggestionsAlter() {
  62. $this->drupalGet('theme-test/suggestion-alter');
  63. $this->assertText('Original template for testing hook_theme_suggestions_HOOK_alter().');
  64. // Install test_theme and test that themes can alter template suggestions.
  65. $this->config('system.theme')
  66. ->set('default', 'test_theme')
  67. ->save();
  68. $this->drupalGet('theme-test/suggestion-alter');
  69. $this->assertText('Template overridden based on new theme suggestion provided by the test_theme theme via hook_theme_suggestions_HOOK_alter().');
  70. // Enable the theme_suggestions_test module to test modules implementing
  71. // suggestions alter hooks.
  72. \Drupal::service('module_installer')->install(['theme_suggestions_test']);
  73. $this->resetAll();
  74. $this->drupalGet('theme-test/suggestion-alter');
  75. $this->assertText('Template overridden based on new theme suggestion provided by a module via hook_theme_suggestions_HOOK_alter().');
  76. }
  77. /**
  78. * Tests that theme suggestion alter hooks work for specific theme calls.
  79. */
  80. public function testSpecificSuggestionsAlter() {
  81. // Test that the default template is rendered.
  82. $this->drupalGet('theme-test/specific-suggestion-alter');
  83. $this->assertText('Template for testing specific theme calls.');
  84. $this->config('system.theme')
  85. ->set('default', 'test_theme')
  86. ->save();
  87. // Test a specific theme call similar to '#theme' => 'node__article'.
  88. $this->drupalGet('theme-test/specific-suggestion-alter');
  89. $this->assertText('Template matching the specific theme call.');
  90. $this->assertText('theme_test_specific_suggestions__variant', 'Specific theme call is added to the suggestions array.');
  91. // Ensure that the base hook is used to determine the suggestion alter hook.
  92. \Drupal::service('module_installer')->install(['theme_suggestions_test']);
  93. $this->resetAll();
  94. $this->drupalGet('theme-test/specific-suggestion-alter');
  95. $this->assertText('Template overridden based on suggestion alter hook determined by the base hook.');
  96. $raw_content = $this->getSession()->getPage()->getContent();
  97. $this->assertTrue(strpos($raw_content, 'theme_test_specific_suggestions__variant') < strpos($raw_content, 'theme_test_specific_suggestions__variant__foo'), 'Specific theme call is added to the suggestions array before the suggestions alter hook.');
  98. }
  99. /**
  100. * Tests execution order of theme suggestion alter hooks.
  101. *
  102. * Hook hook_theme_suggestions_alter() should fire before
  103. * hook_theme_suggestions_HOOK_alter() within an extension (module or theme).
  104. */
  105. public function testExecutionOrder() {
  106. // Install our test theme and module.
  107. $this->config('system.theme')
  108. ->set('default', 'test_theme')
  109. ->save();
  110. \Drupal::service('module_installer')->install(['theme_suggestions_test']);
  111. $this->resetAll();
  112. // Send two requests so that we get all the messages we've set via
  113. // \Drupal\Core\Messenger\MessengerInterface::addStatus().
  114. $this->drupalGet('theme-test/suggestion-alter');
  115. // Ensure that the order is first by extension, then for a given extension,
  116. // the hook-specific one after the generic one.
  117. $expected_order = [
  118. 'theme_suggestions_test_theme_suggestions_alter() executed.',
  119. 'theme_suggestions_test_theme_suggestions_theme_test_suggestions_alter() executed.',
  120. 'theme_test_theme_suggestions_alter() executed for theme_test_suggestions.',
  121. 'theme_test_theme_suggestions_theme_test_suggestions_alter() executed.',
  122. 'test_theme_theme_suggestions_alter() executed.',
  123. 'test_theme_theme_suggestions_theme_test_suggestions_alter() executed.',
  124. ];
  125. $content = preg_replace('/\s+/', ' ', Xss::filter($this->getSession()->getPage()->getContent(), []));
  126. $order = 0;
  127. foreach ($expected_order as $expected_string) {
  128. $this->assertGreaterThan($order, strpos($content, $expected_string));
  129. $order = strpos($content, $expected_string);
  130. }
  131. }
  132. }