use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Drupal\migrate_drupal\MigrationConfigurationTrait;
use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait;
+use Drupal\Tests\WebAssert;
/**
* Provides a base class for testing migration upgrades in the UI.
*/
abstract class MigrateUpgradeTestBase extends BrowserTestBase {
+
use MigrationConfigurationTrait;
+ use CreateTestContentEntitiesTrait;
/**
* Use the Standard profile to test help implementations of many core modules.
*/
protected $sourceDatabase;
- /**
- * Modules to enable.
- *
- * @var array
- */
- public static $modules = [
- 'language',
- 'content_translation',
- 'migrate_drupal_ui',
- 'telephone',
- 'aggregator',
- 'book',
- 'forum',
- 'statistics',
- 'migration_provider_test',
- ];
-
/**
* {@inheritdoc}
*/
}
/**
- * Executes all steps of migrations upgrade.
+ * 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().
*/
- public function testMigrateUpgrade() {
- $connection_options = $this->sourceDatabase->getConnectionOptions();
- $this->drupalGet('/upgrade');
- $this->assertSession()->responseContains('Upgrade a site by importing its database and files into a clean and empty new install of Drupal 8.');
-
- $this->drupalPostForm(NULL, [], t('Continue'));
- $this->assertText('Provide credentials for the database of the Drupal site you want to upgrade.');
- $this->assertFieldByName('mysql[host]');
-
- $driver = $connection_options['driver'];
- $connection_options['prefix'] = $connection_options['prefix']['default'];
-
- // Use the driver connection form to get the correct options out of the
- // database settings. This supports all of the databases we test against.
- $drivers = drupal_get_database_types();
- $form = $drivers[$driver]->getFormOptions($connection_options);
- $connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']);
- $version = $this->getLegacyDrupalVersion($this->sourceDatabase);
- $edit = [
- $driver => $connection_options,
- 'source_private_file_path' => $this->getSourceBasePath(),
- 'version' => $version,
- ];
- if ($version == 6) {
- $edit['d6_source_base_path'] = $this->getSourceBasePath();
+ 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);
}
- else {
- $edit['source_base_path'] = $this->getSourceBasePath();
+ return $edit;
+ }
+
+ /**
+ * Tests the displayed upgrade paths.
+ *
+ * @param \Drupal\Tests\WebAssert $session
+ * The web-assert session.
+ * @param array $available_paths
+ * An array of modules that will be upgraded.
+ * @param array $missing_paths
+ * An array of modules that will not be upgraded.
+ */
+ protected function assertUpgradePaths(WebAssert $session, array $available_paths, array $missing_paths) {
+ // Test the available migration paths.
+ foreach ($available_paths as $available) {
+ $session->elementExists('xpath', "//span[contains(@class, 'checked') and text() = '$available']");
+ $session->elementNotExists('xpath', "//span[contains(@class, 'error') and text() = '$available']");
}
- if (count($drivers) !== 1) {
- $edit['driver'] = $driver;
+
+ // Test the missing migration paths.
+ foreach ($missing_paths as $missing) {
+ $session->elementExists('xpath', "//span[contains(@class, 'error') and text() = '$missing']");
+ $session->elementNotExists('xpath', "//span[contains(@class, 'checked') and text() = '$missing']");
}
- $edits = $this->translatePostValues($edit);
- // Ensure submitting the form with invalid database credentials gives us a
- // nice warning.
- $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade'));
- $this->assertText('Resolve the issue below to continue the upgrade.');
+ // Test the total count of missing and available paths.
+ $session->elementsCount('xpath', "//span[contains(@class, 'upgrade-analysis-report__status-icon--error')]", count($missing_paths));
+ $session->elementsCount('xpath', "//span[contains(@class, 'upgrade-analysis-report__status-icon--checked')]", count($available_paths));
+ }
- $this->drupalPostForm(NULL, $edits, t('Review upgrade'));
- $this->assertResponse(200);
- $this->assertText('Upgrade analysis report');
- // Ensure we get errors about missing modules.
- $this->assertSession()->pageTextContains(t('Source module not found for migration_provider_no_annotation.'));
- $this->assertSession()->pageTextContains(t('Source module not found for migration_provider_test.'));
- $this->assertSession()->pageTextContains(t('Destination module not found for migration_provider_test'));
+ /**
+ * Gets the source base path for the concrete test.
+ *
+ * @return string
+ * The source base path.
+ */
+ abstract protected function getSourceBasePath();
- // Uninstall the module causing the missing module error messages.
- $this->container->get('module_installer')->uninstall(['migration_provider_test'], TRUE);
+ /**
+ * Gets the expected number of entities per entity type after migration.
+ *
+ * @return int[]
+ * An array of expected counts keyed by entity type ID.
+ */
+ abstract protected function getEntityCounts();
- // Restart the upgrade process.
- $this->drupalGet('/upgrade');
- $this->assertSession()->responseContains('Upgrade a site by importing its database and files into a clean and empty new install of Drupal 8.');
+ /**
+ * Gets the available upgrade paths.
+ *
+ * @return string[]
+ * An array of available upgrade paths.
+ */
+ abstract protected function getAvailablePaths();
- $this->drupalPostForm(NULL, [], t('Continue'));
- $this->assertSession()->pageTextContains('Provide credentials for the database of the Drupal site you want to upgrade.');
- $this->assertSession()->fieldExists('mysql[host]');
+ /**
+ * Gets the missing upgrade paths.
+ *
+ * @return string[]
+ * An array of missing upgrade paths.
+ */
+ abstract protected function getMissingPaths();
+
+ /**
+ * Gets expected number of entities per entity after incremental migration.
+ *
+ * @return int[]
+ * An array of expected counts keyed by entity type ID.
+ */
+ abstract protected function getEntityCountsIncremental();
+
+ /**
+ * Helper method to assert the text on the 'Upgrade analysis report' page.
+ *
+ * @param \Drupal\Tests\WebAssert $session
+ * The current session.
+ * @param array $all_available
+ * Array of modules that will be upgraded.
+ * @param array $all_missing
+ * Array of modules that will not be upgraded.
+ */
+ protected function assertReviewPage(WebAssert $session, array $all_available, array $all_missing) {
+ $this->assertText('What will be upgraded?');
- $this->drupalPostForm(NULL, $edits, t('Review upgrade'));
- $this->assertSession()->statusCodeEquals(200);
- $this->assertSession()->pageTextContains('Upgrade analysis report');
// Ensure there are no errors about the missing modules from the test module.
- $this->assertSession()->pageTextNotContains(t('Source module not found for migration_provider_no_annotation.'));
- $this->assertSession()->pageTextNotContains(t('Source module not found for migration_provider_test.'));
- $this->assertSession()->pageTextNotContains(t('Destination module not found for migration_provider_test'));
+ $session->pageTextNotContains(t('Source module not found for migration_provider_no_annotation.'));
+ $session->pageTextNotContains(t('Source module not found for migration_provider_test.'));
+ $session->pageTextNotContains(t('Destination module not found for migration_provider_test'));
// Ensure there are no errors about any other missing migration providers.
- $this->assertSession()->pageTextNotContains(t('module not found'));
- $this->drupalPostForm(NULL, [], t('Perform upgrade'));
- $this->assertText(t('Congratulations, you upgraded Drupal!'));
+ $session->pageTextNotContains(t('module not found'));
+
+ // Test the available migration paths.
+ foreach ($all_available as $available) {
+ $session->elementExists('xpath', "//span[contains(@class, 'checked') and text() = '$available']");
+ $session->elementNotExists('xpath', "//span[contains(@class, 'error') and text() = '$available']");
+ }
+
+ // Test the missing migration paths.
+ foreach ($all_missing as $missing) {
+ $session->elementExists('xpath', "//span[contains(@class, 'error') and text() = '$missing']");
+ $session->elementNotExists('xpath', "//span[contains(@class, 'checked') and text() = '$missing']");
+ }
+ }
+
+ /**
+ * Helper method that asserts text on the ID conflict form.
+ *
+ * @param \Drupal\Tests\WebAssert $session
+ * The current session.
+ * @param $session
+ * The current session.
+ */
+ protected function assertIdConflict(WebAssert $session) {
+ $session->pageTextContains('WARNING: Content may be overwritten on your new site.');
+ $session->pageTextContains('There is conflicting content of these types:');
+ $session->pageTextContains('custom block entities');
+ $session->pageTextContains('custom menu link entities');
+ $session->pageTextContains('file entities');
+ $session->pageTextContains('taxonomy term entities');
+ $session->pageTextContains('user entities');
+ $session->pageTextContains('comments');
+ $session->pageTextContains('content item revisions');
+ $session->pageTextContains('content items');
+ $session->pageTextContains('There is translated content of these types:');
+ }
+ /**
+ * Checks that migrations have been performed successfully.
+ *
+ * @param array $expected_counts
+ * The expected counts of each entity type.
+ * @param int $version
+ * The Drupal version.
+ */
+ protected function assertMigrationResults(array $expected_counts, $version) {
// Have to reset all the statics after migration to ensure entities are
// loadable.
$this->resetAll();
-
- $expected_counts = $this->getEntityCounts();
- foreach (array_keys(\Drupal::entityTypeManager()
- ->getDefinitions()) as $entity_type) {
- $real_count = \Drupal::entityQuery($entity_type)->count()->execute();
+ foreach (array_keys(\Drupal::entityTypeManager()->getDefinitions()) as $entity_type) {
+ $real_count = (int) \Drupal::entityQuery($entity_type)->count()->execute();
$expected_count = isset($expected_counts[$entity_type]) ? $expected_counts[$entity_type] : 0;
- $this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
+ $this->assertSame($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
}
$plugin_manager = \Drupal::service('plugin.manager.migration');
// A completed migration should have maps with
// MigrateIdMapInterface::STATUS_IGNORED or
// MigrateIdMapInterface::STATUS_IMPORTED.
- if ($row['source_row_status'] == MigrateIdMapInterface::STATUS_FAILED || $row['source_row_status'] == MigrateIdMapInterface::STATUS_NEEDS_UPDATE) {
- $this->fail($message);
- }
- else {
- $this->pass($message);
- }
+ $this->assertNotSame(MigrateIdMapInterface::STATUS_FAILED, $row['source_row_status'], $message);
+ $this->assertNotSame(MigrateIdMapInterface::STATUS_NEEDS_UPDATE, $row['source_row_status'], $message);
}
}
- \Drupal::service('module_installer')->install(['forum']);
- \Drupal::service('module_installer')->install(['book']);
}
- /**
- * 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;
- }
-
- /**
- * Gets the source base path for the concrete test.
- *
- * @return string
- * The source base path.
- */
- abstract protected function getSourceBasePath();
-
- /**
- * Gets the expected number of entities per entity type after migration.
- *
- * @return int[]
- * An array of expected counts keyed by entity type ID.
- */
- abstract protected function getEntityCounts();
-
}