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