927551f7b58fbeddf99768036b0a600ee3915271
[yaffs-website] / web / core / modules / views / tests / src / Unit / EventSubscriber / RouteSubscriberTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\views\Unit\EventSubscriber\RouteSubscriberTest.
6  */
7
8 namespace Drupal\Tests\views\Unit\EventSubscriber;
9
10 use Drupal\Core\Routing\RouteBuildEvent;
11 use Drupal\Tests\UnitTestCase;
12 use Drupal\views\EventSubscriber\RouteSubscriber;
13 use Symfony\Component\Routing\Route;
14 use Symfony\Component\Routing\RouteCollection;
15
16 /**
17  * @coversDefaultClass \Drupal\views\EventSubscriber\RouteSubscriber
18  * @group views
19  */
20 class RouteSubscriberTest extends UnitTestCase {
21
22   /**
23    * The mocked entity manager.
24    *
25    * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
26    */
27   protected $entityManager;
28
29   /**
30    * The mocked view storage.
31    *
32    * @var \Drupal\views\ViewStorage|\PHPUnit_Framework_MockObject_MockObject
33    */
34   protected $viewStorage;
35
36   /**
37    * The tested views route subscriber.
38    *
39    * @var \Drupal\views\EventSubscriber\RouteSubscriber|\Drupal\Tests\views\Unit\EventSubscriber\TestRouteSubscriber
40    */
41   protected $routeSubscriber;
42
43   /**
44    * The mocked key value storage.
45    *
46    * @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
47    */
48   protected $state;
49
50   protected function setUp() {
51     $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
52     $this->viewStorage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
53       ->disableOriginalConstructor()
54       ->getMock();
55     $this->entityManager->expects($this->any())
56       ->method('getStorage')
57       ->with('view')
58       ->will($this->returnValue($this->viewStorage));
59     $this->state = $this->getMock('\Drupal\Core\State\StateInterface');
60     $this->routeSubscriber = new TestRouteSubscriber($this->entityManager, $this->state);
61   }
62
63   /**
64    * @covers ::routeRebuildFinished
65    */
66   public function testRouteRebuildFinished() {
67     list($display_1, $display_2) = $this->setupMocks();
68
69     $display_1->expects($this->once())
70       ->method('collectRoutes')
71       ->will($this->returnValue(['test_id.page_1' => 'views.test_id.page_1']));
72     $display_2->expects($this->once())
73       ->method('collectRoutes')
74       ->will($this->returnValue(['test_id.page_2' => 'views.test_id.page_2']));
75
76     $this->routeSubscriber->routes();
77
78     $this->state->expects($this->once())
79       ->method('set')
80       ->with('views.view_route_names', ['test_id.page_1' => 'views.test_id.page_1', 'test_id.page_2' => 'views.test_id.page_2']);
81     $this->routeSubscriber->routeRebuildFinished();
82   }
83
84   /**
85    * Tests the onAlterRoutes method.
86    *
87    * @see \Drupal\views\EventSubscriber\RouteSubscriber::onAlterRoutes()
88    */
89   public function testOnAlterRoutes() {
90     $collection = new RouteCollection();
91     // The first route will be overridden later.
92     $collection->add('test_route', new Route('test_route', ['_controller' => 'Drupal\Tests\Core\Controller\TestController']));
93     $route_2 = new Route('test_route/example', ['_controller' => 'Drupal\Tests\Core\Controller\TestController']);
94     $collection->add('test_route_2', $route_2);
95
96     $route_event = new RouteBuildEvent($collection, 'views');
97
98     list($display_1, $display_2) = $this->setupMocks();
99
100     // The page_1 display overrides an existing route, so the dynamicRoutes
101     // should only call the second display.
102     $display_1->expects($this->once())
103       ->method('collectRoutes')
104       ->willReturnCallback(function () use ($collection) {
105         $collection->add('views.test_id.page_1', new Route('test_route', ['_controller' => 'Drupal\views\Routing\ViewPageController']));
106         return ['test_id.page_1' => 'views.test_id.page_1'];
107       });
108     $display_1->expects($this->once())
109       ->method('alterRoutes')
110       ->willReturn(['test_id.page_1' => 'test_route']);
111
112     $display_2->expects($this->once())
113       ->method('collectRoutes')
114       ->willReturnCallback(function () use ($collection) {
115         $collection->add('views.test_id.page_2', new Route('test_route', ['_controller' => 'Drupal\views\Routing\ViewPageController']));
116         return ['test_id.page_2' => 'views.test_id.page_2'];
117       });
118     $display_2->expects($this->once())
119       ->method('alterRoutes')
120       ->willReturn([]);
121
122     // Ensure that even both the collectRoutes() and alterRoutes() methods
123     // are called on the displays, we ensure that the route first defined by
124     // views is dropped.
125
126     $this->routeSubscriber->routes();
127     $this->assertNull($this->routeSubscriber->onAlterRoutes($route_event));
128
129     $this->state->expects($this->once())
130       ->method('set')
131       ->with('views.view_route_names', ['test_id.page_1' => 'test_route', 'test_id.page_2' => 'views.test_id.page_2']);
132
133     $collection = $route_event->getRouteCollection();
134     $this->assertEquals(['test_route', 'test_route_2', 'views.test_id.page_2'], array_keys($collection->all()));
135
136     $this->routeSubscriber->routeRebuildFinished();
137   }
138
139   /**
140    * Sets up mocks of Views objects needed for testing.
141    *
142    * @return \Drupal\views\Plugin\views\display\DisplayRouterInterface[]|\PHPUnit_Framework_MockObject_MockObject[]
143    *   An array of two mocked view displays.
144    */
145   protected function setupMocks() {
146     $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
147       ->disableOriginalConstructor()
148       ->getMock();
149     $view = $this->getMockBuilder('Drupal\views\Entity\View')
150       ->disableOriginalConstructor()
151       ->getMock();
152     $this->viewStorage->expects($this->any())
153       ->method('load')
154       ->will($this->returnValue($view));
155
156     $view->expects($this->any())
157       ->method('getExecutable')
158       ->will($this->returnValue($executable));
159     $view->expects($this->any())
160       ->method('id')
161       ->will($this->returnValue('test_id'));
162     $executable->storage = $view;
163
164     $executable->expects($this->any())
165       ->method('setDisplay')
166       ->will($this->returnValueMap([
167         ['page_1', TRUE],
168         ['page_2', TRUE],
169         ['page_3', FALSE],
170       ]));
171
172     // Ensure that only the first two displays are actually called.
173     $display_1 = $this->getMock('Drupal\views\Plugin\views\display\DisplayRouterInterface');
174     $display_2 = $this->getMock('Drupal\views\Plugin\views\display\DisplayRouterInterface');
175
176     $display_collection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection')
177       ->disableOriginalConstructor()
178       ->getMock();
179     $display_collection->expects($this->any())
180       ->method('get')
181       ->will($this->returnValueMap([
182         ['page_1', $display_1],
183         ['page_2', $display_2],
184       ]));
185     $executable->displayHandlers = $display_collection;
186
187     $this->routeSubscriber->applicableViews = [];
188     $this->routeSubscriber->applicableViews[] = ['test_id', 'page_1'];
189     $this->routeSubscriber->applicableViews[] = ['test_id', 'page_2'];
190     $this->routeSubscriber->applicableViews[] = ['test_id', 'page_3'];
191
192     return [$display_1, $display_2];
193   }
194
195 }
196
197 /**
198  * Provides a test route subscriber.
199  */
200 class TestRouteSubscriber extends RouteSubscriber {
201
202   /**
203    * The applicable views.
204    *
205    * @var array
206    */
207   public $applicableViews;
208
209   /**
210    * {@inheritdoc}
211    */
212   protected function getApplicableViews() {
213     return $this->applicableViews;
214   }
215
216 }