View source
<?php
namespace Drupal\Tests\layout_builder\Unit;
use Drupal\Component\Plugin\Context\ContextInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Component\Plugin\Factory\FactoryInterface;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
use Drupal\layout_builder\SectionStorage\SectionStorageDefinition;
use Drupal\layout_builder\SectionStorage\SectionStorageManager;
use Drupal\layout_builder\SectionStorageInterface;
use Drupal\Tests\UnitTestCase;
class SectionStorageManagerTest extends UnitTestCase {
protected $manager;
protected $plugin;
protected $discovery;
protected $factory;
protected $contextHandler;
protected function setUp() : void {
parent::setUp();
$cache = $this
->prophesize(CacheBackendInterface::class);
$module_handler = $this
->prophesize(ModuleHandlerInterface::class);
$this->contextHandler = $this
->prophesize(ContextHandlerInterface::class);
$this->manager = new SectionStorageManager(new \ArrayObject(), $cache
->reveal(), $module_handler
->reveal(), $this->contextHandler
->reveal());
$this->discovery = $this
->prophesize(DiscoveryInterface::class);
$reflection_property = new \ReflectionProperty($this->manager, 'discovery');
$reflection_property
->setAccessible(TRUE);
$reflection_property
->setValue($this->manager, $this->discovery
->reveal());
$this->plugin = $this
->prophesize(SectionStorageInterface::class);
$this->factory = $this
->prophesize(FactoryInterface::class);
$this->factory
->createInstance('the_plugin_id', [])
->willReturn($this->plugin
->reveal());
$reflection_property = new \ReflectionProperty($this->manager, 'factory');
$reflection_property
->setAccessible(TRUE);
$reflection_property
->setValue($this->manager, $this->factory
->reveal());
}
public function testLoadEmpty() {
$result = $this->manager
->loadEmpty('the_plugin_id');
$this
->assertInstanceOf(SectionStorageInterface::class, $result);
$this
->assertSame($this->plugin
->reveal(), $result);
}
public function testLoad() {
$contexts = [
'the_context' => $this
->prophesize(ContextInterface::class)
->reveal(),
];
$this->contextHandler
->applyContextMapping($this->plugin, $contexts)
->shouldBeCalled();
$result = $this->manager
->load('the_plugin_id', $contexts);
$this
->assertSame($this->plugin
->reveal(), $result);
}
public function testLoadNull() {
$contexts = [
'the_context' => $this
->prophesize(ContextInterface::class)
->reveal(),
];
$this->contextHandler
->applyContextMapping($this->plugin, $contexts)
->willThrow(new ContextException());
$result = $this->manager
->load('the_plugin_id', $contexts);
$this
->assertNull($result);
}
public function testFindDefinitions() {
$this->discovery
->getDefinitions()
->willReturn([
'plugin1' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
'plugin2' => (new SectionStorageDefinition([
'weight' => -5,
]))
->setClass(SectionStorageInterface::class),
'plugin3' => (new SectionStorageDefinition([
'weight' => -5,
]))
->setClass(SectionStorageInterface::class),
'plugin4' => (new SectionStorageDefinition([
'weight' => 10,
]))
->setClass(SectionStorageInterface::class),
]);
$expected = [
'plugin2',
'plugin3',
'plugin1',
'plugin4',
];
$result = $this->manager
->getDefinitions();
$this
->assertSame($expected, array_keys($result));
}
public function testFindByContext($plugin_is_applicable) {
$cacheability = new CacheableMetadata();
$contexts = [
'foo' => new Context(new ContextDefinition('foo')),
];
$definitions = [
'no_access' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
'missing_contexts' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
'provider_access' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
];
$this->discovery
->getDefinitions()
->willReturn($definitions);
$provider_access = $this
->prophesize(SectionStorageInterface::class);
$provider_access
->isApplicable($cacheability)
->willReturn($plugin_is_applicable);
$no_access = $this
->prophesize(SectionStorageInterface::class);
$no_access
->isApplicable($cacheability)
->willReturn(FALSE);
$missing_contexts = $this
->prophesize(SectionStorageInterface::class);
$this->contextHandler
->filterPluginDefinitionsByContexts($contexts, $definitions)
->willReturnArgument(1);
$this->contextHandler
->applyContextMapping($no_access, $contexts)
->shouldBeCalled();
$this->contextHandler
->applyContextMapping($provider_access, $contexts)
->shouldBeCalled();
$this->contextHandler
->applyContextMapping($missing_contexts, $contexts)
->willThrow(new ContextException());
$this->factory
->createInstance('no_access', [])
->willReturn($no_access
->reveal());
$this->factory
->createInstance('missing_contexts', [])
->willReturn($missing_contexts
->reveal());
$this->factory
->createInstance('provider_access', [])
->willReturn($provider_access
->reveal());
$result = $this->manager
->findByContext($contexts, $cacheability);
if ($plugin_is_applicable) {
$this
->assertSame($provider_access
->reveal(), $result);
}
else {
$this
->assertNull($result);
}
}
public function providerTestFindByContext() {
$data = [];
$data['plugin access: true'] = [
TRUE,
];
$data['plugin access: false'] = [
FALSE,
];
return $data;
}
public function testFindByContextCacheableSectionStorage() {
$cacheability = new CacheableMetadata();
$contexts = [
'foo' => new Context(new ContextDefinition('foo')),
];
$definitions = [
'first' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
'second' => (new SectionStorageDefinition())
->setClass(SectionStorageInterface::class),
];
$this->discovery
->getDefinitions()
->willReturn($definitions);
$first_plugin = $this
->prophesize(SectionStorageInterface::class);
$first_plugin
->willImplement(CacheableDependencyInterface::class);
$first_plugin
->getCacheContexts()
->shouldNotBeCalled();
$first_plugin
->getCacheTags()
->shouldNotBeCalled();
$first_plugin
->getCacheMaxAge()
->shouldNotBeCalled();
$first_plugin
->isApplicable($cacheability)
->will(function ($arguments) {
$arguments[0]
->addCacheTags([
'first_plugin',
]);
return FALSE;
});
$second_plugin = $this
->prophesize(SectionStorageInterface::class);
$second_plugin
->isApplicable($cacheability)
->will(function ($arguments) {
$arguments[0]
->addCacheTags([
'second_plugin',
]);
return TRUE;
});
$this->factory
->createInstance('first', [])
->willReturn($first_plugin
->reveal());
$this->factory
->createInstance('second', [])
->willReturn($second_plugin
->reveal());
$this->contextHandler
->filterPluginDefinitionsByContexts($contexts, $definitions)
->willReturnArgument(1);
$this->contextHandler
->applyContextMapping($first_plugin, $contexts)
->shouldBeCalled();
$this->contextHandler
->applyContextMapping($second_plugin, $contexts)
->shouldBeCalled();
$result = $this->manager
->findByContext($contexts, $cacheability);
$this
->assertSame($second_plugin
->reveal(), $result);
$this
->assertSame([
'first_plugin',
'second_plugin',
], $cacheability
->getCacheTags());
}
}