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