DrupalComponentTest.php

Same filename and directory in other branches
  1. 8.9.x core/tests/Drupal/Tests/Component/DrupalComponentTest.php
  2. 10 core/tests/Drupal/Tests/Component/DrupalComponentTest.php
  3. 11.x core/tests/Drupal/Tests/Component/DrupalComponentTest.php

Namespace

Drupal\Tests\Component

File

core/tests/Drupal/Tests/Component/DrupalComponentTest.php

View source
<?php

namespace Drupal\Tests\Component;

use org\bovigo\vfs\vfsStream;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\TestCase;

/**
 * General tests for \Drupal\Component that can't go anywhere else.
 *
 * @group Component
 */
class DrupalComponentTest extends TestCase {
    
    /**
     * Tests that classes in Component do not use any Core class.
     */
    public function testNoCoreInComponent() {
        $component_path = dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))) . '/lib/Drupal/Component';
        foreach ($this->findPhpClasses($component_path) as $class) {
            $this->assertNoCoreUsage($class);
        }
    }
    
    /**
     * Tests that classes in Component Tests do not use any Core class.
     */
    public function testNoCoreInComponentTests() {
        $component_path = dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))) . '/tests/Drupal/Tests/Component';
        foreach ($this->findPhpClasses($component_path) as $class) {
            $this->assertNoCoreUsage($class);
        }
    }
    
    /**
     * Tests LICENSE.txt is present and has the correct content.
     *
     * @param $component_path
     *   The path to the component.
     *
     * @dataProvider \Drupal\Tests\Component\DrupalComponentTest::getComponents
     */
    public function testComponentLicense($component_path) {
        $this->assertFileExists($component_path . DIRECTORY_SEPARATOR . 'LICENSE.txt');
        $this->assertSame('e84dac1d9fbb5a4a69e38654ce644cea769aa76b', hash_file('sha1', $component_path . DIRECTORY_SEPARATOR . 'LICENSE.txt'));
    }
    
    /**
     * Data provider.
     *
     * @return array
     */
    public function getComponents() {
        $root_component_path = dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))) . '/lib/Drupal/Component';
        $component_paths = [];
        foreach (new \DirectoryIterator($root_component_path) as $file) {
            if ($file->isDir() && !$file->isDot()) {
                $component_paths[$file->getBasename()] = [
                    $file->getPathname(),
                ];
            }
        }
        return $component_paths;
    }
    
    /**
     * Searches a directory recursively for PHP classes.
     *
     * @param string $dir
     *   The full path to the directory that should be checked.
     *
     * @return array
     *   An array of class paths.
     */
    protected function findPhpClasses($dir) {
        $classes = [];
        foreach (new \DirectoryIterator($dir) as $file) {
            if ($file->isDir() && !$file->isDot()) {
                $classes = array_merge($classes, $this->findPhpClasses($file->getPathname()));
            }
            elseif ($file->getExtension() == 'php') {
                $classes[] = $file->getPathname();
            }
        }
        return $classes;
    }
    
    /**
     * Asserts that the given class is not using any class from Core namespace.
     *
     * @param string $class_path
     *   The full path to the class that should be checked.
     *
     * @internal
     */
    protected function assertNoCoreUsage(string $class_path) : void {
        $contents = file_get_contents($class_path);
        preg_match_all('/^.*Drupal\\\\Core.*$/m', $contents, $matches);
        $matches = array_filter($matches[0], function ($line) {
            // Filter references that don't really matter.
            return preg_match('/@see|E_USER_DEPRECATED|expectDeprecation/', $line) === 0;
        });
        $this->assertEmpty($matches, "Checking for illegal reference to 'Drupal\\Core' namespace in {$class_path}");
    }
    
    /**
     * Data provider for testAssertNoCoreUsage().
     *
     * @return array
     *   Data for testAssertNoCoreUsage() in the form:
     *   - TRUE if the test passes, FALSE otherwise.
     *   - File data as a string. This will be used as a virtual file.
     */
    public function providerAssertNoCoreUsage() {
        return [
            [
                TRUE,
                '@see \\Drupal\\Core\\Something',
            ],
            [
                FALSE,
                '\\Drupal\\Core\\Something',
            ],
            [
                FALSE,
                "@see \\Drupal\\Core\\Something\n" . '\\Drupal\\Core\\Something',
            ],
            [
                FALSE,
                "\\Drupal\\Core\\Something\n" . '@see \\Drupal\\Core\\Something',
            ],
        ];
    }
    
    /**
     * @covers \Drupal\Tests\Component\DrupalComponentTest::assertNoCoreUsage
     * @dataProvider providerAssertNoCoreUsage
     */
    public function testAssertNoCoreUsage($expected_pass, $file_data) {
        // Set up a virtual file to read.
        $vfs_root = vfsStream::setup('root');
        vfsStream::newFile('Test.php')->at($vfs_root)
            ->setContent($file_data);
        $file_uri = vfsStream::url('root/Test.php');
        try {
            $pass = TRUE;
            $this->assertNoCoreUsage($file_uri);
        } catch (AssertionFailedError $e) {
            $pass = FALSE;
        }
        $this->assertEquals($expected_pass, $pass, $expected_pass ? 'Test caused a false positive' : 'Test failed to detect Core usage');
    }

}

Classes

Title Deprecated Summary
DrupalComponentTest General tests for \Drupal\Component that can't go anywhere else.

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