diff options
5 files changed, 93 insertions, 31 deletions
diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php index 9df2994bb800..04a5186368b3 100644 --- a/core/lib/Drupal/Core/Asset/AssetResolver.php +++ b/core/lib/Drupal/Core/Asset/AssetResolver.php @@ -101,8 +101,18 @@ class AssetResolver implements AssetResolverInterface { * loaded, excluding any libraries that have already been loaded. */ protected function getLibrariesToLoad(AttachedAssetsInterface $assets) { + // The order of libraries passed in via assets can differ, so to reduce + // variation, first normalize the requested libraries to the minimal + // representative set before then expanding the list to include all + // dependencies. + // @see Drupal\FunctionalTests\Core\Asset\AssetOptimizationTestUmami + // @todo: https://www.drupal.org/project/drupal/issues/1945262 + $libraries = $assets->getLibraries(); + if ($libraries) { + $libraries = $this->libraryDependencyResolver->getMinimalRepresentativeSubset($libraries); + } return array_diff( - $this->libraryDependencyResolver->getLibrariesWithDependencies($assets->getLibraries()), + $this->libraryDependencyResolver->getLibrariesWithDependencies($libraries), $this->libraryDependencyResolver->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()) ); } diff --git a/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php index d4c6021b80fa..3ec64eb9ee2e 100644 --- a/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php +++ b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTest.php @@ -57,6 +57,15 @@ class AssetOptimizationTest extends BrowserTestBase { } /** + * Creates a user and requests a page. + */ + protected function requestPage(): void { + $user = $this->createUser(); + $this->drupalLogin($user); + $this->drupalGet(''); + } + + /** * Helper to test aggregate file URLs. * * @param array $settings @@ -73,44 +82,35 @@ class AssetOptimizationTest extends BrowserTestBase { 'preprocess' => TRUE, 'gzip' => TRUE, ])->save(); - $user = $this->createUser(); - $this->drupalLogin($user); - $this->drupalGet(''); + $this->requestPage(); $session = $this->getSession(); $page = $session->getPage(); - $elements = $page->findAll('xpath', '//link[@rel="stylesheet"]'); - $urls = []; - foreach ($elements as $element) { + // Collect all the URLs for all the script and styles prior to making any + // more requests. + $style_elements = $page->findAll('xpath', '//link[@rel="stylesheet"]'); + $script_elements = $page->findAll('xpath', '//script'); + $style_urls = []; + foreach ($style_elements as $element) { if ($element->hasAttribute('href')) { - $urls[] = $element->getAttribute('href'); + $style_urls[] = $element->getAttribute('href'); } } - foreach ($urls as $url) { - $this->assertAggregate($url); + $script_urls = []; + foreach ($script_elements as $element) { + if ($element->hasAttribute('src')) { + $script_urls[] = $element->getAttribute('src'); + } } - foreach ($urls as $url) { + foreach ($style_urls as $url) { + $this->assertAggregate($url); $this->assertAggregate($url, FALSE); - } - - foreach ($urls as $url) { $this->assertInvalidAggregates($url); } - $elements = $page->findAll('xpath', '//script'); - $urls = []; - foreach ($elements as $element) { - if ($element->hasAttribute('src')) { - $urls[] = $element->getAttribute('src'); - } - } - foreach ($urls as $url) { + foreach ($script_urls as $url) { $this->assertAggregate($url); - } - foreach ($urls as $url) { $this->assertAggregate($url, FALSE); - } - foreach ($urls as $url) { $this->assertInvalidAggregates($url); } } @@ -125,16 +125,20 @@ class AssetOptimizationTest extends BrowserTestBase { */ protected function assertAggregate(string $url, bool $from_php = TRUE): void { $url = $this->getAbsoluteUrl($url); - $this->assertStringContainsString($this->fileAssetsPath, $url); + // Not every script or style on a page is aggregated. + if (!str_contains($url, $this->fileAssetsPath)) { + return; + } $session = $this->getSession(); $session->visit($url); $this->assertSession()->statusCodeEquals(200); $headers = $session->getResponseHeaders(); if ($from_php) { $this->assertEquals(['no-store, private'], $headers['Cache-Control']); + $this->assertArrayHasKey('X-Generator', $headers); } else { - $this->assertArrayNotHasKey('Cache-Control', $headers); + $this->assertArrayNotHasKey('X-Generator', $headers); } } @@ -147,6 +151,11 @@ class AssetOptimizationTest extends BrowserTestBase { * @throws \Behat\Mink\Exception\ExpectationException */ protected function assertInvalidAggregates(string $url): void { + $url = $this->getAbsoluteUrl($url); + // Not every script or style on a page is aggregated. + if (!str_contains($url, $this->fileAssetsPath)) { + return; + } $session = $this->getSession(); $session->visit($this->replaceGroupDelta($url)); $this->assertSession()->statusCodeEquals(200); diff --git a/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTestUmami.php b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTestUmami.php new file mode 100644 index 000000000000..67a329b7f047 --- /dev/null +++ b/core/tests/Drupal/FunctionalTests/Asset/AssetOptimizationTestUmami.php @@ -0,0 +1,30 @@ +<?php + +namespace Drupal\FunctionalTests\Asset; + +/** + * Tests asset aggregation with the Umami install profile. + * + * Umami includes several core modules as well as the Claro theme, this + * results in a more complex asset dependency tree to test than the testing + * profile. + * + * @group asset + */ +class AssetOptimizationTestUmami extends AssetOptimizationTest { + + /** + * {@inheritdoc} + */ + protected $profile = 'demo_umami'; + + /** + * {@inheritdoc} + */ + protected function requestPage(): void { + $user = $this->createUser([], NULL, TRUE); + $this->drupalLogin($user); + $this->drupalGet('node/add/article'); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Asset/AssetResolverTest.php b/core/tests/Drupal/Tests/Core/Asset/AssetResolverTest.php index b2589385abfa..76ee6d23f870 100644 --- a/core/tests/Drupal/Tests/Core/Asset/AssetResolverTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/AssetResolverTest.php @@ -92,6 +92,9 @@ class AssetResolverTest extends UnitTestCase { $this->libraryDependencyResolver->expects($this->any()) ->method('getLibrariesWithDependencies') ->willReturnArgument(0); + $this->libraryDependencyResolver->expects($this->any()) + ->method('getMinimalRepresentativeSubset') + ->willReturnArgument(0); $this->moduleHandler = $this->createMock('\Drupal\Core\Extension\ModuleHandlerInterface'); $this->themeManager = $this->createMock('\Drupal\Core\Theme\ThemeManagerInterface'); $active_theme = $this->getMockBuilder('\Drupal\Core\Theme\ActiveTheme') diff --git a/core/themes/olivero/olivero.libraries.yml b/core/themes/olivero/olivero.libraries.yml index f4137008e5bd..173055404b92 100644 --- a/core/themes/olivero/olivero.libraries.yml +++ b/core/themes/olivero/olivero.libraries.yml @@ -52,12 +52,12 @@ global-styling: js: js/checkbox.js: {} - js/navigation-utils.js: {} dependencies: - core/drupal - core/once - core/tabbable + - olivero/navigation-base book: version: VERSION @@ -213,6 +213,15 @@ messages: dependencies: - olivero/global-styling +navigation-base: + version: VERSION + js: + js/navigation-utils.js: {} + dependencies: + - core/drupal + - core/once + - core/tabbable + navigation-primary: version: VERSION css: @@ -225,8 +234,7 @@ navigation-primary: js/second-level-navigation.js: {} js/nav-resize.js: {} dependencies: - - core/drupal - - core/once + - olivero/navigation-base navigation-secondary: version: VERSION @@ -265,6 +273,8 @@ search-wide: css/components/header-search-wide.css: {} js: js/search.js: {} + dependencies: + - olivero/navigation-primary sidebar: version: VERSION |