Unverified Commit 7204a00a authored by larowlan's avatar larowlan

Issue #2870009 by Lendude, dawehner: Update: Convert system functional tests to phpunit

parent 7f9287e8
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\Development\ConfigSchemaChecker; use Drupal\Core\Config\Development\ConfigSchemaChecker;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel; use Drupal\Core\DrupalKernel;
use Drupal\Core\Extension\MissingDependencyException; use Drupal\Core\Extension\MissingDependencyException;
use Drupal\Core\Serialization\Yaml; use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Session\UserSession; use Drupal\Core\Session\UserSession;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Yaml\Yaml as SymfonyYaml; use Symfony\Component\Yaml\Yaml as SymfonyYaml;
...@@ -448,4 +450,210 @@ protected function rebuildAll() { ...@@ -448,4 +450,210 @@ protected function rebuildAll() {
$this->container->get('stream_wrapper_manager')->register(); $this->container->get('stream_wrapper_manager')->register();
} }
/**
* Returns the parameters that will be used when Simpletest installs Drupal.
*
* @see install_drupal()
* @see install_state_defaults()
*
* @return array
* Array of parameters for use in install_drupal().
*/
protected function installParameters() {
$connection_info = Database::getConnectionInfo();
$driver = $connection_info['default']['driver'];
$connection_info['default']['prefix'] = $connection_info['default']['prefix']['default'];
unset($connection_info['default']['driver']);
unset($connection_info['default']['namespace']);
unset($connection_info['default']['pdo']);
unset($connection_info['default']['init_commands']);
// Remove database connection info that is not used by SQLite.
if ($driver === 'sqlite') {
unset($connection_info['default']['username']);
unset($connection_info['default']['password']);
unset($connection_info['default']['host']);
unset($connection_info['default']['port']);
}
$parameters = [
'interactive' => FALSE,
'parameters' => [
'profile' => $this->profile,
'langcode' => 'en',
],
'forms' => [
'install_settings_form' => [
'driver' => $driver,
$driver => $connection_info['default'],
],
'install_configure_form' => [
'site_name' => 'Drupal',
'site_mail' => 'simpletest@example.com',
'account' => [
'name' => $this->rootUser->name,
'mail' => $this->rootUser->getEmail(),
'pass' => [
'pass1' => isset($this->rootUser->pass_raw) ? $this->rootUser->pass_raw : $this->rootUser->passRaw,
'pass2' => isset($this->rootUser->pass_raw) ? $this->rootUser->pass_raw : $this->rootUser->passRaw,
],
],
// form_type_checkboxes_value() requires NULL instead of FALSE values
// for programmatic form submissions to disable a checkbox.
'enable_update_status_module' => NULL,
'enable_update_status_emails' => NULL,
],
],
];
// If we only have one db driver available, we cannot set the driver.
include_once DRUPAL_ROOT . '/core/includes/install.inc';
if (count($this->getDatabaseTypes()) == 1) {
unset($parameters['forms']['install_settings_form']['driver']);
}
return $parameters;
}
/**
* Sets up the base URL based upon the environment variable.
*
* @throws \Exception
* Thrown when no SIMPLETEST_BASE_URL environment variable is provided.
*/
protected function setupBaseUrl() {
global $base_url;
// Get and set the domain of the environment we are running our test
// coverage against.
$base_url = getenv('SIMPLETEST_BASE_URL');
if (!$base_url) {
throw new \Exception(
'You must provide a SIMPLETEST_BASE_URL environment variable to run some PHPUnit based functional tests.'
);
}
// Setup $_SERVER variable.
$parsed_url = parse_url($base_url);
$host = $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '');
$path = isset($parsed_url['path']) ? rtrim(rtrim($parsed_url['path']), '/') : '';
$port = isset($parsed_url['port']) ? $parsed_url['port'] : 80;
$this->baseUrl = $base_url;
// If the passed URL schema is 'https' then setup the $_SERVER variables
// properly so that testing will run under HTTPS.
if ($parsed_url['scheme'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
$_SERVER['HTTP_HOST'] = $host;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['SERVER_ADDR'] = '127.0.0.1';
$_SERVER['SERVER_PORT'] = $port;
$_SERVER['SERVER_SOFTWARE'] = NULL;
$_SERVER['SERVER_NAME'] = 'localhost';
$_SERVER['REQUEST_URI'] = $path . '/';
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['SCRIPT_NAME'] = $path . '/index.php';
$_SERVER['SCRIPT_FILENAME'] = $path . '/index.php';
$_SERVER['PHP_SELF'] = $path . '/index.php';
$_SERVER['HTTP_USER_AGENT'] = 'Drupal command line';
}
/**
* Prepares the current environment for running the test.
*
* Also sets up new resources for the testing environment, such as the public
* filesystem and configuration directories.
*
* This method is private as it must only be called once by
* BrowserTestBase::setUp() (multiple invocations for the same test would have
* unpredictable consequences) and it must not be callable or overridable by
* test classes.
*/
protected function prepareEnvironment() {
// Bootstrap Drupal so we can use Drupal's built in functions.
$this->classLoader = require __DIR__ . '/../../../../../autoload.php';
$request = Request::createFromGlobals();
$kernel = TestRunnerKernel::createFromRequest($request, $this->classLoader);
// TestRunnerKernel expects the working directory to be DRUPAL_ROOT.
chdir(DRUPAL_ROOT);
$kernel->prepareLegacyRequest($request);
$this->prepareDatabasePrefix();
$this->originalSite = $kernel->findSitePath($request);
// Create test directory ahead of installation so fatal errors and debug
// information can be logged during installation process.
file_prepare_directory($this->siteDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
// Prepare filesystem directory paths.
$this->publicFilesDirectory = $this->siteDirectory . '/files';
$this->privateFilesDirectory = $this->siteDirectory . '/private';
$this->tempFilesDirectory = $this->siteDirectory . '/temp';
$this->translationFilesDirectory = $this->siteDirectory . '/translations';
// Ensure the configImporter is refreshed for each test.
$this->configImporter = NULL;
// Unregister all custom stream wrappers of the parent site.
$wrappers = \Drupal::service('stream_wrapper_manager')->getWrappers(StreamWrapperInterface::ALL);
foreach ($wrappers as $scheme => $info) {
stream_wrapper_unregister($scheme);
}
// Reset statics.
drupal_static_reset();
$this->container = NULL;
// Unset globals.
unset($GLOBALS['config_directories']);
unset($GLOBALS['config']);
unset($GLOBALS['conf']);
// Log fatal errors.
ini_set('log_errors', 1);
ini_set('error_log', DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log');
// Change the database prefix.
$this->changeDatabasePrefix();
// After preparing the environment and changing the database prefix, we are
// in a valid test environment.
drupal_valid_test_ua($this->databasePrefix);
// Reset settings.
new Settings([
// For performance, simply use the database prefix as hash salt.
'hash_salt' => $this->databasePrefix,
]);
drupal_set_time_limit($this->timeLimit);
// Save and clean the shutdown callbacks array because it is static cached
// and will be changed by the test run. Otherwise it will contain callbacks
// from both environments and the testing environment will try to call the
// handlers defined by the original one.
$callbacks = &drupal_register_shutdown_function();
$this->originalShutdownCallbacks = $callbacks;
$callbacks = [];
}
/**
* Returns all supported database driver installer objects.
*
* This wraps drupal_get_database_types() for use without a current container.
*
* @return \Drupal\Core\Database\Install\Tasks[]
* An array of available database driver installer objects.
*/
protected function getDatabaseTypes() {
if ($this->originalContainer) {
\Drupal::setContainer($this->originalContainer);
}
$database_types = drupal_get_database_types();
if ($this->originalContainer) {
\Drupal::unsetContainer();
}
return $database_types;
}
} }
...@@ -141,7 +141,7 @@ public static function getDatabaseConnection() { ...@@ -141,7 +141,7 @@ public static function getDatabaseConnection() {
* @see \Drupal\simpletest\TestBase::prepareEnvironment() * @see \Drupal\simpletest\TestBase::prepareEnvironment()
* @see drupal_valid_test_ua() * @see drupal_valid_test_ua()
*/ */
private function prepareDatabasePrefix() { protected function prepareDatabasePrefix() {
$test_db = new TestDatabase(); $test_db = new TestDatabase();
$this->siteDirectory = $test_db->getTestSitePath(); $this->siteDirectory = $test_db->getTestSitePath();
$this->databasePrefix = $test_db->getDatabasePrefix(); $this->databasePrefix = $test_db->getDatabasePrefix();
...@@ -150,7 +150,7 @@ private function prepareDatabasePrefix() { ...@@ -150,7 +150,7 @@ private function prepareDatabasePrefix() {
/** /**
* Changes the database connection to the prefixed one. * Changes the database connection to the prefixed one.
*/ */
private function changeDatabasePrefix() { protected function changeDatabasePrefix() {
if (empty($this->databasePrefix)) { if (empty($this->databasePrefix)) {
$this->prepareDatabasePrefix(); $this->prepareDatabasePrefix();
} }
...@@ -158,7 +158,7 @@ private function changeDatabasePrefix() { ...@@ -158,7 +158,7 @@ private function changeDatabasePrefix() {
// If the test is run with argument dburl then use it. // If the test is run with argument dburl then use it.
$db_url = getenv('SIMPLETEST_DB'); $db_url = getenv('SIMPLETEST_DB');
if (!empty($db_url)) { if (!empty($db_url)) {
$database = Database::convertDbUrlToConnectionInfo($db_url, DRUPAL_ROOT); $database = Database::convertDbUrlToConnectionInfo($db_url, isset($this->root) ? $this->root : DRUPAL_ROOT);
Database::addConnectionInfo('default', 'default', $database); Database::addConnectionInfo('default', 'default', $database);
} }
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\UrlHelper; use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Database\Database;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
...@@ -389,69 +388,6 @@ protected function setUp() { ...@@ -389,69 +388,6 @@ protected function setUp() {
$this->rebuildAll(); $this->rebuildAll();
} }
/**
* Returns the parameters that will be used when Simpletest installs Drupal.
*
* @see install_drupal()
* @see install_state_defaults()
*
* @return array
* Array of parameters for use in install_drupal().
*/
protected function installParameters() {
$connection_info = Database::getConnectionInfo();
$driver = $connection_info['default']['driver'];
$connection_info['default']['prefix'] = $connection_info['default']['prefix']['default'];
unset($connection_info['default']['driver']);
unset($connection_info['default']['namespace']);
unset($connection_info['default']['pdo']);
unset($connection_info['default']['init_commands']);
// Remove database connection info that is not used by SQLite.
if ($driver == 'sqlite') {
unset($connection_info['default']['username']);
unset($connection_info['default']['password']);
unset($connection_info['default']['host']);
unset($connection_info['default']['port']);
}
$parameters = [
'interactive' => FALSE,
'parameters' => [
'profile' => $this->profile,
'langcode' => 'en',
],
'forms' => [
'install_settings_form' => [
'driver' => $driver,
$driver => $connection_info['default'],
],
'install_configure_form' => [
'site_name' => 'Drupal',
'site_mail' => 'simpletest@example.com',
'account' => [
'name' => $this->rootUser->name,
'mail' => $this->rootUser->getEmail(),
'pass' => [
'pass1' => $this->rootUser->pass_raw,
'pass2' => $this->rootUser->pass_raw,
],
],
// \Drupal\Core\Render\Element\Checkboxes::valueCallback() requires
// NULL instead of FALSE values for programmatic form submissions to
// disable a checkbox.
'enable_update_status_module' => NULL,
'enable_update_status_emails' => NULL,
],
],
];
// If we only have one db driver available, we cannot set the driver.
include_once DRUPAL_ROOT . '/core/includes/install.inc';
if (count($this->getDatabaseTypes()) == 1) {
unset($parameters['forms']['install_settings_form']['driver']);
}
return $parameters;
}
/** /**
* Preserve the original batch, and instantiate the test batch. * Preserve the original batch, and instantiate the test batch.
*/ */
...@@ -479,21 +415,6 @@ protected function restoreBatch() { ...@@ -479,21 +415,6 @@ protected function restoreBatch() {
$batch = $this->originalBatch; $batch = $this->originalBatch;
} }
/**
* Returns all supported database driver installer objects.
*
* This wraps drupal_get_database_types() for use without a current container.
*
* @return \Drupal\Core\Database\Install\Tasks[]
* An array of available database driver installer objects.
*/
protected function getDatabaseTypes() {
\Drupal::setContainer($this->originalContainer);
$database_types = drupal_get_database_types();
\Drupal::unsetContainer();
return $database_types;
}
/** /**
* Queues custom translations to be written to settings.php. * Queues custom translations to be written to settings.php.
* *
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace Drupal\system\Tests\Update; namespace Drupal\system\Tests\Update;
@trigger_error(__NAMESPACE__ . '\DbUpdatesTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\FunctionalTests\Update\DbUpdatesTrait instead. See https://www.drupal.org/node/2896640.', E_USER_DEPRECATED);
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url; use Drupal\Core\Url;
...@@ -10,6 +12,10 @@ ...@@ -10,6 +12,10 @@
* pending db updates through the Update UI. * pending db updates through the Update UI.
* *
* This should be used only by classes extending \Drupal\simpletest\WebTestBase. * This should be used only by classes extending \Drupal\simpletest\WebTestBase.
*
* @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\FunctionalTests\Update\DbUpdatesTrait.
* @see https://www.drupal.org/node/2896640
*/ */
trait DbUpdatesTrait { trait DbUpdatesTrait {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace Drupal\system\Tests\Update; namespace Drupal\system\Tests\Update;
@trigger_error(__NAMESPACE__ . '\UpdatePathTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\FunctionalTests\Update\UpdatePathTestBase instead. See https://www.drupal.org/node/2896640.', E_USER_DEPRECATED);
use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Crypt;
use Drupal\Tests\SchemaCheckTestTrait; use Drupal\Tests\SchemaCheckTestTrait;
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
...@@ -34,6 +36,10 @@ ...@@ -34,6 +36,10 @@
* *
* @ingroup update_api * @ingroup update_api
* *
* @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\FunctionalTests\Update\UpdatePathTestBase.
* @see https://www.drupal.org/node/2896640
*
* @see hook_update_N() * @see hook_update_N()
*/ */
abstract class UpdatePathTestBase extends WebTestBase { abstract class UpdatePathTestBase extends WebTestBase {
......
<?php <?php
namespace Drupal\system\Tests\Update; namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/** /**
* Ensures that the automated cron module is installed on update. * Ensures that the automated cron module is installed on update.
...@@ -14,7 +16,7 @@ class AutomatedCronUpdateWithAutomatedCronTest extends UpdatePathTestBase { ...@@ -14,7 +16,7 @@ class AutomatedCronUpdateWithAutomatedCronTest extends UpdatePathTestBase {
*/ */
protected function setDatabaseDumpFiles() { protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [ $this->databaseDumpFiles = [
__DIR__ . '/../../../tests/fixtures/update/drupal-8.bare.standard.php.gz', __DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
]; ];
} }
......
<?php <?php
namespace Drupal\system\Tests\Update; namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/** /**
* Ensures that the automated cron module is not installed on update. * Ensures that the automated cron module is not installed on update.
...@@ -14,8 +16,8 @@ class AutomatedCronUpdateWithoutAutomatedCronTest extends UpdatePathTestBase { ...@@ -14,8 +16,8 @@ class AutomatedCronUpdateWithoutAutomatedCronTest extends UpdatePathTestBase {
*/ */
protected function setDatabaseDumpFiles() { protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [ $this->databaseDumpFiles = [
__DIR__ . '/../../../tests/fixtures/update/drupal-8.bare.standard.php.gz', __DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../tests/fixtures/update/drupal-8.without_automated_cron.php', __DIR__ . '/../../../../tests/fixtures/update/drupal-8.without_automated_cron.php',
]; ];
} }
......
<?php <?php
namespace Drupal\system\Tests\Update; namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/** /**
* Tests system_update_8200(). * Tests system_update_8200().
...@@ -16,8 +18,8 @@ class ConfigOverridesUpdateTest extends UpdatePathTestBase { ...@@ -16,8 +18,8 @@ class ConfigOverridesUpdateTest extends UpdatePathTestBase {
*/ */
protected function setDatabaseDumpFiles() { protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [ $this->databaseDumpFiles = [
__DIR__ . '/../../../tests/fixtures/update/drupal-8.filled.standard.php.gz', __DIR__ . '/../../../../tests/fixtures/update/drupal-8.filled.standard.php.gz',
__DIR__ . '/../../../tests/fixtures/update/drupal-8.config-override-fix.php', __DIR__ . '/../../../../tests/fixtures/update/drupal-8.config-override-fix.php',
]; ];
} }
......
<?php
namespace Drupal\Tests\system\Functional\Update;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
/**
* Provides methods to conditionally enable db update functions and apply
* pending db updates through the Update UI.
*
* This should be used only by classes extending \Drupal\Tests\BrowserTestBase.
*/
trait DbUpdatesTrait {
use StringTranslationTrait;
/**
* Enables db updates until the specified index.
*
* @param string $module
* The name of the module defining the update functions.
* @param string $group
* A name identifying the group of update functions to enable.
* @param $index
* The index of the last update function to run.
*/
protected function enableUpdates($module, $group, $index) {
$this->container->get('state')->set($module . '.db_updates.' . $group, $index);
}
/**
* Applies any pending DB updates through the Update UI.
*/
protected function applyUpdates() {
$this->drupalGet(Url::fromRoute('system.db_update'));
$this->clickLink($this->t('Continue'));
$this->clickLink($this->t('Apply pending updates'));
}
/**
* Conditionally load Update API functions for the specified group.
*
* @param string $module
* The name of the module defining the update functions.
* @param string $group
* A name identifying the group of update functions to enable.
*/
public static function includeUpdates($module, $group) {
if ($index = \Drupal::state()->get($module . '.db_updates.' . $group)) {
module_load_include('inc', $module, 'update/' . $group . '_' . $index);
}
}
}
<?php <?php
namespace Drupal\system\Tests\Update; namespace Drupal\Tests\system\Functional\Update;
use Drupal\simpletest\WebTestBase; use Drupal\Tests\BrowserTestBase;
/** /**
* Tests that the hook invocation for determining update dependencies works * Tests that the hook invocation for determining update dependencies works
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* @group Update * @group Update