class PermissionHandlerTest

Same name 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::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::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::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.

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