class DefaultPluginManagerTest

Same name in this branch
  1. 11.x core/tests/Drupal/KernelTests/Core/Plugin/DefaultPluginManagerTest.php \Drupal\KernelTests\Core\Plugin\DefaultPluginManagerTest
Same name in other branches
  1. 9 core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php \Drupal\Tests\Core\Plugin\DefaultPluginManagerTest
  2. 8.9.x core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php \Drupal\Tests\Core\Plugin\DefaultPluginManagerTest
  3. 10 core/tests/Drupal/KernelTests/Core/Plugin/DefaultPluginManagerTest.php \Drupal\KernelTests\Core\Plugin\DefaultPluginManagerTest
  4. 10 core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php \Drupal\Tests\Core\Plugin\DefaultPluginManagerTest

Tests the DefaultPluginManager.

@group Plugin

@coversDefaultClass \Drupal\Core\Plugin\DefaultPluginManager

Hierarchy

Expanded class hierarchy of DefaultPluginManagerTest

File

core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php, line 23

Namespace

Drupal\Tests\Core\Plugin
View source
class DefaultPluginManagerTest extends UnitTestCase {
    
    /**
     * The expected plugin definitions.
     *
     * @var array
     */
    protected $expectedDefinitions;
    
    /**
     * The namespaces to look for plugin definitions.
     *
     * @var \Traversable
     */
    protected $namespaces;
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $this->expectedDefinitions = [
            'apple' => [
                'id' => 'apple',
                'label' => 'Apple',
                'color' => 'green',
                'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Apple',
            ],
            'banana' => [
                'id' => 'banana',
                'label' => 'Banana',
                'color' => 'yellow',
                'uses' => [
                    'bread' => 'Banana bread',
                    'loaf' => [
                        'singular' => '@count loaf',
                        'plural' => '@count loaves',
                    ],
                ],
                'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Banana',
            ],
        ];
        $this->namespaces = new \ArrayObject();
        $this->namespaces['Drupal\\plugin_test'] = $this->root . '/core/modules/system/tests/modules/plugin_test/src';
    }
    
    /**
     * Tests the plugin manager with a plugin that extends a non-installed class.
     */
    public function testDefaultPluginManagerWithPluginExtendingNonInstalledClass() : void {
        $definitions = [];
        $definitions['extending_non_installed_class'] = [
            'id' => 'extending_non_installed_class',
            'label' => 'A plugin whose class is extending from a non-installed module class',
            'color' => 'pink',
            'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\ExtendingNonInstalledClass',
            'provider' => 'plugin_test',
        ];
        $module_handler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', FruitInterface::class);
        $plugin_manager->getDefinition('plugin_test', FALSE);
        $this->assertTrue(TRUE, 'No PHP fatal error occurred when retrieving the definitions of a module with plugins that depend on a non-installed module class should not cause a PHP fatal.');
    }
    
    /**
     * Tests the plugin manager with a disabled module.
     */
    public function testDefaultPluginManagerWithDisabledModule() : void {
        $definitions = $this->expectedDefinitions;
        $definitions['cherry'] = [
            'id' => 'cherry',
            'label' => 'Cherry',
            'color' => 'red',
            'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Cherry',
            'provider' => 'disabled_module',
        ];
        $module_handler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $module_handler->expects($this->once())
            ->method('moduleExists')
            ->with('disabled_module')
            ->willReturn(FALSE);
        $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', FruitInterface::class);
        $this->assertEmpty($plugin_manager->getDefinition('cherry', FALSE), 'Plugin information of a disabled module is not available');
    }
    
    /**
     * Tests the plugin manager and object plugin definitions.
     */
    public function testDefaultPluginManagerWithObjects() : void {
        $definitions = $this->expectedDefinitions;
        $definitions['cherry'] = (object) [
            'id' => 'cherry',
            'label' => 'Cherry',
            'color' => 'red',
            'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Cherry',
            'provider' => 'disabled_module',
        ];
        $module_handler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $module_handler->expects($this->once())
            ->method('moduleExists')
            ->with('disabled_module')
            ->willReturn(FALSE);
        $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', FruitInterface::class);
        $this->assertEmpty($plugin_manager->getDefinition('cherry', FALSE), 'Plugin information is available');
    }
    
    /**
     * Tests the plugin manager behavior for a missing plugin ID.
     */
    public function testGetDefinitionPluginNotFoundException() : void {
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions);
        $this->expectException(PluginNotFoundException::class);
        $this->expectExceptionMessage('The "missing" plugin does not exist. Valid plugin IDs for Drupal\\Tests\\Core\\Plugin\\TestPluginManager are: apple, banana');
        $plugin_manager->getDefinition('missing');
    }
    
    /**
     * Tests the plugin manager with no cache and altering.
     */
    public function testDefaultPluginManager() : void {
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions());
        $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana'));
    }
    
    /**
     * Tests the plugin manager with no cache and altering.
     */
    public function testDefaultPluginManagerWithAlter() : void {
        $module_handler = $this->getMockBuilder('Drupal\\Core\\Extension\\ModuleHandler')
            ->disableOriginalConstructor()
            ->getMock();
        // Configure the stub.
        $alter_hook_name = $this->randomMachineName();
        $module_handler->expects($this->once())
            ->method('alter')
            ->with($this->equalTo($alter_hook_name), $this->equalTo($this->expectedDefinitions));
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, $alter_hook_name, FruitInterface::class);
        $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions());
        $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana'));
    }
    
    /**
     * Tests the plugin manager with caching and altering.
     */
    public function testDefaultPluginManagerWithEmptyCache() : void {
        $cid = $this->randomMachineName();
        $cache_backend = $this->getMockBuilder('Drupal\\Core\\Cache\\MemoryBackend')
            ->disableOriginalConstructor()
            ->getMock();
        $cache_backend->expects($this->once())
            ->method('get')
            ->with($cid)
            ->willReturn(FALSE);
        $cache_backend->expects($this->once())
            ->method('set')
            ->with($cid, $this->expectedDefinitions);
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        $plugin_manager->setCacheBackend($cache_backend, $cid);
        $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions());
        $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana'));
    }
    
    /**
     * Tests the plugin manager with caching and altering.
     */
    public function testDefaultPluginManagerWithFilledCache() : void {
        $cid = $this->randomMachineName();
        $cache_backend = $this->getMockBuilder('Drupal\\Core\\Cache\\MemoryBackend')
            ->disableOriginalConstructor()
            ->getMock();
        $cache_backend->expects($this->once())
            ->method('get')
            ->with($cid)
            ->willReturn((object) [
            'data' => $this->expectedDefinitions,
        ]);
        $cache_backend->expects($this->never())
            ->method('set');
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        $plugin_manager->setCacheBackend($cache_backend, $cid);
        $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions());
    }
    
    /**
     * Tests the plugin manager with caching disabled.
     */
    public function testDefaultPluginManagerNoCache() : void {
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        $cid = $this->randomMachineName();
        $cache_backend = $this->getMockBuilder('Drupal\\Core\\Cache\\MemoryBackend')
            ->disableOriginalConstructor()
            ->getMock();
        $cache_backend->expects($this->never())
            ->method('get');
        $cache_backend->expects($this->never())
            ->method('set');
        $plugin_manager->setCacheBackend($cache_backend, $cid);
        $plugin_manager->useCaches(FALSE);
        $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions());
        $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana'));
    }
    
    /**
     * Tests the plugin manager cache clear with tags.
     */
    public function testCacheClearWithTags() : void {
        $cid = $this->randomMachineName();
        $cache_backend = $this->createMock('Drupal\\Core\\Cache\\CacheBackendInterface');
        $cache_tags_invalidator = $this->createMock('Drupal\\Core\\Cache\\CacheTagsInvalidatorInterface');
        $cache_tags_invalidator->expects($this->once())
            ->method('invalidateTags')
            ->with([
            'tag',
        ]);
        $cache_backend->expects($this->never())
            ->method('deleteMultiple');
        $this->getContainerWithCacheTagsInvalidator($cache_tags_invalidator);
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        $plugin_manager->setCacheBackend($cache_backend, $cid, [
            'tag',
        ]);
        $plugin_manager->clearCachedDefinitions();
    }
    
    /**
     * Tests plugins with the proper interface.
     *
     * @covers ::createInstance
     */
    public function testCreateInstanceWithJustValidInterfaces() : void {
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, FruitInterface::class);
        foreach ($this->expectedDefinitions as $plugin_id => $definition) {
            $this->assertNotNull($plugin_manager->createInstance($plugin_id));
        }
    }
    
    /**
     * Tests plugins without the proper interface.
     *
     * @covers ::createInstance
     */
    public function testCreateInstanceWithInvalidInterfaces() : void {
        $module_handler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $module_handler->expects($this->any())
            ->method('moduleExists')
            ->with('plugin_test')
            ->willReturn(TRUE);
        $this->expectedDefinitions['kale'] = [
            'id' => 'kale',
            'label' => 'Kale',
            'color' => 'green',
            'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Kale',
            'provider' => 'plugin_test',
        ];
        $this->expectedDefinitions['apple']['provider'] = 'plugin_test';
        $this->expectedDefinitions['banana']['provider'] = 'plugin_test';
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, NULL, FruitInterface::class);
        $this->expectException(PluginException::class);
        $this->expectExceptionMessage('Plugin "kale" (Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Kale) must implement interface Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\FruitInterface');
        $plugin_manager->createInstance('kale');
    }
    
    /**
     * Tests plugins without a required interface.
     *
     * @covers ::getDefinitions
     */
    public function testGetDefinitionsWithoutRequiredInterface() : void {
        $module_handler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $module_handler->expects($this->any())
            ->method('moduleExists')
            ->with('plugin_test')
            ->willReturn(FALSE);
        $this->expectedDefinitions['kale'] = [
            'id' => 'kale',
            'label' => 'Kale',
            'color' => 'green',
            'class' => 'Drupal\\plugin_test\\Plugin\\plugin_test\\fruit\\Kale',
            'provider' => 'plugin_test',
        ];
        $this->expectedDefinitions['apple']['provider'] = 'plugin_test';
        $this->expectedDefinitions['banana']['provider'] = 'plugin_test';
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, NULL);
        $this->assertIsArray($plugin_manager->getDefinitions());
    }
    
    /**
     * @covers ::getCacheContexts
     */
    public function testGetCacheContexts() : void {
        $module_handler = $this->prophesize(ModuleHandlerInterface::class);
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler->reveal(), NULL);
        $cache_contexts = $plugin_manager->getCacheContexts();
        $this->assertIsArray($cache_contexts);
        array_map(function ($cache_context) {
            $this->assertIsString($cache_context);
        }, $cache_contexts);
    }
    
    /**
     * @covers ::getCacheTags
     */
    public function testGetCacheTags() : void {
        $module_handler = $this->prophesize(ModuleHandlerInterface::class);
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler->reveal(), NULL);
        $cache_tags = $plugin_manager->getCacheTags();
        $this->assertIsArray($cache_tags);
        array_map(function ($cache_tag) {
            $this->assertIsString($cache_tag);
        }, $cache_tags);
    }
    
    /**
     * @covers ::getCacheMaxAge
     */
    public function testGetCacheMaxAge() : void {
        $module_handler = $this->prophesize(ModuleHandlerInterface::class);
        $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler->reveal(), NULL);
        $cache_max_age = $plugin_manager->getCacheMaxAge();
        $this->assertIsInt($cache_max_age);
    }
    
    /**
     * @covers ::findDefinitions
     * @covers ::extractProviderFromDefinition
     */
    public function testProviderExists() : void {
        $definitions = [];
        $definitions['array_based_found'] = [
            'provider' => 'module_found',
        ];
        $definitions['array_based_missing'] = [
            'provider' => 'module_missing',
        ];
        $definitions['stdClass_based_found'] = (object) [
            'provider' => 'module_found',
        ];
        $definitions['stdClass_based_missing'] = (object) [
            'provider' => 'module_missing',
        ];
        $definitions['classed_object_found'] = new ObjectDefinition([
            'provider' => 'module_found',
        ]);
        $definitions['classed_object_missing'] = new ObjectDefinition([
            'provider' => 'module_missing',
        ]);
        $expected = [];
        $expected['array_based_found'] = $definitions['array_based_found'];
        $expected['stdClass_based_found'] = $definitions['stdClass_based_found'];
        $expected['classed_object_found'] = $definitions['classed_object_found'];
        $module_handler = $this->prophesize(ModuleHandlerInterface::class);
        $module_handler->moduleExists('module_found')
            ->willReturn(TRUE)
            ->shouldBeCalled();
        $module_handler->moduleExists('module_missing')
            ->willReturn(FALSE)
            ->shouldBeCalled();
        $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler->reveal());
        $result = $plugin_manager->getDefinitions();
        $this->assertEquals($expected, $result);
    }
    
    /**
     * @covers ::processDefinition
     * @dataProvider providerTestProcessDefinition
     */
    public function testProcessDefinition($definition, $expected) : void {
        $module_handler = $this->prophesize(ModuleHandlerInterface::class);
        $plugin_manager = new TestPluginManagerWithDefaults($this->namespaces, $this->expectedDefinitions, $module_handler->reveal(), NULL);
        $plugin_manager->processDefinition($definition, 'the_plugin_id');
        $this->assertEquals($expected, $definition);
    }
    public static function providerTestProcessDefinition() {
        $data = [];
        $data['merge'][] = [
            'foo' => [
                'bar' => [
                    'asdf',
                ],
            ],
        ];
        $data['merge'][] = [
            'foo' => [
                'bar' => [
                    'baz',
                    'asdf',
                ],
            ],
        ];
        $object_definition = (object) [
            'foo' => [
                'bar' => [
                    'asdf',
                ],
            ],
        ];
        $data['object_definition'] = [
            $object_definition,
            clone $object_definition,
        ];
        $data['no_form'][] = [
            'class' => TestPluginForm::class,
        ];
        $data['no_form'][] = [
            'class' => TestPluginForm::class,
            'foo' => [
                'bar' => [
                    'baz',
                ],
            ],
        ];
        $data['default_form'][] = [
            'class' => TestPluginForm::class,
            'forms' => [
                'configure' => 'stdClass',
            ],
        ];
        $data['default_form'][] = [
            'class' => TestPluginForm::class,
            'forms' => [
                'configure' => 'stdClass',
            ],
            'foo' => [
                'bar' => [
                    'baz',
                ],
            ],
        ];
        $data['class_with_slashes'][] = [
            'class' => '\\Drupal\\Tests\\Core\\Plugin\\TestPluginForm',
        ];
        $data['class_with_slashes'][] = [
            'class' => 'Drupal\\Tests\\Core\\Plugin\\TestPluginForm',
            'foo' => [
                'bar' => [
                    'baz',
                ],
            ],
        ];
        $data['object_with_class_with_slashes'][] = (new PluginDefinition())->setClass('\\Drupal\\Tests\\Core\\Plugin\\TestPluginForm');
        $data['object_with_class_with_slashes'][] = (new PluginDefinition())->setClass('Drupal\\Tests\\Core\\Plugin\\TestPluginForm');
        return $data;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
DefaultPluginManagerTest::$expectedDefinitions protected property The expected plugin definitions.
DefaultPluginManagerTest::$namespaces protected property The namespaces to look for plugin definitions.
DefaultPluginManagerTest::providerTestProcessDefinition public static function
DefaultPluginManagerTest::setUp protected function Overrides UnitTestCase::setUp
DefaultPluginManagerTest::testCacheClearWithTags public function Tests the plugin manager cache clear with tags.
DefaultPluginManagerTest::testCreateInstanceWithInvalidInterfaces public function Tests plugins without the proper interface.
DefaultPluginManagerTest::testCreateInstanceWithJustValidInterfaces public function Tests plugins with the proper interface.
DefaultPluginManagerTest::testDefaultPluginManager public function Tests the plugin manager with no cache and altering.
DefaultPluginManagerTest::testDefaultPluginManagerNoCache public function Tests the plugin manager with caching disabled.
DefaultPluginManagerTest::testDefaultPluginManagerWithAlter public function Tests the plugin manager with no cache and altering.
DefaultPluginManagerTest::testDefaultPluginManagerWithDisabledModule public function Tests the plugin manager with a disabled module.
DefaultPluginManagerTest::testDefaultPluginManagerWithEmptyCache public function Tests the plugin manager with caching and altering.
DefaultPluginManagerTest::testDefaultPluginManagerWithFilledCache public function Tests the plugin manager with caching and altering.
DefaultPluginManagerTest::testDefaultPluginManagerWithObjects public function Tests the plugin manager and object plugin definitions.
DefaultPluginManagerTest::testDefaultPluginManagerWithPluginExtendingNonInstalledClass public function Tests the plugin manager with a plugin that extends a non-installed class.
DefaultPluginManagerTest::testGetCacheContexts public function @covers ::getCacheContexts
DefaultPluginManagerTest::testGetCacheMaxAge public function @covers ::getCacheMaxAge
DefaultPluginManagerTest::testGetCacheTags public function @covers ::getCacheTags
DefaultPluginManagerTest::testGetDefinitionPluginNotFoundException public function Tests the plugin manager behavior for a missing plugin ID.
DefaultPluginManagerTest::testGetDefinitionsWithoutRequiredInterface public function Tests plugins without a required interface.
DefaultPluginManagerTest::testProcessDefinition public function @covers ::processDefinition
@dataProvider providerTestProcessDefinition
DefaultPluginManagerTest::testProviderExists public function @covers ::findDefinitions
@covers ::extractProviderFromDefinition
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.
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::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::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.