View source
<?php
namespace Drupal\Tests\system\Functional\Theme;
use Drupal\Tests\BrowserTestBase;
class ThemeUiTest extends BrowserTestBase {
protected $defaultTheme = 'stark';
protected $testModules = [
'help' => 'Help',
'test_module_required_by_theme' => 'Test Module Required by Theme',
'test_another_module_required_by_theme' => 'Test Another Module Required by Theme',
];
protected function setUp() {
parent::setUp();
$this
->drupalLogin($this
->drupalCreateUser([
'administer themes',
'administer modules',
]));
}
public function testModulePermissions() {
$this
->drupalLogin($this
->drupalCreateUser([
'administer themes',
]));
$this
->drupalGet('admin/appearance');
$this
->assertSession()
->pageTextContains('This theme requires the listed modules to operate correctly. They must first be enabled by a user with permissions to do so.');
$this
->drupalGet('admin/appearance/install?theme=test_theme_depending_on_modules');
$this
->assertSession()
->statusCodeEquals(404);
$this
->drupalLogin($this
->drupalCreateUser([
'administer themes',
'administer modules',
]));
$this
->drupalGet('admin/appearance');
$this
->assertSession()
->pageTextNotContains('This theme requires the listed modules to operate correctly. They must first be enabled by a user with permissions to do so.');
}
public function testThemeInstallWithModuleDependencies($theme_name, array $first_modules, array $second_modules, array $required_by_messages, $base_theme_to_uninstall, array $base_theme_module_names) {
$assert_session = $this
->assertSession();
$page = $this
->getSession()
->getPage();
$all_dependent_modules = array_merge($first_modules, $second_modules);
$this
->drupalGet('admin/appearance');
$assert_module_enabled_message = function ($enabled_modules) {
$count = count($enabled_modules);
$module_enabled_text = $count === 1 ? "{$this->testModules[$enabled_modules[0]]} has been enabled." : $count . " modules have been enabled:";
$this
->assertSession()
->pageTextContains($module_enabled_text);
};
foreach ($all_dependent_modules as $module) {
$expected_required_list_items[$module] = $this->testModules[$module] . " (disabled)";
}
$this
->assertUninstallableTheme($expected_required_list_items, $theme_name);
$first_module_form_post = [];
foreach ($first_modules as $module) {
$first_module_form_post["modules[{$module}][enable]"] = 1;
}
$this
->drupalPostForm('admin/modules', $first_module_form_post, 'Install');
$assert_module_enabled_message($first_modules);
$this
->drupalGet('admin/appearance');
foreach ($first_modules as $module) {
$expected_required_list_items[$module] = $this->testModules[$module];
}
$this
->assertUninstallableTheme($expected_required_list_items, $theme_name);
$second_module_form_post = [];
foreach ($second_modules as $module) {
$second_module_form_post["modules[{$module}][enable]"] = 1;
}
$this
->drupalPostForm('admin/modules', $second_module_form_post, 'Install');
$assert_module_enabled_message($second_modules);
$this
->drupalGet('admin/appearance');
$page
->clickLink("Install {$theme_name} theme");
$assert_session
->addressEquals('admin/appearance');
$assert_session
->pageTextContains("The {$theme_name} theme has been installed");
$this
->drupalGet('admin/modules/uninstall');
foreach ($all_dependent_modules as $attribute) {
$assert_session
->elementExists('css', "[name=\"uninstall[{$attribute}]\"][disabled]");
}
foreach ($required_by_messages as $selector => $message) {
$assert_session
->elementTextContains('css', $selector, $message);
}
$this
->uninstallTheme($theme_name);
$this
->drupalGet('admin/modules/uninstall');
$modules_to_uninstall = array_diff($all_dependent_modules, $base_theme_module_names);
$this
->uninstallModules($modules_to_uninstall);
if (!empty($base_theme_to_uninstall)) {
$this
->uninstallTheme($base_theme_to_uninstall);
$this
->drupalGet('admin/modules/uninstall');
$this
->uninstallModules($base_theme_module_names);
}
}
protected function uninstallModules(array $module_names) {
$assert_session = $this
->assertSession();
$this
->drupalGet('admin/modules/uninstall');
foreach ($module_names as $attribute) {
$assert_session
->elementExists('css', "[name=\"uninstall[{$attribute}]\"]:not([disabled])");
}
$to_uninstall = [];
foreach ($module_names as $attribute) {
$to_uninstall["uninstall[{$attribute}]"] = 1;
}
if (!empty($to_uninstall)) {
$this
->drupalPostForm('admin/modules/uninstall', $to_uninstall, 'Uninstall');
$assert_session
->pageTextContains('The following modules will be completely uninstalled from your site, and all data from these modules will be lost!');
$assert_session
->pageTextContains('Would you like to continue with uninstalling the above?');
foreach ($module_names as $module_name) {
$assert_session
->pageTextContains($this->testModules[$module_name]);
}
$this
->getSession()
->getPage()
->pressButton('Uninstall');
$assert_session
->pageTextContains('The selected modules have been uninstalled.');
}
}
protected function uninstallTheme($theme_name) {
$this
->drupalGet('admin/appearance');
$this
->clickLink("Uninstall {$theme_name} theme");
$this
->assertSession()
->pageTextContains("The {$theme_name} theme has been uninstalled.");
}
public function providerTestThemeInstallWithModuleDependencies() {
return [
'test theme with a module dependency and base theme with a different module dependency' => [
'theme_name' => 'Test Theme with a Module Dependency and Base Theme with a Different Module Dependency',
'first_modules' => [
'test_module_required_by_theme',
'test_another_module_required_by_theme',
],
'second_modules' => [
'help',
],
'required_by_messages' => [
'[data-drupal-selector="edit-test-another-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
'[data-drupal-selector="edit-test-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
'[data-drupal-selector="edit-help"] .item-list' => 'Required by the theme: Test Theme with a Module Dependency and Base Theme with a Different Module Dependency',
],
'base_theme_to_uninstall' => 'Test Theme Depending on Modules',
'base_theme_module_names' => [
'test_module_required_by_theme',
'test_another_module_required_by_theme',
],
],
'Test Theme Depending on Modules' => [
'theme_name' => 'Test Theme Depending on Modules',
'first_modules' => [
'test_module_required_by_theme',
],
'second_modules' => [
'test_another_module_required_by_theme',
],
'required_by_messages' => [
'[data-drupal-selector="edit-test-another-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
'[data-drupal-selector="edit-test-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
],
'base_theme_to_uninstall' => '',
'base_theme_module_names' => [],
],
'test theme with a base theme depending on modules' => [
'theme_name' => 'Test Theme with a Base Theme Depending on Modules',
'first_modules' => [
'test_module_required_by_theme',
],
'second_modules' => [
'test_another_module_required_by_theme',
],
'required_by_messages' => [
'[data-drupal-selector="edit-test-another-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
'[data-drupal-selector="edit-test-module-required-by-theme"] .item-list' => 'Required by the theme: Test Theme Depending on Modules',
],
'base_theme_to_uninstall' => 'Test Theme Depending on Modules',
'base_theme_module_names' => [
'test_module_required_by_theme',
'test_another_module_required_by_theme',
],
],
];
}
protected function assertUninstallableTheme(array $expected_requires_list_items, $theme_name) {
$theme_container = $this
->getSession()
->getPage()
->find('css', "h3:contains(\"{$theme_name}\")")
->getParent();
$requires_list_items = $theme_container
->findAll('css', '.theme-info__requires li');
$this
->assertCount(count($expected_requires_list_items), $requires_list_items);
foreach ($requires_list_items as $key => $item) {
$this
->assertContains($item
->getText(), $expected_requires_list_items);
}
$incompatible = $theme_container
->find('css', '.incompatible');
$expected_incompatible_text = 'This theme requires the listed modules to operate correctly. They must first be enabled via the Extend page.';
$this
->assertSame($expected_incompatible_text, $incompatible
->getText());
$this
->assertFalse($theme_container
->hasLink('Install Test Theme Depending on Modules theme'));
}
public function testInstallModuleWithMissingDependencies() {
$this
->drupalGet('admin/appearance');
$theme_container = $this
->getSession()
->getPage()
->find('css', 'h3:contains("Test Theme Depending on Nonexisting Module")')
->getParent();
$this
->assertStringContainsString('Requires: test_module_non_existing (missing)', $theme_container
->getText());
$this
->assertStringContainsString('This theme requires the listed modules to operate correctly.', $theme_container
->getText());
}
public function testInstallModuleWithIncompatibleDependencies() {
$this->container
->get('module_installer')
->install([
'test_module_compatible_constraint',
'test_module_incompatible_constraint',
]);
$this
->drupalGet('admin/appearance');
$theme_container = $this
->getSession()
->getPage()
->find('css', 'h3:contains("Test Theme Depending on Version Constrained Modules")')
->getParent();
$this
->assertStringContainsString('Requires: Test Module Theme Depends on with Compatible ConstraintTest Module Theme Depends on with Incompatible Constraint (>=8.x-2.x) (incompatible with version 8.x-1.8)', $theme_container
->getText());
$this
->assertStringContainsString('This theme requires the listed modules to operate correctly.', $theme_container
->getText());
}
}