comparison core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 7a779792577d
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 namespace Drupal\Tests\migrate\Kernel;
4
5 use Drupal\KernelTests\KernelTestBase;
6 use Drupal\migrate\Plugin\MigrateIdMapInterface;
7 use Drupal\migrate\Plugin\MigrationInterface;
8 use Drupal\migrate\Row;
9
10 /**
11 * Base class for tests of Migrate source plugins.
12 */
13 abstract class MigrateSourceTestBase extends KernelTestBase {
14
15 /**
16 * {@inheritdoc}
17 */
18 public static $modules = ['migrate'];
19
20 /**
21 * The mocked migration.
22 *
23 * @var MigrationInterface|\Prophecy\Prophecy\ObjectProphecy
24 */
25 protected $migration;
26
27 /**
28 * The source plugin under test.
29 *
30 * @var \Drupal\migrate\Plugin\MigrateSourceInterface
31 */
32 protected $plugin;
33
34 /**
35 * The data provider.
36 *
37 * @see \Drupal\Tests\migrate\Kernel\MigrateSourceTestBase::testSource
38 *
39 * @return array
40 * Array of data sets to test, each of which is a numerically indexed array
41 * with the following elements:
42 * - An array of source data, which can be optionally processed and set up
43 * by subclasses.
44 * - An array of expected result rows.
45 * - (optional) The number of result rows the plugin under test is expected
46 * to return. If this is not a numeric value, the plugin will not be
47 * counted.
48 * - (optional) Array of configuration options for the plugin under test.
49 */
50 abstract public function providerSource();
51
52 /**
53 * {@inheritdoc}
54 */
55 protected function setUp() {
56 parent::setUp();
57
58 // Create a mock migration. This will be injected into the source plugin
59 // under test.
60 $this->migration = $this->prophesize(MigrationInterface::class);
61
62 $this->migration->id()->willReturn(
63 $this->randomMachineName(16)
64 );
65 // Prophesize a useless ID map plugin and an empty set of destination IDs.
66 // Calling code can override these prophecies later and set up different
67 // behaviors.
68 $this->migration->getIdMap()->willReturn(
69 $this->prophesize(MigrateIdMapInterface::class)->reveal()
70 );
71 $this->migration->getDestinationIds()->willReturn([]);
72 }
73
74 /**
75 * Determines the plugin to be tested by reading the class @covers annotation.
76 *
77 * @return string
78 */
79 protected function getPluginClass() {
80 $annotations = $this->getAnnotations();
81
82 if (isset($annotations['class']['covers'])) {
83 return $annotations['class']['covers'][0];
84 }
85 else {
86 $this->fail('No plugin class was specified');
87 }
88 }
89
90 /**
91 * Instantiates the source plugin under test.
92 *
93 * @param array $configuration
94 * The source plugin configuration.
95 *
96 * @return \Drupal\migrate\Plugin\MigrateSourceInterface|object
97 * The fully configured source plugin.
98 */
99 protected function getPlugin(array $configuration) {
100 // Only create the plugin once per test.
101 if ($this->plugin) {
102 return $this->plugin;
103 }
104
105 $class = ltrim($this->getPluginClass(), '\\');
106
107 /** @var \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager */
108 $plugin_manager = $this->container->get('plugin.manager.migrate.source');
109
110 foreach ($plugin_manager->getDefinitions() as $id => $definition) {
111 if (ltrim($definition['class'], '\\') == $class) {
112 $this->plugin = $plugin_manager
113 ->createInstance($id, $configuration, $this->migration->reveal());
114
115 $this->migration
116 ->getSourcePlugin()
117 ->willReturn($this->plugin);
118
119 return $this->plugin;
120 }
121 }
122 $this->fail('No plugin found for class ' . $class);
123 }
124
125 /**
126 * Tests the source plugin against a particular data set.
127 *
128 * @param array $source_data
129 * The source data that the source plugin will read.
130 * @param array $expected_data
131 * The result rows the source plugin is expected to return.
132 * @param mixed $expected_count
133 * (optional) How many rows the source plugin is expected to return.
134 * Defaults to count($expected_data). If set to a non-null, non-numeric
135 * value (like FALSE or 'nope'), the source plugin will not be counted.
136 * @param array $configuration
137 * (optional) Configuration for the source plugin.
138 * @param mixed $high_water
139 * (optional) The value of the high water field.
140 *
141 * @dataProvider providerSource
142 */
143 public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = [], $high_water = NULL) {
144 $plugin = $this->getPlugin($configuration);
145
146 // All source plugins must define IDs.
147 $this->assertNotEmpty($plugin->getIds());
148
149 // If there is a high water mark, set it in the high water storage.
150 if (isset($high_water)) {
151 $this->container
152 ->get('keyvalue')
153 ->get('migrate:high_water')
154 ->set($this->migration->reveal()->id(), $high_water);
155 }
156
157 if (is_null($expected_count)) {
158 $expected_count = count($expected_data);
159 }
160 // If an expected count was given, assert it only if the plugin is
161 // countable.
162 if (is_numeric($expected_count)) {
163 $this->assertInstanceOf('\Countable', $plugin);
164 $this->assertCount($expected_count, $plugin);
165 }
166
167 $i = 0;
168 /** @var \Drupal\migrate\Row $row */
169 foreach ($plugin as $row) {
170 $this->assertInstanceOf(Row::class, $row);
171
172 $expected = $expected_data[$i++];
173 $actual = $row->getSource();
174
175 foreach ($expected as $key => $value) {
176 $this->assertArrayHasKey($key, $actual);
177
178 if (is_array($value)) {
179 ksort($value);
180 ksort($actual[$key]);
181 $this->assertEquals($value, $actual[$key]);
182 }
183 else {
184 $this->assertSame((string) $value, (string) $actual[$key]);
185 }
186 }
187 }
188 // False positives occur if the foreach is not entered. So, confirm the
189 // foreach loop was entered if the expected count is greater than 0.
190 if ($expected_count > 0) {
191 $this->assertGreaterThan(0, $i);
192 }
193 }
194
195 }