Version 1
[yaffs-website] / web / core / modules / views / tests / src / Unit / Plugin / Derivative / ViewsLocalTaskTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\views\Unit\Plugin\Derivative\ViewsLocalTaskTest.
6  */
7
8 namespace Drupal\Tests\views\Unit\Plugin\Derivative;
9
10 use Drupal\Tests\UnitTestCase;
11 use Drupal\views\Plugin\Derivative\ViewsLocalTask;
12 use Symfony\Component\Routing\Route;
13 use Symfony\Component\Routing\RouteCollection;
14
15 /**
16  * @coversDefaultClass \Drupal\views\Plugin\Derivative\ViewsLocalTask
17  * @group views
18  */
19 class ViewsLocalTaskTest extends UnitTestCase {
20
21   /**
22    * The mocked route provider.
23    *
24    * @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
25    */
26   protected $routeProvider;
27
28   /**
29    * The mocked key value storage.
30    *
31    * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface|\PHPUnit_Framework_MockObject_MockObject
32    */
33   protected $state;
34
35   /**
36    * @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
37    */
38   protected $viewStorage;
39
40   protected $baseDefinition = [
41     'class' => '\Drupal\views\Plugin\Menu\LocalTask\ViewsLocalTask',
42     'deriver' => '\Drupal\views\Plugin\Derivative\ViewsLocalTask'
43   ];
44
45   /**
46    * The tested local task derivative class.
47    *
48    * @var \Drupal\views\Plugin\Derivative\ViewsLocalTask
49    */
50   protected $localTaskDerivative;
51
52   protected function setUp() {
53     $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
54     $this->state = $this->getMock('Drupal\Core\State\StateInterface');
55     $this->viewStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
56
57     $this->localTaskDerivative = new TestViewsLocalTask($this->routeProvider, $this->state, $this->viewStorage);
58   }
59
60   /**
61    * Tests fetching the derivatives on no view with hook menu.
62    *
63    * @see \Drupal\views\Plugin\Derivative\ViewsLocalTask::getDerivativeDefinitions()
64    */
65   public function testGetDerivativeDefinitionsWithoutHookMenuViews() {
66     $result = [];
67     $this->localTaskDerivative->setApplicableMenuViews($result);
68
69     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
70     $this->assertEquals([], $definitions);
71   }
72
73   /**
74    * Tests fetching the derivatives on a view with without a local task.
75    */
76   public function testGetDerivativeDefinitionsWithoutLocalTask() {
77     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
78       ->disableOriginalConstructor()
79       ->getMock();
80     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
81       ->setMethods(['getOption'])
82       ->disableOriginalConstructor()
83       ->getMockForAbstractClass();
84     $display_plugin->expects($this->once())
85       ->method('getOption')
86       ->with('menu')
87       ->will($this->returnValue(['type' => 'normal']));
88     $executable->display_handler = $display_plugin;
89
90     $storage = $this->getMockBuilder('Drupal\views\Entity\View')
91       ->disableOriginalConstructor()
92       ->getMock();
93     $storage->expects($this->any())
94       ->method('id')
95       ->will($this->returnValue('example_view'));
96     $storage->expects($this->any())
97       ->method('getExecutable')
98       ->willReturn($executable);
99
100     $this->viewStorage->expects($this->any())
101       ->method('load')
102       ->with('example_view')
103       ->willReturn($storage);
104
105     $result = [['example_view', 'page_1']];
106     $this->localTaskDerivative->setApplicableMenuViews($result);
107
108     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
109     $this->assertEquals([], $definitions);
110   }
111
112   /**
113    * Tests fetching the derivatives on a view with a default local task.
114    */
115   public function testGetDerivativeDefinitionsWithLocalTask() {
116     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
117       ->disableOriginalConstructor()
118       ->getMock();
119     $storage = $this->getMockBuilder('Drupal\views\Entity\View')
120       ->disableOriginalConstructor()
121       ->getMock();
122     $storage->expects($this->any())
123       ->method('id')
124       ->will($this->returnValue('example_view'));
125     $storage->expects($this->any())
126       ->method('getExecutable')
127       ->willReturn($executable);
128     $executable->storage = $storage;
129
130     $this->viewStorage->expects($this->any())
131       ->method('load')
132       ->with('example_view')
133       ->willReturn($storage);
134
135     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
136       ->setMethods(['getOption'])
137       ->disableOriginalConstructor()
138       ->getMockForAbstractClass();
139     $display_plugin->expects($this->once())
140       ->method('getOption')
141       ->with('menu')
142       ->will($this->returnValue(['type' => 'tab', 'weight' => 12, 'title' => 'Example title']));
143     $executable->display_handler = $display_plugin;
144
145     $result = [['example_view', 'page_1']];
146     $this->localTaskDerivative->setApplicableMenuViews($result);
147
148     // Mock the view route names state.
149     $view_route_names = [];
150     $view_route_names['example_view.page_1'] = 'view.example_view.page_1';
151     $this->state->expects($this->once())
152       ->method('get')
153       ->with('views.view_route_names')
154       ->will($this->returnValue($view_route_names));
155
156     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
157     $this->assertCount(1, $definitions);
158     $this->assertEquals('view.example_view.page_1', $definitions['view.example_view.page_1']['route_name']);
159     $this->assertEquals(12, $definitions['view.example_view.page_1']['weight']);
160     $this->assertEquals('Example title', $definitions['view.example_view.page_1']['title']);
161     $this->assertEquals($this->baseDefinition['class'], $definitions['view.example_view.page_1']['class']);
162     $this->assertTrue(empty($definitions['view.example_view.page_1']['base_route']));
163   }
164
165   /**
166    * Tests fetching the derivatives on a view which overrides an existing route.
167    */
168   public function testGetDerivativeDefinitionsWithOverrideRoute() {
169     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
170       ->disableOriginalConstructor()
171       ->getMock();
172     $storage = $this->getMockBuilder('Drupal\views\Entity\View')
173       ->disableOriginalConstructor()
174       ->getMock();
175     $storage->expects($this->any())
176       ->method('id')
177       ->will($this->returnValue('example_view'));
178     $storage->expects($this->any())
179       ->method('getExecutable')
180       ->willReturn($executable);
181     $executable->storage = $storage;
182
183     $this->viewStorage->expects($this->any())
184       ->method('load')
185       ->with('example_view')
186       ->willReturn($storage);
187
188     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
189       ->setMethods(['getOption'])
190       ->disableOriginalConstructor()
191       ->getMockForAbstractClass();
192     $display_plugin->expects($this->once())
193       ->method('getOption')
194       ->with('menu')
195       ->will($this->returnValue(['type' => 'tab', 'weight' => 12]));
196     $executable->display_handler = $display_plugin;
197
198     $result = [['example_view', 'page_1']];
199     $this->localTaskDerivative->setApplicableMenuViews($result);
200
201     // Mock the view route names state.
202     $view_route_names = [];
203     // Setup a view which overrides an existing route.
204     $view_route_names['example_view.page_1'] = 'example_overridden_route';
205     $this->state->expects($this->once())
206       ->method('get')
207       ->with('views.view_route_names')
208       ->will($this->returnValue($view_route_names));
209
210     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
211     $this->assertCount(0, $definitions);
212   }
213
214   /**
215    * Tests fetching the derivatives on a view with a default local task.
216    */
217   public function testGetDerivativeDefinitionsWithDefaultLocalTask() {
218     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
219       ->disableOriginalConstructor()
220       ->getMock();
221     $storage = $this->getMockBuilder('Drupal\views\Entity\View')
222       ->disableOriginalConstructor()
223       ->getMock();
224     $storage->expects($this->any())
225       ->method('id')
226       ->will($this->returnValue('example_view'));
227     $storage->expects($this->any())
228       ->method('getExecutable')
229       ->willReturn($executable);
230     $executable->storage = $storage;
231
232     $this->viewStorage->expects($this->any())
233       ->method('load')
234       ->with('example_view')
235       ->willReturn($storage);
236
237     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
238       ->setMethods(['getOption'])
239       ->disableOriginalConstructor()
240       ->getMockForAbstractClass();
241     $display_plugin->expects($this->exactly(2))
242       ->method('getOption')
243       ->with('menu')
244       ->will($this->returnValue(['type' => 'default tab', 'weight' => 12, 'title' => 'Example title']));
245     $executable->display_handler = $display_plugin;
246
247     $result = [['example_view', 'page_1']];
248     $this->localTaskDerivative->setApplicableMenuViews($result);
249
250     // Mock the view route names state.
251     $view_route_names = [];
252     $view_route_names['example_view.page_1'] = 'view.example_view.page_1';
253     $this->state->expects($this->exactly(2))
254       ->method('get')
255       ->with('views.view_route_names')
256       ->will($this->returnValue($view_route_names));
257
258     $definitions = $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
259     $this->assertCount(1, $definitions);
260     $plugin = $definitions['view.example_view.page_1'];
261     $this->assertEquals('view.example_view.page_1', $plugin['route_name']);
262     $this->assertEquals(12, $plugin['weight']);
263     $this->assertEquals('Example title', $plugin['title']);
264     $this->assertEquals($this->baseDefinition['class'], $plugin['class']);
265     $this->assertEquals('view.example_view.page_1', $plugin['base_route']);
266
267     // Setup the prefix of the derivative.
268     $definitions['views_view:view.example_view.page_1'] = $definitions['view.example_view.page_1'];
269     unset($definitions['view.example_view.page_1']);
270     $this->localTaskDerivative->alterLocalTasks($definitions);
271
272     $plugin = $definitions['views_view:view.example_view.page_1'];
273     $this->assertCount(1, $definitions);
274     $this->assertEquals('view.example_view.page_1', $plugin['route_name']);
275     $this->assertEquals(12, $plugin['weight']);
276     $this->assertEquals('Example title', $plugin['title']);
277     $this->assertEquals($this->baseDefinition['class'], $plugin['class']);
278     $this->assertEquals('view.example_view.page_1', $plugin['base_route']);
279   }
280
281   /**
282    * Tests fetching the derivatives on a view with a local task and a parent.
283    *
284    * The parent is defined by another module, not views.
285    */
286   public function testGetDerivativeDefinitionsWithExistingLocalTask() {
287     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
288       ->disableOriginalConstructor()
289       ->getMock();
290     $storage = $this->getMockBuilder('Drupal\views\Entity\View')
291       ->disableOriginalConstructor()
292       ->getMock();
293     $storage->expects($this->any())
294       ->method('id')
295       ->will($this->returnValue('example_view'));
296     $storage->expects($this->any())
297       ->method('getExecutable')
298       ->willReturn($executable);
299     $executable->storage = $storage;
300
301     $this->viewStorage->expects($this->any())
302       ->method('load')
303       ->with('example_view')
304       ->willReturn($storage);
305
306     $display_plugin = $this->getMockBuilder('Drupal\views\Plugin\views\display\PathPluginBase')
307       ->setMethods(['getOption', 'getPath'])
308       ->disableOriginalConstructor()
309       ->getMockForAbstractClass();
310     $display_plugin->expects($this->exactly(2))
311       ->method('getOption')
312       ->with('menu')
313       ->will($this->returnValue(['type' => 'tab', 'weight' => 12, 'title' => 'Example title']));
314     $display_plugin->expects($this->once())
315       ->method('getPath')
316       ->will($this->returnValue('path/example'));
317     $executable->display_handler = $display_plugin;
318
319     $result = [['example_view', 'page_1']];
320     $this->localTaskDerivative->setApplicableMenuViews($result);
321
322     // Mock the view route names state.
323     $view_route_names = [];
324     $view_route_names['example_view.page_1'] = 'view.example_view.page_1';
325     $this->state->expects($this->exactly(2))
326       ->method('get')
327       ->with('views.view_route_names')
328       ->will($this->returnValue($view_route_names));
329
330     // Mock the route provider.
331     $route_collection = new RouteCollection();
332     $route_collection->add('test_route', new Route('/path'));
333     $this->routeProvider->expects($this->any())
334       ->method('getRoutesByPattern')
335       ->with('/path')
336       ->will($this->returnValue($route_collection));
337
338     // Setup the existing local task of the test_route.
339     $definitions['test_route_tab'] = $other_tab = [
340       'route_name' => 'test_route',
341       'title' => 'Test route',
342       'base_route' => 'test_route',
343     ];
344
345     $definitions += $this->localTaskDerivative->getDerivativeDefinitions($this->baseDefinition);
346
347     // Setup the prefix of the derivative.
348     $definitions['views_view:view.example_view.page_1'] = $definitions['view.example_view.page_1'];
349     unset($definitions['view.example_view.page_1']);
350     $this->localTaskDerivative->alterLocalTasks($definitions);
351
352     $plugin = $definitions['views_view:view.example_view.page_1'];
353     $this->assertCount(2, $definitions);
354
355     // Ensure the other local task was not changed.
356     $this->assertEquals($other_tab, $definitions['test_route_tab']);
357
358     $this->assertEquals('view.example_view.page_1', $plugin['route_name']);
359     $this->assertEquals(12, $plugin['weight']);
360     $this->assertEquals('Example title', $plugin['title']);
361     $this->assertEquals($this->baseDefinition['class'], $plugin['class']);
362     $this->assertEquals('test_route', $plugin['base_route']);
363   }
364
365 }
366
367 /**
368  * Replaces the applicable views call for easier testability.
369  */
370 class TestViewsLocalTask extends ViewsLocalTask {
371
372   /**
373    * Sets applicable views result.
374    */
375   public function setApplicableMenuViews($result) {
376     $this->result = $result;
377   }
378
379   /**
380    * {@inheritdoc}
381    */
382   protected function getApplicableMenuViews() {
383     return $this->result;
384   }
385
386 }