Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc01a52823 | |||
| d84283e8cc | |||
| 9f1768c098 | |||
| 4babd8cdb7 | |||
| 312318201b | |||
| 3d9ac7137e | |||
| 838e230d54 | |||
| c26ac2e85d | |||
| ee3504f673 | |||
| 31256fae74 | |||
| 0c91f5a454 | |||
| 1ab21607a5 | |||
| 05fc7360c9 | |||
| 4c3211871d | |||
| 95f7d16801 | |||
| 400b2086ff | |||
| 7ef99eb8cf | |||
| ab4b2404c7 | |||
| d859c2875c | |||
| d14ff96dfa | |||
| bc53f961e7 | |||
| 91b2170fdb | |||
| fadadf8a64 | |||
| 65be624c43 | |||
| 3e5d4ba208 | |||
| dfea1a4f0d | |||
| 2409994d32 | |||
| 05dd1161a4 | |||
| 7ed61f310b | |||
| 15b8b5cdf0 | |||
| e6eb619c08 | |||
| 8826294d5d | |||
| cf2780d5c2 | |||
| 154bf3d9f5 | |||
| 768d683beb | |||
| 7f8aca035d | |||
| 8db1cdf462 | |||
| 48dc7ef01e | |||
| d782e76640 | |||
| e693c811f0 | |||
| d2f37aab56 | |||
| 8d08094ac3 | |||
| 8483f7adef | |||
| 4cffe42b56 | |||
| 84935b9585 | |||
| bf8f9164c0 | |||
| 64b5af4b58 | |||
| 959721b58a | |||
| 746fa817c1 | |||
| cfce223e9b | |||
| 375d8ffb56 | |||
| 4fe95b0e61 |
@@ -3371,6 +3371,7 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3557,6 +3558,7 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
define("tool_behat/steps",["exports","core/ajax","core/templates","core/pending"],(function(_exports,_ajax,_templates,_pending){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_pending=_interopRequireDefault(_pending);
|
||||
/**
|
||||
* Enhancements for the step definitions page.
|
||||
*
|
||||
* @module tool_behat/steps
|
||||
* @copyright 2022 Catalyst IT EU
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
var getRequiredFieldsContent=function(entityData){var _entityData$required;return null!==(_entityData$required=entityData.required)&&void 0!==_entityData$required&&_entityData$required.length?_templates.default.renderForPromise("tool_behat/steprequiredfields",{fields:entityData.required}):Promise.resolve({html:"",js:""})};_exports.init=function(){var fn,_ref;document.addEventListener("change",(fn=regeneratorRuntime.mark((function _callee(e){var entityElement,stepElement,pendingPromise,entityData,_yield$getRequiredFie,html,js,stepRequiredFields;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if(entityElement=e.target.closest(".entities"),stepElement=e.target.closest(".stepcontent"),entityElement&&stepElement){_context.next=4;break}return _context.abrupt("return");case 4:return pendingPromise=new _pending.default("tool_behat/steps:change"),_context.next=7,entityType=e.target.value,_ajax.default.call([{methodname:"tool_behat_get_entity_generator",args:{entitytype:entityType}}])[0];case 7:return entityData=_context.sent,_context.next=10,getRequiredFieldsContent(entityData);case 10:if(_yield$getRequiredFie=_context.sent,html=_yield$getRequiredFie.html,js=_yield$getRequiredFie.js,!(stepRequiredFields=stepElement.querySelector(".steprequiredfields"))){_context.next=19;break}return _context.next=17,_templates.default.replaceNode(stepRequiredFields,html,js);case 17:_context.next=21;break;case 19:return _context.next=21,_templates.default.appendNodeContents(stepElement,html,js);case 21:pendingPromise.resolve();case 22:case"end":return _context.stop()}var entityType}),_callee)})),_ref=function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))},function(_x){return _ref.apply(this,arguments)}))}}));
|
||||
|
||||
//# sourceMappingURL=steps.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"steps.min.js","sources":["../src/steps.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\nimport Ajax from 'core/ajax';\nimport Templates from 'core/templates';\nimport PendingJS from 'core/pending';\n\n/**\n * Enhancements for the step definitions page.\n *\n * @module tool_behat/steps\n * @copyright 2022 Catalyst IT EU\n * @author Mark Johnson <mark.johnson@catalyst-eu.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Call the get_entity_generator web service function\n *\n * Takes the name of an entity generator and returns an object containing a list of the required fields.\n *\n * @param {String} entityType\n * @returns {Promise}\n */\nconst getGeneratorEntities = (entityType) => Ajax.call([{\n methodname: 'tool_behat_get_entity_generator',\n args: {entitytype: entityType}\n}])[0];\n\n/**\n * Render HTML for required fields\n *\n * Takes the entity data returned from getGeneratorEntities and renders the HTML to display the required fields.\n *\n * @param {String} entityData\n * @return {Promise}\n */\nconst getRequiredFieldsContent = (entityData) => {\n if (!entityData.required?.length) {\n return Promise.resolve({\n html: '',\n js: ''\n });\n }\n return Templates.renderForPromise('tool_behat/steprequiredfields', {fields: entityData.required});\n};\n\nexport const init = () => {\n // When an entity is selected in the \"the following exist\" step, fetch and display the required fields.\n document.addEventListener('change', async(e) => {\n const entityElement = e.target.closest('.entities');\n const stepElement = e.target.closest('.stepcontent');\n if (!entityElement || !stepElement) {\n return;\n }\n\n const pendingPromise = new PendingJS('tool_behat/steps:change');\n\n const entityData = await getGeneratorEntities(e.target.value);\n const {html, js} = await getRequiredFieldsContent(entityData);\n\n const stepRequiredFields = stepElement.querySelector('.steprequiredfields');\n if (stepRequiredFields) {\n await Templates.replaceNode(stepRequiredFields, html, js);\n } else {\n await Templates.appendNodeContents(stepElement, html, js);\n }\n pendingPromise.resolve();\n });\n};\n"],"names":["getRequiredFieldsContent","entityData","required","_entityData$required","length","Templates","renderForPromise","fields","Promise","resolve","html","js","document","addEventListener","e","entityElement","target","closest","stepElement","pendingPromise","PendingJS","entityType","value","Ajax","call","methodname","args","entitytype","stepRequiredFields","querySelector","replaceNode","appendNodeContents"],"mappings":";;;;;;;;;IAiDMA,yBAA2B,SAACC,yEACzBA,WAAWC,0CAAXC,qBAAqBC,OAMnBC,mBAAUC,iBAAiB,gCAAiC,CAACC,OAAQN,WAAWC,WAL5EM,QAAQC,QAAQ,CACnBC,KAAM,GACNC,GAAI,oBAMI,uBAEhBC,SAASC,iBAAiB,sCAAU,iBAAMC,oNAChCC,cAAgBD,EAAEE,OAAOC,QAAQ,aACjCC,YAAcJ,EAAEE,OAAOC,QAAQ,gBAChCF,eAAkBG,kFAIjBC,eAAiB,IAAIC,iBAAU,2CAhCfC,WAkCwBP,EAAEE,OAAOM,MAlClBC,cAAKC,KAAK,CAAC,CACpDC,WAAY,kCACZC,KAAM,CAACC,WAAYN,eACnB,iBA+BUpB,0CACmBD,yBAAyBC,2DAA3CS,2BAAAA,KAAMC,yBAAAA,KAEPiB,mBAAqBV,YAAYW,cAAc,wEAE3CxB,mBAAUyB,YAAYF,mBAAoBlB,KAAMC,mEAEhDN,mBAAU0B,mBAAmBb,YAAaR,KAAMC,YAE1DQ,eAAeV,mDA3CM,IAACY"}
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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/>.
|
||||
|
||||
import Ajax from 'core/ajax';
|
||||
import Templates from 'core/templates';
|
||||
import PendingJS from 'core/pending';
|
||||
|
||||
/**
|
||||
* Enhancements for the step definitions page.
|
||||
*
|
||||
* @module tool_behat/steps
|
||||
* @copyright 2022 Catalyst IT EU
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Call the get_entity_generator web service function
|
||||
*
|
||||
* Takes the name of an entity generator and returns an object containing a list of the required fields.
|
||||
*
|
||||
* @param {String} entityType
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const getGeneratorEntities = (entityType) => Ajax.call([{
|
||||
methodname: 'tool_behat_get_entity_generator',
|
||||
args: {entitytype: entityType}
|
||||
}])[0];
|
||||
|
||||
/**
|
||||
* Render HTML for required fields
|
||||
*
|
||||
* Takes the entity data returned from getGeneratorEntities and renders the HTML to display the required fields.
|
||||
*
|
||||
* @param {String} entityData
|
||||
* @return {Promise}
|
||||
*/
|
||||
const getRequiredFieldsContent = (entityData) => {
|
||||
if (!entityData.required?.length) {
|
||||
return Promise.resolve({
|
||||
html: '',
|
||||
js: ''
|
||||
});
|
||||
}
|
||||
return Templates.renderForPromise('tool_behat/steprequiredfields', {fields: entityData.required});
|
||||
};
|
||||
|
||||
export const init = () => {
|
||||
// When an entity is selected in the "the following exist" step, fetch and display the required fields.
|
||||
document.addEventListener('change', async(e) => {
|
||||
const entityElement = e.target.closest('.entities');
|
||||
const stepElement = e.target.closest('.stepcontent');
|
||||
if (!entityElement || !stepElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingPromise = new PendingJS('tool_behat/steps:change');
|
||||
|
||||
const entityData = await getGeneratorEntities(e.target.value);
|
||||
const {html, js} = await getRequiredFieldsContent(entityData);
|
||||
|
||||
const stepRequiredFields = stepElement.querySelector('.steprequiredfields');
|
||||
if (stepRequiredFields) {
|
||||
await Templates.replaceNode(stepRequiredFields, html, js);
|
||||
} else {
|
||||
await Templates.appendNodeContents(stepElement, html, js);
|
||||
}
|
||||
pendingPromise.resolve();
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Return data about an entity generator.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_behat\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/externallib.php');
|
||||
|
||||
/**
|
||||
* External function for getting properties of entity generators.
|
||||
*/
|
||||
class get_entity_generator extends \external_api {
|
||||
|
||||
/**
|
||||
* Define parameters for external function.
|
||||
*
|
||||
* The parameter is either in the format 'entity' or 'component_name > entity'. There is no appropriate param type for a
|
||||
* string like this containing angle brackets, so we will do PARAM_RAW. The value will be parsed by
|
||||
* behat_data_generators::parse_entity_type, which validates the format of the parameter and throws an exception if it is not
|
||||
* correct.
|
||||
*
|
||||
* @return \external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): \external_function_parameters {
|
||||
return new \external_function_parameters([
|
||||
'entitytype' => new \external_value(PARAM_RAW, 'Entity type that can be created by a generator.'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of the required fields for a given entity type.
|
||||
*
|
||||
* @param string $entitytype
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(string $entitytype): array {
|
||||
global $CFG;
|
||||
|
||||
// Ensure we can load Behat and Facebook namespaces in behat libraries.
|
||||
require_once("{$CFG->dirroot}/vendor/autoload.php");
|
||||
require_once("{$CFG->libdir}/tests/behat/behat_data_generators.php");
|
||||
|
||||
$params = self::validate_parameters(self::execute_parameters(), ['entitytype' => $entitytype]);
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
$generators = new \behat_data_generators();
|
||||
$entity = $generators->get_entity($params['entitytype']);
|
||||
return ['required' => $entity['required']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define return values.
|
||||
*
|
||||
* Return required fields
|
||||
*
|
||||
* @return \external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): \external_single_structure {
|
||||
return new \external_single_structure([
|
||||
'required' => new \external_multiple_structure(
|
||||
new \external_value(PARAM_TEXT, 'Required field'),
|
||||
'Required fields',
|
||||
VALUE_OPTIONAL
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Define web service functions for tool_behat
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$functions = [
|
||||
'tool_behat_get_entity_generator' => [
|
||||
'classname' => 'tool_behat\\external\\get_entity_generator',
|
||||
'methodname' => 'execute',
|
||||
'description' => 'Get the generator details for an entity',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'capabilities' => 'moodle/site:config'
|
||||
]
|
||||
];
|
||||
@@ -56,6 +56,7 @@ if ($components) {
|
||||
$form = new steps_definitions_form(null, array('components' => $componentswithsteps));
|
||||
|
||||
// Output contents.
|
||||
$PAGE->requires->js_call_amd('tool_behat/steps', 'init');
|
||||
$renderer = $PAGE->get_renderer('tool_behat');
|
||||
echo $renderer->render_stepsdefinitions($steps, $form);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/behat/classes/behat_generator_base.php');
|
||||
|
||||
/**
|
||||
* Renderer for behat tool web features
|
||||
*
|
||||
@@ -106,6 +108,32 @@ class tool_behat_renderer extends plugin_renderer_base {
|
||||
},
|
||||
$stepsdefinitions
|
||||
);
|
||||
|
||||
$elementstrings = [];
|
||||
$count = 1;
|
||||
$stepsdefinitions = preg_replace_callback('/(the following ")ELEMENT\d?_STRING(" exist:)/',
|
||||
function($matches) use (&$elementstrings, &$count) {
|
||||
// Replace element type arguments with a user-friendly select.
|
||||
if (empty($elementstrings)) {
|
||||
$behatgenerators = new behat_data_generators();
|
||||
$componententities = $behatgenerators->get_all_entities();
|
||||
ksort($componententities);
|
||||
$elementstrings = [];
|
||||
foreach ($componententities as $component => $entities) {
|
||||
asort($entities);
|
||||
foreach ($entities as $entity) {
|
||||
$string = ($component === 'core') ? $entity : $component . ' > ' . $entity;
|
||||
$elementstrings[$string] = $string;
|
||||
}
|
||||
}
|
||||
}
|
||||
$select = html_writer::select($elementstrings, 'entities' . $count, '', ['' => 'choosedots'],
|
||||
['class' => 'entities']);
|
||||
$count++;
|
||||
return $matches[1] . $select . $matches[2];
|
||||
},
|
||||
$stepsdefinitions
|
||||
);
|
||||
}
|
||||
|
||||
// Steps definitions.
|
||||
|
||||
@@ -29,3 +29,9 @@
|
||||
#page-admin-tool-behat-index .steps-definitions .stepregex {
|
||||
color: #060;
|
||||
}
|
||||
|
||||
#page-admin-tool-behat-index .steprequiredfields {
|
||||
font-weight: bold;
|
||||
font-size: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{{!
|
||||
This file is part of Moodle - https://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/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_behat/steprequiredfields
|
||||
|
||||
Display a Gherkin-style table row showing required columns for a step.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"fields": [
|
||||
"user",
|
||||
"role",
|
||||
"context"
|
||||
]
|
||||
}
|
||||
}}
|
||||
<pre class="steprequiredfields">
|
||||
|{{#fields}} {{{.}}} |{{/fields}}
|
||||
</pre>
|
||||
@@ -13,6 +13,10 @@ Feature: List the system steps definitions
|
||||
Scenario: Accessing the list
|
||||
Then I should see "Step definitions"
|
||||
And I should not see "There aren't steps definitions matching this filter"
|
||||
And I should not see "the following \"ELEMENT_STRING\" exist:"
|
||||
And "entities1" "select" should exist
|
||||
And the "entities1" select box should contain "users"
|
||||
And the "entities1" select box should contain "mod_assign > submissions"
|
||||
|
||||
@javascript
|
||||
Scenario: Filtering by type
|
||||
@@ -34,3 +38,11 @@ Feature: List the system steps definitions
|
||||
Then I should not see "There aren't steps definitions matching this filter"
|
||||
And I should see "Checks the provided element and selector type exists in the current page."
|
||||
And I should see "Checks that an element and selector type exists in another element and selector type on the current page."
|
||||
|
||||
@javascript
|
||||
Scenario: Get required fields
|
||||
Given I set the field "entities1" to "users"
|
||||
And I should see "| username |"
|
||||
When I set the field "entities1" to "mod_quiz > user overrides"
|
||||
Then I should not see "| username |"
|
||||
And I should see "| quiz | user |"
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for get_entity_generator web service
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_behat\external;
|
||||
|
||||
/**
|
||||
* Tests for get_entity_generator web service
|
||||
*
|
||||
* @covers \tool_behat\external\get_entity_generator
|
||||
*/
|
||||
class get_entity_generator_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Log in as admin
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generator for a core entity.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_core_entity(): void {
|
||||
$generator = get_entity_generator::execute('users');
|
||||
$this->assertEquals(['required' => ['username']], $generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generator for the plugin entity.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_plugin_entity(): void {
|
||||
$generator = get_entity_generator::execute('mod_book > chapters');
|
||||
$this->assertEquals(['required' => ['book', 'title', 'content']], $generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generator for an entity with no required fields.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_no_requried(): void {
|
||||
$generator = get_entity_generator::execute('mod_forum > posts');
|
||||
$this->assertEquals(['required' => []], $generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get the generator for a core entity that does not exist.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_invalid_entity(): void {
|
||||
$this->expectException('coding_exception');
|
||||
get_entity_generator::execute('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get a generator form a plugin that does not exist.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_invalid_plugin(): void {
|
||||
$this->expectException('coding_exception');
|
||||
get_entity_generator::execute('foo > bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get a generator for an entity that does not exist, from a plugin that does.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_execute_invalid_plugin_entity(): void {
|
||||
$this->expectException('coding_exception');
|
||||
get_entity_generator::execute('mod_book > bar');
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2020061501; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version
|
||||
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -79,6 +79,19 @@ class locale {
|
||||
* @return string|false Returns the new current locale, or FALSE on error.
|
||||
*/
|
||||
protected function set_locale(int $category = LC_ALL, string $locale = '0') {
|
||||
return setlocale($category, $locale);
|
||||
if (strlen($locale) <= 255 || PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
|
||||
// We can set the whole locale all together.
|
||||
return setlocale($category, $locale);
|
||||
}
|
||||
|
||||
// Too long locale with linux or windows, let's split it into known and supported categories.
|
||||
$split = explode(';', $locale);
|
||||
foreach ($split as $element) {
|
||||
[$category, $value] = explode('=', $element);
|
||||
if (defined($category)) { // Only if the category exists, there are OS differences.
|
||||
setlocale(constant($category), $value);
|
||||
}
|
||||
}
|
||||
return setlocale(LC_ALL, 0); // Finally, return the complete configured locale.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Tests for \tool_langimport\locale class.
|
||||
*
|
||||
* @coversDefaultClass \tool_langimport\locale
|
||||
* @copyright 2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
@@ -34,6 +35,7 @@ class locale_testcase extends \advanced_testcase {
|
||||
/**
|
||||
* Test that \tool_langimport\locale::check_locale_availability() works as expected.
|
||||
*
|
||||
* @covers ::check_locale_availability
|
||||
* @return void
|
||||
*/
|
||||
public function test_check_locale_availability() {
|
||||
@@ -68,4 +70,100 @@ class locale_testcase extends \advanced_testcase {
|
||||
$this->expectException(coding_exception::class);
|
||||
$locale->check_locale_availability('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test \tool_langimport\locale::set_locale() own logic.
|
||||
*
|
||||
* We have to explicitly test set_locale() own logic and results,
|
||||
* that effectively sets the current locale, so we need to restore
|
||||
* the original locale after every test (ugly, from a purist unit test
|
||||
* point of view, but needed).
|
||||
*
|
||||
* @dataProvider set_locale_provider
|
||||
* @covers ::set_locale
|
||||
*
|
||||
* @param string $set locale string to be set.
|
||||
* @param string $ret expected results returned after setting the locale.
|
||||
*/
|
||||
public function test_set_locale(string $set, string $ret) {
|
||||
// Make set_locale() public.
|
||||
$loc = new \tool_langimport\locale();
|
||||
$rc = new \ReflectionClass(\tool_langimport\locale::class);
|
||||
$rm = $rc->getMethod('set_locale');
|
||||
$rm->setAccessible(true);
|
||||
|
||||
// Capture current locale for later restore (funnily, using the set_locale() method itself.
|
||||
$originallocale = $rm->invokeArgs($loc, [LC_ALL, 0]);
|
||||
|
||||
// Assert we get the locale defined as expected.
|
||||
$this->assertEquals($ret, $rm->invokeArgs($loc, [LC_ALL, $set]));
|
||||
|
||||
// We have finished, restore the original locale, so this doesn't affect other tests at distance.
|
||||
// (again, funnily, using the very same set_locale() method).
|
||||
$rm->invokeArgs($loc, [LC_ALL, $originallocale]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_set_locale().
|
||||
*
|
||||
* Provides a locale to be set (as 'set') and a expected return value (as 'ret'). Note that
|
||||
* some of the locales are OS dependent, so only the ones matching the OS will be provided.
|
||||
*
|
||||
* We make extensive use of the en_AU.UTF-8/English_Australia.1252 locale that is mandatory to
|
||||
* be installed in any system running PHPUnit tests.
|
||||
*/
|
||||
public function set_locale_provider(): array {
|
||||
// Let's list the allowed categories by OS.
|
||||
$bsdallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
|
||||
$winallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
|
||||
$linuxallowed = [
|
||||
'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME',
|
||||
'LC_PAPER', 'LC_NAME', 'LC_ADDRESS', 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'
|
||||
];
|
||||
|
||||
// The base locale name is also OS dependent.
|
||||
$baselocale = get_string('locale', 'langconfig');
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
$baselocale = get_string('localewin', 'langconfig');
|
||||
}
|
||||
|
||||
// Here we'll go accumulating cases to be provided.
|
||||
$cases = [];
|
||||
|
||||
// First, the simplest case, just pass a locale name, without categories.
|
||||
$cases['rawlocale'] = [
|
||||
'set' => $baselocale,
|
||||
'ret' => $baselocale,
|
||||
];
|
||||
|
||||
// Now, let's fill ALL LC categories, we should get back the locale name if all them are set with same value.
|
||||
// Note that this case is the one that, under Linux only, covers the changes performed to the set_locale() method.
|
||||
// Pick the correct categories depending on the OS.
|
||||
$oscategories = $bsdallowed; // Default to BSD/Dawrwin ones because they are the standard 6 supported by PHP.
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
$oscategories = $winallowed;
|
||||
} else if (PHP_OS_FAMILY === 'Linux') {
|
||||
$oscategories = $linuxallowed;
|
||||
}
|
||||
|
||||
$localestr = '';
|
||||
foreach ($oscategories as $category) {
|
||||
// Format is different by OS too, so let build the string conditionally.
|
||||
if (PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
|
||||
// BSD uses slashes (/) separated list of the 6 values in exact order.
|
||||
$localestr .= '/' . $baselocale;
|
||||
} else {
|
||||
// Linux/Windows use semicolon (;) separated list of category=value pairs.
|
||||
$localestr .= ';' . $category . '=' . $baselocale;
|
||||
}
|
||||
}
|
||||
$cases['allcategories'] = [
|
||||
'set' => trim($localestr, ';/'),
|
||||
'ret' => $baselocale,
|
||||
];
|
||||
|
||||
// Return all the built cases.
|
||||
return $cases;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class backup_files_edit_form extends moodleform {
|
||||
$mform->setType('component', PARAM_COMPONENT);
|
||||
|
||||
$mform->addElement('hidden', 'returnurl', $this->_customdata['returnurl']);
|
||||
$mform->setType('returnurl', PARAM_URL);
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$this->add_action_buttons(true, get_string('savechanges'));
|
||||
$this->set_data($this->_customdata['data']);
|
||||
|
||||
@@ -14,12 +14,12 @@ Feature: Block appearances
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | course | name | element |
|
||||
| survey | C1 | Test survey name | 4 |
|
||||
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add a "Survey" to section "1" and I fill the form with:
|
||||
| Name | Test survey name |
|
||||
| Survey type | ATTLS (20 item version) |
|
||||
| Description | Test survey description |
|
||||
And I add a "Book" to section "1" and I fill the form with:
|
||||
| Name | Test book name |
|
||||
| Description | Test book description |
|
||||
@@ -28,9 +28,8 @@ Feature: Block appearances
|
||||
| Chapter title | Book title |
|
||||
| Content | Book content test test |
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I am on the "Course 1" course page logged in as teacher1
|
||||
And I turn editing mode on
|
||||
And I add the "Comments" block
|
||||
And I configure the "Comments" block
|
||||
And I set the following fields to these values:
|
||||
|
||||
@@ -14,12 +14,11 @@ Feature: Block region moving
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | course | template |
|
||||
| survey | Test survey name | C1 | 4 |
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add a "Survey" to section "1" and I fill the form with:
|
||||
| Name | Test survey name |
|
||||
| Survey type | ATTLS (20 item version) |
|
||||
| Description | Test survey description |
|
||||
And I add a "Book" to section "1" and I fill the form with:
|
||||
| Name | Test book name |
|
||||
| Description | Test book description |
|
||||
|
||||
@@ -64,7 +64,7 @@ class blog_edit_external_form extends moodleform {
|
||||
$mform->setDefault('id', 0);
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_URL);
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
$mform->setDefault('returnurl', 0);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
"behat/mink-goutte-driver": "^1.3",
|
||||
"symfony/process": "^4.0 || ^5.0",
|
||||
"behat/behat": "3.11.*",
|
||||
"oleg-andreyev/mink-phpwebdriver": "^1.0.1"
|
||||
"oleg-andreyev/mink-phpwebdriver": "^1.2.1"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-0": {
|
||||
|
||||
Generated
+102
-101
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0f399055c931a91e7867d3ed8b26c3fd",
|
||||
"content-hash": "6028a65eecf888063d53e711aa91adf8",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
@@ -1003,16 +1003,16 @@
|
||||
},
|
||||
{
|
||||
"name": "oleg-andreyev/mink-phpwebdriver",
|
||||
"version": "v1.0.1",
|
||||
"version": "v1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/oleg-andreyev/MinkPhpWebDriver.git",
|
||||
"reference": "66207ad04b45ad4348dd68ab2a918da2875ae46f"
|
||||
"reference": "e265917faf79b649f4e5d4419325e02c096caec2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/oleg-andreyev/MinkPhpWebDriver/zipball/66207ad04b45ad4348dd68ab2a918da2875ae46f",
|
||||
"reference": "66207ad04b45ad4348dd68ab2a918da2875ae46f",
|
||||
"url": "https://api.github.com/repos/oleg-andreyev/MinkPhpWebDriver/zipball/e265917faf79b649f4e5d4419325e02c096caec2",
|
||||
"reference": "e265917faf79b649f4e5d4419325e02c096caec2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1021,11 +1021,12 @@
|
||||
"php-webdriver/webdriver": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8",
|
||||
"behat/mink-extension": "^2.3",
|
||||
"ext-json": "*",
|
||||
"mink/driver-testsuite": "dev-integration-branch",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"symfony/phpunit-bridge": "^5.2"
|
||||
"symfony/phpunit-bridge": "^4.4 || ^5.4 || ^6.0"
|
||||
},
|
||||
"type": "mink-driver",
|
||||
"extra": {
|
||||
@@ -1061,9 +1062,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/oleg-andreyev/MinkPhpWebDriver/issues",
|
||||
"source": "https://github.com/oleg-andreyev/MinkPhpWebDriver/tree/v1.0.1"
|
||||
"source": "https://github.com/oleg-andreyev/MinkPhpWebDriver/tree/v1.2.1"
|
||||
},
|
||||
"time": "2021-01-30T23:07:29+00:00"
|
||||
"time": "2022-11-21T15:35:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@@ -1177,16 +1178,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-webdriver/webdriver",
|
||||
"version": "1.12.1",
|
||||
"version": "1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-webdriver/php-webdriver.git",
|
||||
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a"
|
||||
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
|
||||
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
|
||||
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/6dfe5f814b796c1b5748850aa19f781b9274c36c",
|
||||
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1236,9 +1237,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
|
||||
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.1"
|
||||
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.13.1"
|
||||
},
|
||||
"time": "2022-05-03T12:16:34+00:00"
|
||||
"time": "2022-10-11T11:49:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
@@ -2914,16 +2915,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.4.12",
|
||||
"version": "v5.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1"
|
||||
"reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c072aa8f724c3af64e2c7a96b796a4863d24dba1",
|
||||
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/ea59bb0edfaf9f28d18d8791410ee0355f317669",
|
||||
"reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2993,7 +2994,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3009,7 +3010,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-17T13:18:05+00:00"
|
||||
"time": "2022-10-26T21:41:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -3470,16 +3471,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v5.4.12",
|
||||
"version": "v5.4.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447"
|
||||
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2d67c1f9a1937406a9be3171b4b22250c0a11447",
|
||||
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51",
|
||||
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3514,7 +3515,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.4.13"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3530,20 +3531,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-02T13:48:16+00:00"
|
||||
"time": "2022-09-21T19:53:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3558,7 +3559,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3596,7 +3597,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3612,20 +3613,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
|
||||
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
|
||||
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3637,7 +3638,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3677,7 +3678,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3693,20 +3694,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
|
||||
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3720,7 +3721,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3764,7 +3765,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3780,20 +3781,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3805,7 +3806,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3848,7 +3849,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3864,20 +3865,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3892,7 +3893,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3931,7 +3932,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3947,20 +3948,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3969,7 +3970,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4007,7 +4008,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4023,20 +4024,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php73",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
|
||||
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
||||
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
|
||||
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4045,7 +4046,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4086,7 +4087,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4102,20 +4103,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4124,7 +4125,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4169,7 +4170,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4185,20 +4186,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.26.0",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
|
||||
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4207,7 +4208,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4248,7 +4249,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4264,7 +4265,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
@@ -4413,16 +4414,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v5.4.12",
|
||||
"version": "v5.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058"
|
||||
"reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/2fc515e512d721bf31ea76bd02fe23ada4640058",
|
||||
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
|
||||
"reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4479,7 +4480,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/string/tree/v5.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4495,20 +4496,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-12T17:03:11+00:00"
|
||||
"time": "2022-10-05T15:16:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v4.4.45",
|
||||
"version": "v4.4.47",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "4e6b4c0dbeb04d6f004ed7f43eb0905ce8396def"
|
||||
"reference": "45036b1d53accc48fe9bab71ccd86d57eba0dd94"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/4e6b4c0dbeb04d6f004ed7f43eb0905ce8396def",
|
||||
"reference": "4e6b4c0dbeb04d6f004ed7f43eb0905ce8396def",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/45036b1d53accc48fe9bab71ccd86d57eba0dd94",
|
||||
"reference": "45036b1d53accc48fe9bab71ccd86d57eba0dd94",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4568,7 +4569,7 @@
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v4.4.45"
|
||||
"source": "https://github.com/symfony/translation/tree/v4.4.47"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4584,7 +4585,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-02T12:44:49+00:00"
|
||||
"time": "2022-10-03T15:15:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
|
||||
@@ -34,7 +34,7 @@ require_once($CFG->dirroot.'/course/lib.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT);
|
||||
$switchrole = optional_param('switchrole', -1, PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', '', PARAM_RAW);
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
|
||||
if (strpos($returnurl, '?') === false) {
|
||||
// Looks like somebody did not set proper page url, better go to course page.
|
||||
@@ -43,7 +43,7 @@ if (strpos($returnurl, '?') === false) {
|
||||
if (strpos($returnurl, $CFG->wwwroot) !== 0) {
|
||||
$returnurl = $CFG->wwwroot.$returnurl;
|
||||
}
|
||||
$returnurl = clean_param($returnurl, PARAM_URL);
|
||||
$returnurl = clean_param($returnurl, PARAM_LOCALURL);
|
||||
}
|
||||
|
||||
$PAGE->set_url('/course/switchrole.php', array('id'=>$id, 'switchrole'=>$switchrole));
|
||||
|
||||
@@ -28,9 +28,8 @@ Feature: Users can be added to multiple groups at once
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Participants"
|
||||
And I click on "Edit groups for \"Student 1\"" "link" in the "student1" "table_row"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "student1" "table_row"
|
||||
And I open the autocomplete suggestions list in the "student1" "table_row"
|
||||
And I click on "Group 1" item in the autocomplete list
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "student1" "table_row"
|
||||
And I click on "Group 2" item in the autocomplete list
|
||||
And I press the escape key
|
||||
And I click on "Save changes" "link" in the "student1" "table_row"
|
||||
|
||||
@@ -26,8 +26,7 @@ Feature: We can set the grade to pass value
|
||||
| name | Test Assignment 1 |
|
||||
| intro | Submit your online text |
|
||||
| assignsubmission_onlinetext_enabled | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I am on the "Course 1" course page logged in as teacher1
|
||||
|
||||
@javascript
|
||||
Scenario: Validate that switching the type of grading used correctly disables grade to pass
|
||||
@@ -115,11 +114,10 @@ Feature: We can set the grade to pass value
|
||||
|
||||
Scenario: Set a valid grade to pass for workshop activity
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | section | idnumber |
|
||||
| workshop | Test Workshop 1 | Test workshop | C1 | 1 | workshop1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Test Workshop 1 | C1 | workshop1 |
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I follow "Test Workshop 1"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I am on the "Test Workshop 1" "workshop activity editing" page
|
||||
And I set the following fields to these values:
|
||||
| grade | 80 |
|
||||
| Submission grade to pass | 40 |
|
||||
@@ -138,19 +136,16 @@ Feature: We can set the grade to pass value
|
||||
And the field "Grade to pass" matches value "10"
|
||||
And I set the field "Grade to pass" to "15"
|
||||
And I press "Save changes"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test Workshop 1"
|
||||
And I follow "Edit settings"
|
||||
And I am on the "Test Workshop 1" "workshop activity editing" page
|
||||
And the field "Submission grade to pass" matches value "45"
|
||||
And the field "Assessment grade to pass" matches value "15"
|
||||
|
||||
Scenario: Set an invalid grade to pass for workshop activity
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | section | idnumber |
|
||||
| workshop | Test Workshop 1 | Test workshop | C1 | 1 | workshop1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Test Workshop 1 | C1 | workshop1 |
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I follow "Test Workshop 1"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I am on the "Test Workshop 1" "workshop activity editing" page
|
||||
And I set the following fields to these values:
|
||||
| grade | 80 |
|
||||
| Submission grade to pass | 90 |
|
||||
|
||||
+7
-6
@@ -1346,12 +1346,13 @@ $string['unsupporteddbfilepertable'] = 'For full support of UTF-8 both MySQL and
|
||||
$string['unsupporteddblargeprefix'] = 'For full support of UTF-8 both MySQL and MariaDB require you to change your MySQL setting \'innodb_large_prefix\' to \'ON\'. See the documentation for further details.';
|
||||
$string['unsupporteddbstorageengine'] = 'The database storage engine being used is no longer supported.';
|
||||
$string['unsupporteddbtablerowformat'] = 'Your database has tables using Antelope as the file format. You are recommended to convert the tables to the Barracuda file format. See the documentation <a href="https://docs.moodle.org/en/cli">Administration via command line</a> for details of a tool for converting InnoDB tables to Barracuda.';
|
||||
$string['unsupportedphpversion7'] = 'PHP version 7 is not supported.';
|
||||
$string['unsupportedphpversion71'] = 'PHP version 7.1 is not supported.';
|
||||
$string['unsupportedphpversion72'] = 'PHP version 7.2 is not supported.';
|
||||
$string['unsupportedphpversion73'] = 'PHP version 7.3 is not supported.';
|
||||
$string['unsupportedphpversion74'] = 'PHP version 7.4 is not supported.';
|
||||
$string['unsupportedphpversion80'] = 'PHP version 8.0 is not supported.';
|
||||
$string['unsupportedphpversion7'] = 'PHP version 7 and higher are not supported.';
|
||||
$string['unsupportedphpversion71'] = 'PHP version 7.1 and higher are not supported.';
|
||||
$string['unsupportedphpversion72'] = 'PHP version 7.2 and higher are not supported.';
|
||||
$string['unsupportedphpversion73'] = 'PHP version 7.3 and higher are not supported.';
|
||||
$string['unsupportedphpversion74'] = 'PHP version 7.4 and higher are not supported.';
|
||||
$string['unsupportedphpversion80'] = 'PHP version 8.0 and higher are not supported.';
|
||||
$string['unsupportedphpversion81'] = 'PHP version 8.1 and higher are not supported.';
|
||||
$string['unsuspenduser'] = 'Activate user account';
|
||||
$string['updateaccounts'] = 'Update existing accounts';
|
||||
$string['updatecomponent'] = 'Update component';
|
||||
|
||||
@@ -112,6 +112,7 @@ $string['america/cayenne'] = 'America/Cayenne';
|
||||
$string['america/cayman'] = 'America/Cayman';
|
||||
$string['america/chicago'] = 'America/Chicago';
|
||||
$string['america/chihuahua'] = 'America/Chihuahua';
|
||||
$string['america/ciudad_juarez'] = 'America/Ciudad_Juarez';
|
||||
$string['america/costa_rica'] = 'America/Costa_Rica';
|
||||
$string['america/creston'] = 'America/Creston';
|
||||
$string['america/cuiaba'] = 'America/Cuiaba';
|
||||
|
||||
@@ -165,6 +165,15 @@ abstract class behat_generator_base {
|
||||
*/
|
||||
protected abstract function get_creatable_entities(): array;
|
||||
|
||||
/**
|
||||
* Get the list of available generators for this class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function get_available_generators(): array {
|
||||
return $this->get_creatable_entities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the work to generate an entity.
|
||||
*
|
||||
|
||||
@@ -440,13 +440,12 @@ trait behat_session_trait {
|
||||
if ($containerselectortype === 'NodeElement' && is_a($containerelement, NodeElement::class)) {
|
||||
// Support a NodeElement being passed in for use in step chaining.
|
||||
$containernode = $containerelement;
|
||||
$locatorexceptionmsg = $element;
|
||||
} else {
|
||||
// Gets the container, it will always be text based.
|
||||
$containernode = $this->get_text_selector_node($containerselectortype, $containerelement);
|
||||
$locatorexceptionmsg = $element . '" in the "' . $containerelement. '" "' . $containerselectortype. '"';
|
||||
}
|
||||
|
||||
$locatorexceptionmsg = $element . '" in the "' . $this->get_selector_description($containerselectortype, $containerelement);
|
||||
$exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $locatorexceptionmsg);
|
||||
|
||||
return $this->find($selectortype, $element, $exception, $containernode);
|
||||
|
||||
@@ -145,7 +145,7 @@ XPATH
|
||||
descendant::*[
|
||||
contains(concat(' ', normalize-space(@class), ' '), ' dropdown-toggle ')
|
||||
and
|
||||
contains(normalize-space(.), %locator%)
|
||||
(contains(normalize-space(.), %locator%) or descendant::*[%titleMatch%])
|
||||
]
|
||||
]
|
||||
XPATH
|
||||
|
||||
@@ -991,8 +991,9 @@ class core_user {
|
||||
$preferences['user_home_page_preference'] = array('type' => PARAM_INT, 'null' => NULL_ALLOWED, 'default' => HOMEPAGE_MY,
|
||||
'choices' => array(HOMEPAGE_SITE, HOMEPAGE_MY),
|
||||
'permissioncallback' => function ($user, $preferencename) {
|
||||
global $CFG;
|
||||
return (!empty($CFG->defaulthomepage) && ($CFG->defaulthomepage == HOMEPAGE_USER));
|
||||
global $CFG, $USER;
|
||||
return $user->id == $USER->id &&
|
||||
(!empty($CFG->defaulthomepage) && ($CFG->defaulthomepage == HOMEPAGE_USER));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -1657,3 +1657,14 @@ function restrict_php_version_74(&$result) {
|
||||
function restrict_php_version_80($result) {
|
||||
return restrict_php_version($result, '8.0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current PHP version is greater than or equal to
|
||||
* PHP version 8.1
|
||||
*
|
||||
* @param object $result an environment_results instance
|
||||
* @return bool result of version check
|
||||
*/
|
||||
function restrict_php_version_81($result) {
|
||||
return restrict_php_version($result, '8.1');
|
||||
}
|
||||
|
||||
@@ -170,4 +170,51 @@ class behat_data_generators extends behat_base {
|
||||
$instance = new $componentclass($component);
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all entities that can be created in all components using the_following_entities_exist()
|
||||
*
|
||||
* @return array
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function get_all_entities(): array {
|
||||
global $CFG;
|
||||
// Ensure the generator class is loaded.
|
||||
require_once($CFG->libdir . '/behat/classes/behat_generator_base.php');
|
||||
$componenttypes = core_component::get_component_list();
|
||||
$coregenerator = $this->get_instance_for_component('core');
|
||||
$pluginswithentities = ['core' => array_keys($coregenerator->get_available_generators())];
|
||||
foreach ($componenttypes as $components) {
|
||||
foreach ($components as $component => $componentdir) {
|
||||
try {
|
||||
$plugingenerator = $this->get_instance_for_component($component);
|
||||
$entities = array_keys($plugingenerator->get_available_generators());
|
||||
if (!empty($entities)) {
|
||||
$pluginswithentities[$component] = $entities;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// The component has no generator, skip it.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pluginswithentities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required fields for a specific creatable entity.
|
||||
*
|
||||
* @param string $entitytype
|
||||
* @return mixed
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function get_entity(string $entitytype): array {
|
||||
[$component, $entity] = $this->parse_entity_type($entitytype);
|
||||
$generator = $this->get_instance_for_component($component);
|
||||
$entities = $generator->get_available_generators();
|
||||
if (!array_key_exists($entity, $entities)) {
|
||||
throw new coding_exception('No generator for ' . $entity . ' in component ' . $component);
|
||||
}
|
||||
return $entities[$entity];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ class behat_forms extends behat_base {
|
||||
public function i_open_the_autocomplete_suggestions_list($container = null, $containertype = null) {
|
||||
$csstarget = ".form-autocomplete-downarrow";
|
||||
if ($container && $containertype) {
|
||||
$this->execute('behat_general::i_click_on', [$csstarget, 'css_element', $container, $containertype]);
|
||||
$this->execute('behat_general::i_click_on_in_the', [$csstarget, 'css_element', $container, $containertype]);
|
||||
} else {
|
||||
$this->execute('behat_general::i_click_on', [$csstarget, 'css_element']);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
require_once(__DIR__ . '/../../behat/behat_base.php');
|
||||
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Behat\Mink\Exception\ExpectationException;
|
||||
@@ -1162,20 +1163,12 @@ EOF;
|
||||
* @throws ElementNotFoundException Thrown by behat_base::find
|
||||
* @param string $element The locator of the specified selector
|
||||
* @param string $selectortype The selector type
|
||||
* @param string $containerelement The container selector type
|
||||
* @param string $containerselectortype The container locator
|
||||
* @param NodeElement|string $containerelement The locator of the container selector
|
||||
* @param string $containerselectortype The container selector type
|
||||
*/
|
||||
public function should_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) {
|
||||
// Get the container node.
|
||||
$containernode = $this->find($containerselectortype, $containerelement);
|
||||
|
||||
// Specific exception giving info about where can't we find the element.
|
||||
$containerdescription = $this->get_selector_description($containerselectortype, $containerelement);
|
||||
$locatorexceptionmsg = "{$element} not found in the {$containerdescription}}";
|
||||
$exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $locatorexceptionmsg);
|
||||
|
||||
// Looks for the requested node inside the container node.
|
||||
$this->find($selectortype, $element, $exception, $containernode);
|
||||
// Will throw an ElementNotFoundException if it does not exist.
|
||||
$this->get_node_in_container($selectortype, $element, $containerselectortype, $containerelement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1187,8 +1180,8 @@ EOF;
|
||||
* @throws ExpectationException
|
||||
* @param string $element The locator of the specified selector
|
||||
* @param string $selectortype The selector type
|
||||
* @param string $containerelement The container selector type
|
||||
* @param string $containerselectortype The container locator
|
||||
* @param NodeElement|string $containerelement The locator of the container selector
|
||||
* @param string $containerselectortype The container selector type
|
||||
*/
|
||||
public function should_not_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) {
|
||||
// Get the container node.
|
||||
@@ -2157,4 +2150,42 @@ EOF;
|
||||
// Set the list new list of editors.
|
||||
set_config('texteditors', implode(',', $list));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to check for minimal Moodle version.
|
||||
*
|
||||
* @Given the site is running Moodle version :minversion or higher
|
||||
* @param string $minversion The minimum version of Moodle required (inclusive).
|
||||
*/
|
||||
public function the_site_is_running_moodle_version_or_higher(string $minversion): void {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
$currentversion = normalize_version(get_config('', 'release'));
|
||||
|
||||
if (version_compare($currentversion, $minversion, '<')) {
|
||||
throw new Moodle\BehatExtension\Exception\SkippedException(
|
||||
'Site must be running Moodle version ' . $minversion . ' or higher'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to check for maximum Moodle version.
|
||||
*
|
||||
* @Given the site is running Moodle version :maxversion or lower
|
||||
* @param string $maxversion The maximum version of Moodle required (inclusive).
|
||||
*/
|
||||
public function the_site_is_running_moodle_version_or_lower(string $maxversion): void {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
$currentversion = normalize_version(get_config('', 'release'));
|
||||
|
||||
if (version_compare($currentversion, $maxversion, '>')) {
|
||||
throw new Moodle\BehatExtension\Exception\SkippedException(
|
||||
'Site must be running Moodle version ' . $maxversion . ' or lower'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
@core
|
||||
Feature: Check for minimum or maximimum version of Moodle
|
||||
In order adapt acceptance tests for different versions of Moodle
|
||||
As a developer
|
||||
I should be able to skip tests according to the Moodle version present on a site
|
||||
|
||||
Scenario: Minimum version too low
|
||||
Given the site is running Moodle version 99.0 or higher
|
||||
# The following steps should not be executed. If they are, the test will fail.
|
||||
When I log in as "admin"
|
||||
Then I should not see "Moodle"
|
||||
|
||||
Scenario: Maximum version too high
|
||||
Given the site is running Moodle version 3.0 or lower
|
||||
# The following steps should not be executed. If they are, the test will fail.
|
||||
When I log in as "admin"
|
||||
Then I should not see "Moodle"
|
||||
|
||||
Scenario: Minimum version OK
|
||||
Given the site is running Moodle version 3.0 or higher
|
||||
When I log in as "admin"
|
||||
Then I should see "Moodle"
|
||||
|
||||
Scenario: Maximum version OK
|
||||
Given the site is running Moodle version 99.0 or lower
|
||||
When I log in as "admin"
|
||||
Then I should see "Moodle"
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -17824,12 +17824,15 @@
|
||||
var el = _ClickableComponent.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs); // swap icon with menu item text.
|
||||
}, props), attrs);
|
||||
|
||||
el.replaceChild(createEl('span', {
|
||||
className: 'vjs-menu-item-text',
|
||||
textContent: this.localize(this.options_.label)
|
||||
}), el.querySelector('.vjs-icon-placeholder'));
|
||||
var iconplaceholder = el.querySelector('.vjs-icon-placeholder');
|
||||
if (typeof iconplaceholder === 'object' && iconplaceholder !== null) {
|
||||
el.replaceChild(_ClickableComponent.prototype.createEl.call(this, 'span', {
|
||||
className: 'vjs-menu-item-text',
|
||||
textContent: this.localize(this.options_.label)
|
||||
}), iconplaceholder);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
/**
|
||||
@@ -18894,21 +18897,17 @@
|
||||
var _proto = SubsCapsMenuItem.prototype;
|
||||
|
||||
_proto.createEl = function createEl(type, props, attrs) {
|
||||
var el = _TextTrackMenuItem.prototype.createEl.call(this, type, props, attrs);
|
||||
var parentSpan = el.querySelector('.vjs-menu-item-text');
|
||||
var el = _TextTrackMenuItem.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
|
||||
if (this.options_.track.kind === 'captions') {
|
||||
parentSpan.appendChild(createEl('span', {
|
||||
className: 'vjs-icon-placeholder'
|
||||
}, {
|
||||
'aria-hidden': true
|
||||
}));
|
||||
parentSpan.appendChild(createEl('span', {
|
||||
className: 'vjs-control-text',
|
||||
// space added as the text will visually flow with the
|
||||
// label
|
||||
textContent: " " + this.localize('Captions')
|
||||
}));
|
||||
const menuitem = el.querySelector('.vjs-menu-item-text');
|
||||
if (this.options_.track.kind === 'captions' && menuitem) {
|
||||
const icon = document.createElement("span");
|
||||
icon.className = 'vjs-icon-placeholder';
|
||||
menuitem.appendChild(icon);
|
||||
el.appendChild(menuitem);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
@@ -19059,20 +19058,18 @@
|
||||
var _proto = AudioTrackMenuItem.prototype;
|
||||
|
||||
_proto.createEl = function createEl(type, props, attrs) {
|
||||
var el = _MenuItem.prototype.createEl.call(this, type, props, attrs);
|
||||
var parentSpan = el.querySelector('.vjs-menu-item-text');
|
||||
var el = _MenuItem.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
|
||||
if (this.options_.track.kind === 'main-desc') {
|
||||
parentSpan.appendChild(_MenuItem.prototype.createEl.call(this, 'span', {
|
||||
className: 'vjs-icon-placeholder'
|
||||
}, {
|
||||
'aria-hidden': true
|
||||
}));
|
||||
parentSpan.appendChild(_MenuItem.prototype.createEl.call(this, 'span', {
|
||||
className: 'vjs-control-text',
|
||||
textContent: this.localize('Descriptions')
|
||||
}));
|
||||
}
|
||||
const menuitem = el.querySelector('.vjs-menu-item-text');
|
||||
if (this.options_.track.kind === 'main' && menuitem) {
|
||||
const icon = document.createElement("span");
|
||||
icon.className = 'vjs-icon-placeholder';
|
||||
menuitem.appendChild(icon);
|
||||
el.appendChild(menuitem);
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
@@ -42,4 +42,6 @@ Changes:
|
||||
In order to improve the validation, a couple of minor changes have been added to the video-lazy.js:
|
||||
1. Partial upgrade from VideoJS 7.17.0 for 'Subtitles' label check in 17824 - 17833
|
||||
2. Partial upgrade from VideoJS 7.17.0 for 'Captions' label check from 18897 - 18911
|
||||
3. Partial upgrade from VideoJS 7.17.0 for 'Description' label check from 19062 - 19075
|
||||
3. Partial upgrade from VideoJS 7.17.0 for 'Description' label check from 19062 - 19075
|
||||
4. Fixed the video controls not being displayed when playing a video
|
||||
5. Fixed the menu item not being displayed as expected
|
||||
@@ -262,8 +262,10 @@ Feature: Delete messages from conversations
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
And I go back in "view-conversation" message drawer
|
||||
Then I should not see "Student 2" in the "//*[@data-region='message-drawer']//div[@data-region='view-overview-favourites']" "xpath_element"
|
||||
And I send "Hi!" message to "Student 2" user
|
||||
And I go back in "view-conversation" message drawer
|
||||
And I go back in "view-search" message drawer
|
||||
And the following "private messages" exist:
|
||||
| user | contact | message |
|
||||
| student1 | student2 | Hi! |
|
||||
And I open messaging
|
||||
And I open the "Starred" conversations list
|
||||
And I should see "Student 2" in the "//*[@data-region='message-drawer']//div[@data-region='view-overview-favourites']" "xpath_element"
|
||||
And I select "Student 2" conversation in the "favourites" conversations list
|
||||
And I should see "Hi!" in the "Student 2" "core_message > Message conversation"
|
||||
|
||||
@@ -118,7 +118,8 @@ Feature: Message delete conversations
|
||||
And I should not see "Hi!" in the "Student 2" "core_message > Message conversation"
|
||||
And I go back in "view-conversation" message drawer
|
||||
And I should not see "Student 2" in the "favourites" "core_message > Message list area"
|
||||
And I send "Hi!" message to "Student 2" user
|
||||
And I go back in "view-conversation" message drawer
|
||||
And I go back in "view-search" message drawer
|
||||
And the following "private messages" exist:
|
||||
| user | contact | message |
|
||||
| student1 | student2 | Hi! |
|
||||
And I open messaging
|
||||
And I should see "Student 2" in the "favourites" "core_message > Message list area"
|
||||
|
||||
@@ -14,18 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* PHPUnit data generator tests.
|
||||
*
|
||||
* @package mod_data
|
||||
* @category phpunit
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
/**
|
||||
* PHPUnit data generator testcase.
|
||||
*
|
||||
@@ -33,8 +21,12 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @category phpunit
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \mod_data_generator
|
||||
*/
|
||||
class mod_data_generator_testcase extends advanced_testcase {
|
||||
/**
|
||||
* @covers ::create_instance
|
||||
*/
|
||||
public function test_generator() {
|
||||
global $DB;
|
||||
|
||||
@@ -72,6 +64,9 @@ class mod_data_generator_testcase extends advanced_testcase {
|
||||
$this->assertEquals(GRADE_TYPE_VALUE, $gitem->gradetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create_field
|
||||
*/
|
||||
public function test_create_field() {
|
||||
global $DB;
|
||||
|
||||
@@ -104,7 +99,6 @@ class mod_data_generator_testcase extends advanced_testcase {
|
||||
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $fieldtype) {
|
||||
|
||||
// Creating variables dynamically.
|
||||
$fieldname = 'field-' . $count;
|
||||
$record = new StdClass();
|
||||
@@ -124,10 +118,15 @@ class mod_data_generator_testcase extends advanced_testcase {
|
||||
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$fieldname = 'field-' . $i;
|
||||
$this->assertTrue(strpos($addtemplate, '[[' . $fieldname . ']]') >= 0);
|
||||
$position = strpos($addtemplate, '[[' . $fieldname . ']]');
|
||||
$this->assertIsNumeric($position);
|
||||
$this->assertGreaterThanOrEqual(0, $position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create_entry
|
||||
*/
|
||||
public function test_create_entry() {
|
||||
global $DB;
|
||||
|
||||
@@ -166,7 +165,6 @@ class mod_data_generator_testcase extends advanced_testcase {
|
||||
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $fieldtype) {
|
||||
|
||||
// Creating variables dynamically.
|
||||
$fieldname = 'field-' . $count;
|
||||
$record = new StdClass();
|
||||
@@ -174,13 +172,10 @@ class mod_data_generator_testcase extends advanced_testcase {
|
||||
$record->type = $fieldtype;
|
||||
$record->required = 1;
|
||||
|
||||
${$fieldname} = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_field($record, $data);
|
||||
$this->assertInstanceOf('data_field_' . $fieldtype, ${$fieldname});
|
||||
$this->getDataGenerator()->get_plugin_generator('mod_data')->create_field($record, $data);
|
||||
$count++;
|
||||
}
|
||||
|
||||
$this->assertEquals(count($fieldtypes), $DB->count_records('data_fields', array('dataid' => $data->id)));
|
||||
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $data->id), 'id');
|
||||
|
||||
$contents = array();
|
||||
|
||||
@@ -649,7 +649,7 @@ class mod_forum_maildigest_testcase extends advanced_testcase {
|
||||
];
|
||||
$this->queue_tasks_and_assert($expect);
|
||||
|
||||
$tasks = $DB->get_records('task_adhoc');
|
||||
$tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
|
||||
$task = reset($tasks);
|
||||
$this->assertGreaterThanOrEqual(time(), $task->nextruntime);
|
||||
}
|
||||
@@ -689,7 +689,7 @@ class mod_forum_maildigest_testcase extends advanced_testcase {
|
||||
];
|
||||
$this->queue_tasks_and_assert($expect);
|
||||
|
||||
$tasks = $DB->get_records('task_adhoc');
|
||||
$tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
|
||||
$task = reset($tasks);
|
||||
$digesttime = usergetmidnight(time(), \core_date::get_server_timezone()) + ($CFG->digestmailtime * 3600);
|
||||
$this->assertLessThanOrEqual($digesttime, $task->nextruntime);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
@mod @mod_quiz
|
||||
Feature: Several attempts in a quiz
|
||||
As a student
|
||||
In order to demonstrate what I know
|
||||
I need to be able to attempt quizzes and sometimes take multiple attempts
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | One | student1@example.com |
|
||||
| student2 | Student | One | student2@example.com |
|
||||
| teacher | Teacher | One | teacher@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| teacher | C1 | teacher |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | questiontext |
|
||||
| Test questions | truefalse | TF1 | First question |
|
||||
| Test questions | truefalse | TF2 | Second question |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | preferredbehaviour | navmethod |
|
||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | free |
|
||||
And quiz "Quiz 1" contains the following questions:
|
||||
| question | page | requireprevious |
|
||||
| TF1 | 1 | 1 |
|
||||
| TF2 | 2 | 1 |
|
||||
# Add some attempts
|
||||
And user "student1" has attempted "Quiz 1" with responses:
|
||||
| slot | response |
|
||||
| 1 | True |
|
||||
| 2 | False |
|
||||
And user "student2" has attempted "Quiz 1" with responses:
|
||||
| slot | response |
|
||||
| 1 | True |
|
||||
| 2 | True |
|
||||
# Add a second attempt by student1
|
||||
And user "student1" has attempted "Quiz 1" with responses:
|
||||
| slot | response |
|
||||
| 1 | False |
|
||||
| 2 | False |
|
||||
|
||||
@javascript
|
||||
Scenario: The redo question buttons are visible after 2 attempts are preset for student1.
|
||||
Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "student1"
|
||||
Then "Re-attempt quiz" "button" should exist
|
||||
And "1" row "Marks / 2.00" column of "quizattemptsummary" table should contain "1.00"
|
||||
And "2" row "Marks / 2.00" column of "quizattemptsummary" table should contain "0.00"
|
||||
@@ -99,9 +99,6 @@ class mod_quiz_generator extends testing_module_generator {
|
||||
/**
|
||||
* Create a quiz attempt for a particular user at a particular course.
|
||||
*
|
||||
* Currently this method can only create a first attempt for each
|
||||
* user at each quiz. TODO remove this limitation.
|
||||
*
|
||||
* @param int $quizid the quiz id (from the mdl_quit table, not cmid).
|
||||
* @param int $userid the user id.
|
||||
* @param array $forcedrandomquestions slot => questionid. Optional,
|
||||
@@ -116,12 +113,18 @@ class mod_quiz_generator extends testing_module_generator {
|
||||
// Build quiz object and load questions.
|
||||
$quizobj = quiz::create($quizid, $userid);
|
||||
|
||||
if (quiz_get_user_attempts($quizid, $userid, 'all', true)) {
|
||||
throw new coding_exception('mod_quiz_generator is currently limited to only ' .
|
||||
'be able to create one attempt for each user. (This should be fixed.)');
|
||||
$attemptnumber = 1;
|
||||
$attempt = null;
|
||||
|
||||
if ($attempts = quiz_get_user_attempts($quizid, $userid, 'all', true)) {
|
||||
// There is/are already an attempt/some attempts.
|
||||
// Take the last attempt.
|
||||
$attempt = end($attempts);
|
||||
// Take the attempt number of the last attempt and increase it.
|
||||
$attemptnumber = $attempt->attempt + 1;
|
||||
}
|
||||
|
||||
return quiz_prepare_and_start_new_attempt($quizobj, 1, null, false,
|
||||
return quiz_prepare_and_start_new_attempt($quizobj, $attemptnumber, $attempt, false,
|
||||
$forcedrandomquestions, $forcedvariants);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,31 +20,20 @@ Feature: A teacher can use activity completion to track a student progress
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
|
||||
Scenario: Require survey view
|
||||
Given I add a "Survey" to section "1" and I fill the form with:
|
||||
| Name | Test survey name |
|
||||
| Survey type | Critical incidents |
|
||||
| Description | Test survey description |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| id_completionview | 1 |
|
||||
| id_completionsubmit | 0 |
|
||||
And I log out
|
||||
When I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
Given the following "activities" exist:
|
||||
| activity | course | name | template | completion | completionview | completionsubmit |
|
||||
| survey | C1 | Test survey name | 5 | 2 | 1 | 0 |
|
||||
When I am on the "Course 1" course page logged in as student1
|
||||
And the "Test survey name" "survey" activity with "auto" completion should be marked as not complete
|
||||
And I follow "Test survey name"
|
||||
And I am on "Course 1" course homepage
|
||||
Then the "Test survey name" "survey" activity with "auto" completion should be marked as complete
|
||||
|
||||
Scenario: Require survey submission
|
||||
Given I add a "Survey" to section "1" and I fill the form with:
|
||||
| Name | Test survey name |
|
||||
| Survey type | Critical incidents |
|
||||
| Description | Test survey description |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| id_completionsubmit | 1 |
|
||||
And I log out
|
||||
When I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
Given the following "activities" exist:
|
||||
| activity | course | name | template | completion | completionsubmit |
|
||||
| survey | C1 | Test survey name | 5 | 2 | 1 |
|
||||
When I am on the "Course 1" course page logged in as student1
|
||||
And the "Test survey name" "survey" activity with "auto" completion should be marked as not complete
|
||||
And I follow "Test survey name"
|
||||
And I press "Click here to continue"
|
||||
|
||||
@@ -4,7 +4,7 @@ Feature: A teacher can set three types of survey activity
|
||||
As a teacher
|
||||
I need to set survey activities and select which survey type suits my needs
|
||||
|
||||
Scenario: Switching between the three survey types
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
@@ -15,12 +15,12 @@ Feature: A teacher can set three types of survey activity
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
When I add a "Survey" to section "1" and I fill the form with:
|
||||
| Name | Test survey name |
|
||||
| Survey type | ATTLS (20 item version) |
|
||||
| Description | Test survey description |
|
||||
And I follow "Test survey name"
|
||||
|
||||
Scenario: Switching between the three survey types
|
||||
Given the following "activities" exist:
|
||||
| activity | course | name |
|
||||
| survey | C1 | Test survey name |
|
||||
When I am on the "Test survey name" "survey activity" page
|
||||
Then I should see "Attitudes Towards Thinking and Learning"
|
||||
And I follow "Edit settings"
|
||||
And I set the following fields to these values:
|
||||
@@ -33,3 +33,15 @@ Feature: A teacher can set three types of survey activity
|
||||
And I press "Save and display"
|
||||
And I should see "In this online unit..."
|
||||
And I should see "my learning focuses on issues that interest me."
|
||||
|
||||
@javascript
|
||||
Scenario: Survey activity is created via UI
|
||||
Given I am on the "Course 1" course page
|
||||
And I turn editing mode on
|
||||
And I add a "Survey" to section "1"
|
||||
And I set the following fields to these values:
|
||||
| Name | Test survey name |
|
||||
| Description | Test survey description |
|
||||
| Survey type | Critical incidents |
|
||||
When I press "Save and return to course"
|
||||
Then I should see "Test survey name"
|
||||
|
||||
@@ -36,7 +36,7 @@ class mod_wiki_filesedit_form extends moodleform {
|
||||
$mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options);
|
||||
|
||||
$mform->addElement('hidden', 'returnurl', $data->returnurl);
|
||||
$mform->setType('returnurl', PARAM_URL);
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$mform->addElement('hidden', 'subwiki', $data->subwikiid);
|
||||
$mform->setType('subwiki', PARAM_INT);
|
||||
|
||||
@@ -21,45 +21,33 @@ Feature: Workshop submission removal
|
||||
| student3 | c1 | student |
|
||||
| teacher1 | c1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypefile |
|
||||
| workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | submissiontypefile |
|
||||
| workshop | TestWorkshop | c1 | workshop1 | 1 |
|
||||
# Teacher sets up assessment form and changes the phase to submission.
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
| id_description__idx_2_editor | |
|
||||
And I change phase in workshop "TestWorkshop" to "Submission phase"
|
||||
And I log out
|
||||
# Student1 submits.
|
||||
And I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
And I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission1 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# Student2 submits.
|
||||
And I log in as "student2"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as student2
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission2 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# Teacher allocates student3 to be reviewer of student2's submission.
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
And I am on the "TestWorkshop" "workshop activity" page logged in as teacher1
|
||||
And I allocate submissions in workshop "TestWorkshop" as:"
|
||||
| Participant | Reviewer |
|
||||
| Sam2 Student2 | Sam3 Student3 |
|
||||
And I log out
|
||||
|
||||
Scenario: Students can delete their submissions as long as the submissions are editable and not allocated for assessments
|
||||
Given I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
When I follow "Submission1"
|
||||
Then I should see "Submission1"
|
||||
And "Delete submission" "button" should exist
|
||||
@@ -70,30 +58,21 @@ Feature: Workshop submission removal
|
||||
And I should see "You have not submitted your work yet"
|
||||
|
||||
Scenario: Students cannot delete their submissions if the submissions are not editable
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as teacher1
|
||||
And I change phase in workshop "TestWorkshop" to "Closed"
|
||||
And I log out
|
||||
And I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
And I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
When I follow "Submission1"
|
||||
Then I should see "Submission1"
|
||||
And "Delete submission" "button" should not exist
|
||||
|
||||
Scenario: Students cannot delete their submissions if the submissions are allocated for assessments
|
||||
Given I log in as "student2"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as student2
|
||||
When I follow "Submission2"
|
||||
Then I should see "Submission2"
|
||||
And "Delete submission" "button" should not exist
|
||||
|
||||
Scenario: Teachers can delete submissions even if the submissions are allocated for assessments.
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as teacher1
|
||||
And "Submission1" "link" should exist
|
||||
And "Submission2" "link" should exist
|
||||
When I follow "Submission2"
|
||||
|
||||
@@ -16,16 +16,23 @@ Feature: Teachers can embed images into instructions and conclusion fields
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | course | name |
|
||||
| workshop | C1 | Workshop with embedded images |
|
||||
And I am on the "Workshop with embedded images" "workshop activity editing" page logged in as admin
|
||||
And I set the following fields to these values:
|
||||
| instructauthorseditor[format] | 1 |
|
||||
| instructreviewerseditor[format] | 1 |
|
||||
| conclusioneditor[format] | 1 |
|
||||
And I press "Save and display"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
# Upload an image into the private files.
|
||||
And I follow "Manage private files"
|
||||
And I upload "mod/workshop/tests/fixtures/moodlelogo.png" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
# Create and edit the workshop.
|
||||
When I add a "Workshop" to section "1" and I fill the form with:
|
||||
| Workshop name | Workshop with embedded images |
|
||||
And I am on the "Workshop with embedded images" "workshop activity editing" page
|
||||
# Edit the workshop.
|
||||
When I am on the "Workshop with embedded images" "workshop activity editing" page
|
||||
And I expand all fieldsets
|
||||
And I set the field "Instructions for submission" to "<p>Image test</p>"
|
||||
And I select the text in the "Instructions for submission" Atto editor
|
||||
|
||||
@@ -17,11 +17,10 @@ Feature: Provide example submission
|
||||
| user | course | role |
|
||||
| teacher1 | c1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | useexamples |
|
||||
| workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | useexamples |
|
||||
| workshop | TestWorkshop | c1 | workshop1 | 1 |
|
||||
# As a teacher, define the assessment form to be used in the workshop.
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
When I am on the "Course1" course page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
|
||||
@@ -19,8 +19,8 @@ Feature: Exporting workshop submissions and assessments to a portfolio
|
||||
| student2 | c1 | student |
|
||||
| teacher1 | c1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypefile |
|
||||
| workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | submissiontypefile |
|
||||
| workshop | TestWorkshop | c1 | workshop1 | 1 |
|
||||
# Admin needs to enable portfolio API and set a portfolio instance first.
|
||||
And I log in as "admin"
|
||||
And the following config values are set as admin:
|
||||
@@ -28,34 +28,24 @@ Feature: Exporting workshop submissions and assessments to a portfolio
|
||||
And I navigate to "Plugins > Portfolios > Manage portfolios" in site administration
|
||||
And I set portfolio instance "File download" to "Enabled and visible"
|
||||
And I click on "Save" "button"
|
||||
And I log out
|
||||
# Teacher sets up assessment form and changes the phase to submission.
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
And I change phase in workshop "TestWorkshop" to "Submission phase"
|
||||
And I log out
|
||||
# Student1 submits.
|
||||
And I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
And I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission1 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# Student2 submits.
|
||||
And I log in as "student2"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as student2
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission2 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# Teacher allocates reviewers and changes the phase to assessment.
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
And I am on the "TestWorkshop" "workshop activity" page logged in as teacher1
|
||||
And I should see "to allocate: 2"
|
||||
And I should see "Workshop submissions report"
|
||||
And I should see "Submitted (2) / not submitted (0)"
|
||||
@@ -68,12 +58,9 @@ Feature: Exporting workshop submissions and assessments to a portfolio
|
||||
And I follow "TestWorkshop"
|
||||
And I should see "to allocate: 0"
|
||||
And I change phase in workshop "TestWorkshop" to "Assessment phase"
|
||||
And I log out
|
||||
|
||||
Scenario: Students can export their own submission to a portfolio.
|
||||
Given I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
When I follow "Submission1"
|
||||
Then I should see "Submission1"
|
||||
And "Export this page" "button" should exist
|
||||
@@ -83,12 +70,9 @@ Feature: Exporting workshop submissions and assessments to a portfolio
|
||||
And I should see "Summary of your export"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "Return to where you were"
|
||||
And I log out
|
||||
|
||||
Scenario: Students can export submission they have peer-assessed.
|
||||
Given I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
Given I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
And I should see "Submission2"
|
||||
And I follow "Submission2"
|
||||
And "Export this page" "button" should exist
|
||||
@@ -98,14 +82,11 @@ Feature: Exporting workshop submissions and assessments to a portfolio
|
||||
And I should see "Summary of your export"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "Return to where you were"
|
||||
And I log out
|
||||
|
||||
Scenario: If the portfolio API is disabled, the portfolio export button is not displayed.
|
||||
Given the following config values are set as admin:
|
||||
| enableportfolios | 0 |
|
||||
When I log in as "student1"
|
||||
And I am on "Course1" course homepage
|
||||
And I follow "TestWorkshop"
|
||||
When I am on the "TestWorkshop" "workshop activity" page logged in as student1
|
||||
And I follow "Submission1"
|
||||
Then I should see "Submission1"
|
||||
And "Export this page" "button" should not exist
|
||||
|
||||
@@ -19,19 +19,17 @@ Feature: File types of the submission and feedback attachments can be limitted
|
||||
| student1 | c1 | student |
|
||||
| student2 | c1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 2 | 1 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | TestWorkshop | c1 | workshop1 | 2 | 1 |
|
||||
|
||||
@_file_upload @javascript
|
||||
Scenario: Student submission attachments obey the list of allowed file types
|
||||
# Define workshop to accept only images as submission attachments.
|
||||
Given I am on the TestWorkshop "workshop activity" page logged in as teacher1
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
Given I am on the "TestWorkshop" "workshop activity editing" page logged in as teacher1
|
||||
And I expand all fieldsets
|
||||
And I set the field "Submission attachment allowed file types" to "image"
|
||||
And I press "Save and display"
|
||||
And I change phase in workshop "TestWorkshop" to "Submission phase"
|
||||
And I log out
|
||||
# As a student, attempt to attach a non-image file.
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student1
|
||||
And I press "Add submission"
|
||||
@@ -58,8 +56,7 @@ Feature: File types of the submission and feedback attachments can be limitted
|
||||
@_file_upload @javascript
|
||||
Scenario: Overall feedback attachments obey the list of allowed file types
|
||||
# Define workshop to accept only .php files as overall feedback attachments.
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
Given I am on the "Course1" course page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
@@ -70,20 +67,17 @@ Feature: File types of the submission and feedback attachments can be limitted
|
||||
And I set the field "Feedback attachment allowed file types" to "PHP"
|
||||
And I press "Save and display"
|
||||
And I change phase in workshop "TestWorkshop" to "Submission phase"
|
||||
And I log out
|
||||
# As a student, attempt to attach an invalid file.
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student1
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission1 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# As a teacher, allocate that submission to be assessed by another student.
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as teacher1
|
||||
And I allocate submissions in workshop "TestWorkshop" as:"
|
||||
| Participant | Reviewer |
|
||||
| Sam1 Student1 | Sam2 Student2 |
|
||||
And I change phase in workshop "TestWorkshop" to "Assessment phase"
|
||||
And I log out
|
||||
# As the other student, assess the assigned submission.
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student2
|
||||
And I follow "Submission1"
|
||||
|
||||
@@ -17,8 +17,8 @@ Feature: Setting grades to pass via workshop editing form
|
||||
|
||||
Scenario: Adding a new workshop with grade to pass field set
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| workshop | Awesome workshop | Grades to pass are set here | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Awesome workshop | c1 | workshop1 |
|
||||
When I am on the "Awesome workshop" "workshop activity editing" page logged in as teacher1
|
||||
And I set the field "Submission grade to pass" to "45"
|
||||
And I set the field "Assessment grade to pass" to "10.5"
|
||||
@@ -29,14 +29,10 @@ Feature: Setting grades to pass via workshop editing form
|
||||
|
||||
@javascript
|
||||
Scenario: Grade to pass kept even with submission types without online text (MDL-64862)
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course1" course homepage with editing mode on
|
||||
When I add a "Workshop" to section "1" and I fill the form with:
|
||||
| Workshop name | Another workshop |
|
||||
| Description | Grades to pass are set here |
|
||||
| Submission grade to pass | 42 |
|
||||
| Assessment grade to pass | 10.1 |
|
||||
| submissiontypetextavailable | 0 |
|
||||
Given the following "activities" exist:
|
||||
| activity | course | name | submissiongradepass | gradinggradepass | submissiontypetextavailable |
|
||||
| workshop | c1 | Another workshop | 42 | 10.1 | 0 |
|
||||
When I am on the "Course1" course page logged in as teacher1
|
||||
Then I should not see "Adding a new Workshop"
|
||||
And I am on the "Another workshop" "workshop activity editing" page
|
||||
And the field "Submission grade to pass" matches value "42.00"
|
||||
@@ -44,16 +40,16 @@ Feature: Setting grades to pass via workshop editing form
|
||||
|
||||
Scenario: Adding a new workshop with grade to pass fields left empty
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| workshop | Another awesome workshop | No grades to pass are set here | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Another awesome workshop | c1 | workshop1 |
|
||||
When I am on the "Another awesome workshop" "workshop activity editing" page logged in as teacher1
|
||||
Then the field "Submission grade to pass" matches value "0.00"
|
||||
And the field "Assessment grade to pass" matches value "0.00"
|
||||
|
||||
Scenario: Adding a new workshop with non-numeric value of a grade to pass
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| workshop | Another awesome workshop | Invalid grade to pass is set here | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | section |
|
||||
| workshop | Another awesome workshop | c1 | workshop1 | 1 |
|
||||
When I am on the "Another awesome workshop" "workshop activity editing" page logged in as teacher1
|
||||
And I set the field "Assessment grade to pass" to "You shall not pass!"
|
||||
And I press "Save and return to course"
|
||||
@@ -62,8 +58,8 @@ Feature: Setting grades to pass via workshop editing form
|
||||
|
||||
Scenario: Adding a new workshop with invalid value of a grade to pass
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| workshop | Almost awesome workshop | Invalid grade to pass is set here | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | section |
|
||||
| workshop | Almost awesome workshop | c1 | workshop1 | 1 |
|
||||
When I am on the "Almost awesome workshop" "workshop activity editing" page logged in as teacher1
|
||||
And I set the field "Assessment grade to pass" to "10000000"
|
||||
And I press "Save and return to course"
|
||||
@@ -72,8 +68,8 @@ Feature: Setting grades to pass via workshop editing form
|
||||
|
||||
Scenario: Emptying grades to pass fields sets them to zero
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| workshop | Super awesome workshop | Grade to pass are set and then unset here | c1 | workshop1 | 1 |
|
||||
| activity | name | course | idnumber | section |
|
||||
| workshop | Super awesome workshop | c1 | workshop1 | 1 |
|
||||
When I am on the "Super awesome workshop" "workshop activity editing" page logged in as teacher1
|
||||
And I set the field "Submission grade to pass" to "59.99"
|
||||
And I set the field "Assessment grade to pass" to "0.000"
|
||||
|
||||
@@ -67,8 +67,8 @@ Feature: Submission types
|
||||
@javascript @_file_upload
|
||||
Scenario: All submission fields required
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | All required | Test workshop description | TEST | workshop1 | 2 | 2 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | All required | TEST | workshop1 | 2 | 2 |
|
||||
And I am on the "All required" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
@@ -88,8 +88,8 @@ Feature: Submission types
|
||||
|
||||
Scenario: Online text required, file attachment optional
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Optional file | Test workshop description | TEST | workshop1 | 2 | 1 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Optional file | TEST | workshop1 | 2 | 1 |
|
||||
And I am on the "Optional file" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
@@ -107,8 +107,8 @@ Feature: Submission types
|
||||
@javascript @_file_upload
|
||||
Scenario: Online text optional, file attachment required
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Optional text | Test workshop description | TEST | workshop1 | 1 | 2 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Optional text | TEST | workshop1 | 1 | 2 |
|
||||
And I am on the "Optional text" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
@@ -125,8 +125,8 @@ Feature: Submission types
|
||||
|
||||
Scenario: Online text only
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Only text | Test workshop description | TEST | workshop1 | 2 | 0 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Only text | TEST | workshop1 | 2 | 0 |
|
||||
And I am on the "Only text" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
@@ -145,8 +145,8 @@ Feature: Submission types
|
||||
@javascript @_file_upload
|
||||
Scenario: File attachment only
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Only file | Test workshop description | TEST | workshop1 | 0 | 2 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | Only file | TEST | workshop1 | 0 | 2 |
|
||||
And I am on the "Only file" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
@@ -166,8 +166,8 @@ Feature: Submission types
|
||||
@javascript @_file_upload
|
||||
Scenario: Neither submission type explicitly required
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| workshop | Neither required | Test workshop description | TEST | workshop1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Neither required | TEST | workshop1 |
|
||||
And I am on the "Neither required" "workshop activity" page
|
||||
And I follow "Switch to the submission phase"
|
||||
And I press "Continue"
|
||||
|
||||
@@ -23,17 +23,15 @@ Feature: Workshop submission and assessment
|
||||
| student4 | c1 | student |
|
||||
| teacher1 | c1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 2 | 1 |
|
||||
| activity | name | course | idnumber | submissiontypetext | submissiontypefile |
|
||||
| workshop | TestWorkshop | c1 | workshop1 | 2 | 1 |
|
||||
# teacher1 sets up assessment form and changes the phase to submission
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course1" course homepage
|
||||
When I am on the "Course1" course page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
| id_description__idx_2_editor | |
|
||||
And I change phase in workshop "TestWorkshop" to "Submission phase"
|
||||
And I log out
|
||||
# student1 submits
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student1
|
||||
Then I should see "Submit your work"
|
||||
@@ -41,21 +39,16 @@ Feature: Workshop submission and assessment
|
||||
| Title | Submission1 |
|
||||
| Submission content | Some content |
|
||||
And "//div[@class='submission-full' and contains(.,'Submission1') and contains(.,'submitted on')]" "xpath_element" should exist
|
||||
And I log out
|
||||
# student2 submits
|
||||
And I log in as "student2"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as student2
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission2 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# student3 submits
|
||||
And I log in as "student3"
|
||||
And I am on "Course1" course homepage
|
||||
And I am on the "Course1" course page logged in as student3
|
||||
And I add a submission in workshop "TestWorkshop" as:"
|
||||
| Title | Submission3 |
|
||||
| Submission content | Some content |
|
||||
And I log out
|
||||
# teacher1 allocates reviewers and changes the phase to assessment
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as teacher1
|
||||
And I should see "to allocate: 3"
|
||||
@@ -75,7 +68,6 @@ Feature: Workshop submission and assessment
|
||||
And I am on the TestWorkshop "workshop activity" page
|
||||
And I should see "to allocate: 0"
|
||||
And I change phase in workshop "TestWorkshop" to "Assessment phase"
|
||||
And I log out
|
||||
# student1 assesses work of student2 and student3
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student1
|
||||
And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 2') and contains(.,'total: 2')]" "xpath_element" should exist
|
||||
@@ -94,7 +86,6 @@ Feature: Workshop submission and assessment
|
||||
| peercomment__idx_1 | Very good |
|
||||
| Feedback for the author | No comments |
|
||||
And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 0') and contains(.,'total: 2')]" "xpath_element" should exist
|
||||
And I log out
|
||||
# student2 assesses work of student1
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student2
|
||||
And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 1') and contains(.,'total: 1')]" "xpath_element" should exist
|
||||
@@ -105,7 +96,6 @@ Feature: Workshop submission and assessment
|
||||
| peercomment__idx_1 | |
|
||||
| Feedback for the author | Keep it up |
|
||||
And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 0') and contains(.,'total: 1')]" "xpath_element" should exist
|
||||
And I log out
|
||||
# teacher1 makes sure he can see all peer grades
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as teacher1
|
||||
And I should see grade "52" for workshop participant "Sam1" set by peer "Sam2"
|
||||
|
||||
@@ -19,8 +19,8 @@ Feature: Workshop 'Late submissions are allowed' task
|
||||
| student2 | c1 | student |
|
||||
| teacher1 | c1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | latesubmissions | submisstionstart | submissionend |
|
||||
| workshop | TestWorkshop1 | TW3 with Submission deadline in future (1 Jan 2030)| c1 | workshop1 | 1 | 1514904308 | 1893369600 |
|
||||
| activity | name | course | idnumber | latesubmissions | submisstionstart | submissionend |
|
||||
| workshop | TestWorkshop1 | c1 | workshop1 | 1 | 1514904308 | 1893369600 |
|
||||
# Teacher sets up assessment form and changes the phase to submission.
|
||||
And I am on the "TestWorkshop1" "workshop activity" page logged in as teacher1
|
||||
And I edit assessment form in workshop "TestWorkshop1" as:"
|
||||
@@ -28,7 +28,6 @@ Feature: Workshop 'Late submissions are allowed' task
|
||||
| id_description__idx_1_editor | Aspect2 |
|
||||
| id_description__idx_2_editor | Aspect3 |
|
||||
And I change phase in workshop "TestWorkshop1" to "Submission phase"
|
||||
And I log out
|
||||
|
||||
@javascript
|
||||
Scenario: Student1 add his submission to TestWorkshop1 before submission deadline, but student2 does not submitt
|
||||
@@ -39,7 +38,6 @@ Feature: Workshop 'Late submissions are allowed' task
|
||||
And I add a submission in workshop "TestWorkshop1" as:"
|
||||
| Title | Submission from s1 |
|
||||
| Submission content | Some content from student1 |
|
||||
And I log out
|
||||
|
||||
# Teacher modifies submission deadline.
|
||||
When I am on the "TestWorkshop1" "workshop activity" page logged in as teacher1
|
||||
@@ -51,20 +49,17 @@ Feature: Workshop 'Late submissions are allowed' task
|
||||
And I set the field "id_submissionend_year" to "2018"
|
||||
And I click on "Save and display" "button"
|
||||
And I follow "Switch to the assessment phase"
|
||||
And I log out
|
||||
|
||||
# Student1 has already submitted and cannot see 'Late submissions are allowed'.
|
||||
When I am on the "TestWorkshop1" "workshop activity" page logged in as student1
|
||||
Then I should see "Submissions deadline:"
|
||||
And I should not see "Late submissions are allowed"
|
||||
And I log out
|
||||
|
||||
# Student2 has not submitted yet who can see 'Late submissions are allowed' text after the submission deadline.
|
||||
When I am on the "TestWorkshop1" "workshop activity" page logged in as student2
|
||||
Then I should see "Submissions deadline:"
|
||||
And I should see "Monday, 1 January 2018"
|
||||
And I should see "Late submissions are allowed"
|
||||
And I log out
|
||||
|
||||
# Teacher can see 'Late submissions are allowed' text after submission deadline.
|
||||
When I am on the "TestWorkshop1" "workshop activity" page logged in as teacher1
|
||||
|
||||
@@ -17,15 +17,14 @@ Feature: Workshop should remember collapsed/expanded sections in view page.
|
||||
| teacher1 | c1 | editingteacher |
|
||||
| student1 | c1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| workshop | Workshop 1 | Workshop 1 description | c1 | workshop1 |
|
||||
| activity | name | course | idnumber |
|
||||
| workshop | Workshop 1 | c1 | workshop1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Check section in view page can be remembered.
|
||||
Given I am on the "Workshop 1" "workshop activity" page logged in as teacher1
|
||||
When I change phase in workshop "Workshop 1" to "Submission phase"
|
||||
And I wait until the page is ready
|
||||
And I log out
|
||||
|
||||
And I am on the "Workshop 1" "workshop activity" page logged in as student1
|
||||
Then I should see "You have not submitted your work yet"
|
||||
|
||||
@@ -34,7 +34,7 @@ Feature: A teacher can put questions in categories in the question bank
|
||||
And I press "submitbutton"
|
||||
Then I should see "New Category 1 ID number newcatidnumber (0)"
|
||||
And I should see "Created as a test" in the "New Category 1" "list_item"
|
||||
And "New Category 1 [newcatidnumber]" "option" should exist in the "Parent category" "select"
|
||||
And the "Parent category" select box should contain "New Category 1 [newcatidnumber]"
|
||||
|
||||
Scenario: A question category can be edited
|
||||
When I am on the "Course 1" "core_question > course question categories" page logged in as "teacher1"
|
||||
|
||||
@@ -61,7 +61,7 @@ if ($formaction == 'bulkchange.php') {
|
||||
|
||||
$userids = optional_param_array('userid', array(), PARAM_INT);
|
||||
$default = new moodle_url('/user/index.php', ['id' => $course->id]);
|
||||
$returnurl = new moodle_url(optional_param('returnto', $default, PARAM_URL));
|
||||
$returnurl = new moodle_url(optional_param('returnto', $default, PARAM_LOCALURL));
|
||||
|
||||
if (empty($userids)) {
|
||||
$userids = optional_param_array('bulkuser', array(), PARAM_INT);
|
||||
|
||||
@@ -1538,4 +1538,36 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
|
||||
// Try to retrieve other user private files info.
|
||||
core_user_external::get_private_files_info($user2->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test verifying that update_user_preferences prevents changes to the default homepage for other users.
|
||||
*/
|
||||
public function test_update_user_preferences_homepage_permission_callback() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = self::getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$adminuser = get_admin();
|
||||
|
||||
// Allow user selection of the default homepage via preferences.
|
||||
set_config('defaulthomepage', HOMEPAGE_USER);
|
||||
|
||||
// Try to save another user's home page preference which uses the permissioncallback.
|
||||
$preferences = [
|
||||
[
|
||||
'name' => 'user_home_page_preference',
|
||||
'value' => '3',
|
||||
'userid' => $adminuser->id,
|
||||
]
|
||||
];
|
||||
$result = core_user_external::set_user_preferences($preferences);
|
||||
$result = \external_api::clean_returnvalue(core_user_external::set_user_preferences_returns(), $result);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertCount(0, $result['saved']);
|
||||
|
||||
// Verify no change to the preference, checking from DB to avoid cache.
|
||||
$this->assertEquals(null, $DB->get_field('user_preferences', 'value',
|
||||
['userid' => $adminuser->id, 'name' => 'user_home_page_preference']));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -29,9 +29,9 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2020061518.00; // 20200615 = branching date YYYYMMDD - do not modify!
|
||||
$version = 2020061519.00; // 20200615 = branching date YYYYMMDD - do not modify!
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '3.9.18 (Build: 20221114)'; // Human-friendly version name
|
||||
$release = '3.9.19 (Build: 20230116)'; // Human-friendly version name
|
||||
$branch = '39'; // This version's branch.
|
||||
$maturity = MATURITY_STABLE; // This version's maturity level.
|
||||
|
||||
Reference in New Issue
Block a user