3 namespace Drupal\simpletest;
5 @trigger_error(__NAMESPACE__ . '\InstallerTestBase is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\FunctionalTests\Installer\InstallerTestBase, see https://www.drupal.org/node/2988752.', E_USER_DEPRECATED);
7 use Drupal\Core\DrupalKernel;
8 use Drupal\Core\Language\Language;
9 use Drupal\Core\Session\UserSession;
10 use Drupal\Core\Site\Settings;
11 use Symfony\Component\DependencyInjection\ContainerBuilder;
12 use Symfony\Component\DependencyInjection\Reference;
13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpFoundation\RequestStack;
17 * Base class for testing the interactive installer.
19 * @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0.
20 * Use \Drupal\FunctionalTests\Installer\InstallerTestBase. See
21 * https://www.drupal.org/node/2988752
23 abstract class InstallerTestBase extends WebTestBase {
26 * Custom settings.php values to write for a test run.
29 * An array of settings to write out, in the format expected by
30 * drupal_rewrite_settings().
32 protected $settings = [];
35 * The language code in which to install Drupal.
39 protected $langcode = 'en';
42 * The installation profile to install.
46 protected $profile = 'testing';
49 * Additional parameters to use for installer screens.
51 * @see WebTestBase::installParameters()
55 protected $parameters = [];
58 * A string translation map used for translated installer screens.
60 * Keys are English strings, values are translated strings.
64 protected $translations = [
65 'Save and continue' => 'Save and continue',
69 * Whether the installer has completed.
73 protected $isInstalled = FALSE;
78 protected function setUp() {
79 $this->isInstalled = FALSE;
81 // Define information about the user 1 account.
82 $this->rootUser = new UserSession([
85 'mail' => 'admin@example.com',
86 'pass_raw' => $this->randomMachineName(),
89 // If any $settings are defined for this test, copy and prepare an actual
90 // settings.php, so as to resemble a regular installation.
91 if (!empty($this->settings)) {
92 // Not using File API; a potential error must trigger a PHP warning.
93 copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
94 $this->writeSettings($this->settings);
97 // Note that WebTestBase::installParameters() returns form input values
98 // suitable for a programmed \Drupal::formBuilder()->submitForm().
99 // @see WebTestBase::translatePostValues()
100 $this->parameters = $this->installParameters();
102 // Set up a minimal container (required by WebTestBase). Set cookie and
103 // server information so that XDebug works.
104 // @see install_begin_request()
105 $request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER);
106 $this->container = new ContainerBuilder();
107 $request_stack = new RequestStack();
108 $request_stack->push($request);
110 ->set('request_stack', $request_stack);
112 ->setParameter('language.default_values', Language::$defaultValues);
114 ->register('language.default', 'Drupal\Core\Language\LanguageDefault')
115 ->addArgument('%language.default_values%');
117 ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
118 ->addArgument(new Reference('language.default'));
120 ->set('app.root', DRUPAL_ROOT);
121 \Drupal::setContainer($this->container);
123 $this->visitInstaller();
126 $this->setUpLanguage();
129 $this->setUpProfile();
131 // Address the requirements problem screen, if any.
132 $this->setUpRequirementsProblem();
134 // Configure settings.
135 $this->setUpSettings();
137 // @todo Allow test classes based on this class to act on further installer
143 if ($this->isInstalled) {
144 // Import new settings.php written by the installer.
145 $request = Request::createFromGlobals();
146 $class_loader = require $this->container->get('app.root') . '/autoload.php';
147 Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
148 foreach ($GLOBALS['config_directories'] as $type => $path) {
149 $this->configDirectories[$type] = $path;
152 // After writing settings.php, the installer removes write permissions
153 // from the site directory. To allow drupal_generate_test_ua() to write
154 // a file containing the private key for drupal_valid_test_ua(), the site
155 // directory has to be writable.
156 // WebTestBase::tearDown() will delete the entire test site directory.
157 // Not using File API; a potential error must trigger a PHP warning.
158 chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
159 $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
160 $this->kernel->prepareLegacyRequest($request);
161 $this->container = $this->kernel->getContainer();
163 // Manually configure the test mail collector implementation to prevent
164 // tests from sending out emails and collect them in state instead.
165 $this->container->get('config.factory')
166 ->getEditable('system.mail')
167 ->set('interface.default', 'test_mail_collector')
173 * Visits the interactive installer.
175 protected function visitInstaller() {
176 $this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
180 * Installer step: Select language.
182 protected function setUpLanguage() {
184 'langcode' => $this->langcode,
186 $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
190 * Installer step: Select installation profile.
192 protected function setUpProfile() {
194 'profile' => $this->profile,
196 $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
200 * Installer step: Configure settings.
202 protected function setUpSettings() {
203 $edit = $this->translatePostValues($this->parameters['forms']['install_settings_form']);
204 $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
208 * Installer step: Requirements problem.
210 * Override this method to test specific requirements warnings or errors
211 * during the installer.
213 * @see system_requirements()
215 protected function setUpRequirementsProblem() {
216 // By default, skip the "recommended PHP version" warning on older test
217 // environments. This allows the installer to be tested consistently on
218 // both recommended PHP versions and older (but still supported) versions.
219 if (version_compare(phpversion(), '7.0') < 0) {
220 $this->continueOnExpectedWarnings(['PHP']);
225 * Final installer step: Configure site.
227 protected function setUpSite() {
228 $edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']);
229 $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
230 // If we've got to this point the site is installed using the regular
231 // installation workflow.
232 $this->isInstalled = TRUE;
238 * WebTestBase::refreshVariables() tries to operate on persistent storage,
239 * which is only available after the installer completed.
241 protected function refreshVariables() {
242 if ($this->isInstalled) {
243 parent::refreshVariables();
248 * Continues installation when an expected warning is found.
250 * @param string[] $expected_warnings
251 * A list of warning summaries to expect on the requirements screen (e.g.
252 * 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings
253 * are found, the test will click the "continue anyway" link to go to the
254 * next screen of the installer. If an expected warning is not found, or if
255 * a warning not in the list is present, a fail is raised.
257 protected function continueOnExpectedWarnings($expected_warnings = []) {
258 // Don't try to continue if there are errors.
259 if (strpos($this->getTextContent(), 'Errors found') !== FALSE) {
262 // Allow only details elements that are directly after the warning header
263 // or each other. There is no guaranteed wrapper we can rely on across
264 // distributions. When there are multiple warnings, the selectors will be:
265 // - h3#warning+details summary
266 // - h3#warning+details+details summary
268 // We add one more selector than expected warnings to confirm that there
269 // isn't any other warning before clicking the link.
270 // @todo Make this more reliable in
271 // https://www.drupal.org/project/drupal/issues/2927345.
273 for ($i = 0; $i <= count($expected_warnings); $i++) {
274 $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary';
276 $warning_elements = $this->cssSelect(implode(', ', $selectors));
278 // Confirm that there are only the expected warnings.
280 foreach ($warning_elements as $warning) {
281 $warnings[] = trim((string) $warning);
283 $this->assertEqual($expected_warnings, $warnings);
284 $this->clickLink('continue anyway');