function ThemeNotUsingClassyLibraryTest::testThemeAccountsForClassyExtensions

Checks for theme-specific equivalents of all Classy library-extends.

Classy extends several core libraries with its own assets, these are defined in the `libraries-extend:` list in classy.info.yml. Classy adds additional assets to these libraries (e.g. when the `file/drupal.file` library loads, the assets of `classy/file` are loaded as well). For a theme to be properly decoupled from Classy's libraries, these core library extensions must become the responsibility of that theme.

@dataProvider providerTestThemeAccountsForClassyExtensions

Parameters

string $theme: The theme being tested.

string[] $extends_to_skip: Classy library-extends excluded from the test.

File

core/tests/Drupal/KernelTests/Core/Theme/ThemeNotUsingClassyLibraryTest.php, line 220

Class

ThemeNotUsingClassyLibraryTest
Tests that themes do not depend on Classy libraries.

Namespace

Drupal\KernelTests\Core\Theme

Code

public function testThemeAccountsForClassyExtensions($theme, array $extends_to_skip) {
    $theme_path = $this->themeHandler
        ->getTheme($theme)
        ->getPath();
    // Get a list of libraries overridden by the current theme. In a theme's
    // info.yml file, these are the libraries listed in `libraries-override:`.
    // They are libraries altered by the current theme.
    $theme_library_overrides = $this->themeInitialization
        ->getActiveThemeByName($theme)
        ->getLibrariesOverride()[$theme_path] ?? [];
    // Get a list of libraries extended by the current theme. In a theme's
    // info.yml file, these are the libraries listed in `libraries-extend:`.
    // The current theme adds additional files to these libraries.
    $theme_extends = $this->themeHandler
        ->getTheme($theme)->info['libraries-extend'] ?? [];
    // Some Classy libraries extend core libraries (i.e. they are not standalone
    // libraries. Rather, they extend the functionality of existing core
    // libraries). These extensions that were implemented in Classy need to be
    // accounted for in the current theme by either 1) The current theme
    // extending the core library with local copy of the Classy library 2)
    // Overriding the core library altogether.
    // The following iterates through each library extended by Classy to confirm
    // that the current theme accounts for these these extensions.
    foreach ($this->classyLibrariesExtend as $library_extended => $info) {
        if (in_array($library_extended, $extends_to_skip)) {
            continue;
        }
        $extends_core_library = isset($theme_extends[$library_extended]);
        $overrides_core_library = isset($theme_library_overrides[$library_extended]);
        // Every core library extended by Classy must be extended or overridden by
        // the current theme.
        $this->assertTrue($extends_core_library || $overrides_core_library, "{$library_extended} is extended by Classy and should be extended or overridden by {$theme}");
        // If the core library is overridden, confirm that the override does not
        // include any Classy assets.
        if ($overrides_core_library) {
            $overridden_with = $theme_library_overrides[$library_extended];
            // A library override variable can be one of three types:
            // - bool (set to false): this means the override simply prevents the
            //   library from loading.
            // - array: this means some files in the overridden library are changed,
            //   but not necessarily all of them.
            // - string (which is what is being looked for here): this means the
            //   library is replaced with a completely different library.
            $override_replaces_library = gettype($overridden_with) === 'string';
            if ($override_replaces_library) {
                // Make sure the replacement library does not come from Classy.
                $this->assertFalse(substr($overridden_with, 0, 7) === 'classy/', "{$library_extended} is replaced with {$overridden_with}. The replacement should not be a Classy library.");
            }
            // If the override doesn't prevent the core library from loading
            // entirely, and it doesn't replace it with another library, each asset
            // must be checked to confirm it isn't coming from Classy.
            if ($overridden_with !== FALSE && !$override_replaces_library) {
                foreach ([
                    'component',
                    'layout',
                ] as $category) {
                    if (isset($overridden_with['css'][$category])) {
                        foreach ($overridden_with['css'][$category] as $css_file) {
                            $this->assertFalse(strpos($css_file, 'core/themes/classy/css'), "Override is loading a Classy asset: {$css_file}");
                        }
                    }
                }
                if (isset($overridden_with['js'])) {
                    foreach ($overridden_with['js'] as $js_file) {
                        $this->assertFalse(strpos($js_file, 'core/themes/classy/js'), "Override is loading a Classy asset: {$js_file}");
                    }
                }
            }
        }
        // If the library is extended, make sure it's not being extended with a
        // Classy library.
        if ($extends_core_library) {
            foreach ($theme_extends[$library_extended] as $library) {
                $this->assertFalse(substr($library, 0, 7) === 'classy/', "{$theme} is extending the core library: {$library_extended} with {$library}. Core libraries should not be extended with a Classy library.");
            }
        }
    }
}

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