class PathBasedBreadcrumbBuilderTest

Same name in other branches
  1. 9 core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php \Drupal\Tests\system\Unit\Breadcrumbs\PathBasedBreadcrumbBuilderTest
  2. 8.9.x core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php \Drupal\Tests\system\Unit\Breadcrumbs\PathBasedBreadcrumbBuilderTest
  3. 11.x core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php \Drupal\Tests\system\Unit\Breadcrumbs\PathBasedBreadcrumbBuilderTest

@coversDefaultClass \Drupal\system\PathBasedBreadcrumbBuilder @group system

Hierarchy

Expanded class hierarchy of PathBasedBreadcrumbBuilderTest

File

core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php, line 27

Namespace

Drupal\Tests\system\Unit\Breadcrumbs
View source
class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
    
    /**
     * The path based breadcrumb builder object to test.
     *
     * @var \Drupal\system\PathBasedBreadcrumbBuilder
     */
    protected $builder;
    
    /**
     * The mocked title resolver.
     *
     * @var \Drupal\Core\Controller\TitleResolverInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $titleResolver;
    
    /**
     * The mocked access manager.
     *
     * @var \Drupal\Core\Access\AccessManagerInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $accessManager;
    
    /**
     * The request matching mock object.
     *
     * @var \Symfony\Component\Routing\Matcher\RequestMatcherInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $requestMatcher;
    
    /**
     * The mocked route request context.
     *
     * @var \Drupal\Core\Routing\RequestContext|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $context;
    
    /**
     * The mocked current user.
     *
     * @var \Drupal\Core\Session\AccountInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $currentUser;
    
    /**
     * The mocked path processor.
     *
     * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $pathProcessor;
    
    /**
     * The mocked current path.
     *
     * @var \Drupal\Core\Path\CurrentPathStack|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $currentPath;
    
    /**
     * The mocked path matcher service.
     *
     * @var \Drupal\Core\Path\PathMatcherInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $pathMatcher;
    
    /**
     * {@inheritdoc}
     *
     * @covers ::__construct
     */
    protected function setUp() : void {
        parent::setUp();
        $this->requestMatcher = $this->createMock('\\Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface');
        $config_factory = $this->getConfigFactoryStub([
            'system.site' => [
                'front' => 'test_frontpage',
            ],
        ]);
        $this->pathProcessor = $this->createMock('\\Drupal\\Core\\PathProcessor\\InboundPathProcessorInterface');
        $this->context = $this->createMock('\\Drupal\\Core\\Routing\\RequestContext');
        $this->accessManager = $this->createMock('\\Drupal\\Core\\Access\\AccessManagerInterface');
        $this->titleResolver = $this->createMock('\\Drupal\\Core\\Controller\\TitleResolverInterface');
        $this->currentUser = $this->createMock('Drupal\\Core\\Session\\AccountInterface');
        $this->currentPath = $this->getMockBuilder('Drupal\\Core\\Path\\CurrentPathStack')
            ->disableOriginalConstructor()
            ->getMock();
        $this->pathMatcher = $this->createMock(PathMatcherInterface::class);
        $this->builder = new TestPathBasedBreadcrumbBuilder($this->context, $this->accessManager, $this->requestMatcher, $this->pathProcessor, $config_factory, $this->titleResolver, $this->currentUser, $this->currentPath, $this->pathMatcher);
        $this->builder
            ->setStringTranslation($this->getStringTranslationStub());
        $cache_contexts_manager = $this->getMockBuilder('Drupal\\Core\\Cache\\Context\\CacheContextsManager')
            ->disableOriginalConstructor()
            ->getMock();
        $cache_contexts_manager->method('assertValidTokens')
            ->willReturn(TRUE);
        $container = new Container();
        $container->set('cache_contexts_manager', $cache_contexts_manager);
        \Drupal::setContainer($container);
    }
    
    /**
     * Tests the build method on the frontpage.
     *
     * @covers ::build
     */
    public function testBuildOnFrontpage() : void {
        $this->pathMatcher
            ->expects($this->once())
            ->method('isFrontPage')
            ->willReturn(TRUE);
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        $this->assertEquals([], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests the build method with one path element.
     *
     * @covers ::build
     */
    public function testBuildWithOnePathElement() : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/example');
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests the build method with two path elements.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     */
    public function testBuildWithTwoPathElements() : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/example/baz');
        $this->setupStubPathProcessor();
        $route_1 = new Route('/example');
        $this->requestMatcher
            ->expects($this->exactly(1))
            ->method('matchRequest')
            ->willReturnCallback(function (Request $request) use ($route_1) {
            if ($request->getPathInfo() == '/example') {
                return [
                    RouteObjectInterface::ROUTE_NAME => 'example',
                    RouteObjectInterface::ROUTE_OBJECT => $route_1,
                    '_raw_variables' => new InputBag([]),
                ];
            }
        });
        $this->setupAccessManagerToAllow();
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
            1 => new Link('Example', new Url('example')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
            'user.permissions',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests the build method with three path elements.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     */
    public function testBuildWithThreePathElements() : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/example/bar/baz');
        $this->setupStubPathProcessor();
        $route_1 = new Route('/example/bar');
        $route_2 = new Route('/example');
        $this->requestMatcher
            ->expects($this->exactly(2))
            ->method('matchRequest')
            ->willReturnCallback(function (Request $request) use ($route_1, $route_2) {
            if ($request->getPathInfo() == '/example/bar') {
                return [
                    RouteObjectInterface::ROUTE_NAME => 'example_bar',
                    RouteObjectInterface::ROUTE_OBJECT => $route_1,
                    '_raw_variables' => new InputBag([]),
                ];
            }
            elseif ($request->getPathInfo() == '/example') {
                return [
                    RouteObjectInterface::ROUTE_NAME => 'example',
                    RouteObjectInterface::ROUTE_OBJECT => $route_2,
                    '_raw_variables' => new InputBag([]),
                ];
            }
        });
        $this->accessManager
            ->expects($this->any())
            ->method('check')
            ->willReturnOnConsecutiveCalls(AccessResult::allowed()->cachePerPermissions(), AccessResult::allowed()->addCacheContexts([
            'bar',
        ])
            ->addCacheTags([
            'example',
        ]));
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        $this->assertEquals([
            new Link('Home', new Url('<front>')),
            new Link('Example', new Url('example')),
            new Link('Bar', new Url('example_bar')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'bar',
            'url.path.is_front',
            'url.path.parent',
            'user.permissions',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([
            'example',
        ], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests that exceptions during request matching are caught.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     *
     * @dataProvider providerTestBuildWithException
     */
    public function testBuildWithException($exception_class, $exception_argument) : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/example/bar');
        $this->setupStubPathProcessor();
        $this->requestMatcher
            ->expects($this->any())
            ->method('matchRequest')
            ->will($this->throwException(new $exception_class($exception_argument)));
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        // No path matched, though at least the frontpage is displayed.
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Provides exception types for testBuildWithException.
     *
     * @return array
     *   The list of exception test cases.
     *
     * @see \Drupal\Tests\system\Unit\Breadcrumbs\PathBasedBreadcrumbBuilderTest::testBuildWithException()
     */
    public static function providerTestBuildWithException() {
        return [
            [
                'Drupal\\Core\\ParamConverter\\ParamNotConvertedException',
                '',
            ],
            [
                'Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException',
                [],
            ],
            [
                'Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException',
                '',
            ],
        ];
    }
    
    /**
     * Tests the build method with a non processed path.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     */
    public function testBuildWithNonProcessedPath() : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/example/bar');
        $this->pathProcessor
            ->expects($this->once())
            ->method('processInbound')
            ->willReturn(FALSE);
        $this->requestMatcher
            ->expects($this->any())
            ->method('matchRequest')
            ->willReturn([]);
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        // No path matched, though at least the frontpage is displayed.
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests the build method with an invalid path.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     */
    public function testBuildWithInvalidPath() : void {
        // The parse_url() function returns FALSE for '/:123/foo' so the
        // Request::create() method therefore considers it to be an invalid URI.
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/:123/foo/bar');
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        // No path matched, though at least the frontpage is displayed.
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Tests the applied method.
     *
     * @covers ::applies
     */
    public function testApplies() : void {
        $this->assertTrue($this->builder
            ->applies($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface')));
    }
    
    /**
     * Tests the breadcrumb for a user path.
     *
     * @covers ::build
     * @covers ::getRequestForPath
     */
    public function testBuildWithUserPath() : void {
        $this->context
            ->expects($this->once())
            ->method('getPathInfo')
            ->willReturn('/user/1/edit');
        $this->setupStubPathProcessor();
        $route_1 = new Route('/user/1');
        $this->requestMatcher
            ->expects($this->exactly(1))
            ->method('matchRequest')
            ->willReturnCallback(function (Request $request) use ($route_1) {
            if ($request->getPathInfo() == '/user/1') {
                return [
                    RouteObjectInterface::ROUTE_NAME => 'user_page',
                    RouteObjectInterface::ROUTE_OBJECT => $route_1,
                    '_raw_variables' => new InputBag([]),
                ];
            }
        });
        $this->setupAccessManagerToAllow();
        $this->titleResolver
            ->expects($this->once())
            ->method('getTitle')
            ->with($this->anything(), $route_1)
            ->willReturn('Admin');
        $breadcrumb = $this->builder
            ->build($this->createMock('Drupal\\Core\\Routing\\RouteMatchInterface'));
        $this->assertEquals([
            0 => new Link('Home', new Url('<front>')),
            1 => new Link('Admin', new Url('user_page')),
        ], $breadcrumb->getLinks());
        $this->assertEqualsCanonicalizing([
            'url.path.is_front',
            'url.path.parent',
            'user.permissions',
        ], $breadcrumb->getCacheContexts());
        $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags());
        $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
    }
    
    /**
     * Setup the access manager to always allow access to routes.
     */
    public function setupAccessManagerToAllow() {
        $this->accessManager
            ->expects($this->any())
            ->method('check')
            ->willReturn((new AccessResultAllowed())->cachePerPermissions());
    }
    protected function setupStubPathProcessor() {
        $this->pathProcessor
            ->expects($this->any())
            ->method('processInbound')
            ->willReturnArgument(0);
    }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title Overrides
PathBasedBreadcrumbBuilderTest::$accessManager protected property The mocked access manager.
PathBasedBreadcrumbBuilderTest::$builder protected property The path based breadcrumb builder object to test.
PathBasedBreadcrumbBuilderTest::$context protected property The mocked route request context.
PathBasedBreadcrumbBuilderTest::$currentPath protected property The mocked current path.
PathBasedBreadcrumbBuilderTest::$currentUser protected property The mocked current user.
PathBasedBreadcrumbBuilderTest::$pathMatcher protected property The mocked path matcher service.
PathBasedBreadcrumbBuilderTest::$pathProcessor protected property The mocked path processor.
PathBasedBreadcrumbBuilderTest::$requestMatcher protected property The request matching mock object.
PathBasedBreadcrumbBuilderTest::$titleResolver protected property The mocked title resolver.
PathBasedBreadcrumbBuilderTest::providerTestBuildWithException public static function Provides exception types for testBuildWithException.
PathBasedBreadcrumbBuilderTest::setUp protected function @covers ::__construct Overrides UnitTestCase::setUp
PathBasedBreadcrumbBuilderTest::setupAccessManagerToAllow public function Setup the access manager to always allow access to routes.
PathBasedBreadcrumbBuilderTest::setupStubPathProcessor protected function
PathBasedBreadcrumbBuilderTest::testApplies public function Tests the applied method.
PathBasedBreadcrumbBuilderTest::testBuildOnFrontpage public function Tests the build method on the frontpage.
PathBasedBreadcrumbBuilderTest::testBuildWithException public function Tests that exceptions during request matching are caught.
PathBasedBreadcrumbBuilderTest::testBuildWithInvalidPath public function Tests the build method with an invalid path.
PathBasedBreadcrumbBuilderTest::testBuildWithNonProcessedPath public function Tests the build method with a non processed path.
PathBasedBreadcrumbBuilderTest::testBuildWithOnePathElement public function Tests the build method with one path element.
PathBasedBreadcrumbBuilderTest::testBuildWithThreePathElements public function Tests the build method with three path elements.
PathBasedBreadcrumbBuilderTest::testBuildWithTwoPathElements public function Tests the build method with two path elements.
PathBasedBreadcrumbBuilderTest::testBuildWithUserPath public function Tests the breadcrumb for a user path.
PhpUnitWarnings::$deprecationWarnings private static property Deprecation warnings from PHPUnit to raise with @trigger_error().
PhpUnitWarnings::addWarning public function Converts PHPUnit deprecation warnings to E_USER_DEPRECATED.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
RandomGeneratorTrait::randomStringValidate Deprecated public function Callback for random string validation.
UnitTestCase::$root protected property The app root. 1
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getConfigStorageStub public function Returns a stub config storage that returns the supplied configuration.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::setUpBeforeClass public static function
UnitTestCase::__get public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.