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 @@
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\Development\ConfigSchemaChecker;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Extension\MissingDependencyException;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Session\UserSession;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
......@@ -448,4 +450,210 @@ protected function rebuildAll() {
$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() {
* @see \Drupal\simpletest\TestBase::prepareEnvironment()
* @see drupal_valid_test_ua()
*/
private function prepareDatabasePrefix() {
protected function prepareDatabasePrefix() {
$test_db = new TestDatabase();
$this->siteDirectory = $test_db->getTestSitePath();
$this->databasePrefix = $test_db->getDatabasePrefix();
......@@ -150,7 +150,7 @@ private function prepareDatabasePrefix() {
/**
* Changes the database connection to the prefixed one.
*/
private function changeDatabasePrefix() {
protected function changeDatabasePrefix() {
if (empty($this->databasePrefix)) {
$this->prepareDatabasePrefix();
}
......@@ -158,7 +158,7 @@ private function changeDatabasePrefix() {
// If the test is run with argument dburl then use it.
$db_url = getenv('SIMPLETEST_DB');
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);
}
......
......@@ -8,7 +8,6 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Database\Database;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Session\AccountInterface;
......@@ -389,69 +388,6 @@ protected function setUp() {
$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.
*/
......@@ -479,21 +415,6 @@ protected function restoreBatch() {
$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.
*
......
......@@ -2,6 +2,8 @@
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\Url;
......@@ -10,6 +12,10 @@
* pending db updates through the Update UI.
*
* 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 {
......
......@@ -2,6 +2,8 @@
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\Tests\SchemaCheckTestTrait;
use Drupal\Core\Database\Database;
......@@ -34,6 +36,10 @@
*
* @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()
*/
abstract class UpdatePathTestBase extends WebTestBase {
......
<?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.
......@@ -14,7 +16,7 @@ class AutomatedCronUpdateWithAutomatedCronTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
......
<?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.
......@@ -14,8 +16,8 @@ class AutomatedCronUpdateWithoutAutomatedCronTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__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.bare.standard.php.gz',
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.without_automated_cron.php',
];
}
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests system_update_8200().
......@@ -16,8 +18,8 @@ class ConfigOverridesUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__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.filled.standard.php.gz',
__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
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
......@@ -10,7 +10,7 @@
*
* @group Update
*/
class DependencyHookInvocationTest extends WebTestBase {
class DependencyHookInvocationTest extends BrowserTestBase {
/**
* Modules to enable.
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that missing update dependencies are correctly flagged.
*
* @group Update
*/
class DependencyMissingTest extends WebTestBase {
class DependencyMissingTest extends BrowserTestBase {
/**
* Modules to enable.
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that update functions are run in the proper order.
*
* @group Update
*/
class DependencyOrderingTest extends WebTestBase {
class DependencyOrderingTest extends BrowserTestBase {
/**
* Modules to enable.
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path after fixing field schema data uninstallation.
......@@ -16,9 +18,9 @@ class FieldSchemaDataUninstallUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-content-uninstall.php',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.field-schema-data-uninstall-2573667.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.block-content-uninstall.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.field-schema-data-uninstall-2573667.php',
];
}
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\filter\Entity\FilterFormat;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests that the allowed html configutations are updated with attributes.
......@@ -16,7 +17,7 @@ class FilterHtmlUpdateTest extends UpdatePathTestBase {
*/
public function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\Core\Site\Settings;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests system_update_8300().
......@@ -16,7 +17,7 @@ class InstallProfileSystemInstall8300Test extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that a module implementing hook_update_8000() causes an error to be
......@@ -10,7 +10,7 @@
*
* @group Update
*/
class InvalidUpdateHookTest extends WebTestBase {
class InvalidUpdateHookTest extends BrowserTestBase {
/**
* Modules to enable.
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\node\Entity\Node;
/**
......@@ -18,8 +19,8 @@ class LocalActionsAndTasksConvertedIntoBlocksUpdateTest extends UpdatePathTestBa
*/
public function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.local-actions-tasks-into-blocks-507488.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.local-actions-tasks-into-blocks-507488.php',
];
}
......
<?php
namespace Drupal\system\Tests\Update;
namespace Drupal\Tests\system\Functional\Update;
/**
* Runs MenuTreeSerializationTitleTest with a dump filled with content.
......@@ -14,7 +14,7 @@ class MenuTreeSerializationTitleFilledTest extends MenuTreeSerializationTitleTes
*/
protected function setDatabaseDumpFiles() {
parent::setDatabaseDumpFiles();
$this->databaseDumpFiles[0] = __DIR__ . '/../../../tests/fixtures/update/drupal-8.filled.standard.php.gz';
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../tests/fixtures/update/drupal-8.filled.standard.php.gz';
}
}