diff --git a/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php new file mode 100644 index 0000000..002ff45 --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php @@ -0,0 +1,182 @@ +migration = $this->prophesize(MigrationInterface::class); + + $this->migration->id()->willReturn( + $this->randomMachineName(16) + ); + // Prophesize a useless ID map plugin, an empty high water property, and + // an empty set of destination IDs. Calling code can override these + // prophecies later and set up different behaviors. + $this->migration->getIdMap()->willReturn( + $this->prophesize(MigrateIdMapInterface::class)->reveal() + ); + $this->migration->getHighWaterProperty()->willReturn([]); + $this->migration->getDestinationIds()->willReturn([]); + } + + /** + * Determines the plugin to be tested by reading the class @covers annotation. + * + * @return string + */ + protected function getPluginClass() { + $annotations = $this->getAnnotations(); + + if (isset($annotations['class']['covers'])) { + return $annotations['class']['covers'][0]; + } + else { + $this->fail('No plugin class was specified'); + } + } + + /** + * Instantiates the source plugin under test. + * + * @param array $configuration + * The source plugin configuration. + * + * @return \Drupal\migrate\Plugin\MigrateSourceInterface|object + * The fully configured source plugin. + */ + protected function getPlugin(array $configuration) { + // Only create the plugin once per test. + if ($this->plugin) { + return $this->plugin; + } + + $class = ltrim($this->getPluginClass(), '\\'); + + /** @var \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.migrate.source'); + + foreach ($plugin_manager->getDefinitions() as $id => $definition) { + if (ltrim($definition['class'], '\\') == $class) { + $this->plugin = $plugin_manager + ->createInstance($id, $configuration, $this->migration->reveal()); + + $this->migration + ->getSourcePlugin() + ->willReturn($this->plugin); + + return $this->plugin; + } + } + $this->fail('No plugin found for class ' . $class); + } + + /** + * Tests the source plugin against a particular data set. + * + * @param array $source_data + * The source data that the source plugin will read. + * @param array $expected_data + * The result rows the source plugin is expected to return. + * @param mixed $expected_count + * (optional) How many rows the source plugin is expected to return. + * Defaults to count($expected_data). If set to a non-null, non-numeric + * value (like FALSE or 'nope'), the source plugin will not be counted. + * @param array $configuration + * (optional) Configuration for the source plugin. + * + * @dataProvider providerSource + */ + public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = []) { + $plugin = $this->getPlugin($configuration); + + // All source plugins must define IDs. + $this->assertNotEmpty($plugin->getIds()); + + 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); + } + + $i = 0; + /** @var \Drupal\migrate\Row $row */ + foreach ($plugin as $row) { + $this->assertInstanceOf(Row::class, $row); + + $expected = $expected_data[$i++]; + $actual = $row->getSource(); + + foreach ($expected as $key => $value) { + $this->assertArrayHasKey($key, $actual); + + if (is_array($value)) { + ksort($value); + ksort($actual[$key]); + $this->assertEquals($value, $actual[$key]); + } + else { + $this->assertSame((string) $value, (string) $actual[$key]); + } + } + } + } + +} diff --git a/core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php b/core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php new file mode 100644 index 0000000..f04183f --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php @@ -0,0 +1,84 @@ + ':memory:']; + $pdo = Connection::open($connection_options); + $connection = new Connection($pdo, $connection_options); + + // Create the tables and fill them with data. + foreach ($source_data as $table => $rows) { + // Use the biggest row to build the table schema. + $counts = array_map('count', $rows); + asort($counts); + end($counts); + $pilot = $rows[key($counts)]; + + $connection->schema() + ->createTable($table, [ + // SQLite uses loose affinity typing, so it's OK for every field to + // be a text field. + 'fields' => array_map(function() { return ['type' => 'text']; }, $pilot), + ]); + + $fields = array_keys($pilot); + $insert = $connection->insert($table)->fields($fields); + array_walk($rows, [$insert, 'values']); + $insert->execute(); + } + + return $connection; + } + + /** + * Tests the source plugin against a particular data set. + * + * @param array $source_data + * The source data that the plugin will read. See getDatabase() for the + * expected format. + * @param array $expected_data + * The result rows the plugin is expected to return. + * @param int $expected_count + * (optional) How many rows the source plugin is expected to return. + * @param array $configuration + * (optional) Configuration for the source plugin. + * + * @dataProvider providerSource + * + * @requires extension pdo_sqlite + */ + public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = []) { + $plugin = $this->getPlugin($configuration); + + // 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); + $property = $reflector->getProperty('database'); + $property->setAccessible(TRUE); + $property->setValue($plugin, $this->getDatabase($source_data)); + + parent::testSource($source_data, $expected_data, $expected_count, $configuration); + } + +} diff --git a/core/modules/migrate/tests/src/Unit/MigrateSqlSourceTestCase.php b/core/modules/migrate/tests/src/Unit/MigrateSqlSourceTestCase.php index 764e14f..a185ac8 100644 --- a/core/modules/migrate/tests/src/Unit/MigrateSqlSourceTestCase.php +++ b/core/modules/migrate/tests/src/Unit/MigrateSqlSourceTestCase.php @@ -6,6 +6,9 @@ /** * Base class for Migrate module source unit tests. + * + * @deprecated in Drupal 8.2.0, will be removed before Drupal 9.0.0. Use + * \Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase instead. */ abstract class MigrateSqlSourceTestCase extends MigrateTestCase { diff --git a/core/modules/user/tests/src/Kernel/Plugin/migrate/source/d7/RoleTest.php b/core/modules/user/tests/src/Kernel/Plugin/migrate/source/d7/RoleTest.php new file mode 100644 index 0000000..d2d43a4 --- /dev/null +++ b/core/modules/user/tests/src/Kernel/Plugin/migrate/source/d7/RoleTest.php @@ -0,0 +1,72 @@ + 1, + 'name' => 'anonymous user', + 'permissions' => [ + 'access content', + ], + ], + [ + 'rid' => 2, + 'name' => 'authenticated user', + 'permissions' => [ + 'access comments', + 'access content', + 'post comments', + 'post comments without approval', + ], + ], + [ + 'rid' => 3, + 'name' => 'administrator', + 'permissions' => [ + 'access comments', + 'administer comments', + 'post comments', + 'post comments without approval', + 'access content', + 'administer content types', + 'administer nodes', + ], + ], + ]; + $data = [ + [[], $expected], + ]; + foreach ($expected as $row) { + foreach ($row['permissions'] as $permission) { + $data[0][0]['role_permission'][] = [ + 'permission' => $permission, + 'rid' => $row['rid'], + ]; + } + unset($row['permissions']); + $data[0][0]['role'][] = $row; + } + return $data; + } + +} diff --git a/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php b/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php deleted file mode 100644 index 48727b8..0000000 --- a/core/modules/user/tests/src/Unit/Plugin/migrate/source/d7/RoleTest.php +++ /dev/null @@ -1,73 +0,0 @@ - 'test', - 'source' => array( - 'plugin' => 'd7_user_role', - ), - ); - - protected $expectedResults = array( - array( - 'rid' => 1, - 'name' => 'anonymous user', - 'permissions' => array( - 'access content', - ), - ), - array( - 'rid' => 2, - 'name' => 'authenticated user', - 'permissions' => array( - 'access comments', - 'access content', - 'post comments', - 'post comments without approval', - ), - ), - array( - 'rid' => 3, - 'name' => 'administrator', - 'permissions' => array( - 'access comments', - 'administer comments', - 'post comments', - 'post comments without approval', - 'access content', - 'administer content types', - 'administer nodes', - ), - ), - ); - - /** - * {@inheritdoc} - */ - protected function setUp() { - foreach ($this->expectedResults as $row) { - foreach ($row['permissions'] as $permission) { - $this->databaseContents['role_permission'][] = array( - 'permission' => $permission, - 'rid' => $row['rid'], - ); - } - unset($row['permissions']); - $this->databaseContents['role'][] = $row; - } - parent::setUp(); - } - -}