class PermissionHandlerTest

Same name and namespace in other branches
  1. 9 core/modules/user/tests/src/Unit/PermissionHandlerTest.php \Drupal\Tests\user\Unit\PermissionHandlerTest
  2. 8.9.x core/modules/user/tests/src/Unit/PermissionHandlerTest.php \Drupal\Tests\user\Unit\PermissionHandlerTest
  3. 10 core/modules/user/tests/src/Unit/PermissionHandlerTest.php \Drupal\Tests\user\Unit\PermissionHandlerTest

Tests the permission handler.

@group user

@coversDefaultClass \Drupal\user\PermissionHandler @runTestsInSeparateProcesses

Hierarchy

Expanded class hierarchy of PermissionHandlerTest

File

core/modules/user/tests/src/Unit/PermissionHandlerTest.php, line 26

Namespace

Drupal\Tests\user\Unit
View source
class PermissionHandlerTest extends UnitTestCase {
    
    /**
     * The tested permission handler.
     *
     * @var \Drupal\user\PermissionHandler
     */
    protected $permissionHandler;
    
    /**
     * The mocked module handler.
     *
     * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $moduleHandler;
    
    /**
     * The mocked string translation.
     *
     * @var \Drupal\Tests\user\Unit\TestTranslationManager
     */
    protected $stringTranslation;
    
    /**
     * The mocked callable resolver.
     *
     * @var \Drupal\Core\Utility\CallableResolver|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $callableResolver;
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $this->stringTranslation = new TestTranslationManager();
        $this->callableResolver = $this->createMock('Drupal\\Core\\Utility\\CallableResolver');
    }
    
    /**
     * Provides an extension object for a given module with a human name.
     *
     * @param string $module
     *   The module machine name.
     * @param string $name
     *   The module human name.
     *
     * @return \Drupal\Core\Extension\Extension
     *   The extension object.
     */
    protected function mockModuleExtension($module, $name) {
        $extension = new Extension('vfs:/', $module, "modules/{$module}");
        $extension->info['name'] = $name;
        return $extension;
    }
    
    /**
     * Tests permissions provided by YML files.
     *
     * @covers ::__construct
     * @covers ::getPermissions
     * @covers ::buildPermissionsYaml
     * @covers ::moduleProvidesPermissions
     */
    public function testBuildPermissionsYaml() : void {
        vfsStreamWrapper::register();
        $root = new vfsStreamDirectory('modules');
        vfsStreamWrapper::setRoot($root);
        $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $this->moduleHandler
            ->expects($this->once())
            ->method('getModuleDirectories')
            ->willReturn([
            'module_a' => vfsStream::url('modules/module_a'),
            'module_b' => vfsStream::url('modules/module_b'),
            'module_c' => vfsStream::url('modules/module_c'),
        ]);
        $url = vfsStream::url('modules');
        mkdir($url . '/module_a');
        file_put_contents($url . '/module_a/module_a.permissions.yml', "access_module_a: single_description");
        mkdir($url . '/module_b');
        file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
'access module b':
  title: 'Access B'
  description: 'bla bla'
'access module a via module b':
  title: 'Access A via B'
  provider: 'module_a'
EOF
);
        mkdir($url . '/module_c');
        file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
'access_module_c':
  title: 'Access C'
  description: 'bla bla'
  'restrict access': TRUE
EOF
);
        $modules = [
            'module_a',
            'module_b',
            'module_c',
        ];
        $this->moduleHandler
            ->expects($this->any())
            ->method('getModuleList')
            ->willReturn(array_flip($modules));
        $this->callableResolver
            ->expects($this->never())
            ->method('getCallableFromDefinition');
        $module_extension_list = $this->createMock(ModuleExtensionList::class);
        $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
        $actual_permissions = $this->permissionHandler
            ->getPermissions();
        $this->assertPermissions($actual_permissions);
        $this->assertTrue($this->permissionHandler
            ->moduleProvidesPermissions('module_a'));
        $this->assertTrue($this->permissionHandler
            ->moduleProvidesPermissions('module_b'));
        $this->assertTrue($this->permissionHandler
            ->moduleProvidesPermissions('module_c'));
        $this->assertFalse($this->permissionHandler
            ->moduleProvidesPermissions('module_d'));
    }
    
    /**
     * Tests permissions sort inside a module.
     *
     * @covers ::__construct
     * @covers ::getPermissions
     * @covers ::buildPermissionsYaml
     * @covers ::sortPermissions
     */
    public function testBuildPermissionsSortPerModule() : void {
        vfsStreamWrapper::register();
        $root = new vfsStreamDirectory('modules');
        vfsStreamWrapper::setRoot($root);
        $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $this->moduleHandler
            ->expects($this->once())
            ->method('getModuleDirectories')
            ->willReturn([
            'module_a' => vfsStream::url('modules/module_a'),
            'module_b' => vfsStream::url('modules/module_b'),
            'module_c' => vfsStream::url('modules/module_c'),
        ]);
        $module_extension_list = $this->createMock(ModuleExtensionList::class);
        $module_extension_list->expects($this->exactly(3))
            ->method('getName')
            ->willReturnMap([
            [
                'module_a',
                'Module a',
            ],
            [
                'module_b',
                'Module b',
            ],
            [
                'module_c',
                'A Module',
            ],
        ]);
        $url = vfsStream::url('modules');
        mkdir($url . '/module_a');
        file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
access_module_a2: single_description2
access_module_a1: single_description1
EOF
);
        mkdir($url . '/module_b');
        file_put_contents($url . '/module_b/module_b.permissions.yml', "access_module_a3: single_description");
        mkdir($url . '/module_c');
        file_put_contents($url . '/module_c/module_c.permissions.yml', "access_module_a4: single_description");
        $modules = [
            'module_a',
            'module_b',
            'module_c',
        ];
        $this->moduleHandler
            ->expects($this->once())
            ->method('getModuleList')
            ->willReturn(array_flip($modules));
        $permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
        $actual_permissions = $permissionHandler->getPermissions();
        $this->assertEquals([
            'access_module_a4',
            'access_module_a1',
            'access_module_a2',
            'access_module_a3',
        ], array_keys($actual_permissions));
    }
    
    /**
     * Tests dynamic callback permissions provided by YML files.
     *
     * @covers ::__construct
     * @covers ::getPermissions
     * @covers ::buildPermissionsYaml
     */
    public function testBuildPermissionsYamlCallback() : void {
        vfsStreamWrapper::register();
        $root = new vfsStreamDirectory('modules');
        vfsStreamWrapper::setRoot($root);
        $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $this->moduleHandler
            ->expects($this->once())
            ->method('getModuleDirectories')
            ->willReturn([
            'module_a' => vfsStream::url('modules/module_a'),
            'module_b' => vfsStream::url('modules/module_b'),
            'module_c' => vfsStream::url('modules/module_c'),
        ]);
        $url = vfsStream::url('modules');
        mkdir($url . '/module_a');
        file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
permission_callbacks:
  - 'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription'
EOF
);
        mkdir($url . '/module_b');
        file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
permission_callbacks:
  - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
  - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider'
EOF
);
        mkdir($url . '/module_c');
        file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
permission_callbacks:
  - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess'
EOF
);
        $modules = [
            'module_a',
            'module_b',
            'module_c',
        ];
        $this->moduleHandler
            ->expects($this->any())
            ->method('getModuleList')
            ->willReturn(array_flip($modules));
        $this->callableResolver
            ->expects($this->exactly(4))
            ->method('getCallableFromDefinition')
            ->willReturnMap([
            [
                'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription',
                [
                    new TestPermissionCallbacks(),
                    'singleDescription',
                ],
            ],
            [
                'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription',
                [
                    new TestPermissionCallbacks(),
                    'titleDescription',
                ],
            ],
            [
                'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider',
                [
                    new TestPermissionCallbacks(),
                    'titleProvider',
                ],
            ],
            [
                'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess',
                [
                    new TestPermissionCallbacks(),
                    'titleDescriptionRestrictAccess',
                ],
            ],
        ]);
        $module_extension_list = $this->createMock(ModuleExtensionList::class);
        $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
        $actual_permissions = $this->permissionHandler
            ->getPermissions();
        $this->assertPermissions($actual_permissions);
    }
    
    /**
     * Tests a YAML file containing both static permissions and a callback.
     */
    public function testPermissionsYamlStaticAndCallback() : void {
        vfsStreamWrapper::register();
        $root = new vfsStreamDirectory('modules');
        vfsStreamWrapper::setRoot($root);
        $this->moduleHandler = $this->createMock('Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $this->moduleHandler
            ->expects($this->once())
            ->method('getModuleDirectories')
            ->willReturn([
            'module_a' => vfsStream::url('modules/module_a'),
        ]);
        $url = vfsStream::url('modules');
        mkdir($url . '/module_a');
        file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
'access module a':
  title: 'Access A'
  description: 'bla bla'
permission_callbacks:
  - 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
EOF
);
        $modules = [
            'module_a',
        ];
        $this->moduleHandler
            ->expects($this->any())
            ->method('getModuleList')
            ->willReturn(array_flip($modules));
        $this->callableResolver
            ->expects($this->once())
            ->method('getCallableFromDefinition')
            ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
            ->willReturn([
            new TestPermissionCallbacks(),
            'titleDescription',
        ]);
        $module_extension_list = $this->createMock(ModuleExtensionList::class);
        $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->callableResolver, $module_extension_list);
        $actual_permissions = $this->permissionHandler
            ->getPermissions();
        $this->assertCount(2, $actual_permissions);
        $this->assertEquals('Access A', $actual_permissions['access module a']['title']);
        $this->assertEquals('module_a', $actual_permissions['access module a']['provider']);
        $this->assertEquals('bla bla', $actual_permissions['access module a']['description']);
        $this->assertEquals('Access B', $actual_permissions['access module b']['title']);
        $this->assertEquals('module_a', $actual_permissions['access module b']['provider']);
        $this->assertEquals('bla bla', $actual_permissions['access module b']['description']);
    }
    
    /**
     * Checks that the permissions are like expected.
     *
     * @param array $actual_permissions
     *   The actual permissions
     *
     * @internal
     */
    protected function assertPermissions(array $actual_permissions) : void {
        $this->assertCount(4, $actual_permissions);
        $this->assertEquals('single_description', $actual_permissions['access_module_a']['title']);
        $this->assertEquals('module_a', $actual_permissions['access_module_a']['provider']);
        $this->assertEquals('Access B', $actual_permissions['access module b']['title']);
        $this->assertEquals('module_b', $actual_permissions['access module b']['provider']);
        $this->assertEquals('Access C', $actual_permissions['access_module_c']['title']);
        $this->assertEquals('module_c', $actual_permissions['access_module_c']['provider']);
        $this->assertTrue($actual_permissions['access_module_c']['restrict access']);
        $this->assertEquals('module_a', $actual_permissions['access module a via module b']['provider']);
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
ExpectDeprecationTrait::expectDeprecation public function Adds an expected deprecation.
ExpectDeprecationTrait::getCallableName private static function Returns a callable as a string suitable for inclusion in a message.
ExpectDeprecationTrait::setUpErrorHandler public function Sets up the test error handler.
ExpectDeprecationTrait::tearDownErrorHandler public function Tears down the test error handler.
PermissionHandlerTest::$callableResolver protected property The mocked callable resolver.
PermissionHandlerTest::$moduleHandler protected property The mocked module handler.
PermissionHandlerTest::$permissionHandler protected property The tested permission handler.
PermissionHandlerTest::$stringTranslation protected property The mocked string translation.
PermissionHandlerTest::assertPermissions protected function Checks that the permissions are like expected.
PermissionHandlerTest::mockModuleExtension protected function Provides an extension object for a given module with a human name.
PermissionHandlerTest::setUp protected function Overrides UnitTestCase::setUp
PermissionHandlerTest::testBuildPermissionsSortPerModule public function Tests permissions sort inside a module.
PermissionHandlerTest::testBuildPermissionsYaml public function Tests permissions provided by YML files.
PermissionHandlerTest::testBuildPermissionsYamlCallback public function Tests dynamic callback permissions provided by YML files.
PermissionHandlerTest::testPermissionsYamlStaticAndCallback public function Tests a YAML file containing both static permissions and a callback.
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.
UnitTestCase::$root protected property The app root.
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

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