Merge branch 'MDL-37958_master' of git://github.com/dmonllao/moodle
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
@tool_behat
|
||||
Feature: Edit capabilities
|
||||
In order to extend and restrict moodle features
|
||||
As an admin or teacher
|
||||
I need to allow/deny the existing capabilities at different levels
|
||||
|
||||
Background:
|
||||
Given the following "users" exists:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exists:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@javascript
|
||||
Scenario: Default system capabilities modification
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Teacher" role:
|
||||
| capability | permission |
|
||||
| block/mnet_hosts:myaddinstance | Allow |
|
||||
| moodle/community:add | Inherit |
|
||||
| moodle/grade:managesharedforms | Prevent |
|
||||
| moodle/course:request | Prohibit |
|
||||
When I follow "Edit Teacher role"
|
||||
Then the "block/mnet_hosts:myaddinstance" field should match "1" value
|
||||
And the "moodle/community:add" field should match "0" value
|
||||
And the "moodle/grade:managesharedforms" field should match "-1" value
|
||||
And the "moodle/course:request" field should match "-1000" value
|
||||
|
||||
@javascript
|
||||
Scenario: Course capabilities overrides
|
||||
Given I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I expand "Users" node
|
||||
And I follow "Permissions"
|
||||
And I override the system permissions of "Student" role with:
|
||||
| mod/forum:deleteanypost | Prohibit |
|
||||
| mod/forum:editanypost | Prevent |
|
||||
| mod/forum:addquestion | Allow |
|
||||
When I select "Student (3)" from "Advanced role override"
|
||||
Then the "mod/forum:deleteanypost" field should match "-1000" value
|
||||
And the "mod/forum:editanypost" field should match "-1" value
|
||||
And the "mod/forum:addquestion" field should match "1" value
|
||||
|
||||
@javascript
|
||||
Scenario: Module capabilities overrides
|
||||
Given I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | I'm the name |
|
||||
| Forum introduction | I'm the introduction |
|
||||
And I follow "I'm the name"
|
||||
And I follow "Permissions"
|
||||
And I override the system permissions of "Student" role with:
|
||||
| mod/forum:deleteanypost | Prohibit |
|
||||
| mod/forum:editanypost | Prevent |
|
||||
| mod/forum:addquestion | Allow |
|
||||
When I select "Student (3)" from "Advanced role override"
|
||||
Then the "mod/forum:deleteanypost" field should match "-1000" value
|
||||
And the "mod/forum:editanypost" field should match "-1" value
|
||||
And the "mod/forum:addquestion" field should match "1" value
|
||||
@@ -0,0 +1,44 @@
|
||||
@blocks
|
||||
Feature: Allowed blocks controls
|
||||
In order to prevent the use of some blocks
|
||||
As an admin
|
||||
I need to restrict some blocks to be used in courses
|
||||
|
||||
Background:
|
||||
Given the following "users" exists:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course $NASTYSTRING1 | C1 | 0 |
|
||||
And the following "course enrolments" exists:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@javascript
|
||||
Scenario: Blocks can be added with the default permissions
|
||||
Given I log in as "teacher1"
|
||||
And I follow "Course $NASTYSTRING1"
|
||||
And I turn editing mode on
|
||||
When I add the "Course completion status" block
|
||||
And I add the "Activities" block
|
||||
Then I should see "Activities"
|
||||
And I should see "Course completion status"
|
||||
|
||||
@javascript
|
||||
Scenario: Blocks can not be added when the admin restricts the permissions
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Teacher" role:
|
||||
| block/activity_modules:addinstance | Prohibit |
|
||||
And I am on homepage
|
||||
And I follow "Course $NASTYSTRING1"
|
||||
And I expand "Users" node
|
||||
And I follow "Permissions"
|
||||
And I override the system permissions of "Teacher" role with:
|
||||
| block/completionstatus:addinstance | Prohibit |
|
||||
And I log out
|
||||
When I log in as "teacher1"
|
||||
And I follow "Course $NASTYSTRING1"
|
||||
And I turn editing mode on
|
||||
Then the "Add a block" select box should not contain "Activities"
|
||||
And the "Add a block" select box should not contain "Course completion status"
|
||||
@@ -196,6 +196,21 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the double quote character.
|
||||
*
|
||||
* Double quote is the argument delimiter, it can be escaped
|
||||
* with a backslash, but we auto-remove this backslashes
|
||||
* before the step execution, this method is useful when using
|
||||
* arguments as arguments for other steps.
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function escape($string) {
|
||||
return str_replace('"', '\"', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the passed closure until returns true or time outs.
|
||||
*
|
||||
|
||||
@@ -29,7 +29,7 @@ use Behat\Mink\Session as Session,
|
||||
Behat\Mink\Element\NodeElement as NodeElement;
|
||||
|
||||
/**
|
||||
* Representation of a moodle field.
|
||||
* Representation of a form field.
|
||||
*
|
||||
* Basically an interface with Mink session.
|
||||
*
|
||||
|
||||
@@ -219,13 +219,14 @@ class behat_forms extends behat_base {
|
||||
|
||||
$fieldnode = $this->find_field($locator);
|
||||
|
||||
// Gets the field instance.
|
||||
// Get the field.
|
||||
$field = $this->get_field($fieldnode, $locator);
|
||||
$fieldvalue = $field->get_value();
|
||||
|
||||
// Checks if the provided value matches the current field value.
|
||||
if ($value != $field->get_value()) {
|
||||
if (trim($value) != trim($fieldvalue)) {
|
||||
throw new ExpectationException(
|
||||
'The \'' . $locator . '\' value is \'' . $field->get_value() . '\'' ,
|
||||
'The \'' . $locator . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' ,
|
||||
$this->getSession()
|
||||
);
|
||||
}
|
||||
@@ -299,7 +300,13 @@ class behat_forms extends behat_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance of the form element field.
|
||||
* Gets an instance of the form field.
|
||||
*
|
||||
* Not all the fields are part of a moodle form, in this
|
||||
* cases it fallsback to the generic form field. Also note
|
||||
* that this generic field type is using a generic setValue()
|
||||
* method from the Behat API, which is not always good to set
|
||||
* the value of form elements.
|
||||
*
|
||||
* @param NodeElement $fieldnode The current node
|
||||
* @param string $locator Just to send an exception that makes sense for the user
|
||||
@@ -308,8 +315,16 @@ class behat_forms extends behat_base {
|
||||
protected function get_field(NodeElement $fieldnode, $locator) {
|
||||
global $CFG;
|
||||
|
||||
// Get the field type.
|
||||
$type = $this->get_node_type($fieldnode, $locator);
|
||||
// Get the field type if is part of a moodleform.
|
||||
if ($this->is_moodleform_field($fieldnode)) {
|
||||
$type = $this->get_node_type($fieldnode, $locator);
|
||||
}
|
||||
|
||||
// If is not a moodleforms field use the base field type.
|
||||
if (empty($type)) {
|
||||
$type = 'field';
|
||||
}
|
||||
|
||||
$classname = 'behat_form_' . $type;
|
||||
|
||||
// Fallsback on the default form field if nothing specific exists.
|
||||
@@ -324,16 +339,34 @@ class behat_forms extends behat_base {
|
||||
return new $classname($this->getSession(), $fieldnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects when the field is a moodleform field type.
|
||||
*
|
||||
* Note that there are fields inside moodleforms that are not
|
||||
* moodleform element; this method can not detect this, this will
|
||||
* be managed by get_node_type, after failing to find the form
|
||||
* element element type.
|
||||
*
|
||||
* @param NodeElement $fieldnode
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_moodleform_field(NodeElement $fieldnode) {
|
||||
|
||||
// We already waited when getting the NodeElement and we don't want an exception if it's not part of a moodleform.
|
||||
$parentformfound = $fieldnode->find('xpath', "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]/fieldset");
|
||||
|
||||
return ($parentformfound != false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive method to find the field type.
|
||||
*
|
||||
* Depending on the field the felement class node is a level or in another. We
|
||||
* look recursively for a parent node with a 'felement' class to find the field type.
|
||||
*
|
||||
* @throws ExpectationException
|
||||
* @param NodeElement $fieldnode The current node
|
||||
* @param string $locator Just to send an exception that makes sense for the user
|
||||
* @return mixed String or NodeElement depending if we have reached the felement node
|
||||
* @param NodeElement $fieldnode The current node.
|
||||
* @param string $locator Just to send an exception that makes sense for the user.
|
||||
* @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
|
||||
*/
|
||||
protected function get_node_type(NodeElement $fieldnode, $locator) {
|
||||
|
||||
@@ -345,9 +378,9 @@ class behat_forms extends behat_base {
|
||||
return substr($class, 10);
|
||||
}
|
||||
|
||||
// Stop propagation through the DOM, something went wrong!.
|
||||
// Stop propagation through the DOM, if it does not have a felement is not part of a moodle form.
|
||||
if (strstr($class, 'fcontainer') != false) {
|
||||
throw new ExpectationException('No field type for ' . $locator . ' found, ensure the field exists', $this->getSession());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,16 @@ class behat_navigation extends behat_base {
|
||||
public function i_expand_node($nodetext) {
|
||||
|
||||
$xpath = "//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]
|
||||
/child::li
|
||||
/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]
|
||||
/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]
|
||||
|
|
||||
//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]
|
||||
/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed'))]
|
||||
/descendant::li
|
||||
/descendant::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]
|
||||
/descendant::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]";
|
||||
/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]
|
||||
/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]
|
||||
";
|
||||
|
||||
$node = $this->find('xpath', $xpath);
|
||||
$node->click();
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Steps definitions related with permissions.
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../behat/behat_base.php');
|
||||
|
||||
use Behat\Mink\Exception\ExpectationException as ExpectationException,
|
||||
Behat\Behat\Context\Step\Given as Given,
|
||||
Behat\Gherkin\Node\TableNode as TableNode;
|
||||
|
||||
/**
|
||||
* Steps definitions to set up permissions to capabilities.
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_permissions extends behat_base {
|
||||
|
||||
/**
|
||||
* Set system level permissions to the specified role. Expects a table with capability name and permission (Inherit/Allow/Prevent/Prohibit) columns.
|
||||
* @Given /^I set the following system permissions of "(?P<rolefullname_string>(?:[^"]|\\")*)" role:$/
|
||||
* @param string $rolename
|
||||
* @param TableNode $table
|
||||
* @return void Executes other steps
|
||||
*/
|
||||
public function i_set_the_following_system_permissions_of_role($rolename, $table) {
|
||||
|
||||
return array(
|
||||
new Given('I am on homepage'),
|
||||
new Given('I expand "Front page settings" node'),
|
||||
new Given('I expand "Site administration" node'),
|
||||
new Given('I expand "Users" node'),
|
||||
new Given('I expand "Permissions" node'),
|
||||
new Given('I follow "Define roles"'),
|
||||
new Given('I follow "Edit ' . $this->escape($rolename) . ' role"'),
|
||||
new Given('I fill the capabilities form with the following permissions:', $table),
|
||||
new Given('I press "Save changes"')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides system capabilities at category, course and module levels. This step begins after clicking 'Permissions' link. Expects a table with capability name and permission (Inherit/Allow/Prevent/Prohibit) columns.
|
||||
* @Given /^I override the system permissions of "(?P<rolefullname_string>(?:[^"]|\\")*)" role with:$/
|
||||
* @param string $rolename
|
||||
* @param TableNode $table
|
||||
* @return void Executes other steps
|
||||
*/
|
||||
public function i_override_the_system_permissions_of_role_with($rolename, $table) {
|
||||
|
||||
// We don't know the number of overrides so we have to get it to match the option contents.
|
||||
$roleoption = $this->find('xpath', '//select[@name="roleid"]/option[contains(text(),"' . $this->escape($rolename) . '")]');
|
||||
|
||||
return array(
|
||||
new Given('I select "' . $this->escape($roleoption->getText()) . '" from "Advanced role override"'),
|
||||
new Given('I fill the capabilities form with the following permissions:', $table),
|
||||
new Given('I press "Save changes"')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the advanced permissions form with the provided data. Expects a table with capability name and permission (Inherit/Allow/Prevent/Prohibit) columns.
|
||||
* @Given /^I fill the capabilities form with the following permissions:$/
|
||||
* @param TableNode $table
|
||||
* @return void
|
||||
*/
|
||||
public function i_fill_the_capabilities_form_with_the_following_permissions($table) {
|
||||
|
||||
// Ensure we are using the advanced view.
|
||||
// Wrapped in a try/catch to capture the exception and continue execution, we don't know if advanced mode was already enabled.
|
||||
try {
|
||||
$advancedtoggle = $this->find_button('Show advanced');
|
||||
if ($advancedtoggle) {
|
||||
$this->getSession()->getPage()->pressButton('Show advanced');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// We already are in advanced mode.
|
||||
}
|
||||
|
||||
// Using getRows() as we are not sure if tests writers will add the header.
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
|
||||
if (count($row) !== 2) {
|
||||
throw new ExpectationException('You should specify a table with capability/permission columns', $this->getSession());
|
||||
}
|
||||
|
||||
list($capability, $permission) = $row;
|
||||
|
||||
// Skip the headers row if it was provided
|
||||
if (strtolower($capability) == 'capability' || strtolower($capability) == 'capabilities') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Checking the permission value.
|
||||
$permissionconstant = 'CAP_'. strtoupper($permission);
|
||||
if (!defined($permissionconstant)) {
|
||||
throw new ExpectationException(
|
||||
'The provided permission value "' . $permission . '" is not valid. Use Inherit, Allow, Prevent or Prohibited',
|
||||
$this->getSession()
|
||||
);
|
||||
}
|
||||
|
||||
// Converting from permission to constant value.
|
||||
$permissionvalue = constant($permissionconstant);
|
||||
|
||||
// Here we wait for the element to appear and exception if it does not exists.
|
||||
$radio = $this->find('xpath', '//input[@name="' . $capability . '" and @value="' . $permissionvalue . '"]');
|
||||
$radio->click();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user