Version 1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Config / Entity / ConfigEntityStorageTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Config\Entity;
4
5 use Drupal\Component\Uuid\UuidInterface;
6 use Drupal\Core\Cache\Cache;
7 use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
8 use Drupal\Core\Config\Config;
9 use Drupal\Core\Config\ConfigDuplicateUUIDException;
10 use Drupal\Core\Config\ConfigFactoryInterface;
11 use Drupal\Core\Config\ConfigManagerInterface;
12 use Drupal\Core\Config\Entity\ConfigEntityBase;
13 use Drupal\Core\Config\Entity\ConfigEntityInterface;
14 use Drupal\Core\Config\Entity\ConfigEntityStorage;
15 use Drupal\Core\Config\Entity\ConfigEntityType;
16 use Drupal\Core\Config\ImmutableConfig;
17 use Drupal\Core\Config\TypedConfigManagerInterface;
18 use Drupal\Core\Entity\EntityInterface;
19 use Drupal\Core\Entity\EntityMalformedException;
20 use Drupal\Core\Entity\EntityManagerInterface;
21 use Drupal\Core\Entity\EntityStorageException;
22 use Drupal\Core\Entity\Query\QueryFactoryInterface;
23 use Drupal\Core\Entity\Query\QueryInterface;
24 use Drupal\Core\Extension\ModuleHandlerInterface;
25 use Drupal\Core\Language\Language;
26 use Drupal\Core\Language\LanguageManagerInterface;
27 use Drupal\Tests\UnitTestCase;
28 use Prophecy\Argument;
29 use Symfony\Component\DependencyInjection\ContainerBuilder;
30
31 /**
32  * @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityStorage
33  * @group Config
34  */
35 class ConfigEntityStorageTest extends UnitTestCase {
36
37   /**
38    * The type ID of the entity under test.
39    *
40    * @var string
41    */
42   protected $entityTypeId;
43
44   /**
45    * The module handler.
46    *
47    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
48    */
49   protected $moduleHandler;
50
51   /**
52    * The UUID service.
53    *
54    * @var \Drupal\Component\Uuid\UuidInterface|\Prophecy\Prophecy\ProphecyInterface
55    */
56   protected $uuidService;
57
58   /**
59    * The language manager.
60    *
61    * @var \Drupal\Core\Language\LanguageManagerInterface|\Prophecy\Prophecy\ProphecyInterface
62    */
63   protected $languageManager;
64
65   /**
66    * The config storage.
67    *
68    * @var \Drupal\Core\Config\Entity\ConfigEntityStorage
69    */
70   protected $entityStorage;
71
72   /**
73    * The config factory service.
74    *
75    * @var \Drupal\Core\Config\ConfigFactoryInterface|\Prophecy\Prophecy\ProphecyInterface
76    */
77   protected $configFactory;
78
79   /**
80    * The entity query.
81    *
82    * @var \Drupal\Core\Entity\Query\QueryInterface|\Prophecy\Prophecy\ProphecyInterface
83    */
84   protected $entityQuery;
85
86   /**
87    * The mocked cache backend.
88    *
89    * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\Prophecy\Prophecy\ProphecyInterface
90    */
91   protected $cacheTagsInvalidator;
92
93   /**
94    * The configuration manager.
95    *
96    * @var \Drupal\Core\Config\ConfigManagerInterface|\Prophecy\Prophecy\ProphecyInterface
97    */
98   protected $configManager;
99
100   /**
101    * {@inheritdoc}
102    *
103    * @covers ::__construct
104    */
105   protected function setUp() {
106     parent::setUp();
107
108     $this->entityTypeId = 'test_entity_type';
109
110     $entity_type = new ConfigEntityType([
111       'id' => $this->entityTypeId,
112       'class' => get_class($this->getMockEntity()),
113       'provider' => 'the_provider',
114       'config_prefix' => 'the_config_prefix',
115       'entity_keys' => [
116         'id' => 'id',
117         'uuid' => 'uuid',
118         'langcode' => 'langcode',
119       ],
120       'list_cache_tags' => [$this->entityTypeId . '_list'],
121     ]);
122
123     $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
124
125     $this->uuidService = $this->prophesize(UuidInterface::class);
126
127     $this->languageManager = $this->prophesize(LanguageManagerInterface::class);
128     $this->languageManager->getCurrentLanguage()->willReturn(new Language(['id' => 'hu']));
129
130     $this->configFactory = $this->prophesize(ConfigFactoryInterface::class);
131
132     $this->entityQuery = $this->prophesize(QueryInterface::class);
133     $entity_query_factory = $this->prophesize(QueryFactoryInterface::class);
134     $entity_query_factory->get($entity_type, 'AND')->willReturn($this->entityQuery->reveal());
135
136     $this->entityStorage = new ConfigEntityStorage($entity_type, $this->configFactory->reveal(), $this->uuidService->reveal(), $this->languageManager->reveal());
137     $this->entityStorage->setModuleHandler($this->moduleHandler->reveal());
138
139     $entity_manager = $this->prophesize(EntityManagerInterface::class);
140     $entity_manager->getDefinition('test_entity_type')->willReturn($entity_type);
141
142     $this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class);
143
144     $typed_config_manager = $this->prophesize(TypedConfigManagerInterface::class);
145     $typed_config_manager
146       ->getDefinition(Argument::containingString('the_provider.the_config_prefix.'))
147       ->willReturn(['mapping' => ['id' => '', 'uuid' => '', 'dependencies' => '']]);
148
149     $this->configManager = $this->prophesize(ConfigManagerInterface::class);
150
151     $container = new ContainerBuilder();
152     $container->set('entity.manager', $entity_manager->reveal());
153     $container->set('entity.query.config', $entity_query_factory->reveal());
154     $container->set('config.typed', $typed_config_manager->reveal());
155     $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator->reveal());
156     $container->set('config.manager', $this->configManager->reveal());
157     $container->set('language_manager', $this->languageManager->reveal());
158     \Drupal::setContainer($container);
159
160   }
161
162   /**
163    * @covers ::create
164    * @covers ::doCreate
165    */
166   public function testCreateWithPredefinedUuid() {
167     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())->shouldNotBeCalled();
168
169     $entity = $this->getMockEntity();
170     $entity->set('id', 'foo');
171     $entity->set('langcode', 'hu');
172     $entity->set('uuid', 'baz');
173     $entity->setOriginalId('foo');
174     $entity->enforceIsNew();
175
176     $this->moduleHandler->invokeAll('test_entity_type_create', [$entity])
177       ->shouldBeCalled();
178     $this->moduleHandler->invokeAll('entity_create', [$entity, 'test_entity_type'])
179       ->shouldBeCalled();
180
181     $this->uuidService->generate()->shouldNotBeCalled();
182
183     $entity = $this->entityStorage->create(['id' => 'foo', 'uuid' => 'baz']);
184     $this->assertInstanceOf(EntityInterface::class, $entity);
185     $this->assertSame('foo', $entity->id());
186     $this->assertSame('baz', $entity->uuid());
187   }
188
189   /**
190    * @covers ::create
191    * @covers ::doCreate
192    *
193    * @return \Drupal\Core\Entity\EntityInterface
194    */
195   public function testCreate() {
196     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())->shouldNotBeCalled();
197
198     $entity = $this->getMockEntity();
199     $entity->set('id', 'foo');
200     $entity->set('langcode', 'hu');
201     $entity->set('uuid', 'bar');
202     $entity->setOriginalId('foo');
203     $entity->enforceIsNew();
204
205     $this->moduleHandler->invokeAll('test_entity_type_create', [$entity])
206       ->shouldBeCalled();
207     $this->moduleHandler->invokeAll('entity_create', [$entity, 'test_entity_type'])
208       ->shouldBeCalled();
209
210     $this->uuidService->generate()->willReturn('bar');
211
212     $entity = $this->entityStorage->create(['id' => 'foo']);
213     $this->assertInstanceOf(EntityInterface::class, $entity);
214     $this->assertSame('foo', $entity->id());
215     $this->assertSame('bar', $entity->uuid());
216     return $entity;
217   }
218
219   /**
220    * @covers ::create
221    * @covers ::doCreate
222    */
223   public function testCreateWithCurrentLanguage() {
224     $this->languageManager->getLanguage('hu')->willReturn(new Language(['id' => 'hu']));
225
226     $entity = $this->entityStorage->create(['id' => 'foo']);
227     $this->assertSame('hu', $entity->language()->getId());
228   }
229
230   /**
231    * @covers ::create
232    * @covers ::doCreate
233    */
234   public function testCreateWithExplicitLanguage() {
235     $this->languageManager->getLanguage('en')->willReturn(new Language(['id' => 'en']));
236
237     $entity = $this->entityStorage->create(['id' => 'foo', 'langcode' => 'en']);
238     $this->assertSame('en', $entity->language()->getId());
239   }
240
241   /**
242    * @covers ::save
243    * @covers ::doSave
244    *
245    * @param \Drupal\Core\Entity\EntityInterface $entity
246    *
247    * @return \Drupal\Core\Entity\EntityInterface
248    *
249    * @depends testCreate
250    */
251   public function testSaveInsert(EntityInterface $entity) {
252     $immutable_config_object = $this->prophesize(ImmutableConfig::class);
253     $immutable_config_object->isNew()->willReturn(TRUE);
254
255     $config_object = $this->prophesize(Config::class);
256     $config_object->setData(['id' => 'foo', 'uuid' => 'bar', 'dependencies' => []])
257       ->shouldBeCalled();
258     $config_object->save(FALSE)->shouldBeCalled();
259     $config_object->get()->willReturn([]);
260
261     $this->cacheTagsInvalidator->invalidateTags([$this->entityTypeId . '_list'])
262       ->shouldBeCalled();
263
264     $this->configFactory->get('the_provider.the_config_prefix.foo')
265       ->willReturn($immutable_config_object->reveal());
266     $this->configFactory->getEditable('the_provider.the_config_prefix.foo')
267       ->willReturn($config_object->reveal());
268
269     $this->moduleHandler->invokeAll('test_entity_type_presave', [$entity])
270       ->shouldBeCalled();
271     $this->moduleHandler->invokeAll('entity_presave', [$entity, 'test_entity_type'])
272       ->shouldBeCalled();
273     $this->moduleHandler->invokeAll('test_entity_type_insert', [$entity])
274       ->shouldBeCalled();
275     $this->moduleHandler->invokeAll('entity_insert', [$entity, 'test_entity_type'])
276       ->shouldBeCalled();
277
278     $this->entityQuery->condition('uuid', 'bar')->willReturn($this->entityQuery);
279     $this->entityQuery->execute()->willReturn([]);
280
281     $return = $this->entityStorage->save($entity);
282     $this->assertSame(SAVED_NEW, $return);
283     return $entity;
284   }
285
286   /**
287    * @covers ::save
288    * @covers ::doSave
289    *
290    * @param \Drupal\Core\Entity\EntityInterface $entity
291    *
292    * @return \Drupal\Core\Entity\EntityInterface
293    *
294    * @depends testSaveInsert
295    */
296   public function testSaveUpdate(EntityInterface $entity) {
297     $immutable_config_object = $this->prophesize(ImmutableConfig::class);
298     $immutable_config_object->isNew()->willReturn(FALSE);
299
300     $config_object = $this->prophesize(Config::class);
301     $config_object->setData(['id' => 'foo', 'uuid' => 'bar', 'dependencies' => []])
302       ->shouldBeCalled();
303     $config_object->save(FALSE)->shouldBeCalled();
304     $config_object->get()->willReturn([]);
305
306     $this->cacheTagsInvalidator->invalidateTags([$this->entityTypeId . '_list'])
307       ->shouldBeCalled();
308
309     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo'])
310       ->willReturn([])
311       ->shouldBeCalledTimes(2);
312     $this->configFactory
313       ->get('the_provider.the_config_prefix.foo')
314       ->willReturn($immutable_config_object->reveal())
315       ->shouldBeCalledTimes(1);
316     $this->configFactory
317       ->getEditable('the_provider.the_config_prefix.foo')
318       ->willReturn($config_object->reveal())
319       ->shouldBeCalledTimes(1);
320
321     $this->moduleHandler->invokeAll('test_entity_type_presave', [$entity])
322       ->shouldBeCalled();
323     $this->moduleHandler->invokeAll('entity_presave', [$entity, 'test_entity_type'])
324       ->shouldBeCalled();
325     $this->moduleHandler->invokeAll('test_entity_type_update', [$entity])
326       ->shouldBeCalled();
327     $this->moduleHandler->invokeAll('entity_update', [$entity, 'test_entity_type'])
328       ->shouldBeCalled();
329
330     $this->entityQuery->condition('uuid', 'bar')->willReturn($this->entityQuery);
331     $this->entityQuery->execute()->willReturn([$entity->id()]);
332
333     $return = $this->entityStorage->save($entity);
334     $this->assertSame(SAVED_UPDATED, $return);
335     return $entity;
336   }
337
338   /**
339    * @covers ::save
340    * @covers ::doSave
341    *
342    * @depends testSaveInsert
343    */
344   public function testSaveRename(ConfigEntityInterface $entity) {
345     $immutable_config_object = $this->prophesize(ImmutableConfig::class);
346     $immutable_config_object->isNew()->willReturn(FALSE);
347
348     $config_object = $this->prophesize(Config::class);
349     $config_object->setData(['id' => 'bar', 'uuid' => 'bar', 'dependencies' => []])
350       ->shouldBeCalled();
351     $config_object->save(FALSE)
352       ->shouldBeCalled();
353     $config_object->get()->willReturn([]);
354
355     $this->cacheTagsInvalidator->invalidateTags([$this->entityTypeId . '_list'])
356       ->shouldBeCalled();
357
358     $this->configFactory->get('the_provider.the_config_prefix.foo')
359       ->willReturn($immutable_config_object->reveal());
360     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo'])
361       ->willReturn([]);
362     $this->configFactory->rename('the_provider.the_config_prefix.foo', 'the_provider.the_config_prefix.bar')
363       ->shouldBeCalled();
364     $this->configFactory->getEditable('the_provider.the_config_prefix.bar')
365       ->willReturn($config_object->reveal());
366
367     // Performing a rename does not change the original ID until saving.
368     $this->assertSame('foo', $entity->getOriginalId());
369     $entity->set('id', 'bar');
370     $this->assertSame('foo', $entity->getOriginalId());
371
372     $this->entityQuery->condition('uuid', 'bar')->willReturn($this->entityQuery);
373     $this->entityQuery->execute()->willReturn([$entity->id()]);
374
375     $return = $this->entityStorage->save($entity);
376     $this->assertSame(SAVED_UPDATED, $return);
377     $this->assertSame('bar', $entity->getOriginalId());
378   }
379
380   /**
381    * @covers ::save
382    */
383   public function testSaveInvalid() {
384     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())
385       ->shouldNotBeCalled();
386
387     $entity = $this->getMockEntity();
388     $this->setExpectedException(EntityMalformedException::class, 'The entity does not have an ID.');
389     $this->entityStorage->save($entity);
390   }
391
392   /**
393    * @covers ::save
394    * @covers ::doSave
395    */
396   public function testSaveDuplicate() {
397     $config_object = $this->prophesize(ImmutableConfig::class);
398     $config_object->isNew()->willReturn(FALSE);
399
400     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())
401       ->shouldNotBeCalled();
402
403     $this->configFactory->get('the_provider.the_config_prefix.foo')
404       ->willReturn($config_object->reveal());
405
406     $entity = $this->getMockEntity(['id' => 'foo']);
407     $entity->enforceIsNew();
408
409     $this->setExpectedException(EntityStorageException::class);
410     $this->entityStorage->save($entity);
411   }
412
413   /**
414    * @covers ::save
415    * @covers ::doSave
416    */
417   public function testSaveMismatch() {
418     $config_object = $this->prophesize(ImmutableConfig::class);
419     $config_object->isNew()->willReturn(TRUE);
420
421     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())
422       ->shouldNotBeCalled();
423
424     $this->configFactory->get('the_provider.the_config_prefix.foo')
425       ->willReturn($config_object->reveal());
426
427     $this->entityQuery->condition('uuid', NULL)->willReturn($this->entityQuery);
428     $this->entityQuery->execute()->willReturn(['baz']);
429
430     $entity = $this->getMockEntity(['id' => 'foo']);
431     $this->setExpectedException(ConfigDuplicateUUIDException::class, 'when this UUID is already used for');
432     $this->entityStorage->save($entity);
433   }
434
435   /**
436    * @covers ::save
437    * @covers ::doSave
438    */
439   public function testSaveNoMismatch() {
440     $immutable_config_object = $this->prophesize(ImmutableConfig::class);
441     $immutable_config_object->isNew()->willReturn(TRUE);
442
443     $config_object = $this->prophesize(Config::class);
444     $config_object->get()->willReturn([]);
445     $config_object->setData(['id' => 'foo', 'uuid' => NULL, 'dependencies' => []])
446       ->shouldBeCalled();
447     $config_object->save(FALSE)->shouldBeCalled();
448
449     $this->cacheTagsInvalidator->invalidateTags([$this->entityTypeId . '_list'])
450       ->shouldBeCalled();
451
452     $this->configFactory->get('the_provider.the_config_prefix.baz')
453       ->willReturn($immutable_config_object->reveal())
454       ->shouldBeCalled();
455     $this->configFactory->rename('the_provider.the_config_prefix.baz', 'the_provider.the_config_prefix.foo')
456       ->shouldBeCalled();
457     $this->configFactory->getEditable('the_provider.the_config_prefix.foo')
458       ->willReturn($config_object->reveal())
459       ->shouldBeCalled();
460
461     $this->entityQuery->condition('uuid', NULL)->willReturn($this->entityQuery);
462     $this->entityQuery->execute()->willReturn(['baz']);
463
464     $entity = $this->getMockEntity(['id' => 'foo']);
465     $entity->setOriginalId('baz');
466     $entity->enforceIsNew();
467     $this->entityStorage->save($entity);
468   }
469
470   /**
471    * @covers ::save
472    * @covers ::doSave
473    */
474   public function testSaveChangedUuid() {
475     $config_object = $this->prophesize(ImmutableConfig::class);
476     $config_object->get()->willReturn(['id' => 'foo']);
477     $config_object->get('id')->willReturn('foo');
478     $config_object->isNew()->willReturn(FALSE);
479     $config_object->getName()->willReturn('foo');
480     $config_object->getCacheContexts()->willReturn([]);
481     $config_object->getCacheTags()->willReturn(['config:foo']);
482     $config_object->getCacheMaxAge()->willReturn(Cache::PERMANENT);
483
484     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())
485       ->shouldNotBeCalled();
486
487     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo'])
488       ->willReturn([$config_object->reveal()]);
489     $this->configFactory->get('the_provider.the_config_prefix.foo')
490       ->willReturn($config_object->reveal());
491     $this->configFactory->rename(Argument::cetera())->shouldNotBeCalled();
492
493     $this->moduleHandler->getImplementations('entity_load')->willReturn([]);
494     $this->moduleHandler->getImplementations('test_entity_type_load')->willReturn([]);
495
496     $this->entityQuery->condition('uuid', 'baz')->willReturn($this->entityQuery);
497     $this->entityQuery->execute()->willReturn(['foo']);
498
499     $entity = $this->getMockEntity(['id' => 'foo']);
500
501     $entity->set('uuid', 'baz');
502     $this->setExpectedException(ConfigDuplicateUUIDException::class, 'when this entity already exists with UUID');
503     $this->entityStorage->save($entity);
504   }
505
506   /**
507    * @covers ::load
508    * @covers ::postLoad
509    * @covers ::mapFromStorageRecords
510    * @covers ::doLoadMultiple
511    */
512   public function testLoad() {
513     $config_object = $this->prophesize(ImmutableConfig::class);
514     $config_object->get()->willReturn(['id' => 'foo']);
515     $config_object->get('id')->willReturn('foo');
516     $config_object->getCacheContexts()->willReturn([]);
517     $config_object->getCacheTags()->willReturn(['config:foo']);
518     $config_object->getCacheMaxAge()->willReturn(Cache::PERMANENT);
519     $config_object->getName()->willReturn('foo');
520
521     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo'])
522       ->willReturn([$config_object->reveal()]);
523
524     $this->moduleHandler->getImplementations('entity_load')->willReturn([]);
525     $this->moduleHandler->getImplementations('test_entity_type_load')->willReturn([]);
526
527     $entity = $this->entityStorage->load('foo');
528     $this->assertInstanceOf(EntityInterface::class, $entity);
529     $this->assertSame('foo', $entity->id());
530   }
531
532   /**
533    * @covers ::loadMultiple
534    * @covers ::postLoad
535    * @covers ::mapFromStorageRecords
536    * @covers ::doLoadMultiple
537    */
538   public function testLoadMultipleAll() {
539     $foo_config_object = $this->prophesize(ImmutableConfig::class);
540     $foo_config_object->get()->willReturn(['id' => 'foo']);
541     $foo_config_object->get('id')->willReturn('foo');
542     $foo_config_object->getCacheContexts()->willReturn([]);
543     $foo_config_object->getCacheTags()->willReturn(['config:foo']);
544     $foo_config_object->getCacheMaxAge()->willReturn(Cache::PERMANENT);
545     $foo_config_object->getName()->willReturn('foo');
546
547     $bar_config_object = $this->prophesize(ImmutableConfig::class);
548     $bar_config_object->get()->willReturn(['id' => 'bar']);
549     $bar_config_object->get('id')->willReturn('bar');
550     $bar_config_object->getCacheContexts()->willReturn([]);
551     $bar_config_object->getCacheTags()->willReturn(['config:bar']);
552     $bar_config_object->getCacheMaxAge()->willReturn(Cache::PERMANENT);
553     $bar_config_object->getName()->willReturn('foo');
554
555     $this->configFactory->listAll('the_provider.the_config_prefix.')
556       ->willReturn(['the_provider.the_config_prefix.foo' , 'the_provider.the_config_prefix.bar']);
557     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo', 'the_provider.the_config_prefix.bar'])
558       ->willReturn([$foo_config_object->reveal(), $bar_config_object->reveal()]);
559
560     $this->moduleHandler->getImplementations('entity_load')->willReturn([]);
561     $this->moduleHandler->getImplementations('test_entity_type_load')->willReturn([]);
562
563     $entities = $this->entityStorage->loadMultiple();
564     $expected['foo'] = 'foo';
565     $expected['bar'] = 'bar';
566     $this->assertContainsOnlyInstancesOf(EntityInterface::class, $entities);
567     foreach ($entities as $id => $entity) {
568       $this->assertSame($id, $entity->id());
569       $this->assertSame($expected[$id], $entity->id());
570     }
571   }
572
573   /**
574    * @covers ::loadMultiple
575    * @covers ::postLoad
576    * @covers ::mapFromStorageRecords
577    * @covers ::doLoadMultiple
578    */
579   public function testLoadMultipleIds() {
580     $config_object = $this->prophesize(ImmutableConfig::class);
581     $config_object->get()->willReturn(['id' => 'foo']);
582     $config_object->get('id')->willReturn('foo');
583     $config_object->getCacheContexts()->willReturn([]);
584     $config_object->getCacheTags()->willReturn(['config:foo']);
585     $config_object->getCacheMaxAge()->willReturn(Cache::PERMANENT);
586     $config_object->getName()->willReturn('foo');
587
588     $this->configFactory->loadMultiple(['the_provider.the_config_prefix.foo'])
589       ->willReturn([$config_object->reveal()]);
590
591     $this->moduleHandler->getImplementations('entity_load')->willReturn([]);
592     $this->moduleHandler->getImplementations('test_entity_type_load')->willReturn([]);
593
594     $entities = $this->entityStorage->loadMultiple(['foo']);
595     $this->assertContainsOnlyInstancesOf(EntityInterface::class, $entities);
596     foreach ($entities as $id => $entity) {
597       $this->assertSame($id, $entity->id());
598     }
599   }
600
601   /**
602    * @covers ::loadRevision
603    */
604   public function testLoadRevision() {
605     $this->assertSame(NULL, $this->entityStorage->loadRevision(1));
606   }
607
608   /**
609    * @covers ::deleteRevision
610    */
611   public function testDeleteRevision() {
612     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())
613       ->shouldNotBeCalled();
614
615     $this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
616   }
617
618   /**
619    * @covers ::delete
620    * @covers ::doDelete
621    */
622   public function testDelete() {
623     // Dependencies are tested in
624     // \Drupal\Tests\config\Kernel\ConfigDependencyTest.
625     $this->configManager
626       ->getConfigEntitiesToChangeOnDependencyRemoval('config', ['the_provider.the_config_prefix.foo'], FALSE)
627       ->willReturn(['update' => [], 'delete' => [], 'unchanged' => []]);
628     $this->configManager
629       ->getConfigEntitiesToChangeOnDependencyRemoval('config', ['the_provider.the_config_prefix.bar'], FALSE)
630       ->willReturn(['update' => [], 'delete' => [], 'unchanged' => []]);
631
632     $entities = [];
633     foreach (['foo', 'bar'] as $id) {
634       $entity = $this->getMockEntity(['id' => $id]);
635       $entities[] = $entity;
636
637       $config_object = $this->prophesize(Config::class);
638       $config_object->delete()->shouldBeCalled();
639
640       $this->configFactory->getEditable("the_provider.the_config_prefix.$id")
641         ->willReturn($config_object->reveal());
642
643       $this->moduleHandler->invokeAll('test_entity_type_predelete', [$entity])
644         ->shouldBeCalled();
645       $this->moduleHandler->invokeAll('entity_predelete', [$entity, 'test_entity_type'])
646         ->shouldBeCalled();
647
648       $this->moduleHandler->invokeAll('test_entity_type_delete', [$entity])
649         ->shouldBeCalled();
650       $this->moduleHandler->invokeAll('entity_delete', [$entity, 'test_entity_type'])
651         ->shouldBeCalled();
652     }
653
654     $this->cacheTagsInvalidator->invalidateTags([$this->entityTypeId . '_list'])
655       ->shouldBeCalled();
656
657     $this->entityStorage->delete($entities);
658   }
659
660   /**
661    * @covers ::delete
662    * @covers ::doDelete
663    */
664   public function testDeleteNothing() {
665     $this->moduleHandler->getImplementations(Argument::cetera())->shouldNotBeCalled();
666     $this->moduleHandler->invokeAll(Argument::cetera())->shouldNotBeCalled();
667
668     $this->configFactory->get(Argument::cetera())->shouldNotBeCalled();
669     $this->configFactory->getEditable(Argument::cetera())->shouldNotBeCalled();
670
671     $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())->shouldNotBeCalled();
672
673     $this->entityStorage->delete([]);
674   }
675
676   /**
677    * Creates an entity with specific methods mocked.
678    *
679    * @param array $values
680    *   (optional) Values to pass to the constructor.
681    * @param array $methods
682    *   (optional) The methods to mock.
683    *
684    * @return \Drupal\Core\Entity\EntityInterface|\PHPUnit_Framework_MockObject_MockObject
685    */
686   public function getMockEntity(array $values = [], $methods = []) {
687     return $this->getMockForAbstractClass(ConfigEntityBase::class, [$values, 'test_entity_type'], '', TRUE, TRUE, TRUE, $methods);
688   }
689
690 }
691
692 namespace Drupal\Core\Config\Entity;
693
694 if (!defined('SAVED_NEW')) {
695   define('SAVED_NEW', 1);
696 }
697 if (!defined('SAVED_UPDATED')) {
698   define('SAVED_UPDATED', 2);
699 }