3 namespace Drupal\Tests\Core\Plugin\Discovery;
5 use Drupal\Component\Plugin\Definition\DerivablePluginDefinitionInterface;
6 use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
7 use Drupal\Component\Plugin\Exception\InvalidDeriverException;
8 use Drupal\Tests\UnitTestCase;
11 * Unit tests for the derivative discovery decorator.
13 * @coversDefaultClass \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator
17 class DerivativeDiscoveryDecoratorTest extends UnitTestCase {
20 * The mock main discovery object.
22 * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\PHPUnit_Framework_MockObject_MockObject
24 protected $discoveryMain;
29 protected function setUp() {
30 $this->discoveryMain = $discovery_main = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
34 * Tests the getDerivativeFetcher method.
36 * @see \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator::getDerivativeFetcher()
38 public function testGetDerivativeFetcher() {
40 $definitions['non_container_aware_discovery'] = [
41 'id' => 'non_container_aware_discovery',
42 'deriver' => '\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery',
45 $this->discoveryMain->expects($this->any())
46 ->method('getDefinitions')
47 ->will($this->returnValue($definitions));
49 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
50 $definitions = $discovery->getDefinitions();
52 // Ensure that both test derivatives got added.
53 $this->assertEquals(2, count($definitions));
54 $this->assertEquals('non_container_aware_discovery', $definitions['non_container_aware_discovery:test_discovery_0']['id']);
55 $this->assertEquals('\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery', $definitions['non_container_aware_discovery:test_discovery_0']['deriver']);
57 $this->assertEquals('non_container_aware_discovery', $definitions['non_container_aware_discovery:test_discovery_1']['id']);
58 $this->assertEquals('\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery', $definitions['non_container_aware_discovery:test_discovery_1']['deriver']);
62 * Tests the getDerivativeFetcher method with objects instead of arrays.
64 public function testGetDerivativeFetcherWithAnnotationObjects() {
66 $definitions['non_container_aware_discovery'] = (object) [
67 'id' => 'non_container_aware_discovery',
68 'deriver' => '\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscoveryWithObject',
71 $this->discoveryMain->expects($this->any())
72 ->method('getDefinitions')
73 ->will($this->returnValue($definitions));
75 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
76 $definitions = $discovery->getDefinitions();
78 // Ensure that both test derivatives got added.
79 $this->assertEquals(2, count($definitions));
80 $this->assertInstanceOf('\stdClass', $definitions['non_container_aware_discovery:test_discovery_0']);
81 $this->assertEquals('non_container_aware_discovery', $definitions['non_container_aware_discovery:test_discovery_0']->id);
82 $this->assertEquals('\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscoveryWithObject', $definitions['non_container_aware_discovery:test_discovery_0']->deriver);
84 $this->assertInstanceOf('\stdClass', $definitions['non_container_aware_discovery:test_discovery_1']);
85 $this->assertEquals('non_container_aware_discovery', $definitions['non_container_aware_discovery:test_discovery_1']->id);
86 $this->assertEquals('\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscoveryWithObject', $definitions['non_container_aware_discovery:test_discovery_1']->deriver);
90 * Tests getDeriverClass with classed objects instead of arrays.
92 * @covers ::getDeriverClass
94 public function testGetDeriverClassWithClassedDefinitions() {
96 $definition = $this->prophesize(DerivablePluginDefinitionInterface::class);
97 $definition->id()->willReturn('non_container_aware_discovery');
98 $definition->getDeriver()->willReturn(TestDerivativeDiscoveryWithObject::class);
99 $definitions['non_container_aware_discovery'] = $definition->reveal();
101 $this->discoveryMain->expects($this->any())
102 ->method('getDefinitions')
103 ->will($this->returnValue($definitions));
105 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
106 $definitions = $discovery->getDefinitions();
108 // Ensure that both test derivatives got added.
109 $this->assertContainsOnlyInstancesOf(DerivablePluginDefinitionInterface::class, $definitions);
110 $this->assertEquals(['non_container_aware_discovery:test_discovery_0', 'non_container_aware_discovery:test_discovery_1'], array_keys($definitions));
114 * @covers ::getDeriverClass
116 public function testGetDeriverClassWithInvalidClassedDefinitions() {
117 $definition = $this->prophesize(DerivablePluginDefinitionInterface::class);
118 $definition->id()->willReturn('non_existent_discovery');
119 $definition->getDeriver()->willReturn('\Drupal\system\Tests\Plugin\NonExistentDeriver');
121 $definitions['non_existent_discovery'] = $definition->reveal();
123 $this->discoveryMain->expects($this->any())
124 ->method('getDefinitions')
125 ->willReturn($definitions);
127 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
129 $this->setExpectedException(InvalidDeriverException::class, 'Plugin (non_existent_discovery) deriver "\Drupal\system\Tests\Plugin\NonExistentDeriver" does not exist.');
130 $discovery->getDefinitions();
134 * Tests the getDerivativeFetcher method with a non-existent class.
136 * @see \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator::getDeriver().\
138 public function testNonExistentDerivativeFetcher() {
140 // Do this with a class that doesn't exist.
141 $definitions['non_existent_discovery'] = [
142 'id' => 'non_existent_discovery',
143 'deriver' => '\Drupal\system\Tests\Plugin\NonExistentDeriver',
145 $this->discoveryMain->expects($this->any())
146 ->method('getDefinitions')
147 ->will($this->returnValue($definitions));
149 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
150 $this->setExpectedException(InvalidDeriverException::class, 'Plugin (non_existent_discovery) deriver "\Drupal\system\Tests\Plugin\NonExistentDeriver" does not exist.');
151 $discovery->getDefinitions();
155 * Tests the getDerivativeFetcher method with an invalid class.
157 * @see \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator::getDeriver().\
159 public function testInvalidDerivativeFetcher() {
161 // Do this with a class that doesn't implement the interface.
162 $definitions['invalid_discovery'] = [
163 'id' => 'invalid_discovery',
164 'deriver' => '\Drupal\KernelTests\Core\Plugin\DerivativeTest',
166 $this->discoveryMain->expects($this->any())
167 ->method('getDefinitions')
168 ->will($this->returnValue($definitions));
170 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
171 $this->setExpectedException(InvalidDeriverException::class, 'Plugin (invalid_discovery) deriver "\Drupal\KernelTests\Core\Plugin\DerivativeTest" must implement \Drupal\Component\Plugin\Derivative\DeriverInterface.');
172 $discovery->getDefinitions();
176 * Tests derivative definitions when a definition already exists.
178 public function testExistingDerivative() {
180 $definitions['non_container_aware_discovery'] = [
181 'id' => 'non_container_aware_discovery',
182 'deriver' => '\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery',
183 'string' => 'string',
184 'empty_string' => 'not_empty',
185 'array' => ['one', 'two'],
186 'empty_array' => ['three'],
187 'null_value' => TRUE,
189 // This will clash with a derivative id.
190 // @see \Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery
191 $definitions['non_container_aware_discovery:test_discovery_1'] = [
192 'id' => 'non_container_aware_discovery:test_discovery_1',
193 'string' => 'string',
194 'empty_string' => '',
195 'array' => ['one', 'two'],
197 'null_value' => NULL,
200 $this->discoveryMain->expects($this->any())
201 ->method('getDefinitions')
202 ->will($this->returnValue($definitions));
204 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
205 $returned_definitions = $discovery->getDefinitions();
207 // If the definition was merged, there should only be two.
208 $this->assertCount(2, $returned_definitions);
210 $expected = $definitions['non_container_aware_discovery'];
211 $expected['id'] = 'non_container_aware_discovery:test_discovery_1';
212 $this->assertArrayEquals($expected, $returned_definitions['non_container_aware_discovery:test_discovery_1']);
216 * Tests a single definition when a derivative already exists.
218 public function testSingleExistingDerivative() {
220 'id' => 'non_container_aware_discovery',
221 'deriver' => '\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery',
222 'string' => 'string',
223 'empty_string' => 'not_empty',
224 'array' => ['one', 'two'],
225 'empty_array' => ['three'],
226 'null_value' => TRUE,
228 // This will clash with a derivative id.
229 // @see \Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery
230 $derivative_definition = [
231 'id' => 'non_container_aware_discovery:test_discovery_1',
232 'string' => 'string',
233 'empty_string' => '',
234 'array' => ['one', 'two'],
236 'null_value' => NULL,
239 $this->discoveryMain->expects($this->at(0))
240 ->method('getDefinition')
241 ->with('non_container_aware_discovery:test_discovery_1')
242 ->will($this->returnValue($derivative_definition));
243 $this->discoveryMain->expects($this->at(1))
244 ->method('getDefinition')
245 ->with('non_container_aware_discovery')
246 ->will($this->returnValue($base_definition));
248 $discovery = new DerivativeDiscoveryDecorator($this->discoveryMain);
250 $expected = $base_definition;
251 $expected['id'] = 'non_container_aware_discovery:test_discovery_1';
252 $this->assertArrayEquals($expected, $discovery->getDefinition('non_container_aware_discovery:test_discovery_1'));