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..54c9135 --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php @@ -0,0 +1,177 @@ +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([]); + } + + /** + * {@inheritdoc} + */ + protected function tearDown() { + parent::tearDown(); + $this->plugin = NULL; + } + + /** + * 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 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 plugin will read. + * @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. + */ + 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 an expected count was given, assert it only if the plugin is + // countable. + if (is_numeric($expected_count)) { + if ($plugin instanceof \Countable) { + $this->assertCount($expected_count, $plugin); + } + else { + $this->fail('Plugin is not countable.'); + } + } + + $i = 0; + /** @var 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..08be8c1 --- /dev/null +++ b/core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php @@ -0,0 +1,83 @@ +markTestSkipped('The pdo_sqlite extension is unavailable.'); + } + + // Create an in-memory SQLite database. Plugins can interact with it like + // any other database, and it will cease to exist when the connection is + // closed. + $connection_options = ['database' => ':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 + */ + 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/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..88ce0bf --- /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; + } + +}