You are here

MediaMigrationSourceTestBase.php in Media Migration 8

File

tests/src/Kernel/Plugin/migrate/source/d7/MediaMigrationSourceTestBase.php
View source
<?php

namespace Drupal\Tests\media_migration\Kernel\Plugin\migrate\source\d7;

use Drupal\Core\Database\Database;
use Drupal\migrate\Plugin\MigrateDestinationInterface;
use Drupal\migrate\Plugin\MigrateSourceInterface;
use Drupal\migrate\Row;
use Drupal\Tests\media_migration\Traits\MediaMigrationTestDatabaseTrait;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;

/**
 * Base class for testing media migrate source plugins with native databases.
 *
 * Most of the methods are copied from MigrateTestBase and are slightly
 * modified.
 *
 * @see \Drupal\Tests\migrate\Kernel\MigrateTestBase
 */
abstract class MediaMigrationSourceTestBase extends MigrateSqlSourceTestBase {
  use MediaMigrationTestDatabaseTrait;

  /**
   * {@inheritdoc}
   *
   * @todo This should be changed to "protected" after Drupal core 8.x security
   *   support ends.
   * @see https://www.drupal.org/node/2909426
   */
  public static $modules = [
    'media_migration',
    'migrate',
    'migrate_drupal',
  ];

  /**
   * The source database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $sourceDatabase;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $destination_plugin = $this
      ->prophesize(MigrateDestinationInterface::class);
    $destination_plugin
      ->getPluginId()
      ->willReturn($this
      ->randomMachineName(16));
    $this->migration
      ->getDestinationPlugin()
      ->willReturn($destination_plugin
      ->reveal());
    $this
      ->createSourceMigrationConnection();
    $this->sourceDatabase = Database::getConnection('default', 'migrate');
  }

  /**
   * {@inheritdoc}
   *
   * @dataProvider providerSource
   */
  public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = [], $high_water = NULL, $expected_cache_key = NULL) {
    $this
      ->importSourceDatabase($source_data);
    $plugin = $this
      ->getPlugin($configuration);
    $clone_plugin = clone $plugin;

    // All source plugins must define IDs.
    $this
      ->assertNotEmpty($plugin
      ->getIds());

    // If there is a high water mark, set it in the high water storage.
    if (isset($high_water)) {
      $this->container
        ->get('keyvalue')
        ->get('migrate:high_water')
        ->set($this->migration
        ->reveal()
        ->id(), $high_water);
    }
    if (is_null($expected_count)) {
      $expected_count = count($expected_data);
    }

    // If an expected count was given, assert it only if the plugin is
    // countable.
    if (is_numeric($expected_count)) {
      $this
        ->assertInstanceOf('\\Countable', $plugin);
      $this
        ->assertCount($expected_count, $plugin);
    }
    $this
      ->assertPluginCountCacheability($plugin, $expected_count, $expected_cache_key);
    $i = 0;
    $actual_data = [];

    /** @var \Drupal\migrate\Row $row */
    foreach ($plugin as $row) {
      $i++;
      $this
        ->assertInstanceOf(Row::class, $row);
      $actual_data[] = $row
        ->getSource();
    }
    $this
      ->assertEquals($expected_data, $actual_data);

    // False positives occur if the foreach is not entered. So, confirm the
    // foreach loop was entered if the expected count is greater than 0.
    if ($expected_count > 0) {
      $this
        ->assertGreaterThan(0, $i);

      // Test that we can skip all rows.
      // The 'migrate_skip_all_rows_test' test module exists and installed only
      // in Drupal core 9.1+.
      if (\Drupal::moduleHandler()
        ->moduleExists('migrate_skip_all_rows_test')) {
        \Drupal::state()
          ->set('migrate_skip_all_rows_test_migrate_prepare_row', TRUE);
        $iterator_items = iterator_to_array($clone_plugin, FALSE);
        $this
          ->assertEmpty($iterator_items, 'Row not skipped');
      }
    }
  }

  /**
   * Tests the cacheablility of the given source plugin.
   *
   * @param \Drupal\migrate\Plugin\MigrateSourceInterface $plugin
   *   The source plugin instance.
   * @param int $expected_count
   *   The expected source record count.
   * @param string|null $expected_cache_key
   *   The expected cache key (if any). Defaults to NULL.
   */
  protected function assertPluginCountCacheability(MigrateSourceInterface $plugin, int $expected_count, ?string $expected_cache_key) {

    /** @var \Drupal\Core\Cache\MemoryCounterBackend $cache **/
    $cache = \Drupal::cache('migrate');
    if (!is_callable([
      $cache,
      'getCounter',
    ])) {
      return;
    }
    if ($expected_cache_key) {

      // Since we don't yet inject the database connection, we need to use a
      // reflection hack to set it in the plugin instance.
      $reflector = new \ReflectionObject($plugin);

      // Verify the the computed cache key.
      $property = $reflector
        ->getProperty('cacheKey');
      $property
        ->setAccessible(TRUE);
      $this
        ->assertSame($expected_cache_key, $property
        ->getValue($plugin));

      // Cache miss prior to calling ::count().
      $this
        ->assertFalse($cache
        ->get($expected_cache_key, 'cache'));
      $this
        ->assertSame([], $cache
        ->getCounter('set'));
      $count = $plugin
        ->count();
      $this
        ->assertSame($expected_count, $count);
      $this
        ->assertSame([
        $expected_cache_key => 1,
      ], $cache
        ->getCounter('set'));

      // Cache hit afterwards.
      $cache_item = $cache
        ->get($expected_cache_key, 'cache');
      $this
        ->assertNotSame(FALSE, $cache_item, 'This is not a cache hit.');
      $this
        ->assertSame($expected_count, $cache_item->data);
    }
    else {
      $this
        ->assertSame([], $cache
        ->getCounter('set'));
      $plugin
        ->count();
      $this
        ->assertSame([], $cache
        ->getCounter('set'));
    }
  }

  /**
   * {@inheritdoc}
   *
   * @see \Drupal\Tests\migrate\Kernel\MigrateTestBase::cleanupMigrateConnection()
   */
  protected function tearDown() {
    $this
      ->cleanupSourceMigrateConnection();
    parent::tearDown();
  }

}

Classes

Namesort descending Description
MediaMigrationSourceTestBase Base class for testing media migrate source plugins with native databases.