1<?php 2 3namespace Drupal\Tests\Core\Menu; 4 5use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; 6use Drupal\Core\Plugin\Discovery\YamlDiscovery; 7use Drupal\Tests\UnitTestCase; 8use Symfony\Component\DependencyInjection\ContainerBuilder; 9use Symfony\Component\HttpFoundation\RequestStack; 10 11/** 12 * Defines a base unit test for testing existence of local tasks. 13 * 14 * @todo Add tests for access checking and url building, 15 * https://www.drupal.org/node/2112245. 16 */ 17abstract class LocalTaskIntegrationTestBase extends UnitTestCase { 18 19 /** 20 * A list of module directories used for YAML searching. 21 * 22 * @var array 23 */ 24 protected $directoryList; 25 26 /** 27 * The module handler. 28 * 29 * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit\Framework\MockObject\MockObject 30 */ 31 protected $moduleHandler; 32 33 /** 34 * The container. 35 * 36 * @var \Symfony\Component\DependencyInjection\ContainerBuilder 37 */ 38 protected $container; 39 40 /** 41 * {@inheritdoc} 42 */ 43 protected function setUp() { 44 parent::setUp(); 45 46 $container = new ContainerBuilder(); 47 $config_factory = $this->getConfigFactoryStub([]); 48 $container->set('config.factory', $config_factory); 49 $container->set('app.root', $this->root); 50 \Drupal::setContainer($container); 51 $this->container = $container; 52 } 53 54 /** 55 * Sets up the local task manager for the test. 56 */ 57 protected function getLocalTaskManager($module_dirs, $route_name, $route_params) { 58 $manager = $this 59 ->getMockBuilder('Drupal\Core\Menu\LocalTaskManager') 60 ->disableOriginalConstructor() 61 ->setMethods(NULL) 62 ->getMock(); 63 64 $argumentResolver = $this->createMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface'); 65 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'argumentResolver'); 66 $property->setAccessible(TRUE); 67 $property->setValue($manager, $argumentResolver); 68 69 // todo mock a request with a route. 70 $request_stack = new RequestStack(); 71 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'requestStack'); 72 $property->setAccessible(TRUE); 73 $property->setValue($manager, $request_stack); 74 75 $accessManager = $this->createMock('Drupal\Core\Access\AccessManagerInterface'); 76 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'accessManager'); 77 $property->setAccessible(TRUE); 78 $property->setValue($manager, $accessManager); 79 80 $route_provider = $this->createMock('Drupal\Core\Routing\RouteProviderInterface'); 81 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'routeProvider'); 82 $property->setAccessible(TRUE); 83 $property->setValue($manager, $route_provider); 84 85 $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface') 86 ->disableOriginalConstructor() 87 ->getMock(); 88 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'moduleHandler'); 89 $property->setAccessible(TRUE); 90 $property->setValue($manager, $module_handler); 91 // Set all the modules as being existent. 92 $module_handler->expects($this->any()) 93 ->method('moduleExists') 94 ->will($this->returnCallback(function ($module) use ($module_dirs) { 95 return isset($module_dirs[$module]); 96 })); 97 98 $pluginDiscovery = new YamlDiscovery('links.task', $module_dirs); 99 $pluginDiscovery = new ContainerDerivativeDiscoveryDecorator($pluginDiscovery); 100 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'discovery'); 101 $property->setAccessible(TRUE); 102 $property->setValue($manager, $pluginDiscovery); 103 104 $method = new \ReflectionMethod('Drupal\Core\Menu\LocalTaskManager', 'alterInfo'); 105 $method->setAccessible(TRUE); 106 $method->invoke($manager, 'local_tasks'); 107 108 $plugin_stub = $this->createMock('Drupal\Core\Menu\LocalTaskInterface'); 109 $factory = $this->createMock('Drupal\Component\Plugin\Factory\FactoryInterface'); 110 $factory->expects($this->any()) 111 ->method('createInstance') 112 ->will($this->returnValue($plugin_stub)); 113 $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'factory'); 114 $property->setAccessible(TRUE); 115 $property->setValue($manager, $factory); 116 117 $cache_backend = $this->createMock('Drupal\Core\Cache\CacheBackendInterface'); 118 $manager->setCacheBackend($cache_backend, 'local_task.en', ['local_task']); 119 120 return $manager; 121 } 122 123 /** 124 * Tests integration for local tasks. 125 * 126 * @param $route_name 127 * Route name to base task building on. 128 * @param $expected_tasks 129 * A list of tasks groups by level expected at the given route 130 * @param array $route_params 131 * (optional) A list of route parameters used to resolve tasks. 132 */ 133 protected function assertLocalTasks($route_name, $expected_tasks, $route_params = []) { 134 135 $directory_list = []; 136 foreach ($this->directoryList as $key => $value) { 137 $directory_list[$key] = $this->root . '/' . $value; 138 } 139 140 $manager = $this->getLocalTaskManager($directory_list, $route_name, $route_params); 141 142 $tmp_tasks = $manager->getLocalTasksForRoute($route_name); 143 144 // At this point we're just testing existence so pull out keys and then 145 // compare. 146 // 147 // Deeper testing would require a functioning factory which because we are 148 // using the DefaultPluginManager base means we get into dependency soup 149 // because its factories create method and pulling services off the \Drupal 150 // container. 151 $tasks = []; 152 foreach ($tmp_tasks as $level => $level_tasks) { 153 $tasks[$level] = array_keys($level_tasks); 154 } 155 $this->assertEquals($expected_tasks, $tasks); 156 } 157 158} 159