From 530fe2f12a0efab4029841eb7dfd502a9aa07c32 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Thu, 9 Jul 2020 07:47:01 +0800 Subject: [PATCH] MDL-69231 tests: Add role capability setting generator --- .../tests/behat/edit_permissions.feature | 5 +- lib/behat/classes/behat_core_generator.php | 23 +++++++++ lib/testing/generator/data_generator.php | 42 ++++++++++++++++ lib/tests/behat/behat_data_generators.php | 30 +++++++++++- lib/tests/behat/behat_permissions.php | 49 ++++++++++++++----- 5 files changed, 135 insertions(+), 14 deletions(-) diff --git a/admin/tool/behat/tests/behat/edit_permissions.feature b/admin/tool/behat/tests/behat/edit_permissions.feature index bfcbb80eadb..2fabadb3c9b 100644 --- a/admin/tool/behat/tests/behat/edit_permissions.feature +++ b/admin/tool/behat/tests/behat/edit_permissions.feature @@ -21,12 +21,15 @@ Feature: Edit capabilities Scenario: Default system capabilities modification Given I log in as "admin" - And I set the following system permissions of "Teacher" role: + When I navigate to "Users > Permissions > Define roles" in site administration + And I click on "Edit Teacher role" "link" + And I fill the capabilities form with the following permissions: | capability | permission | | block/mnet_hosts:myaddinstance | Allow | | moodle/site:messageanyuser | Inherit | | moodle/grade:managesharedforms | Prevent | | moodle/course:request | Prohibit | + And I press "Save changes" When I follow "Edit Teacher role" Then "block/mnet_hosts:myaddinstance" capability has "Allow" permission And "moodle/site:messageanyuser" capability has "Not set" permission diff --git a/lib/behat/classes/behat_core_generator.php b/lib/behat/classes/behat_core_generator.php index 30d6281c9cb..8d6b34f6870 100644 --- a/lib/behat/classes/behat_core_generator.php +++ b/lib/behat/classes/behat_core_generator.php @@ -144,6 +144,12 @@ class behat_core_generator extends behat_generator_base { 'datagenerator' => 'role', 'required' => ['shortname'], ], + 'role capabilities' => [ + 'singular' => 'role capability', + 'datagenerator' => 'role_capability', + 'required' => ['role'], + 'switchids' => ['role' => 'roleid'], + ], 'grade categories' => [ 'singular' => 'grade category', 'datagenerator' => 'grade_category', @@ -681,6 +687,23 @@ class behat_core_generator extends behat_generator_base { $this->datagenerator->create_role($data); } + /** + * Assign capabilities to a role. + * + * @param array $data + */ + protected function process_role_capability($data): void { + // We require the user to fill the role shortname. + if (empty($data['roleid'])) { + throw new Exception('\'role capability\' requires the field \'roleid\' to be specified'); + } + + $roleid = $data['roleid']; + unset($data['roleid']); + + $this->datagenerator->create_role_capability($roleid, $data, \context_system::instance()); + } + /** * Adds members to cohorts * diff --git a/lib/testing/generator/data_generator.php b/lib/testing/generator/data_generator.php index 5f964d89c2c..7ec50aaa825 100644 --- a/lib/testing/generator/data_generator.php +++ b/lib/testing/generator/data_generator.php @@ -852,6 +852,48 @@ EOD; return $newroleid; } + /** + * Set role capabilities for the specified role. + * + * @param int $roleid The Role to set capabilities for + * @param array $rolecapabilities The list of capability =>permission to set for this role + * @param context $context The context to apply this capability to + */ + public function create_role_capability(int $roleid, array $rolecapabilities, context $context = null): void { + // Map the capabilities into human-readable names. + $allpermissions = [ + 'inherit' => CAP_INHERIT, + 'allow' => CAP_ALLOW, + 'prevent' => CAP_PREVENT, + 'prohibit' => CAP_PROHIBIT, + ]; + + // Fetch all capabilities to check that they exist. + $allcapabilities = get_all_capabilities(); + foreach ($rolecapabilities as $capability => $permission) { + if ($permission === '') { + // Allow items to be skipped. + continue; + } + + if (!array_key_exists($capability, $allcapabilities)) { + throw new \coding_exception("Unknown capability '{$capability}'"); + } + + if (!array_key_exists($permission, $allpermissions)) { + throw new \coding_exception("Unknown capability permissions '{$permission}'"); + } + + assign_capability( + $capability, + $allpermissions[$permission], + $roleid, + $context->id, + true + ); + } + } + /** * Create a tag. * diff --git a/lib/tests/behat/behat_data_generators.php b/lib/tests/behat/behat_data_generators.php index 9c44aad388f..c95b24b6f3f 100644 --- a/lib/tests/behat/behat_data_generators.php +++ b/lib/tests/behat/behat_data_generators.php @@ -93,7 +93,35 @@ class behat_data_generators extends behat_base { } /** - * Creates the specified element. + * Create multiple entities of one entity type. + * + * @Given :count :entitytype exist with the following data: + * + * @param string $entitytype The name of the type entity to add + * @param int $count + * @param TableNode $data + */ + public function the_following_repeated_entities_exist(string $entitytype, int $count, TableNode $data): void { + $rows = $data->getRowsHash(); + + $tabledata = [array_keys($rows)]; + for ($current = 1; $current < $count + 1; $current++) { + $rowdata = []; + foreach ($rows as $fieldname => $fieldtemplate) { + $rowdata[$fieldname] = str_replace('[count]', $current, $fieldtemplate); + } + $tabledata[] = $rowdata; + } + + if (isset($this->movedentitytypes[$entitytype])) { + $entitytype = $this->movedentitytypes[$entitytype]; + } + list($component, $entity) = $this->parse_entity_type($entitytype); + $this->get_instance_for_component($component)->generate_items($entity, new TableNode($tabledata), false); + } + + /** + * Creates the specified (singular) element. * * See the class comment for an overview. * diff --git a/lib/tests/behat/behat_permissions.php b/lib/tests/behat/behat_permissions.php index 155ad85d001..119be436d7d 100644 --- a/lib/tests/behat/behat_permissions.php +++ b/lib/tests/behat/behat_permissions.php @@ -47,22 +47,47 @@ class behat_permissions extends behat_base { * @param TableNode $table */ public function i_set_the_following_system_permissions_of_role($rolename, $table) { + // Applied in the System context. + $context = \context_system::instance(); - $parentnodes = get_string('users', 'admin') . ' > ' . - get_string('permissions', 'role'); + // Translate the specified rolename into a role. + $rolenames = role_get_names($context); + $matched = array_filter($rolenames, function($role) use ($rolename) { + return ($role->localname === $rolename) || ($role->shortname === $rolename) || ($role->description === $rolename); + }); - // Go to home page. - $this->execute("behat_general::i_am_on_homepage"); + if (count($matched) === 0) { + throw new ExpectationException("Unable to find a role with name '{$rolename}'", $this->getSession()); + } else if (count($matched) > 1) { + throw new ExpectationException("Multiple roles matched '{$rolename}'", $this->getSession()); + } - // Navigate to course management page via navigation block. - $this->execute("behat_navigation::i_navigate_to_in_site_administration", - array($parentnodes . ' > ' . get_string('defineroles', 'role')) + $role = reset($matched); + + $permissionmap = [ + get_string('inherit', 'role') => 'inherit', + get_string('allow', 'role') => 'allow', + get_string('prevent', 'role') => 'prevent', + get_string('prohibit', 'role') => 'prohibit', + ]; + + $columns = ['role']; + $newtabledata = [$role->shortname]; + foreach ($table as $data) { + $columns[] = $data['capability']; + $newtabledata[] = $permissionmap[$data['permission']]; + } + + $this->execute( + 'behat_data_generators::the_following_entities_exist', + [ + 'role capabilities', + new TableNode([ + 0 => $columns, + 1 => $newtabledata, + ]) + ] ); - - $this->execute("behat_general::click_link", "Edit " . $this->escape($rolename) . " role"); - $this->execute("behat_permissions::i_fill_the_capabilities_form_with_the_following_permissions", $table); - - $this->execute('behat_forms::press_button', get_string('savechanges')); } /**