c7639388fd1005ca741b6eebf2623dc42abf6a60
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Menu / MenuActiveTrailTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Menu;
4
5 use Drupal\Core\Menu\MenuActiveTrail;
6 use Drupal\Core\Routing\CurrentRouteMatch;
7 use Drupal\Tests\UnitTestCase;
8 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
9 use Symfony\Component\DependencyInjection\Container;
10 use Symfony\Component\HttpFoundation\ParameterBag;
11 use Symfony\Component\HttpFoundation\Request;
12 use Symfony\Component\HttpFoundation\RequestStack;
13 use Symfony\Component\Routing\Route;
14
15 /**
16  * Tests the active menu trail service.
17  *
18  * @group Menu
19  *
20  * @coversDefaultClass \Drupal\Core\Menu\MenuActiveTrail
21  */
22 class MenuActiveTrailTest extends UnitTestCase {
23
24   /**
25    * The tested active menu trail service.
26    *
27    * @var \Drupal\Core\Menu\MenuActiveTrail
28    */
29   protected $menuActiveTrail;
30
31   /**
32    * The test request stack.
33    *
34    * @var \Symfony\Component\HttpFoundation\RequestStack
35    */
36   protected $requestStack;
37
38   /**
39    * The current route match service.
40    *
41    * @var \Drupal\Core\Routing\CurrentRouteMatch;
42    */
43   protected $currentRouteMatch;
44
45   /**
46    * The mocked menu link manager.
47    *
48    * @var \Drupal\Core\Menu\MenuLinkManagerInterface|\PHPUnit_Framework_MockObject_MockObject
49    */
50   protected $menuLinkManager;
51
52   /**
53    * The mocked cache backend.
54    *
55    * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
56    */
57   protected $cache;
58
59   /**
60    * The mocked lock.
61    *
62    * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
63    */
64   protected $lock;
65
66   /**
67    * {@inheritdoc}
68    */
69   protected function setUp() {
70     parent::setUp();
71
72     $this->requestStack = new RequestStack();
73     $this->currentRouteMatch = new CurrentRouteMatch($this->requestStack);
74     $this->menuLinkManager = $this->getMock('Drupal\Core\Menu\MenuLinkManagerInterface');
75     $this->cache = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
76     $this->lock = $this->getMock('\Drupal\Core\Lock\LockBackendInterface');
77
78     $this->menuActiveTrail = new MenuActiveTrail($this->menuLinkManager, $this->currentRouteMatch, $this->cache, $this->lock);
79
80     $container = new Container();
81     $container->set('cache_tags.invalidator', $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidatorInterface'));
82     \Drupal::setContainer($container);
83   }
84
85   /**
86    * Provides test data for all test methods.
87    *
88    * @return array
89    *   Returns a list of test data of which each is an array containing the
90    *   following elements:
91    *     - request: A request object.
92    *     - links: An array of menu links keyed by ID.
93    *     - menu_name: The active menu name.
94    *     - expected_link: The expected active link for the given menu.
95    */
96   public function provider() {
97     $data = [];
98
99     $mock_route = new Route('');
100
101     $request = new Request();
102     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'baby_llama');
103     $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $mock_route);
104     $request->attributes->set('_raw_variables', new ParameterBag([]));
105
106     $link_1 = MenuLinkMock::create(['id' => 'baby_llama_link_1', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'mama_llama_link']);
107     $link_2 = MenuLinkMock::create(['id' => 'baby_llama_link_2', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'papa_llama_link']);
108
109     // @see \Drupal\Core\Menu\MenuLinkManagerInterface::getParentIds()
110     $link_1_parent_ids = ['baby_llama_link_1', 'mama_llama_link', ''];
111     $empty_active_trail = [''];
112
113     // No active link is returned when zero links match the current route.
114     $data[] = [$request, [], $this->randomMachineName(), NULL, $empty_active_trail];
115
116     // The first (and only) matching link is returned when one link matches the
117     // current route.
118     $data[] = [$request, ['baby_llama_link_1' => $link_1], $this->randomMachineName(), $link_1, $link_1_parent_ids];
119
120     // The first of multiple matching links is returned when multiple links
121     // match the current route, where "first" is determined by sorting by key.
122     $data[] = [$request, ['baby_llama_link_1' => $link_1, 'baby_llama_link_2' => $link_2], $this->randomMachineName(), $link_1, $link_1_parent_ids];
123
124     // No active link is returned in case of a 403.
125     $request = new Request();
126     $request->attributes->set('_exception_statuscode', 403);
127     $data[] = [$request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail];
128
129     // No active link is returned when the route name is missing.
130     $request = new Request();
131     $data[] = [$request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail];
132
133     return $data;
134   }
135
136   /**
137    * Tests getActiveLink().
138    *
139    * @covers ::getActiveLink
140    * @dataProvider provider
141    */
142   public function testGetActiveLink(Request $request, $links, $menu_name, $expected_link) {
143     $this->requestStack->push($request);
144     if ($links !== FALSE) {
145       $this->menuLinkManager->expects($this->exactly(2))
146         ->method('loadLinksbyRoute')
147         ->with('baby_llama')
148         ->will($this->returnValue($links));
149     }
150     // Test with menu name.
151     $this->assertSame($expected_link, $this->menuActiveTrail->getActiveLink($menu_name));
152     // Test without menu name.
153     $this->assertSame($expected_link, $this->menuActiveTrail->getActiveLink());
154   }
155
156   /**
157    * Tests getActiveTrailIds().
158    *
159    * @covers ::getActiveTrailIds
160    * @dataProvider provider
161    */
162   public function testGetActiveTrailIds(Request $request, $links, $menu_name, $expected_link, $expected_trail) {
163     $expected_trail_ids = array_combine($expected_trail, $expected_trail);
164
165     $this->requestStack->push($request);
166     if ($links !== FALSE) {
167       // We expect exactly two calls, one for the first call, and one after the
168       // cache clearing below.
169       $this->menuLinkManager->expects($this->exactly(2))
170         ->method('loadLinksbyRoute')
171         ->with('baby_llama')
172         ->will($this->returnValue($links));
173       if ($expected_link !== NULL) {
174         $this->menuLinkManager->expects($this->exactly(2))
175           ->method('getParentIds')
176           ->will($this->returnValueMap([
177             [$expected_link->getPluginId(), $expected_trail_ids],
178           ]));
179       }
180     }
181
182     // Call out the same twice in order to ensure that static caching works.
183     $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
184     $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
185
186     $this->menuActiveTrail->clear();
187     $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
188   }
189
190   /**
191    * Tests getCid()
192    *
193    * @covers ::getCid
194    */
195   public function testGetCid() {
196     $data = $this->provider()[1];
197     /** @var \Symfony\Component\HttpFoundation\Request $request */
198     $request = $data[0];
199     /** @var \Symfony\Component\Routing\Route $route */
200     $route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
201     $route->setPath('/test/{b}/{a}');
202     $request->attributes->get('_raw_variables')->add(['b' => 1, 'a' => 0]);
203     $this->requestStack->push($request);
204
205     $this->menuLinkManager->expects($this->any())
206       ->method('loadLinksbyRoute')
207       ->with('baby_llama')
208       ->will($this->returnValue($data[1]));
209
210     $expected_link = $data[3];
211     $expected_trail = $data[4];
212     $expected_trail_ids = array_combine($expected_trail, $expected_trail);
213
214     $this->menuLinkManager->expects($this->any())
215       ->method('getParentIds')
216       ->will($this->returnValueMap([
217         [$expected_link->getPluginId(), $expected_trail_ids],
218       ]));
219
220     $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($data[2]));
221
222     $this->cache->expects($this->once())
223       ->method('set')
224       // Ensure we normalize the serialized data by sorting them.
225       ->with('active-trail:route:baby_llama:route_parameters:' . serialize(['a' => 0, 'b' => 1]));
226     $this->lock->expects($this->any())
227       ->method('acquire')
228       ->willReturn(TRUE);
229     $this->menuActiveTrail->destruct();
230   }
231
232 }