Issue #2907728 by Lendude, vaplas, dawehner, jibran, alexpott, Mile23: Installer: Convert system functional tests to phpunit

8.6.x
Alex Pott 2018-02-26 16:56:46 +00:00
parent d208812e5c
commit 21dd263835
33 changed files with 502 additions and 175 deletions

View File

@ -97,28 +97,6 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
parent::tearDown();
}
/**
* Transforms a nested array into a flat array suitable for BrowserTestBase::drupalPostForm().
*
* @param array $values
* A multi-dimensional form values array to convert.
*
* @return array
* The flattened $edit array suitable for BrowserTestBase::drupalPostForm().
*/
protected function translatePostValues(array $values) {
$edit = [];
// The easiest and most straightforward way to translate values suitable for
// BrowserTestBase::drupalPostForm() is to actually build the POST data string
// and convert the resulting key/value pairs back into a flat array.
$query = http_build_query($values);
foreach (explode('&', $query) as $item) {
list($key, $value) = explode('=', $item);
$edit[urldecode($key)] = urldecode($value);
}
return $edit;
}
/**
* Tests the displayed upgrade paths.
*

View File

@ -2,6 +2,8 @@
namespace Drupal\system\Tests\Installer;
@trigger_error(__NAMESPACE__ . '\ConfigAfterInstallerTestBase is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\FunctionalTests\Installer\ConfigAfterInstallerTestBase.', E_USER_DEPRECATED);
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
@ -10,6 +12,9 @@ use Drupal\simpletest\InstallerTestBase;
/**
* Provides a class for install profiles to check their installed config.
*
* @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\FunctionalTests\Installer\ConfigAfterInstallerTestBase.
*/
abstract class ConfigAfterInstallerTestBase extends InstallerTestBase {

View File

@ -0,0 +1,44 @@
<?php
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\KernelTests\AssertConfigTrait;
/**
* Provides a class for install profiles to check their installed config.
*/
abstract class ConfigAfterInstallerTestBase extends InstallerTestBase {
use AssertConfigTrait;
/**
* Ensures that all the installed config looks like the exported one.
*
* @param array $skipped_config
* An array of skipped config.
*/
protected function assertInstalledConfig(array $skipped_config) {
$this->addToAssertionCount(1);
/** @var \Drupal\Core\Config\StorageInterface $active_config_storage */
$active_config_storage = $this->container->get('config.storage');
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
$config_manager = $this->container->get('config.manager');
$default_install_path = 'core/profiles/' . $this->profile . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
$profile_config_storage = new FileStorage($default_install_path, StorageInterface::DEFAULT_COLLECTION);
foreach ($profile_config_storage->listAll() as $config_name) {
$result = $config_manager->diff($profile_config_storage, $active_config_storage, $config_name);
try {
$this->assertConfigDiff($result, $config_name, $skipped_config);
}
catch (\Exception $e) {
$this->fail($e->getMessage());
}
}
}
}

View File

@ -1,12 +1,11 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
use Symfony\Component\HttpFoundation\Request;
/**
@ -26,7 +25,8 @@ class DistributionProfileExistingSettingsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->info = [
'type' => 'profile',
'core' => \Drupal::CORE_COMPATIBILITY,
@ -71,7 +71,6 @@ class DistributionProfileExistingSettingsTest extends InstallerTestBase {
],
];
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}
/**

View File

@ -1,10 +1,9 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests distribution profile support.
@ -20,7 +19,8 @@ class DistributionProfileTest extends InstallerTestBase {
*/
protected $info;
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->info = [
'type' => 'profile',
'core' => \Drupal::CORE_COMPATIBILITY,
@ -36,8 +36,6 @@ class DistributionProfileTest extends InstallerTestBase {
$path = $this->siteDirectory . '/profiles/mydistro';
mkdir($path, 0777, TRUE);
file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info));
parent::setUp();
}
/**

View File

@ -1,16 +1,15 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Serialization\Yaml;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests distribution profile support with a 'langcode' query string.
*
* @group Installer
*
* @see \Drupal\system\Tests\Installer\DistributionProfileTranslationTest
* @see \Drupal\FunctionalTests\Installer\DistributionProfileTranslationTest
*/
class DistributionProfileTranslationQueryTest extends InstallerTestBase {
@ -29,7 +28,8 @@ class DistributionProfileTranslationQueryTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->info = [
'type' => 'profile',
'core' => \Drupal::CORE_COMPATIBILITY,
@ -43,22 +43,19 @@ class DistributionProfileTranslationQueryTest extends InstallerTestBase {
],
];
// File API functions are not available yet.
$path = $this->siteDirectory . '/profiles/mydistro';
$path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/mydistro';
mkdir($path, 0777, TRUE);
file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info));
parent::setUp();
// Place a custom local translation in the translations directory.
mkdir($this->root . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE);
file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de'));
file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.fr.po', $this->getPo('fr'));
}
/**
* {@inheritdoc}
*/
protected function visitInstaller() {
// Place a custom local translation in the translations directory.
mkdir(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE);
file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de'));
file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.fr.po', $this->getPo('fr'));
// Pass a different language code than the one set in the distribution
// profile. This distribution language should still be used.
// The unrouted URL assembler does not exist at this point, so we build the
@ -88,11 +85,11 @@ class DistributionProfileTranslationQueryTest extends InstallerTestBase {
// The language should have been automatically detected, all following
// screens should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value');
$this->assertEqual((string) current($elements), 'Save and continue de');
$this->assertEqual(current($elements)->getText(), 'Save and continue de');
$this->translations['Save and continue'] = 'Save and continue de';
// Check the language direction.
$direction = (string) current($this->xpath('/html/@dir'));
$direction = $this->getSession()->getPage()->find('xpath', '/@dir')->getText();
$this->assertEqual($direction, 'ltr');
// Verify that the distribution name appears.

View File

@ -1,16 +1,15 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Serialization\Yaml;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests distribution profile support.
*
* @group Installer
*
* @see \Drupal\system\Tests\Installer\DistributionProfileTest
* @see \Drupal\FunctionalTests\Installer\DistributionProfileTest
*/
class DistributionProfileTranslationTest extends InstallerTestBase {
@ -29,7 +28,8 @@ class DistributionProfileTranslationTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->info = [
'type' => 'profile',
'core' => \Drupal::CORE_COMPATIBILITY,
@ -43,22 +43,13 @@ class DistributionProfileTranslationTest extends InstallerTestBase {
],
];
// File API functions are not available yet.
$path = $this->siteDirectory . '/profiles/mydistro';
$path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/mydistro';
mkdir($path, 0777, TRUE);
file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info));
parent::setUp();
}
/**
* {@inheritdoc}
*/
protected function visitInstaller() {
// Place a custom local translation in the translations directory.
mkdir(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE);
file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de'));
parent::visitInstaller();
mkdir($this->root . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE);
file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de'));
}
/**
@ -83,11 +74,11 @@ class DistributionProfileTranslationTest extends InstallerTestBase {
// The language should have been automatically detected, all following
// screens should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value');
$this->assertEqual((string) current($elements), 'Save and continue de');
$this->assertEqual(current($elements)->getText(), 'Save and continue de');
$this->translations['Save and continue'] = 'Save and continue de';
// Check the language direction.
$direction = (string) current($this->xpath('/html/@dir'));
$direction = current($this->xpath('/@dir'))->getText();
$this->assertEqual($direction, 'ltr');
// Verify that the distribution name appears.

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Component\Utility\Crypt;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests the installer when a config_directory set up but does not exist.
@ -22,7 +21,8 @@ class InstallerConfigDirectorySetNoDirectoryErrorTest extends InstallerTestBase
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->configDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64();
$this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [
'value' => $this->configDirectory . '/sync',
@ -32,7 +32,6 @@ class InstallerConfigDirectorySetNoDirectoryErrorTest extends InstallerTestBase
mkdir($this->publicFilesDirectory);
// Create a file so the directory can not be created.
file_put_contents($this->configDirectory, 'Test');
parent::setUp();
}
/**

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Component\Utility\Crypt;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests the installer when a config_directory set up but does not exist.
@ -22,7 +21,8 @@ class InstallerConfigDirectorySetNoDirectoryTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
$this->syncDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64() . '/sync';
$this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [
'value' => $this->syncDirectory,
@ -33,7 +33,6 @@ class InstallerConfigDirectorySetNoDirectoryTest extends InstallerTestBase {
'value' => $this->publicFilesDirectory . '/config_custom',
'required' => TRUE,
];
parent::setUp();
}
/**

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Database\Database;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests the installer with database errors.

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests the installer with empty settings file.
@ -14,10 +12,11 @@ class InstallerEmptySettingsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Create an empty settings.php file.
touch($this->siteDirectory . '/settings.php');
parent::setUp();
$path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory;
file_put_contents($path . '/settings.php', '');
}
/**

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests the installer when a config_directory has already been set up.
@ -21,14 +19,14 @@ class InstallerExistingConfigDirectoryTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
mkdir($this->siteDirectory . '/config_read_only', 0444);
protected function prepareEnvironment() {
parent::prepareEnvironment();
mkdir($this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/config_read_only', 0444);
$this->expectedFilePerms = fileperms($this->siteDirectory . '/config_read_only');
$this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [
'value' => $this->siteDirectory . '/config_read_only',
'required' => TRUE,
];
parent::setUp();
}
/**

View File

@ -1,8 +1,7 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
/**
@ -16,7 +15,8 @@ class InstallerExistingDatabaseSettingsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure database credentials in settings.php.
$connection_info = Database::getConnectionInfo();
unset($connection_info['default']['pdo']);
@ -26,7 +26,6 @@ class InstallerExistingDatabaseSettingsTest extends InstallerTestBase {
'value' => $connection_info,
'required' => TRUE,
];
parent::setUp();
}
/**

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests the installer with an existing Drupal installation.
@ -11,13 +9,6 @@ use Drupal\simpletest\InstallerTestBase;
*/
class InstallerExistingInstallationTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
}
/**
* Verifies that Drupal can't be reinstalled while an existing installation is
* available.

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\DrupalKernel;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
use Symfony\Component\HttpFoundation\Request;
@ -20,7 +19,8 @@ class InstallerExistingSettingsMismatchProfileBrokenTest extends InstallerTestBa
* Configures a preexisting settings.php file without an install_profile
* setting before invoking the interactive installer.
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure hash salt.
// Any string is valid, so simply use the class name of this test.
$this->settings['settings']['hash_salt'] = (object) [
@ -54,8 +54,6 @@ class InstallerExistingSettingsMismatchProfileBrokenTest extends InstallerTestBa
],
];
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}
/**

View File

@ -1,10 +1,9 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
use Symfony\Component\HttpFoundation\Request;
@ -21,7 +20,8 @@ class InstallerExistingSettingsMismatchProfileTest extends InstallerTestBase {
* Configures a preexisting settings.php file without an install_profile
* setting before invoking the interactive installer.
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure hash salt.
// Any string is valid, so simply use the class name of this test.
$this->settings['settings']['hash_salt'] = (object) [
@ -54,8 +54,6 @@ class InstallerExistingSettingsMismatchProfileTest extends InstallerTestBase {
],
];
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}
/**

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\DrupalKernel;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
use Symfony\Component\HttpFoundation\Request;
@ -20,7 +19,9 @@ class InstallerExistingSettingsNoProfileTest extends InstallerTestBase {
* Configures a preexisting settings.php file without an install_profile
* setting before invoking the interactive installer.
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure hash salt.
// Any string is valid, so simply use the class name of this test.
$this->settings['settings']['hash_salt'] = (object) [
@ -46,8 +47,6 @@ class InstallerExistingSettingsNoProfileTest extends InstallerTestBase {
],
];
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}
/**

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;
@ -21,7 +20,8 @@ class InstallerExistingSettingsTest extends InstallerTestBase {
* Fully configures a preexisting settings.php file before invoking the
* interactive installer.
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure hash salt.
// Any string is valid, so simply use the class name of this test.
$this->settings['settings']['hash_salt'] = (object) [
@ -57,8 +57,6 @@ class InstallerExistingSettingsTest extends InstallerTestBase {
],
];
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}
/**

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Verifies that the early installer uses the correct language direction.
@ -30,11 +28,11 @@ class InstallerLanguageDirectionTest extends InstallerTestBase {
// After selecting a different language than English, all following screens
// should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value');
$this->assertEqual((string) current($elements), 'Save and continue Arabic');
$this->assertEqual(current($elements)->getText(), 'Save and continue Arabic');
$this->translations['Save and continue'] = 'Save and continue Arabic';
// Verify that language direction is right-to-left.
$direction = (string) current($this->xpath('/html/@dir'));
$direction = current($this->xpath('/@dir'))->getText();
$this->assertEqual($direction, 'rtl');
}

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Language\LanguageManager;
use Drupal\simpletest\InstallerTestBase;
/**
* Verifies that the installer language list combines local and remote languages.

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests the interactive installer.
@ -37,11 +35,11 @@ class InstallerTest extends InstallerTestBase {
protected function setUpLanguage() {
// Test that \Drupal\Core\Render\BareHtmlPageRenderer adds assets and
// metatags as expected to the first page of the installer.
$this->assertRaw('core/themes/seven/css/components/buttons.css');
$this->assertRaw("core/themes/seven/css/components/buttons.css");
$this->assertRaw('<meta charset="utf-8" />');
// Assert that the expected title is present.
$this->assertEqual('Choose language', $this->cssSelect('main h2')[0]);
$this->assertEqual('Choose language', $this->cssSelect('main h2')[0]->getText());
parent::setUpLanguage();
}
@ -51,7 +49,7 @@ class InstallerTest extends InstallerTestBase {
*/
protected function setUpProfile() {
// Assert that the expected title is present.
$this->assertEqual('Select an installation profile', $this->cssSelect('main h2')[0]);
$this->assertEqual('Select an installation profile', $this->cssSelect('main h2')[0]->getText());
$result = $this->xpath('//span[contains(@class, :class) and contains(text(), :text)]', [':class' => 'visually-hidden', ':text' => 'Select an installation profile']);
$this->assertEqual(count($result), 1, "Title/Label not displayed when '#title_display' => 'invisible' attribute is set");
@ -63,7 +61,7 @@ class InstallerTest extends InstallerTestBase {
*/
protected function setUpSettings() {
// Assert that the expected title is present.
$this->assertEqual('Database configuration', $this->cssSelect('main h2')[0]);
$this->assertEqual('Database configuration', $this->cssSelect('main h2')[0]->getText());
parent::setUpSettings();
}
@ -73,7 +71,7 @@ class InstallerTest extends InstallerTestBase {
*/
protected function setUpSite() {
// Assert that the expected title is present.
$this->assertEqual('Configure site', $this->cssSelect('main h2')[0]);
$this->assertEqual('Configure site', $this->cssSelect('main h2')[0]->getText());
parent::setUpSite();
}

View File

@ -0,0 +1,316 @@
<?php
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Language\Language;
use Drupal\Core\Session\UserSession;
use Drupal\Core\Site\Settings;
use Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware;
use Drupal\Tests\BrowserTestBase;
use GuzzleHttp\HandlerStack;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Base class for testing the interactive installer.
*/
abstract class InstallerTestBase extends BrowserTestBase {
/**
* Custom settings.php values to write for a test run.
*
* @var array
* An array of settings to write out, in the format expected by
* drupal_rewrite_settings().
*/
protected $settings = [];
/**
* The language code in which to install Drupal.
*
* @var string
*/
protected $langcode = 'en';
/**
* The installation profile to install.
*
* @var string
*/
protected $profile = 'testing';
/**
* Additional parameters to use for installer screens.
*
* @see FunctionalTestSetupTrait::installParameters()
*
* @var array
*/
protected $parameters = [];
/**
* A string translation map used for translated installer screens.
*
* Keys are English strings, values are translated strings.
*
* @var array
*/
protected $translations = [
'Save and continue' => 'Save and continue',
];
/**
* Whether the installer has completed.
*
* @var bool
*/
protected $isInstalled = FALSE;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->isInstalled = FALSE;
$this->setupBaseUrl();
$this->prepareDatabasePrefix();
// Install Drupal test site.
$this->prepareEnvironment();
// Define information about the user 1 account.
$this->rootUser = new UserSession([
'uid' => 1,
'name' => 'admin',
'mail' => 'admin@example.com',
'pass_raw' => $this->randomMachineName(),
]);
// If any $settings are defined for this test, copy and prepare an actual
// settings.php, so as to resemble a regular installation.
if (!empty($this->settings)) {
// Not using File API; a potential error must trigger a PHP warning.
copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
$this->writeSettings($this->settings);
}
// Note that FunctionalTestSetupTrait::installParameters() returns form
// input values suitable for a programmed
// \Drupal::formBuilder()->submitForm().
// @see InstallerTestBase::translatePostValues()
$this->parameters = $this->installParameters();
// Set up a minimal container (required by BrowserTestBase). Set cookie and
// server information so that XDebug works.
// @see install_begin_request()
$request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER);
$this->container = new ContainerBuilder();
$request_stack = new RequestStack();
$request_stack->push($request);
$this->container
->set('request_stack', $request_stack);
$this->container
->setParameter('language.default_values', Language::$defaultValues);
$this->container
->register('language.default', 'Drupal\Core\Language\LanguageDefault')
->addArgument('%language.default_values%');
$this->container
->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
->addArgument(new Reference('language.default'));
$this->container
->register('http_client', 'GuzzleHttp\Client')
->setFactory('http_client_factory:fromOptions');
$this->container
->register('http_client_factory', 'Drupal\Core\Http\ClientFactory')
->setArguments([new Reference('http_handler_stack')]);
$handler_stack = HandlerStack::create();
$test_http_client_middleware = new TestHttpClientMiddleware();
$handler_stack->push($test_http_client_middleware(), 'test.http_client.middleware');
$this->container
->set('http_handler_stack', $handler_stack);
$this->container
->set('app.root', DRUPAL_ROOT);
\Drupal::setContainer($this->container);
// Setup Mink.
$this->initMink();
$this->visitInstaller();
// Select language.
$this->setUpLanguage();
// Select profile.
$this->setUpProfile();
// Address the requirements problem screen, if any.
$this->setUpRequirementsProblem();
// Configure settings.
$this->setUpSettings();
// @todo Allow test classes based on this class to act on further installer
// screens.
// Configure site.
$this->setUpSite();
if ($this->isInstalled) {
// Import new settings.php written by the installer.
$request = Request::createFromGlobals();
$class_loader = require $this->container->get('app.root') . '/autoload.php';
Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
foreach ($GLOBALS['config_directories'] as $type => $path) {
$this->configDirectories[$type] = $path;
}
// After writing settings.php, the installer removes write permissions
// from the site directory. To allow drupal_generate_test_ua() to write
// a file containing the private key for drupal_valid_test_ua(), the site
// directory has to be writable.
// BrowserTestBase::tearDown() will delete the entire test site directory.
// Not using File API; a potential error must trigger a PHP warning.
chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
$this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
$this->kernel->prepareLegacyRequest($request);
$this->container = $this->kernel->getContainer();
// Manually configure the test mail collector implementation to prevent
// tests from sending out emails and collect them in state instead.
$this->container->get('config.factory')
->getEditable('system.mail')
->set('interface.default', 'test_mail_collector')
->save();
}
}
/**
* {@inheritdoc}
*/
protected function initFrontPage() {
// We don't want to visit the front page with the installer when
// initializing Mink, so we do nothing here.
}
/**
* Visits the interactive installer.
*/
protected function visitInstaller() {
$this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
}
/**
* Installer step: Select language.
*/
protected function setUpLanguage() {
$edit = [
'langcode' => $this->langcode,
];
$this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
}
/**
* Installer step: Select installation profile.
*/
protected function setUpProfile() {
$edit = [
'profile' => $this->profile,
];
$this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
}
/**
* Installer step: Configure settings.
*/
protected function setUpSettings() {
$edit = $this->translatePostValues($this->parameters['forms']['install_settings_form']);
$this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
}
/**
* Installer step: Requirements problem.
*
* Override this method to test specific requirements warnings or errors
* during the installer.
*
* @see system_requirements()
*/
protected function setUpRequirementsProblem() {
// By default, skip the "recommended PHP version" warning on older test
// environments. This allows the installer to be tested consistently on
// both recommended PHP versions and older (but still supported) versions.
if (version_compare(phpversion(), '7.0') < 0) {
$this->continueOnExpectedWarnings(['PHP']);
}
}
/**
* Final installer step: Configure site.
*/
protected function setUpSite() {
$edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']);
$this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
// If we've got to this point the site is installed using the regular
// installation workflow.
$this->isInstalled = TRUE;
}
/**
* {@inheritdoc}
*
* FunctionalTestSetupTrait::refreshVariables() tries to operate on persistent
* storage, which is only available after the installer completed.
*/
protected function refreshVariables() {
if ($this->isInstalled) {
parent::refreshVariables();
}
}
/**
* Continues installation when an expected warning is found.
*
* @param string[] $expected_warnings
* A list of warning summaries to expect on the requirements screen (e.g.
* 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings
* are found, the test will click the "continue anyway" link to go to the
* next screen of the installer. If an expected warning is not found, or if
* a warning not in the list is present, a fail is raised.
*/
protected function continueOnExpectedWarnings($expected_warnings = []) {
// Don't try to continue if there are errors.
if (strpos($this->getTextContent(), 'Errors found') !== FALSE) {
return;
}
// Allow only details elements that are directly after the warning header
// or each other. There is no guaranteed wrapper we can rely on across
// distributions. When there are multiple warnings, the selectors will be:
// - h3#warning+details summary
// - h3#warning+details+details summary
// - etc.
// We add one more selector than expected warnings to confirm that there
// isn't any other warning before clicking the link.
// @todo Make this more reliable in
// https://www.drupal.org/project/drupal/issues/2927345.
$selectors = [];
for ($i = 0; $i <= count($expected_warnings); $i++) {
$selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary';
}
$warning_elements = $this->cssSelect(implode(', ', $selectors));
// Confirm that there are only the expected warnings.
$warnings = [];
foreach ($warning_elements as $warning) {
$warnings[] = trim($warning->getText());
}
$this->assertEquals($expected_warnings, $warnings);
$this->clickLink('continue anyway');
$this->checkForMetaRefresh();
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests translation files for multiple languages get imported during install.

View File

@ -1,6 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests that keeping English in a foreign language install works.

View File

@ -1,8 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests translation files for multiple languages get imported during install.

View File

@ -1,15 +1,13 @@
<?php
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
namespace Drupal\FunctionalTests\Installer;
/**
* Installs Drupal in German and checks resulting site.
*
* @group Installer
*
* @see \Drupal\system\Tests\Installer\InstallerTranslationTest
* @see \Drupal\FunctionalTests\Installer\InstallerTranslationTest
*/
class InstallerTranslationQueryTest extends InstallerTestBase {
@ -35,11 +33,11 @@ class InstallerTranslationQueryTest extends InstallerTestBase {
// The language should have been automatically detected, all following
// screens should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value');
$this->assertEqual((string) current($elements), 'Save and continue de');
$this->assertEqual(current($elements)->getText(), 'Save and continue de');
$this->translations['Save and continue'] = 'Save and continue de';
// Check the language direction.
$direction = (string) current($this->xpath('/html/@dir'));
$direction = current($this->xpath('/@dir'))->getText();
$this->assertEqual($direction, 'ltr');
}

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Database\Database;
use Drupal\simpletest\InstallerTestBase;
use Drupal\user\Entity\User;
/**
@ -33,11 +32,11 @@ class InstallerTranslationTest extends InstallerTestBase {
// After selecting a different language than English, all following screens
// should be translated already.
$elements = $this->xpath('//input[@type="submit"]/@value');
$this->assertEqual((string) current($elements), 'Save and continue de');
$this->assertEqual(current($elements)->getText(), 'Save and continue de');
$this->translations['Save and continue'] = 'Save and continue de';
// Check the language direction.
$direction = (string) current($this->xpath('/html/@dir'));
$direction = current($this->xpath('/@dir'))->getText();
$this->assertEqual($direction, 'ltr');
}

View File

@ -1,6 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\KernelTests\AssertConfigTrait;

View File

@ -1,10 +1,9 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests multiple distribution profile support.
@ -23,7 +22,8 @@ class MultipleDistributionsProfileTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Create two distributions.
foreach (['distribution_one', 'distribution_two'] as $name) {
$info = [
@ -38,14 +38,12 @@ class MultipleDistributionsProfileTest extends InstallerTestBase {
],
];
// File API functions are not available yet.
$path = $this->siteDirectory . '/profiles/' . $name;
$path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/' . $name;
mkdir($path, 0777, TRUE);
file_put_contents("$path/$name.info.yml", Yaml::encode($info));
}
// Install the first distribution.
$this->profile = 'distribution_one';
parent::setUp();
}
/**

View File

@ -1,9 +1,8 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Serialization\Yaml;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests distribution profile support.
@ -21,7 +20,11 @@ class SingleVisibleProfileTest extends InstallerTestBase {
*/
protected $profile = NULL;
protected function setUp() {
/**
* {@inheritdoc}
*/
protected function prepareEnvironment() {
parent::prepareEnvironment();
$profiles = ['standard', 'demo_umami'];
foreach ($profiles as $profile) {
$info = [
@ -35,7 +38,6 @@ class SingleVisibleProfileTest extends InstallerTestBase {
mkdir($path, 0777, TRUE);
file_put_contents("$path/$profile.info.yml", Yaml::encode($info));
}
parent::setUp();
}
/**

View File

@ -1,15 +1,15 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that the site name can be set during a non-interactive installation.
*
* @group Installer
*/
class SiteNameTest extends WebTestBase {
class SiteNameTest extends BrowserTestBase {
/**
* The site name to be used when testing.

View File

@ -1,6 +1,6 @@
<?php
namespace Drupal\system\Tests\Installer;
namespace Drupal\FunctionalTests\Installer;
/**
* Tests the interactive installer installing the standard profile.
@ -50,7 +50,7 @@ class StandardInstallerTest extends ConfigAfterInstallerTestBase {
*/
public function testStandardConfig() {
$skipped_config = [];
// \Drupal\simpletest\WebTestBase::installParameters() uses
// FunctionalTestSetupTrait::installParameters() uses
// simpletest@example.com as mail address.
$skipped_config['contact.form.feedback'][] = '- simpletest@example.com';
// \Drupal\filter\Entity\FilterFormat::toArray() drops the roles of filter

View File

@ -321,20 +321,29 @@ abstract class BrowserTestBase extends TestCase {
$this->mink->setDefaultSessionName('default');
$this->registerSessions();
// According to the W3C WebDriver specification a cookie can only be set if
// the cookie domain is equal to the domain of the active document. When the
// browser starts up the active document is not our domain but 'about:blank'
// or similar. To be able to set our User-Agent and Xdebug cookies at the
// start of the test we now do a request to the front page so the active
// document matches the domain.
// @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie
// @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975
$session = $this->getSession();
$session->visit($this->baseUrl);
$this->initFrontPage();
return $session;
}
/**
* Visits the front page when initializing Mink.
*
* According to the W3C WebDriver specification a cookie can only be set if
* the cookie domain is equal to the domain of the active document. When the
* browser starts up the active document is not our domain but 'about:blank'
* or similar. To be able to set our User-Agent and Xdebug cookies at the
* start of the test we now do a request to the front page so the active
* document matches the domain.
*
* @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie
* @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975
*/
protected function initFrontPage() {
$session = $this->getSession();
$session->visit($this->baseUrl);
}
/**
* Gets an instance of the default Mink driver.
*
@ -593,6 +602,7 @@ abstract class BrowserTestBase extends TestCase {
* A new web-assert option for asserting the presence of elements with.
*/
public function assertSession($name = NULL) {
$this->addToAssertionCount(1);
return new WebAssert($this->getSession($name), $this->baseUrl);
}
@ -1307,6 +1317,28 @@ abstract class BrowserTestBase extends TestCase {
return $caller;
}
/**
* Transforms a nested array into a flat array suitable for drupalPostForm().
*
* @param array $values
* A multi-dimensional form values array to convert.
*
* @return array
* The flattened $edit array suitable for BrowserTestBase::drupalPostForm().
*/
protected function translatePostValues(array $values) {
$edit = [];
// The easiest and most straightforward way to translate values suitable for
// BrowserTestBase::drupalPostForm() is to actually build the POST data
// string and convert the resulting key/value pairs back into a flat array.
$query = http_build_query($values);
foreach (explode('&', $query) as $item) {
list($key, $value) = explode('=', $item);
$edit[urldecode($key)] = urldecode($value);
}
return $edit;
}
/**
* Checks for meta refresh tag and if found call drupalGet() recursively.
*