f199562b6b3d8721adf7a9d60132691360e79885
[yaffs-website] / web / core / modules / migrate / tests / src / Unit / MigrateExecutableTest.php
1 <?php
2
3 namespace Drupal\Tests\migrate\Unit;
4
5 use Drupal\Component\Utility\Html;
6 use Drupal\migrate\Plugin\MigrateProcessInterface;
7 use Drupal\migrate\Plugin\MigrationInterface;
8 use Drupal\migrate\Plugin\MigrateIdMapInterface;
9 use Drupal\migrate\MigrateException;
10 use Drupal\migrate\Row;
11
12 /**
13  * @coversDefaultClass \Drupal\migrate\MigrateExecutable
14  * @group migrate
15  */
16 class MigrateExecutableTest extends MigrateTestCase {
17
18   /**
19    * The mocked migration entity.
20    *
21    * @var \Drupal\migrate\Plugin\MigrationInterface|\PHPUnit_Framework_MockObject_MockObject
22    */
23   protected $migration;
24
25   /**
26    * The mocked migrate message.
27    *
28    * @var \Drupal\migrate\MigrateMessageInterface|\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $message;
31
32   /**
33    * The tested migrate executable.
34    *
35    * @var \Drupal\Tests\migrate\Unit\TestMigrateExecutable
36    */
37   protected $executable;
38
39   /**
40    * The migration's configuration values.
41    *
42    * @var array
43    */
44   protected $migrationConfiguration = [
45     'id' => 'test',
46   ];
47
48   /**
49    * {@inheritdoc}
50    */
51   protected function setUp() {
52     parent::setUp();
53     $this->migration = $this->getMigration();
54     $this->message = $this->getMock('Drupal\migrate\MigrateMessageInterface');
55     $event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
56     $this->executable = new TestMigrateExecutable($this->migration, $this->message, $event_dispatcher);
57     $this->executable->setStringTranslation($this->getStringTranslationStub());
58   }
59
60   /**
61    * Tests an import with an incomplete rewinding.
62    */
63   public function testImportWithFailingRewind() {
64     $exception_message = $this->getRandomGenerator()->string();
65     $source = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
66     $source->expects($this->once())
67       ->method('rewind')
68       ->will($this->throwException(new \Exception($exception_message)));
69
70     $this->migration->expects($this->any())
71       ->method('getSourcePlugin')
72       ->will($this->returnValue($source));
73
74     // Ensure that a message with the proper message was added.
75     $this->message->expects($this->once())
76       ->method('display')
77       ->with("Migration failed with source plugin exception: " . Html::escape($exception_message));
78
79     $result = $this->executable->import();
80     $this->assertEquals(MigrationInterface::RESULT_FAILED, $result);
81   }
82
83   /**
84    * Tests the import method with a valid row.
85    */
86   public function testImportWithValidRow() {
87     $source = $this->getMockSource();
88
89     $row = $this->getMockBuilder('Drupal\migrate\Row')
90       ->disableOriginalConstructor()
91       ->getMock();
92
93     $row->expects($this->once())
94       ->method('getSourceIdValues')
95       ->will($this->returnValue(['id' => 'test']));
96
97     $this->idMap->expects($this->once())
98       ->method('lookupDestinationId')
99       ->with(['id' => 'test'])
100       ->will($this->returnValue(['test']));
101
102     $source->expects($this->once())
103       ->method('current')
104       ->will($this->returnValue($row));
105
106     $this->executable->setSource($source);
107
108     $this->migration->expects($this->once())
109       ->method('getProcessPlugins')
110       ->will($this->returnValue([]));
111
112     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
113     $destination->expects($this->once())
114       ->method('import')
115       ->with($row, ['test'])
116       ->will($this->returnValue(['id' => 'test']));
117
118     $this->migration
119       ->method('getDestinationPlugin')
120       ->willReturn($destination);
121
122     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
123   }
124
125   /**
126    * Tests the import method with a valid row.
127    */
128   public function testImportWithValidRowWithoutDestinationId() {
129     $source = $this->getMockSource();
130
131     $row = $this->getMockBuilder('Drupal\migrate\Row')
132       ->disableOriginalConstructor()
133       ->getMock();
134
135     $row->expects($this->once())
136       ->method('getSourceIdValues')
137       ->will($this->returnValue(['id' => 'test']));
138
139     $this->idMap->expects($this->once())
140       ->method('lookupDestinationId')
141       ->with(['id' => 'test'])
142       ->will($this->returnValue(['test']));
143
144     $source->expects($this->once())
145       ->method('current')
146       ->will($this->returnValue($row));
147
148     $this->executable->setSource($source);
149
150     $this->migration->expects($this->once())
151       ->method('getProcessPlugins')
152       ->will($this->returnValue([]));
153
154     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
155     $destination->expects($this->once())
156       ->method('import')
157       ->with($row, ['test'])
158       ->will($this->returnValue(TRUE));
159
160     $this->migration
161       ->method('getDestinationPlugin')
162       ->willReturn($destination);
163
164     $this->idMap->expects($this->never())
165       ->method('saveIdMapping');
166
167     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
168   }
169
170   /**
171    * Tests the import method with a valid row.
172    */
173   public function testImportWithValidRowNoDestinationValues() {
174     $source = $this->getMockSource();
175
176     $row = $this->getMockBuilder('Drupal\migrate\Row')
177       ->disableOriginalConstructor()
178       ->getMock();
179
180     $row->expects($this->once())
181       ->method('getSourceIdValues')
182       ->will($this->returnValue(['id' => 'test']));
183
184     $source->expects($this->once())
185       ->method('current')
186       ->will($this->returnValue($row));
187
188     $this->executable->setSource($source);
189
190     $this->migration->expects($this->once())
191       ->method('getProcessPlugins')
192       ->will($this->returnValue([]));
193
194     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
195     $destination->expects($this->once())
196       ->method('import')
197       ->with($row, ['test'])
198       ->will($this->returnValue([]));
199
200     $this->migration
201       ->method('getDestinationPlugin')
202       ->willReturn($destination);
203
204     $this->idMap->expects($this->once())
205       ->method('saveIdMapping')
206       ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
207
208     $this->idMap->expects($this->once())
209       ->method('messageCount')
210       ->will($this->returnValue(0));
211
212     $this->idMap->expects($this->once())
213       ->method('saveMessage');
214
215     $this->idMap->expects($this->once())
216       ->method('lookupDestinationId')
217       ->with(['id' => 'test'])
218       ->will($this->returnValue(['test']));
219
220     $this->message->expects($this->once())
221       ->method('display')
222       ->with('New object was not saved, no error provided');
223
224     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
225   }
226
227   /**
228    * Tests the import method with a thrown MigrateException.
229    *
230    * The MigrationException in this case is being thrown from the destination.
231    */
232   public function testImportWithValidRowWithDestinationMigrateException() {
233     $exception_message = $this->getRandomGenerator()->string();
234     $source = $this->getMockSource();
235
236     $row = $this->getMockBuilder('Drupal\migrate\Row')
237       ->disableOriginalConstructor()
238       ->getMock();
239
240     $row->expects($this->once())
241       ->method('getSourceIdValues')
242       ->will($this->returnValue(['id' => 'test']));
243
244     $source->expects($this->once())
245       ->method('current')
246       ->will($this->returnValue($row));
247
248     $this->executable->setSource($source);
249
250     $this->migration->expects($this->once())
251       ->method('getProcessPlugins')
252       ->will($this->returnValue([]));
253
254     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
255     $destination->expects($this->once())
256       ->method('import')
257       ->with($row, ['test'])
258       ->will($this->throwException(new MigrateException($exception_message)));
259
260     $this->migration
261       ->method('getDestinationPlugin')
262       ->willReturn($destination);
263
264     $this->idMap->expects($this->once())
265       ->method('saveIdMapping')
266       ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
267
268     $this->idMap->expects($this->once())
269       ->method('saveMessage');
270
271     $this->idMap->expects($this->once())
272       ->method('lookupDestinationId')
273       ->with(['id' => 'test'])
274       ->will($this->returnValue(['test']));
275
276     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
277   }
278
279   /**
280    * Tests the import method with a thrown MigrateException.
281    *
282    * The MigrationException in this case is being thrown from a process plugin.
283    */
284   public function testImportWithValidRowWithProcesMigrateException() {
285     $exception_message = $this->getRandomGenerator()->string();
286     $source = $this->getMockSource();
287
288     $row = $this->getMockBuilder('Drupal\migrate\Row')
289       ->disableOriginalConstructor()
290       ->getMock();
291
292     $row->expects($this->once())
293       ->method('getSourceIdValues')
294       ->willReturn(['id' => 'test']);
295
296     $source->expects($this->once())
297       ->method('current')
298       ->willReturn($row);
299
300     $this->executable->setSource($source);
301
302     $this->migration->expects($this->once())
303       ->method('getProcessPlugins')
304       ->willThrowException(new MigrateException($exception_message));
305
306     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
307     $destination->expects($this->never())
308       ->method('import');
309
310     $this->migration
311       ->method('getDestinationPlugin')
312       ->willReturn($destination);
313
314     $this->idMap->expects($this->once())
315       ->method('saveIdMapping')
316       ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
317
318     $this->idMap->expects($this->once())
319       ->method('saveMessage');
320
321     $this->idMap->expects($this->never())
322       ->method('lookupDestinationId');
323
324     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
325   }
326
327   /**
328    * Tests the import method with a regular Exception being thrown.
329    */
330   public function testImportWithValidRowWithException() {
331     $exception_message = $this->getRandomGenerator()->string();
332     $source = $this->getMockSource();
333
334     $row = $this->getMockBuilder('Drupal\migrate\Row')
335       ->disableOriginalConstructor()
336       ->getMock();
337
338     $row->expects($this->once())
339       ->method('getSourceIdValues')
340       ->will($this->returnValue(['id' => 'test']));
341
342     $source->expects($this->once())
343       ->method('current')
344       ->will($this->returnValue($row));
345
346     $this->executable->setSource($source);
347
348     $this->migration->expects($this->once())
349       ->method('getProcessPlugins')
350       ->will($this->returnValue([]));
351
352     $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
353     $destination->expects($this->once())
354       ->method('import')
355       ->with($row, ['test'])
356       ->will($this->throwException(new \Exception($exception_message)));
357
358     $this->migration
359       ->method('getDestinationPlugin')
360       ->willReturn($destination);
361
362     $this->idMap->expects($this->once())
363       ->method('saveIdMapping')
364       ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
365
366     $this->idMap->expects($this->once())
367       ->method('saveMessage');
368
369     $this->idMap->expects($this->once())
370       ->method('lookupDestinationId')
371       ->with(['id' => 'test'])
372       ->will($this->returnValue(['test']));
373
374     $this->message->expects($this->once())
375       ->method('display')
376       ->with($exception_message);
377
378     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
379   }
380
381   /**
382    * Tests the processRow method.
383    */
384   public function testProcessRow() {
385     $expected = [
386       'test' => 'test destination',
387       'test1' => 'test1 destination'
388     ];
389     foreach ($expected as $key => $value) {
390       $plugins[$key][0] = $this->getMock('Drupal\migrate\Plugin\MigrateProcessInterface');
391       $plugins[$key][0]->expects($this->once())
392         ->method('getPluginDefinition')
393         ->will($this->returnValue([]));
394       $plugins[$key][0]->expects($this->once())
395         ->method('transform')
396         ->will($this->returnValue($value));
397     }
398     $this->migration->expects($this->once())
399       ->method('getProcessPlugins')
400       ->with(NULL)
401       ->will($this->returnValue($plugins));
402     $row = new Row();
403     $this->executable->processRow($row);
404     foreach ($expected as $key => $value) {
405       $this->assertSame($row->getDestinationProperty($key), $value);
406     }
407     $this->assertSame(count($row->getDestination()), count($expected));
408   }
409
410   /**
411    * Tests the processRow method with an empty pipeline.
412    */
413   public function testProcessRowEmptyPipeline() {
414     $this->migration->expects($this->once())
415       ->method('getProcessPlugins')
416       ->with(NULL)
417       ->will($this->returnValue(['test' => []]));
418     $row = new Row();
419     $this->executable->processRow($row);
420     $this->assertSame($row->getDestination(), []);
421   }
422
423   /**
424    * Tests the processRow pipeline exception.
425    */
426   public function testProcessRowPipelineException() {
427     $row = new Row();
428     $plugin = $this->prophesize(MigrateProcessInterface::class);
429     $plugin->getPluginDefinition()->willReturn(['handle_multiples' => FALSE]);
430     $plugin->transform(NULL, $this->executable, $row, 'destination_id')
431       ->willReturn('transform_return_string');
432     $plugin->multiple()->willReturn(TRUE);
433     $plugin->getPluginId()->willReturn('plugin_id');
434     $plugin = $plugin->reveal();
435     $plugins['destination_id'] = [$plugin, $plugin];
436     $this->migration->method('getProcessPlugins')->willReturn($plugins);
437
438     $this->setExpectedException(MigrateException::class, 'Pipeline failed at plugin_id plugin for destination destination_id: transform_return_string received instead of an array,');
439     $this->executable->processRow($row);
440   }
441
442   /**
443    * Tests the processRow method.
444    */
445   public function testProcessRowEmptyDestination() {
446     $expected = [
447       'test' => 'test destination',
448       'test1' => 'test1 destination',
449       'test2' => NULL,
450     ];
451     $row = new Row();
452     $plugins = [];
453     foreach ($expected as $key => $value) {
454       $plugin = $this->prophesize(MigrateProcessInterface::class);
455       $plugin->getPluginDefinition()->willReturn([]);
456       $plugin->transform(NULL, $this->executable, $row, $key)->willReturn($value);
457       $plugin->multiple()->willReturn(TRUE);
458       $plugins[$key][0] = $plugin->reveal();
459     }
460     $this->migration->method('getProcessPlugins')->willReturn($plugins);
461     $this->executable->processRow($row);
462     foreach ($expected as $key => $value) {
463       $this->assertSame($value, $row->getDestinationProperty($key));
464     }
465     $this->assertCount(2, $row->getDestination());
466     $this->assertSame(['test2'], $row->getEmptyDestinationProperties());
467   }
468
469   /**
470    * Returns a mock migration source instance.
471    *
472    * @return \Drupal\migrate\Plugin\MigrateSourceInterface|\PHPUnit_Framework_MockObject_MockObject
473    *   The mocked migration source.
474    */
475   protected function getMockSource() {
476     $iterator = $this->getMock('\Iterator');
477
478     $class = 'Drupal\migrate\Plugin\migrate\source\SourcePluginBase';
479     $source = $this->getMockBuilder($class)
480       ->disableOriginalConstructor()
481       ->setMethods(get_class_methods($class))
482       ->getMockForAbstractClass();
483     $source->expects($this->once())
484       ->method('rewind')
485       ->will($this->returnValue(TRUE));
486     $source->expects($this->any())
487       ->method('initializeIterator')
488       ->will($this->returnValue([]));
489     $source->expects($this->any())
490       ->method('valid')
491       ->will($this->onConsecutiveCalls(TRUE, FALSE));
492
493     return $source;
494   }
495
496 }