class LayoutPluginManagerTest
Same name in this branch
- 11.x core/tests/Drupal/KernelTests/Core/Layout/LayoutPluginManagerTest.php \Drupal\KernelTests\Core\Layout\LayoutPluginManagerTest
Same name in other branches
- 9 core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php \Drupal\Tests\Core\Layout\LayoutPluginManagerTest
- 8.9.x core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php \Drupal\Tests\Core\Layout\LayoutPluginManagerTest
- 10 core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php \Drupal\Tests\Core\Layout\LayoutPluginManagerTest
- 10 core/tests/Drupal/KernelTests/Core/Layout/LayoutPluginManagerTest.php \Drupal\KernelTests\Core\Layout\LayoutPluginManagerTest
@coversDefaultClass \Drupal\Core\Layout\LayoutPluginManager @group Layout
Hierarchy
- class \Drupal\Tests\UnitTestCase extends \PHPUnit\Framework\TestCase uses \Drupal\Tests\PhpUnitCompatibilityTrait, \Prophecy\PhpUnit\ProphecyTrait, \Drupal\TestTools\Extension\DeprecationBridge\ExpectDeprecationTrait, \Drupal\Tests\RandomGeneratorTrait
- class \Drupal\Tests\Core\Layout\LayoutPluginManagerTest extends \Drupal\Tests\UnitTestCase
Expanded class hierarchy of LayoutPluginManagerTest
File
-
core/
tests/ Drupal/ Tests/ Core/ Layout/ LayoutPluginManagerTest.php, line 31
Namespace
Drupal\Tests\Core\LayoutView source
class LayoutPluginManagerTest extends UnitTestCase {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The theme handler.
*
* @var \Drupal\Core\Extension\ThemeHandlerInterface
*/
protected $themeHandler;
/**
* The theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface
*/
protected $themeManager;
/**
* Cache backend instance.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cacheBackend;
/**
* The layout plugin manager.
*
* @var \Drupal\Core\Layout\LayoutPluginManagerInterface
*/
protected $layoutPluginManager;
/**
* {@inheritdoc}
*/
protected function setUp() : void {
parent::setUp();
$this->setUpFilesystem();
$container = new ContainerBuilder();
$container->set('string_translation', $this->getStringTranslationStub());
$this->themeManager = $this->prophesize(ThemeManagerInterface::class);
$container->set('theme.manager', $this->themeManager
->reveal());
\Drupal::setContainer($container);
$this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
$this->moduleHandler
->moduleExists('module_a')
->willReturn(TRUE);
$this->moduleHandler
->moduleExists('theme_a')
->willReturn(FALSE);
$this->moduleHandler
->moduleExists('core')
->willReturn(FALSE);
$this->moduleHandler
->moduleExists('invalid_provider')
->willReturn(FALSE);
$module_a = new Extension('vfs://root', 'module', 'modules/module_a/module_a.layouts.yml');
$this->moduleHandler
->getModule('module_a')
->willReturn($module_a);
$this->moduleHandler
->getModuleDirectories()
->willReturn([
'module_a' => vfsStream::url('root/modules/module_a'),
]);
$this->moduleHandler
->alter('layout', Argument::type('array'))
->shouldBeCalled();
$this->themeHandler = $this->prophesize(ThemeHandlerInterface::class);
$this->themeHandler
->themeExists('theme_a')
->willReturn(TRUE);
$this->themeHandler
->themeExists('core')
->willReturn(FALSE);
$this->themeHandler
->themeExists('invalid_provider')
->willReturn(FALSE);
$theme_a = new Extension('vfs://root', 'theme', 'themes/theme_a/theme_a.layouts.yml');
$this->themeHandler
->getTheme('theme_a')
->willReturn($theme_a);
$this->themeHandler
->getThemeDirectories()
->willReturn([
'theme_a' => vfsStream::url('root/themes/theme_a'),
]);
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
$namespaces = new \ArrayObject([
'Drupal\\Core' => vfsStream::url('root/core/lib/Drupal/Core'),
]);
$class_loader = new ClassLoader();
$class_loader->addPsr4("Drupal\\Core\\", vfsStream::url("root/core/lib/Drupal/Core"));
$class_loader->register(TRUE);
$this->layoutPluginManager = new LayoutPluginManager($namespaces, $this->cacheBackend
->reveal(), $this->moduleHandler
->reveal(), $this->themeHandler
->reveal());
}
/**
* @covers ::getDefinitions
* @covers ::providerExists
*/
public function testGetDefinitions() : void {
$expected = [
'module_a_provided_layout',
'theme_a_provided_layout',
'plugin_provided_layout',
'plugin_provided_by_annotation_layout',
];
$layout_definitions = $this->layoutPluginManager
->getDefinitions();
$this->assertEquals($expected, array_keys($layout_definitions));
$this->assertContainsOnlyInstancesOf(LayoutDefinition::class, $layout_definitions);
}
/**
* @covers ::getDefinition
* @covers ::processDefinition
*/
public function testGetDefinition() : void {
$layout_definition = $this->layoutPluginManager
->getDefinition('theme_a_provided_layout');
$this->assertSame('theme_a_provided_layout', $layout_definition->id());
$this->assertSame('2 column layout', (string) $layout_definition->getLabel());
$this->assertSame('Columns: 2', (string) $layout_definition->getCategory());
$this->assertSame('A theme provided layout', (string) $layout_definition->getDescription());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getLabel());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getCategory());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getDescription());
$this->assertSame('twocol', $layout_definition->getTemplate());
$this->assertSame('themes/theme_a/templates', $layout_definition->getPath());
$this->assertSame('theme_a/twocol', $layout_definition->getLibrary());
$this->assertSame('twocol', $layout_definition->getThemeHook());
$this->assertSame('themes/theme_a/templates', $layout_definition->getTemplatePath());
$this->assertSame('theme_a', $layout_definition->getProvider());
$this->assertSame('right', $layout_definition->getDefaultRegion());
$this->assertSame(LayoutDefault::class, $layout_definition->getClass());
$expected_regions = [
'left' => [
'label' => new TranslatableMarkup('Left region', [], [
'context' => 'layout_region',
]),
],
'right' => [
'label' => new TranslatableMarkup('Right region', [], [
'context' => 'layout_region',
]),
],
];
$regions = $layout_definition->getRegions();
$this->assertEquals($expected_regions, $regions);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['left']['label']);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['right']['label']);
$layout_definition = $this->layoutPluginManager
->getDefinition('module_a_provided_layout');
$this->assertSame('module_a_provided_layout', $layout_definition->id());
$this->assertSame('1 column layout', (string) $layout_definition->getLabel());
$this->assertSame('Columns: 1', (string) $layout_definition->getCategory());
$this->assertSame('A module provided layout', (string) $layout_definition->getDescription());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getLabel());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getCategory());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getDescription());
$this->assertNull($layout_definition->getTemplate());
$this->assertSame('modules/module_a/layouts', $layout_definition->getPath());
$this->assertSame('module_a/onecol', $layout_definition->getLibrary());
$this->assertSame('onecol', $layout_definition->getThemeHook());
$this->assertNull($layout_definition->getTemplatePath());
$this->assertSame('module_a', $layout_definition->getProvider());
$this->assertSame('top', $layout_definition->getDefaultRegion());
$this->assertSame(LayoutDefault::class, $layout_definition->getClass());
$expected_regions = [
'top' => [
'label' => new TranslatableMarkup('Top region', [], [
'context' => 'layout_region',
]),
],
'bottom' => [
'label' => new TranslatableMarkup('Bottom region', [], [
'context' => 'layout_region',
]),
],
];
$regions = $layout_definition->getRegions();
$this->assertEquals($expected_regions, $regions);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['top']['label']);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['bottom']['label']);
// Check that arbitrary property value gets set correctly.
$this->assertSame('ipsum', $layout_definition->get('lorem'));
$core_path = '/core/lib/Drupal/Core';
$layout_definition = $this->layoutPluginManager
->getDefinition('plugin_provided_layout');
$this->assertSame('plugin_provided_layout', $layout_definition->id());
$this->assertEquals('Layout plugin', $layout_definition->getLabel());
$this->assertEquals('Columns: 1', $layout_definition->getCategory());
$this->assertEquals('Test layout', $layout_definition->getDescription());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getLabel());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getCategory());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getDescription());
$this->assertSame('plugin-provided-layout', $layout_definition->getTemplate());
$this->assertSame($core_path, $layout_definition->getPath());
$this->assertNull($layout_definition->getLibrary());
$this->assertSame('plugin_provided_layout', $layout_definition->getThemeHook());
$this->assertSame("{$core_path}/templates", $layout_definition->getTemplatePath());
$this->assertSame('core', $layout_definition->getProvider());
$this->assertSame('main', $layout_definition->getDefaultRegion());
$this->assertSame('Drupal\\Core\\Plugin\\Layout\\TestLayout', $layout_definition->getClass());
$expected_regions = [
'main' => [
'label' => new TranslatableMarkup('Main Region', [], [
'context' => 'layout_region',
]),
],
];
$regions = $layout_definition->getRegions();
$this->assertEquals($expected_regions, $regions);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['main']['label']);
// Check that arbitrary property value gets set correctly.
$this->assertSame('adipiscing', $layout_definition->get('consectetur'));
$layout_definition = $this->layoutPluginManager
->getDefinition('plugin_provided_by_annotation_layout');
$this->assertSame('plugin_provided_by_annotation_layout', $layout_definition->id());
$this->assertEquals('Layout by annotation plugin', $layout_definition->getLabel());
$this->assertEquals('Columns: 2', $layout_definition->getCategory());
$this->assertEquals('Test layout provided by annotated plugin', $layout_definition->getDescription());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getLabel());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getCategory());
$this->assertInstanceOf(TranslatableMarkup::class, $layout_definition->getDescription());
$this->assertSame('plugin-provided-annotation-layout', $layout_definition->getTemplate());
$this->assertSame($core_path, $layout_definition->getPath());
$this->assertNull($layout_definition->getLibrary());
$this->assertSame('plugin_provided_annotation_layout', $layout_definition->getThemeHook());
$this->assertSame("{$core_path}/templates", $layout_definition->getTemplatePath());
$this->assertSame('core', $layout_definition->getProvider());
$this->assertSame('left', $layout_definition->getDefaultRegion());
$this->assertSame('Drupal\\Core\\Plugin\\Layout\\TestAnnotationLayout', $layout_definition->getClass());
$expected_regions = [
'left' => [
'label' => new TranslatableMarkup('Left Region', [], [
'context' => 'layout_region',
]),
],
'right' => [
'label' => new TranslatableMarkup('Right Region', [], [
'context' => 'layout_region',
]),
],
];
$regions = $layout_definition->getRegions();
$this->assertEquals($expected_regions, $regions);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['left']['label']);
$this->assertInstanceOf(TranslatableMarkup::class, $regions['right']['label']);
}
/**
* @covers ::processDefinition
*/
public function testProcessDefinition() : void {
$this->moduleHandler
->alter('layout', Argument::type('array'))
->shouldNotBeCalled();
$this->expectException(InvalidPluginDefinitionException::class);
$this->expectExceptionMessage('The "module_a_derived_layout:array_based" layout definition must extend ' . LayoutDefinition::class);
$module_a_provided_layout = <<<'EOS'
module_a_derived_layout:
deriver: \Drupal\Tests\Core\Layout\LayoutDeriver
array_based: true
EOS;
vfsStream::create([
'modules' => [
'module_a' => [
'module_a.layouts.yml' => $module_a_provided_layout,
],
],
]);
$this->layoutPluginManager
->getDefinitions();
}
/**
* @covers ::getThemeImplementations
*/
public function testGetThemeImplementations() : void {
$core_path = '/core/lib/Drupal/Core';
$expected = [
'layout' => [
'render element' => 'content',
],
'twocol' => [
'render element' => 'content',
'base hook' => 'layout',
'template' => 'twocol',
'path' => 'themes/theme_a/templates',
],
'plugin_provided_layout' => [
'render element' => 'content',
'base hook' => 'layout',
'template' => 'plugin-provided-layout',
'path' => "{$core_path}/templates",
],
'plugin_provided_annotation_layout' => [
'render element' => 'content',
'base hook' => 'layout',
'template' => 'plugin-provided-annotation-layout',
'path' => "{$core_path}/templates",
],
];
$theme_implementations = $this->layoutPluginManager
->getThemeImplementations();
$this->assertEquals($expected, $theme_implementations);
}
/**
* @covers ::getCategories
*/
public function testGetCategories() : void {
$expected = [
'Columns: 1',
'Columns: 2',
];
$categories = $this->layoutPluginManager
->getCategories();
$this->assertEquals($expected, $categories);
}
/**
* @covers ::getSortedDefinitions
*/
public function testGetSortedDefinitions() : void {
// Sorted by category first, then label.
$expected = [
'module_a_provided_layout',
'plugin_provided_layout',
'theme_a_provided_layout',
'plugin_provided_by_annotation_layout',
];
$layout_definitions = $this->layoutPluginManager
->getSortedDefinitions();
$this->assertEquals($expected, array_keys($layout_definitions));
$this->assertContainsOnlyInstancesOf(LayoutDefinition::class, $layout_definitions);
}
/**
* @covers ::getGroupedDefinitions
*/
public function testGetGroupedDefinitions() : void {
$category_expected = [
'Columns: 1' => [
'module_a_provided_layout',
'plugin_provided_layout',
],
'Columns: 2' => [
'theme_a_provided_layout',
'plugin_provided_by_annotation_layout',
],
];
$definitions = $this->layoutPluginManager
->getGroupedDefinitions();
$this->assertEquals(array_keys($category_expected), array_keys($definitions));
foreach ($category_expected as $category => $expected) {
$this->assertArrayHasKey($category, $definitions);
$this->assertEquals($expected, array_keys($definitions[$category]));
$this->assertContainsOnlyInstancesOf(LayoutDefinition::class, $definitions[$category]);
}
}
/**
* @covers ::getLayoutOptions
*
* Test that modules and themes can alter the list of layouts.
*/
public function testGetLayoutOptions() : void {
$this->moduleHandler
->alter([
'plugin_filter_layout',
'plugin_filter_layout__layout',
], Argument::type('array'), [], 'layout')
->shouldBeCalled();
$this->themeManager
->alter([
'plugin_filter_layout',
'plugin_filter_layout__layout',
], Argument::type('array'), [], 'layout')
->shouldBeCalled();
$this->layoutPluginManager
->getLayoutOptions();
}
/**
* Sets up the filesystem with YAML files and annotated plugins.
*/
protected function setUpFilesystem() : void {
$module_a_provided_layout = <<<'EOS'
module_a_provided_layout:
label: 1 column layout
category: 'Columns: 1'
description: 'A module provided layout'
theme_hook: onecol
path: layouts
library: module_a/onecol
regions:
top:
label: Top region
bottom:
label: Bottom region
lorem: ipsum
module_a_derived_layout:
label: 'Invalid provider derived layout'
deriver: \Drupal\Tests\Core\Layout\LayoutDeriver
invalid_provider: true
EOS;
$theme_a_provided_layout = <<<'EOS'
theme_a_provided_layout:
class: '\Drupal\Core\Layout\LayoutDefault'
label: 2 column layout
category: 'Columns: 2'
description: 'A theme provided layout'
template: twocol
path: templates
library: theme_a/twocol
default_region: right
regions:
left:
label: Left region
right:
label: Right region
EOS;
$plugin_provided_layout = <<<'EOS'
<?php
namespace Drupal\Core\Plugin\Layout;
use Drupal\Core\Layout\Attribute\Layout;
use Drupal\Core\Layout\LayoutDefault;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* The TestLayout Class.
*/
#[Layout(
id: 'plugin_provided_layout',
label: new TranslatableMarkup('Layout plugin'),
category: new TranslatableMarkup('Columns: 1'),
description: new TranslatableMarkup('Test layout'),
path: "core/lib/Drupal/Core",
template: "templates/plugin-provided-layout",
regions: [
"main" => [
"label" => new TranslatableMarkup("Main Region", [], ["context" => "layout_region"]),
],
],
consectetur: 'adipiscing',
)]
class TestLayout extends LayoutDefault {}
EOS;
$plugin_provided_by_annotation_layout = <<<'EOS'
<?php
namespace Drupal\Core\Plugin\Layout;
use Drupal\Core\Layout\LayoutDefault;
/**
* @Layout(
* id = "plugin_provided_by_annotation_layout",
* label = @Translation("Layout by annotation plugin"),
* category = @Translation("Columns: 2"),
* description = @Translation("Test layout provided by annotated plugin"),
* path = "core/lib/Drupal/Core",
* template = "templates/plugin-provided-annotation-layout",
* default_region = "left",
* regions = {
* "left" = {
* "label" = @Translation("Left Region", context = "layout_region")
* },
* "right" = {
* "label" = @Translation("Right Region", context = "layout_region")
* }
* }
* )
*/
class TestAnnotationLayout extends LayoutDefault {}
EOS;
vfsStream::setup('root');
vfsStream::create([
'modules' => [
'module_a' => [
'module_a.layouts.yml' => $module_a_provided_layout,
],
],
]);
vfsStream::create([
'themes' => [
'theme_a' => [
'theme_a.layouts.yml' => $theme_a_provided_layout,
],
],
]);
vfsStream::create([
'core' => [
'lib' => [
'Drupal' => [
'Core' => [
'Plugin' => [
'Layout' => [
'TestLayout.php' => $plugin_provided_layout,
'TestAnnotationLayout.php' => $plugin_provided_by_annotation_layout,
],
],
],
],
],
],
]);
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
ExpectDeprecationTrait::expectDeprecation | public | function | Adds an expected deprecation. | |
ExpectDeprecationTrait::getCallableName | private static | function | Returns a callable as a string suitable for inclusion in a message. | |
ExpectDeprecationTrait::setUpErrorHandler | public | function | Sets up the test error handler. | |
ExpectDeprecationTrait::tearDownErrorHandler | public | function | Tears down the test error handler. | |
LayoutPluginManagerTest::$cacheBackend | protected | property | Cache backend instance. | |
LayoutPluginManagerTest::$layoutPluginManager | protected | property | The layout plugin manager. | |
LayoutPluginManagerTest::$moduleHandler | protected | property | The module handler. | |
LayoutPluginManagerTest::$themeHandler | protected | property | The theme handler. | |
LayoutPluginManagerTest::$themeManager | protected | property | The theme manager. | |
LayoutPluginManagerTest::setUp | protected | function | Overrides UnitTestCase::setUp | |
LayoutPluginManagerTest::setUpFilesystem | protected | function | Sets up the filesystem with YAML files and annotated plugins. | |
LayoutPluginManagerTest::testGetCategories | public | function | @covers ::getCategories | |
LayoutPluginManagerTest::testGetDefinition | public | function | @covers ::getDefinition @covers ::processDefinition |
|
LayoutPluginManagerTest::testGetDefinitions | public | function | @covers ::getDefinitions @covers ::providerExists |
|
LayoutPluginManagerTest::testGetGroupedDefinitions | public | function | @covers ::getGroupedDefinitions | |
LayoutPluginManagerTest::testGetLayoutOptions | public | function | @covers ::getLayoutOptions | |
LayoutPluginManagerTest::testGetSortedDefinitions | public | function | @covers ::getSortedDefinitions | |
LayoutPluginManagerTest::testGetThemeImplementations | public | function | @covers ::getThemeImplementations | |
LayoutPluginManagerTest::testProcessDefinition | public | function | @covers ::processDefinition | |
RandomGeneratorTrait::getRandomGenerator | protected | function | Gets the random generator for the utility methods. | |
RandomGeneratorTrait::randomMachineName | protected | function | Generates a unique random string containing letters and numbers. | |
RandomGeneratorTrait::randomObject | public | function | Generates a random PHP object. | |
RandomGeneratorTrait::randomString | public | function | Generates a pseudo-random string of ASCII characters of codes 32 to 126. | |
UnitTestCase::$root | protected | property | The app root. | |
UnitTestCase::getClassResolverStub | protected | function | Returns a stub class resolver. | |
UnitTestCase::getConfigFactoryStub | public | function | Returns a stub config factory that behaves according to the passed array. | |
UnitTestCase::getConfigStorageStub | public | function | Returns a stub config storage that returns the supplied configuration. | |
UnitTestCase::getContainerWithCacheTagsInvalidator | protected | function | Sets up a container with a cache tags invalidator. | |
UnitTestCase::getStringTranslationStub | public | function | Returns a stub translation manager that just returns the passed string. | |
UnitTestCase::setUpBeforeClass | public static | function |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.