5 * Contains \Drupal\Tests\Core\Routing\RouteBuilderTest.
8 namespace Drupal\Tests\Core\Routing;
10 use Drupal\Core\DependencyInjection\ContainerBuilder;
11 use Drupal\Core\Discovery\YamlDiscovery;
12 use Drupal\Core\Routing\RouteBuilder;
13 use Drupal\Core\Routing\RouteBuildEvent;
14 use Drupal\Core\Routing\RoutingEvents;
15 use Drupal\Tests\UnitTestCase;
16 use Symfony\Component\Routing\Route;
17 use Symfony\Component\Routing\RouteCollection;
20 * @coversDefaultClass \Drupal\Core\Routing\RouteBuilder
23 class RouteBuilderTest extends UnitTestCase {
26 * The actual tested route builder.
28 * @var \Drupal\Core\Routing\RouteBuilder
30 protected $routeBuilder;
33 * The mocked matcher dumper.
35 * @var \Drupal\Core\Routing\MatcherDumperInterface|\PHPUnit_Framework_MockObject_MockObject
40 * The mocked lock backend.
42 * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
47 * The mocked event dispatcher.
49 * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
51 protected $dispatcher;
54 * The mocked YAML discovery.
56 * @var \Drupal\Core\Discovery\YamlDiscovery|\PHPUnit_Framework_MockObject_MockObject
58 protected $yamlDiscovery;
63 * @var \Drupal\Core\Extension\ModuleHandlerInterface
65 protected $moduleHandler;
68 * The controller resolver.
70 * @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
72 protected $controllerResolver;
75 * @var \Drupal\Core\Access\CheckProviderInterface|\PHPUnit_Framework_MockObject_MockObject
77 protected $checkProvider;
79 protected function setUp() {
80 $this->dumper = $this->getMock('Drupal\Core\Routing\MatcherDumperInterface');
81 $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
82 $this->dispatcher = $this->getMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface');
83 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
84 $this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
85 $this->yamlDiscovery = $this->getMockBuilder('\Drupal\Core\Discovery\YamlDiscovery')
86 ->disableOriginalConstructor()
88 $this->checkProvider = $this->getMock('\Drupal\Core\Access\CheckProviderInterface');
90 $this->routeBuilder = new TestRouteBuilder($this->dumper, $this->lock, $this->dispatcher, $this->moduleHandler, $this->controllerResolver, $this->checkProvider);
91 $this->routeBuilder->setYamlDiscovery($this->yamlDiscovery);
95 * Tests that the route rebuilding both locks and unlocks.
97 public function testRebuildLockingUnlocking() {
98 $this->lock->expects($this->once())
100 ->with('router_rebuild')
101 ->will($this->returnValue(TRUE));
103 $this->lock->expects($this->once())
105 ->with('router_rebuild');
107 $this->yamlDiscovery->expects($this->any())
109 ->will($this->returnValue([]));
111 $this->assertTrue($this->routeBuilder->rebuild());
115 * Tests route rebuilding with a blocking lock.
117 public function testRebuildBlockingLock() {
118 $this->lock->expects($this->once())
120 ->with('router_rebuild')
121 ->will($this->returnValue(FALSE));
123 $this->lock->expects($this->once())
125 ->with('router_rebuild');
127 $this->lock->expects($this->never())
130 $this->yamlDiscovery->expects($this->never())
133 $this->assertFalse($this->routeBuilder->rebuild());
137 * Tests that provided routes by a module is put into the dumper/dispatcher.
139 * @see \Drupal\Core\Routing\RouteBuilder::rebuild()
141 public function testRebuildWithStaticModuleRoutes() {
142 $this->lock->expects($this->once())
144 ->with('router_rebuild')
145 ->will($this->returnValue(TRUE));
147 $routing_fixtures = new RoutingFixtures();
148 $routes = $routing_fixtures->staticSampleRouteCollection();
150 $this->yamlDiscovery->expects($this->once())
152 ->will($this->returnValue(['test_module' => $routes]));
154 $route_collection = $routing_fixtures->sampleRouteCollection();
155 $route_build_event = new RouteBuildEvent($route_collection);
157 // Ensure that the alter routes events are fired.
158 $this->dispatcher->expects($this->at(0))
160 ->with(RoutingEvents::DYNAMIC, $route_build_event);
162 $this->dispatcher->expects($this->at(1))
164 ->with(RoutingEvents::ALTER, $route_build_event);
166 // Ensure that access checks are set.
167 $this->checkProvider->expects($this->once())
168 ->method('setChecks')
169 ->with($route_collection);
171 // Ensure that the routes are set to the dumper and dumped.
172 $this->dumper->expects($this->at(0))
173 ->method('addRoutes')
174 ->with($route_collection);
175 $this->dumper->expects($this->at(1))
179 $this->assertTrue($this->routeBuilder->rebuild());
183 * Tests the rebuild with routes provided by a callback.
185 * @see \Drupal\Core\Routing\RouteBuilder::rebuild()
187 public function testRebuildWithProviderBasedRoutes() {
188 $this->lock->expects($this->once())
190 ->with('router_rebuild')
191 ->will($this->returnValue(TRUE));
193 $this->yamlDiscovery->expects($this->once())
195 ->will($this->returnValue([
197 'route_callbacks' => [
198 '\Drupal\Tests\Core\Routing\TestRouteSubscriber::routesFromArray',
199 'test_module.route_service:routesFromCollection',
204 $container = new ContainerBuilder();
205 $container->set('test_module.route_service', new TestRouteSubscriber());
206 $this->controllerResolver->expects($this->any())
207 ->method('getControllerFromDefinition')
208 ->will($this->returnCallback(function ($controller) use ($container) {
209 $count = substr_count($controller, ':');
211 list($service, $method) = explode(':', $controller, 2);
212 $object = $container->get($service);
215 list($class, $method) = explode('::', $controller, 2);
216 $object = new $class();
218 return [$object, $method];
221 $route_collection_filled = new RouteCollection();
222 $route_collection_filled->add('test_route.1', new Route('/test-route/1'));
223 $route_collection_filled->add('test_route.2', new Route('/test-route/2'));
225 $route_build_event = new RouteBuildEvent($route_collection_filled);
227 // Ensure that the alter routes events are fired.
228 $this->dispatcher->expects($this->at(0))
230 ->with(RoutingEvents::DYNAMIC, $route_build_event);
232 $this->dispatcher->expects($this->at(1))
234 ->with(RoutingEvents::ALTER, $route_build_event);
236 // Ensure that access checks are set.
237 $this->checkProvider->expects($this->once())
238 ->method('setChecks')
239 ->with($route_collection_filled);
241 // Ensure that the routes are set to the dumper and dumped.
242 $this->dumper->expects($this->at(0))
243 ->method('addRoutes')
244 ->with($route_collection_filled);
245 $this->dumper->expects($this->at(1))
248 $this->assertTrue($this->routeBuilder->rebuild());
252 * Tests \Drupal\Core\Routing\RouteBuilder::rebuildIfNeeded() method.
254 public function testRebuildIfNeeded() {
255 $this->lock->expects($this->once())
257 ->with('router_rebuild')
258 ->will($this->returnValue(TRUE));
260 $this->lock->expects($this->once())
262 ->with('router_rebuild');
264 $this->yamlDiscovery->expects($this->any())
266 ->will($this->returnValue([]));
268 $this->routeBuilder->setRebuildNeeded();
270 // This will trigger a successful rebuild.
271 $this->assertTrue($this->routeBuilder->rebuildIfNeeded());
273 // This will not trigger a rebuild.
274 $this->assertFalse($this->routeBuilder->rebuildIfNeeded());
280 * Extends the core route builder with a setter method for the YAML discovery.
282 class TestRouteBuilder extends RouteBuilder {
285 * The mocked YAML discovery.
287 * @var \Drupal\Core\Discovery\YamlDiscovery|\PHPUnit_Framework_MockObject_MockObject
289 protected $yamlDiscovery;
292 * Sets the YAML discovery.
294 * @param \Drupal\Core\Discovery\YamlDiscovery $yaml_discovery
295 * The YAML discovery to set.
297 public function setYamlDiscovery(YamlDiscovery $yaml_discovery) {
298 $this->yamlDiscovery = $yaml_discovery;
304 protected function getRouteDefinitions() {
305 return $this->yamlDiscovery->findAll();
311 * Provides a callback for route definition.
313 class TestRouteSubscriber {
314 public function routesFromArray() {
316 'test_route.1' => new Route('/test-route/1'),
319 public function routesFromCollection() {
320 $collection = new RouteCollection();
321 $collection->add('test_route.2', new Route('/test-route/2'));