diff --git a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php index 513c074932e3c26ee1dfc12ae7bf7a425fb0b49f..54d9c7303846acd4dbbb0b665f71623c7e80b52d 100644 --- a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php +++ b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php @@ -27,6 +27,7 @@ class NodeTranslationUITest extends ContentTranslationUITestBase { 'url.path.parent', 'url.query_args:_wrapper_format', 'user.roles', + 'url.path.is_front', // These two cache contexts are added by BigPipe. 'cookies:big_pipe_nojs', 'session.exists', diff --git a/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/core/modules/system/src/PathBasedBreadcrumbBuilder.php index ebc5df0b756bf71f3570b9ca7a17369911aa83ce..261ae32a2491184b6aa2614d037fb4b0a686bf18 100644 --- a/core/modules/system/src/PathBasedBreadcrumbBuilder.php +++ b/core/modules/system/src/PathBasedBreadcrumbBuilder.php @@ -144,7 +144,7 @@ public function build(RouteMatchInterface $route_match) { // Add the url.path.parent cache context. This code ignores the last path // part so the result only depends on the path parents. - $breadcrumb->addCacheContexts(['url.path.parent']); + $breadcrumb->addCacheContexts(['url.path.parent', 'url.path.is_front']); // Do not display a breadcrumb on the frontpage. if ($this->pathMatcher->isFrontPage()) { diff --git a/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php b/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90272094672355c6b6246856b3b7e9dc64670ccf --- /dev/null +++ b/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php @@ -0,0 +1,91 @@ +drupalPlaceBlock('system_breadcrumb_block'); + + $user = $this->drupalCreateUser(); + + $this->drupalCreateContentType([ + 'type' => 'page', + ]); + + // Create a node for front page. + $node_front = $this->drupalCreateNode([ + 'uid' => $user->id(), + ]); + + // Create a node with a random alias. + $this->nodeWithAlias = $this->drupalCreateNode([ + 'uid' => $user->id(), + 'type' => 'page', + 'path' => '/' . $this->randomMachineName(), + ]); + + // Configure 'node' as front page. + $this->config('system.site') + ->set('page.front', '/node/' . $node_front->id()) + ->save(); + + \Drupal::cache('render')->deleteAll(); + } + + /** + * Validate that breadcrumb markup get the right cache contexts. + * + * Checking that the breadcrumb will be printed on node canonical routes even + * if it was rendered for the page first. + */ + public function testBreadcrumbsFrontPageCache() { + // Hit front page first as anonymous user with 'cold' render cache. + $this->drupalGet(''); + $web_assert = $this->assertSession(); + // Verify that no breadcrumb block presents. + $web_assert->elementNotExists('css', '.block-system-breadcrumb-block'); + + // Verify that breadcrumb appears correctly for the test content + // (which is not set as front page). + $this->drupalGet($this->nodeWithAlias->path->alias); + $breadcrumbs = $this->assertSession()->elementExists('css', '.block-system-breadcrumb-block'); + $crumbs = $breadcrumbs->findAll('css', 'ol li'); + $this->assertTrue(count($crumbs) === 1); + $this->assertTrue($crumbs[0]->getText() === 'Home'); + } + +} diff --git a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index a24313f4affb81347c628952e44c8ae18d961956..b07f31f62f4470f3b7fa311e21baa5aedd6246a3 100644 --- a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -151,7 +151,7 @@ public function testBuildOnFrontpage() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -168,7 +168,7 @@ public function testBuildWithOnePathElement() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -203,7 +203,11 @@ public function testBuildWithTwoPathElements() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Example', new Url('example'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -254,7 +258,12 @@ public function testBuildWithThreePathElements() { new Link('Example', new Url('example')), new Link('Bar', new Url('example_bar')), ], $breadcrumb->getLinks()); - $this->assertEquals(['bar', 'url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'bar', + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals(['example'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -281,7 +290,7 @@ public function testBuildWithException($exception_class, $exception_argument) { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -325,7 +334,7 @@ public function testBuildWithNonProcessedPath() { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -373,7 +382,11 @@ public function testBuildWithUserPath() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Admin', new Url('user_page'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); }