MenuActiveTrailTest.php 8.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
<?php

/**
 * @file
 * Contains \Drupal\Tests\Core\Menu\MenuActiveTrailTest.
 */

namespace Drupal\Tests\Core\Menu;

use Drupal\Core\Menu\MenuActiveTrail;
use Drupal\Core\Routing\CurrentRouteMatch;
use Drupal\Tests\UnitTestCase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
14
use Symfony\Component\DependencyInjection\Container;
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Route;

/**
 * Tests the active menu trail service.
 *
 * @group Menu
 *
 * @coversDefaultClass \Drupal\Core\Menu\MenuActiveTrail
 */
class MenuActiveTrailTest extends UnitTestCase {

  /**
   * The tested active menu trail service.
   *
   * @var \Drupal\Core\Menu\MenuActiveTrail
   */
  protected $menuActiveTrail;

  /**
   * The test request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The current route match service.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch;
   */
  protected $currentRouteMatch;

  /**
   * The mocked menu link manager.
   *
   * @var \Drupal\Core\Menu\MenuLinkManagerInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $menuLinkManager;

57 58 59 60 61 62 63 64 65 66 67 68 69 70
  /**
   * The mocked cache backend.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $cache;

  /**
   * The mocked lock.
   *
   * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $lock;

71 72 73 74 75 76 77 78 79
  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    $this->requestStack = new RequestStack();
    $this->currentRouteMatch = new CurrentRouteMatch($this->requestStack);
    $this->menuLinkManager = $this->getMock('Drupal\Core\Menu\MenuLinkManagerInterface');
80 81 82 83
    $this->cache = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface');
    $this->lock = $this->getMock('\Drupal\Core\Lock\LockBackendInterface');

    $this->menuActiveTrail = new MenuActiveTrail($this->menuLinkManager, $this->currentRouteMatch, $this->cache, $this->lock);
84

85 86 87
    $container = new Container();
    $container->set('cache_tags.invalidator', $this->getMock('\Drupal\Core\Cache\CacheTagsInvalidatorInterface'));
    \Drupal::setContainer($container);
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
  }

  /**
   * Provides test data for all test methods.
   *
   * @return array
   *   Returns a list of test data of which each is an array containing the
   *   following elements:
   *     - request: A request object.
   *     - links: An array of menu links keyed by ID.
   *     - menu_name: The active menu name.
   *     - expected_link: The expected active link for the given menu.
   */
  public function provider() {
    $data = array();

    $mock_route = new Route('');

    $request = new Request();
    $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'baby_llama');
    $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $mock_route);
    $request->attributes->set('_raw_variables', new ParameterBag(array()));

    $link_1 = MenuLinkMock::create(array('id' => 'baby_llama_link_1', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'mama_llama_link'));
    $link_2 = MenuLinkMock::create(array('id' => 'baby_llama_link_2', 'route_name' => 'baby_llama', 'title' => 'Baby llama', 'parent' => 'papa_llama_link'));

    // @see \Drupal\Core\Menu\MenuLinkManagerInterface::getParentIds()
    $link_1_parent_ids = array('baby_llama_link_1', 'mama_llama_link', '');
    $empty_active_trail = array('');

    // No active link is returned when zero links match the current route.
119
    $data[] = array($request, array(), $this->randomMachineName(), NULL, $empty_active_trail);
120 121 122

    // The first (and only) matching link is returned when one link matches the
    // current route.
123
    $data[] = array($request, array('baby_llama_link_1' => $link_1), $this->randomMachineName(), $link_1, $link_1_parent_ids);
124 125 126

    // The first of multiple matching links is returned when multiple links
    // match the current route, where "first" is determined by sorting by key.
127
    $data[] = array($request, array('baby_llama_link_1' => $link_1, 'baby_llama_link_2' => $link_2), $this->randomMachineName(), $link_1, $link_1_parent_ids);
128 129 130 131

    // No active link is returned in case of a 403.
    $request = new Request();
    $request->attributes->set('_exception_statuscode', 403);
132
    $data[] = array($request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail);
133 134 135

    // No active link is returned when the route name is missing.
    $request = new Request();
136
    $data[] = array($request, FALSE, $this->randomMachineName(), NULL, $empty_active_trail);
137 138 139 140 141 142 143

    return $data;
  }

  /**
   * Tests getActiveLink().
   *
144
   * @covers ::getActiveLink
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
   * @dataProvider provider
   */
  public function testGetActiveLink(Request $request, $links, $menu_name, $expected_link) {
    $this->requestStack->push($request);
    if ($links !== FALSE) {
      $this->menuLinkManager->expects($this->exactly(2))
        ->method('loadLinksbyRoute')
        ->with('baby_llama')
        ->will($this->returnValue($links));
    }
    // Test with menu name.
    $this->assertSame($expected_link, $this->menuActiveTrail->getActiveLink($menu_name));
    // Test without menu name.
    $this->assertSame($expected_link, $this->menuActiveTrail->getActiveLink());
  }

  /**
   * Tests getActiveTrailIds().
   *
164
   * @covers ::getActiveTrailIds
165 166
   * @dataProvider provider
   */
167
  public function testGetActiveTrailIds(Request $request, $links, $menu_name, $expected_link, $expected_trail) {
168 169 170 171
    $expected_trail_ids = array_combine($expected_trail, $expected_trail);

    $this->requestStack->push($request);
    if ($links !== FALSE) {
172 173 174
      // We expect exactly two calls, one for the first call, and one after the
      // cache clearing below.
      $this->menuLinkManager->expects($this->exactly(2))
175 176 177 178
        ->method('loadLinksbyRoute')
        ->with('baby_llama')
        ->will($this->returnValue($links));
      if ($expected_link !== NULL) {
179
        $this->menuLinkManager->expects($this->exactly(2))
180 181 182 183 184 185 186
          ->method('getParentIds')
          ->will($this->returnValueMap(array(
            array($expected_link->getPluginId(), $expected_trail_ids),
          )));
      }
    }

187 188
    // Call out the same twice in order to ensure that static caching works.
    $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
189
    $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

    $this->menuActiveTrail->clear();
    $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($menu_name));
  }

  /**
   * Tests getCid()
   *
   * @covers ::getCid
   */
  public function testGetCid() {
    $data = $this->provider()[1];
    /** @var \Symfony\Component\HttpFoundation\Request $request */
    $request = $data[0];
    /** @var \Symfony\Component\Routing\Route $route */
    $route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
    $route->setPath('/test/{b}/{a}');
    $request->attributes->get('_raw_variables')->add(['b' => 1, 'a' => 0]);
    $this->requestStack->push($request);

    $this->menuLinkManager->expects($this->any())
      ->method('loadLinksbyRoute')
      ->with('baby_llama')
      ->will($this->returnValue($data[1]));

    $expected_link = $data[3];
    $expected_trail = $data[4];
    $expected_trail_ids = array_combine($expected_trail, $expected_trail);

    $this->menuLinkManager->expects($this->any())
      ->method('getParentIds')
      ->will($this->returnValueMap(array(
        array($expected_link->getPluginId(), $expected_trail_ids),
      )));

    $this->assertSame($expected_trail_ids, $this->menuActiveTrail->getActiveTrailIds($data[2]));

    $this->cache->expects($this->once())
      ->method('set')
      // Ensure we normalize the serialized data by sorting them.
      ->with('active-trail:route:baby_llama:route_parameters:' . serialize(['a' => 0, 'b' => 1]));
    $this->lock->expects($this->any())
      ->method('acquire')
      ->willReturn(TRUE);
    $this->menuActiveTrail->destruct();
235 236 237
  }

}