Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / modules / migrate_drupal_ui / tests / src / Functional / MigrateUpgradeTestBase.php
index 20318aef81e9565eb2aa16ad9deb7536deeaba9d..23d5c295f3c6eed43fef5d0e8799f5939e3f6b96 100644 (file)
@@ -6,12 +6,16 @@ use Drupal\Core\Database\Database;
 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.
@@ -27,23 +31,6 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
    */
   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}
    */
@@ -111,88 +98,166 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
   }
 
   /**
-   * 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');
@@ -211,54 +276,10 @@ abstract class MigrateUpgradeTestBase extends BrowserTestBase {
         // 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();
-
 }