Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f21e1443dc | |||
| dc93055e28 | |||
| d57db03d20 | |||
| bd5bcec3f1 | |||
| 261fe42c05 | |||
| 6f622e2393 | |||
| 00b9fe36c1 | |||
| e4b27dd81b | |||
| 5c9704b210 | |||
| f6f2dd5022 | |||
| 9fc5f273e0 | |||
| dd63b85ed4 | |||
| f164d03df5 | |||
| 00ccb3a314 | |||
| 88d4939f25 | |||
| e3be2fcfb6 | |||
| 3585ab5afa | |||
| b7bfc77b52 | |||
| 72d98b0dd5 | |||
| 15916a6f3b | |||
| 48256e0242 | |||
| 18013b2153 | |||
| 9da4095949 | |||
| dc399cd841 | |||
| e4a8272d9c | |||
| 6832ac123d | |||
| e892c66058 | |||
| 48637c438d | |||
| 0e64a10ecf | |||
| 0dd5b86d3f | |||
| b0f89e5b92 | |||
| c4c67cd975 | |||
| 9ae06b8dc7 | |||
| e59e39c78f | |||
| 99e20baa54 | |||
| 7c04ccfdf9 | |||
| 2f8a56eaf0 | |||
| 0a774cefb8 | |||
| 6257ac4de7 | |||
| 5f34ca7b01 | |||
| 624d027753 | |||
| b492fa8255 | |||
| 2d1c45a40e | |||
| 13000ae319 | |||
| 81dee5182b | |||
| 44ec3591c0 | |||
| 3ad36ca4f9 | |||
| ffc0155eab | |||
| 42e3f4d696 | |||
| ff446d05f6 | |||
| a213654a08 | |||
| b7947e03ff | |||
| 2c18225da4 | |||
| 67edcbd16f | |||
| a6154a1cab | |||
| eb7a2e3070 | |||
| 29a6589b8d | |||
| 219206d83e | |||
| 7391010aac | |||
| 713048a0c9 | |||
| 9f018ab557 | |||
| 8e6aeda4ba | |||
| 8af4bb6a40 | |||
| 804ae9ad72 | |||
| 75a49ff1b2 | |||
| 3931e6fe5c | |||
| 8e195adb84 | |||
| 44ab3ba8f1 | |||
| 91de19a803 | |||
| fcbd95d16d | |||
| ccb7bb2767 | |||
| 09be924480 | |||
| 9d9a626038 | |||
| 9a3cf47a77 | |||
| 1fb8bedf50 | |||
| 92b909033e | |||
| 2a36ff8dfb |
+1
-1
@@ -51,5 +51,5 @@ moodle-plugin-ci.phar
|
||||
.eslintignore
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
.phpcs.xml
|
||||
phpcs.xml
|
||||
jsconfig.json
|
||||
|
||||
@@ -39,7 +39,7 @@ module.exports = grunt => {
|
||||
{
|
||||
rule: {
|
||||
_attrs: {
|
||||
ref: './.phpcs.xml.dist',
|
||||
ref: './phpcs.xml.dist',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -52,7 +52,7 @@ module.exports = grunt => {
|
||||
});
|
||||
});
|
||||
|
||||
grunt.file.write('.phpcs.xml', toXML(config, {
|
||||
grunt.file.write('phpcs.xml', toXML(config, {
|
||||
header: true,
|
||||
indent: ' ',
|
||||
}) + "\n");
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -51,12 +51,12 @@
|
||||
<div class="form-password">
|
||||
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
|
||||
<span data-passwordunmask="editor">
|
||||
<input type="hidden"
|
||||
<input type="password"
|
||||
name="{{ name }}"
|
||||
id="{{ id }}"
|
||||
value="{{ value }}"
|
||||
data-size="{{ size }}"
|
||||
class="form-control d-inline-block"
|
||||
class="form-control d-none"
|
||||
>
|
||||
</span>
|
||||
<a href="#" data-passwordunmask="edit" title="{{ edithint }}">
|
||||
|
||||
+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 = 2021051700; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2021051701; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2021051100; // 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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +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/>.
|
||||
|
||||
/**
|
||||
* Tests for \tool_langimport\locale class.
|
||||
*
|
||||
* @package tool_langimport
|
||||
* @copyright 2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_langimport;
|
||||
|
||||
/**
|
||||
@@ -29,6 +21,7 @@ namespace tool_langimport;
|
||||
*
|
||||
* @package tool_langimport
|
||||
* @category test
|
||||
* @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
|
||||
*/
|
||||
@@ -36,6 +29,7 @@ class locale_test 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() {
|
||||
@@ -43,7 +37,7 @@ class locale_test extends \advanced_testcase {
|
||||
// - first setlocale() call which backup current locale
|
||||
// - second setlocale() call which try to set new 'es' locale
|
||||
// - third setlocale() call which restore locale.
|
||||
$mock = $this->getMockBuilder(\tool_langimport\locale::class)
|
||||
$mock = $this->getMockBuilder(locale::class)
|
||||
->onlyMethods(['set_locale'])
|
||||
->getMock();
|
||||
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', 'es', 'en'));
|
||||
@@ -56,7 +50,7 @@ class locale_test extends \advanced_testcase {
|
||||
// - first setlocale() call which backup current locale
|
||||
// - second setlocale() call which fail to set new locale
|
||||
// - third setlocale() call which restore locale.
|
||||
$mock = $this->getMockBuilder(\tool_langimport\locale::class)
|
||||
$mock = $this->getMockBuilder(locale::class)
|
||||
->onlyMethods(['set_locale'])
|
||||
->getMock();
|
||||
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', false, 'en'));
|
||||
@@ -66,8 +60,104 @@ class locale_test extends \advanced_testcase {
|
||||
$this->assertFalse($result);
|
||||
|
||||
// Test an invalid parameter.
|
||||
$locale = new \tool_langimport\locale();
|
||||
$locale = new locale();
|
||||
$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 locale();
|
||||
$rc = new \ReflectionClass(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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,14 +67,10 @@ Feature: Upload users
|
||||
@javascript
|
||||
Scenario: Upload users with custom profile fields
|
||||
# Create user profile field.
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Users > Accounts > User profile fields" in site administration
|
||||
And I click on "Create a new profile field" "link"
|
||||
And I click on "Text area" "link"
|
||||
And I set the following fields to these values:
|
||||
| Short name | superfield |
|
||||
| Name | Super field |
|
||||
And I click on "Save changes" "button"
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name |
|
||||
| text | superfield | Super field |
|
||||
And I log in as "admin"
|
||||
# Upload users.
|
||||
When I navigate to "Users > Accounts > Upload users" in site administration
|
||||
And I upload "lib/tests/fixtures/upload_users_profile.csv" file to "File" filemanager
|
||||
|
||||
@@ -62,15 +62,10 @@ Feature: availability_profile
|
||||
|
||||
@javascript
|
||||
Scenario: Test with custom user profile field
|
||||
# Add custom field.
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Users > Accounts > User profile fields" in site administration
|
||||
And I click on "Create a new profile field" "link"
|
||||
And I click on "Text input" "link"
|
||||
And I set the following fields to these values:
|
||||
| Short name | superfield |
|
||||
| Name | Super field |
|
||||
And I click on "Save changes" "button"
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name |
|
||||
| text | superfield | Super field |
|
||||
And I log in as "admin"
|
||||
|
||||
# Set field value for user.
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -15,25 +15,18 @@ Feature: Block appearances
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | description | course | idnumber | section |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 | 1 |
|
||||
| book | Test book name | Test book description | C1 | book1 | 1 |
|
||||
| activity | name | description | course | idnumber | section | template |
|
||||
| survey | Test survey name | | C1 | survey1 | 1 | 4 |
|
||||
| book | Test book name | Test book description | C1 | book1 | 1 | |
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test survey name"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Survey type | ATTLS (20 item version) |
|
||||
And I press "Save and return to course"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I follow "Test book name"
|
||||
And I set the following fields to these values:
|
||||
| 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,26 +108,16 @@ class completion_criteria_test extends \advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that enrolment timestart/timecreated are used when duration criteria is marked as completed.
|
||||
* Test that enrolment timestart are used when duration criteria is marked as completed.
|
||||
*/
|
||||
public function test_completion_criteria_duration(): void {
|
||||
public function test_completion_criteria_duration_timestart(): void {
|
||||
global $DB;
|
||||
$timestarted = 1610000000;
|
||||
$timecreated = 1620000000;
|
||||
$durationperiod = DAYSECS;
|
||||
|
||||
// Create a course and users.
|
||||
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
|
||||
|
||||
// Enrol User 1 with time start = $timestarted.
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id, 'manual', $timestarted);
|
||||
|
||||
// Enrol User 2 with an empty time start, but update the record like it was created at $timecreated.
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
|
||||
$DB->set_field('user_enrolments', 'timecreated', $timecreated, ['userid' => $user2->id]);
|
||||
$user = $this->getDataGenerator()->create_and_enrol($course, 'student', null, 'manual', $timestarted);
|
||||
|
||||
// Set completion criteria.
|
||||
$criteriadata = (object) [
|
||||
@@ -147,13 +137,49 @@ class completion_criteria_test extends \advanced_testcase {
|
||||
sleep(1);
|
||||
$task->execute();
|
||||
|
||||
// The course for User 1 is supposed to be marked as completed at $timestarted + $durationperiod.
|
||||
$ccompletion = new \completion_completion(['userid' => $user1->id, 'course' => $course->id]);
|
||||
// The course for User is supposed to be marked as completed at $timestarted + $durationperiod.
|
||||
$ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
|
||||
$this->assertEquals($timestarted + $durationperiod, $ccompletion->timecompleted);
|
||||
$this->assertTrue($ccompletion->is_complete());
|
||||
}
|
||||
|
||||
// The course for User 2 is supposed to be marked as completed at $timecreated + $durationperiod.
|
||||
$ccompletion = new \completion_completion(['userid' => $user2->id, 'course' => $course->id]);
|
||||
/**
|
||||
* Test that enrolment timecreated are used when duration criteria is marked as completed.
|
||||
*/
|
||||
public function test_completion_criteria_duration_timecreated(): void {
|
||||
global $DB;
|
||||
|
||||
$timecreated = 1620000000;
|
||||
$durationperiod = DAYSECS;
|
||||
|
||||
// Create a course and users.
|
||||
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
|
||||
|
||||
// Create and enrol user with an empty time start, but update the record like it was created at $timecreated.
|
||||
$user = $this->getDataGenerator()->create_and_enrol($course);
|
||||
$DB->set_field('user_enrolments', 'timecreated', $timecreated, ['userid' => $user->id]);
|
||||
|
||||
// Set completion criteria.
|
||||
$criteriadata = (object) [
|
||||
'id' => $course->id,
|
||||
'criteria_duration' => 1,
|
||||
'criteria_duration_days' => $durationperiod,
|
||||
];
|
||||
$criterion = new \completion_criteria_duration();
|
||||
$criterion->update_config($criteriadata);
|
||||
|
||||
// Run completion scheduled task.
|
||||
$task = new \core\task\completion_regular_task();
|
||||
$this->expectOutputRegex("/Marking complete/");
|
||||
$task->execute();
|
||||
|
||||
// Hopefully, some day MDL-33320 will be fixed and all these sleeps
|
||||
// and double cron calls in behat and unit tests will be removed.
|
||||
sleep(1);
|
||||
$task->execute();
|
||||
|
||||
// The course for user is supposed to be marked as completed at $timecreated + $durationperiod.
|
||||
$ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
|
||||
$this->assertEquals($timecreated + $durationperiod, $ccompletion->timecompleted);
|
||||
$this->assertTrue($ccompletion->is_complete());
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,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
+139
-134
@@ -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": "16fbc0e74dc2b087c7088a17baa4625e",
|
||||
"content-hash": "fa627bec8f3096efcce9cee5d645876a",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
@@ -1005,16 +1005,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.15.1",
|
||||
"version": "v4.15.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
|
||||
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
|
||||
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
|
||||
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1055,22 +1055,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
|
||||
},
|
||||
"time": "2022-09-04T07:30:47+00:00"
|
||||
"time": "2022-11-12T15:38:23+00:00"
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
@@ -1079,11 +1079,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": {
|
||||
@@ -1119,9 +1120,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",
|
||||
@@ -1236,16 +1237,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": {
|
||||
@@ -1295,22 +1296,22 @@
|
||||
],
|
||||
"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": "phpunit/php-code-coverage",
|
||||
"version": "9.2.17",
|
||||
"version": "9.2.23",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
|
||||
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
|
||||
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
|
||||
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1366,7 +1367,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1374,7 +1375,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-30T12:24:04+00:00"
|
||||
"time": "2022-12-28T12:41:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@@ -1619,16 +1620,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.24",
|
||||
"version": "9.5.26",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5"
|
||||
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
|
||||
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
|
||||
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1650,14 +1651,14 @@
|
||||
"phpunit/php-timer": "^5.0.2",
|
||||
"sebastian/cli-parser": "^1.0.1",
|
||||
"sebastian/code-unit": "^1.0.6",
|
||||
"sebastian/comparator": "^4.0.5",
|
||||
"sebastian/comparator": "^4.0.8",
|
||||
"sebastian/diff": "^4.0.3",
|
||||
"sebastian/environment": "^5.1.3",
|
||||
"sebastian/exporter": "^4.0.3",
|
||||
"sebastian/exporter": "^4.0.5",
|
||||
"sebastian/global-state": "^5.0.1",
|
||||
"sebastian/object-enumerator": "^4.0.3",
|
||||
"sebastian/resource-operations": "^3.0.3",
|
||||
"sebastian/type": "^3.1",
|
||||
"sebastian/type": "^3.2",
|
||||
"sebastian/version": "^3.0.2"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -1701,7 +1702,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1711,9 +1712,13 @@
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-30T07:42:16+00:00"
|
||||
"time": "2022-10-28T06:00:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -3027,16 +3032,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": {
|
||||
@@ -3106,7 +3111,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/console/tree/v5.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3122,7 +3127,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-17T13:18:05+00:00"
|
||||
"time": "2022-10-26T21:41:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -3192,16 +3197,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v5.4.11",
|
||||
"version": "v5.4.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "a8b9251016e9476db73e25fa836904bc0bf74c62"
|
||||
"reference": "24cf522668845391c0542bc1de496366072a6d0e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a8b9251016e9476db73e25fa836904bc0bf74c62",
|
||||
"reference": "a8b9251016e9476db73e25fa836904bc0bf74c62",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/24cf522668845391c0542bc1de496366072a6d0e",
|
||||
"reference": "24cf522668845391c0542bc1de496366072a6d0e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3261,7 +3266,7 @@
|
||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.11"
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.13"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3277,7 +3282,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-20T13:00:38+00:00"
|
||||
"time": "2022-08-30T19:10:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -3586,16 +3591,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": {
|
||||
@@ -3630,7 +3635,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": [
|
||||
{
|
||||
@@ -3646,20 +3651,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": {
|
||||
@@ -3674,7 +3679,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3712,7 +3717,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": [
|
||||
{
|
||||
@@ -3728,20 +3733,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": {
|
||||
@@ -3753,7 +3758,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3793,7 +3798,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": [
|
||||
{
|
||||
@@ -3809,20 +3814,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": {
|
||||
@@ -3836,7 +3841,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3880,7 +3885,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": [
|
||||
{
|
||||
@@ -3896,20 +3901,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": {
|
||||
@@ -3921,7 +3926,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -3964,7 +3969,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": [
|
||||
{
|
||||
@@ -3980,20 +3985,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": {
|
||||
@@ -4008,7 +4013,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4047,7 +4052,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": [
|
||||
{
|
||||
@@ -4063,20 +4068,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": {
|
||||
@@ -4085,7 +4090,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4123,7 +4128,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": [
|
||||
{
|
||||
@@ -4139,20 +4144,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": {
|
||||
@@ -4161,7 +4166,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4202,7 +4207,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": [
|
||||
{
|
||||
@@ -4218,20 +4223,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": {
|
||||
@@ -4240,7 +4245,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4285,7 +4290,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": [
|
||||
{
|
||||
@@ -4301,20 +4306,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": {
|
||||
@@ -4323,7 +4328,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.26-dev"
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -4364,7 +4369,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": [
|
||||
{
|
||||
@@ -4380,7 +4385,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
@@ -4529,16 +4534,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": {
|
||||
@@ -4595,7 +4600,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/string/tree/v5.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4611,20 +4616,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-12T17:03:11+00:00"
|
||||
"time": "2022-10-05T15:16:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v5.4.12",
|
||||
"version": "v5.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "42ecc77eb4f229ce2df702a648ec93b8478d76ae"
|
||||
"reference": "f0ed07675863aa6e3939df8b1bc879450b585cab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/42ecc77eb4f229ce2df702a648ec93b8478d76ae",
|
||||
"reference": "42ecc77eb4f229ce2df702a648ec93b8478d76ae",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/f0ed07675863aa6e3939df8b1bc879450b585cab",
|
||||
"reference": "f0ed07675863aa6e3939df8b1bc879450b585cab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4692,7 +4697,7 @@
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/translation/tree/v5.4.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4708,7 +4713,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-02T15:52:22+00:00"
|
||||
"time": "2022-10-07T08:01:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
@@ -4790,16 +4795,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.4.12",
|
||||
"version": "v5.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c"
|
||||
"reference": "e83fe9a72011f07c662da46a05603d66deeeb487"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
|
||||
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/e83fe9a72011f07c662da46a05603d66deeeb487",
|
||||
"reference": "e83fe9a72011f07c662da46a05603d66deeeb487",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4845,7 +4850,7 @@
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.4.12"
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.4.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4861,7 +4866,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-02T15:52:22+00:00"
|
||||
"time": "2022-10-03T15:15:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -35,9 +35,8 @@ Feature: Rename roles within a course
|
||||
And I should see "Learner (Student)" in the ".form-autocomplete-suggestions" "css_element"
|
||||
And I press the escape key
|
||||
And I set the field "Type or select..." in the "Filter 1" "fieldset" to "Tutor (Non-editing teacher)"
|
||||
|
||||
And I click on "Student 1's role assignments" "link"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "Student 1" "table_row"
|
||||
And I open the autocomplete suggestions list in the "Student 1" "table_row"
|
||||
And "Tutor (Non-editing teacher)" "autocomplete_suggestions" should exist
|
||||
And I click on "Cancel" "link"
|
||||
And I press "Enrol users"
|
||||
|
||||
@@ -76,9 +76,9 @@ function xmldb_enrol_lti_upgrade($oldversion) {
|
||||
$sql = "SELECT lu.id, lc.secret
|
||||
FROM {enrol_lti_users} lu
|
||||
JOIN {enrol_lti_lti2_consumer} lc
|
||||
ON (lu.consumerkey = lc.consumerkey256)
|
||||
ON (" . $DB->sql_compare_text('lu.consumerkey', 255) . " = lc.consumerkey256)
|
||||
WHERE lc.ltiversion = :ltiversion
|
||||
AND lu.consumersecret != lc.secret
|
||||
AND " . $DB->sql_compare_text('lu.consumersecret') . " != lc.secret
|
||||
AND lu.lastaccess IS NOT NULL";
|
||||
$affectedltiusersrs = $DB->get_recordset_sql($sql, ['ltiversion' => 'LTI-2p0']);
|
||||
foreach ($affectedltiusersrs as $ltiuser) {
|
||||
@@ -98,7 +98,7 @@ function xmldb_enrol_lti_upgrade($oldversion) {
|
||||
$sql = "SELECT lu.id, lc.secret
|
||||
FROM {enrol_lti_users} lu
|
||||
JOIN {enrol_lti_lti2_consumer} lc
|
||||
ON (lu.consumerkey = lc.consumerkey256)
|
||||
ON (" . $DB->sql_compare_text('lu.consumerkey', 255) . " = lc.consumerkey256)
|
||||
WHERE lu.consumersecret IS NULL
|
||||
AND lu.lastaccess IS NOT NULL";
|
||||
$affectedltiusersrs = $DB->get_recordset_sql($sql);
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -36,7 +36,7 @@ $string['cannotcreatelangdir'] = 'langディレクトリを作成できません
|
||||
$string['cannotcreatetempdir'] = 'tempディレクトリを作成できません。';
|
||||
$string['cannotdownloadcomponents'] = 'コンポーネントをダウンロードできません。';
|
||||
$string['cannotdownloadzipfile'] = 'ZIPファイルをダウンロードできません。';
|
||||
$string['cannotfindcomponent'] = 'コンポーネントを見つけることができません。';
|
||||
$string['cannotfindcomponent'] = 'コンポーネントが見つかりません。';
|
||||
$string['cannotsavemd5file'] = 'mp5ファイルを保存できません。';
|
||||
$string['cannotsavezipfile'] = 'ZIPファイルを保存できません。';
|
||||
$string['cannotunzipfile'] = 'ZIPファイルを展開できません。';
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['thislanguage'] = 'Luganda';
|
||||
@@ -89,7 +89,7 @@ $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
|
||||
$string['welcomep20'] = 'Você está vendo esa página pois instalou com sucesso o pacote<strong>{$a->packname} {$a->packversion}</strong>. Parabéns!';
|
||||
$string['welcomep30'] = 'Esta versão do <strong>{$a->installername}</strong> inclui as aplicações para a criação de um ambiente em que o <strong>Moodle</strong> possa operar:';
|
||||
$string['welcomep40'] = 'O pacote inclui também o <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
|
||||
$string['welcomep50'] = 'O uso das aplicações incluídas neste pacote é regulamentado pelas respectivas licenças. O instalador completo <strong>{$a->installername}</strong> é <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> e é distribuído com uma licença <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>.';
|
||||
$string['welcomep60'] = 'As seguinte páginas guiam passo a passo a configuração de <strong>Moodle</strong> no seu computador. Você pode usar a configuração padrão ou alterá-las de acordo com as suas necessidades.';
|
||||
$string['welcomep50'] = 'O uso de todos os aplicativos deste pacote é regulamentado por suas respectivas licenças. O pacote completo <strong>{$a->installername}</strong> é <a href="https://www.opensource.org/docs/definition_plain.html">código aberto</a> e é distribuído sob a licença <a href="https://www.gnu.org/copyleft/gpl.html">GPL</a>.';
|
||||
$string['welcomep60'] = 'As páginas a seguir conduzirão você por algumas etapas para configurar e instalar o <strong>Moodle</strong> facilmente em seu computador. Você pode aceitar as configurações padrão ou, opcionalmente, alterá-las para atender às suas próprias necessidades.';
|
||||
$string['welcomep70'] = 'Clique no botão "Próximo" abaixo para continuar a configuração do <strong>Moodle</strong>.';
|
||||
$string['wwwroot'] = 'Endereço web';
|
||||
|
||||
@@ -33,12 +33,12 @@ $string['clianswerno'] = 'n';
|
||||
$string['cliansweryes'] = 'd';
|
||||
$string['cliincorrectvalueerror'] = 'Eroare, valoare incorectă "{$a->value}" pentru "{$a->option}"';
|
||||
$string['cliincorrectvalueretry'] = 'Valoare incorectă, încercaţi din nou';
|
||||
$string['clitypevalue'] = 'introduceţi valoarea';
|
||||
$string['clitypevaluedefault'] = 'introduceţi valoarea, apăsaţi Enter pentru a folosi valoarea implicită ({$a})';
|
||||
$string['clitypevalue'] = 'introdu valoarea';
|
||||
$string['clitypevaluedefault'] = 'introdu valoarea, apasă Enter pentru a folosi valoarea implicită ({$a})';
|
||||
$string['cliunknowoption'] = 'Opţiuni necunoscute:
|
||||
{$a}
|
||||
Vă rugăm folosiţi --opţiunea Ajutor.';
|
||||
$string['cliyesnoprompt'] = 'tastați d (pentru \'da\') sau \'n\' (pentru \'nu\')';
|
||||
Te rugăm folosește--opţiunea Ajutor.';
|
||||
$string['cliyesnoprompt'] = 'tastează d (pentru \'da\') sau \'n\' (pentru \'nu\')';
|
||||
$string['environmentrequireinstall'] = 'trebuie instalat şi activat';
|
||||
$string['environmentrequireversion'] = 'versiuna necesară este {$a->needed} în timp ce dumneavoastră rulaţi versiunea {$a->current}';
|
||||
$string['upgradekeyset'] = 'Actualizează cheie (lăsați gol pentru a nu fi setat)';
|
||||
|
||||
+7
-6
@@ -1399,12 +1399,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
|
||||
|
||||
@@ -969,8 +969,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));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -1664,3 +1664,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');
|
||||
}
|
||||
|
||||
@@ -1315,6 +1315,11 @@ EOD;
|
||||
[$data['categoryid']]) + 1;
|
||||
}
|
||||
|
||||
if ($data['datatype'] === 'menu' && isset($data['param1'])) {
|
||||
// Convert new lines to the proper character.
|
||||
$data['param1'] = str_replace('\n', "\n", $data['param1']);
|
||||
}
|
||||
|
||||
// Defaults for other values.
|
||||
$defaults = [
|
||||
'description' => '',
|
||||
|
||||
@@ -575,5 +575,12 @@ class testing_generator_test extends \advanced_testcase {
|
||||
$field7 = $generator->create_custom_profile_field(
|
||||
['datatype' => 'checkbox', 'shortname' => 'areyousure', 'name' => 'Are you sure?']);
|
||||
$this->assertEquals(0, $field7->defaultdata);
|
||||
|
||||
// Check setting options for menu using \n work as expected.
|
||||
$field8 = $generator->create_custom_profile_field([
|
||||
'datatype' => 'menu', 'shortname' => 'cuisine', 'name' => 'Cuisine', 'param1' => 'French\nChinese\nLebanese',
|
||||
'defaultdata' => 'Chinese'
|
||||
]);
|
||||
$this->assertEquals("French\nChinese\nLebanese", $field8->param1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,43 @@ 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 "Home"
|
||||
|
||||
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 "Home"
|
||||
|
||||
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 "Home"
|
||||
|
||||
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 "Home"
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18040,22 +18040,20 @@
|
||||
var _proto = MenuItem.prototype;
|
||||
|
||||
_proto.createEl = function createEl(type, props, attrs) {
|
||||
var el = _ClickableComponent.prototype.createEl.call(this, type, props, attrs);
|
||||
var parentSpan = _ClickableComponent.prototype.createEl.call(this, 'li', assign({
|
||||
// The control is textual, not just an icon
|
||||
this.nonIconControl = true;
|
||||
var el = _ClickableComponent.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
|
||||
parentSpan.appendChild(_ClickableComponent.prototype.createEl.call(this, 'span', {
|
||||
className: 'vjs-icon-placeholder'
|
||||
}, {
|
||||
'aria-hidden': true
|
||||
}));
|
||||
parentSpan.appendChild(_ClickableComponent.prototype.createEl.call(this, 'span', {
|
||||
className: 'vjs-control-text',
|
||||
textContent: this.localize(this.options_.label)
|
||||
}));
|
||||
|
||||
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;
|
||||
}
|
||||
/**
|
||||
@@ -19120,23 +19118,19 @@
|
||||
var _proto = SubsCapsMenuItem.prototype;
|
||||
|
||||
_proto.createEl = function createEl(type, props, attrs) {
|
||||
var el = _TextTrackMenuItem.prototype.createEl.call(this, type, props, attrs);
|
||||
var el = _TextTrackMenuItem.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
|
||||
var parentSpan = el.querySelector('.vjs-menu-item-text');
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
return SubsCapsMenuItem;
|
||||
@@ -19285,20 +19279,17 @@
|
||||
var _proto = AudioTrackMenuItem.prototype;
|
||||
|
||||
_proto.createEl = function createEl(type, props, attrs) {
|
||||
var el = _MenuItem.prototype.createEl.call(this, type, props, attrs);
|
||||
var el = _MenuItem.prototype.createEl.call(this, 'li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
tabIndex: -1
|
||||
}, props), attrs);
|
||||
|
||||
var parentSpan = el.querySelector('.vjs-menu-item-text');
|
||||
|
||||
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;
|
||||
|
||||
@@ -67,4 +67,5 @@ 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 18043 - 18059
|
||||
2. Partial upgrade from VideoJS 7.17.0 for 'Captions' label check from 19123 - 19138
|
||||
3. Partial upgrade from VideoJS 7.17.0 for 'Description' label check from 19288 - 19302
|
||||
3. Partial upgrade from VideoJS 7.17.0 for 'Description' label check from 19288 - 19302
|
||||
4. 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"
|
||||
|
||||
@@ -23,8 +23,12 @@ namespace 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
|
||||
* @coversDefaultClass \mod_data_generator
|
||||
*/
|
||||
class generator_test extends \advanced_testcase {
|
||||
/**
|
||||
* @covers ::create_instance
|
||||
*/
|
||||
public function test_generator() {
|
||||
global $DB;
|
||||
|
||||
@@ -39,9 +43,9 @@ class generator_test extends \advanced_testcase {
|
||||
$this->assertInstanceOf('mod_data_generator', $generator);
|
||||
$this->assertEquals('data', $generator->get_modulename());
|
||||
|
||||
$generator->create_instance(array('course' => $course->id));
|
||||
$generator->create_instance(array('course' => $course->id));
|
||||
$data = $generator->create_instance(array('course' => $course->id));
|
||||
$generator->create_instance(['course' => $course->id]);
|
||||
$generator->create_instance(['course' => $course->id]);
|
||||
$data = $generator->create_instance(['course' => $course->id]);
|
||||
$this->assertEquals(3, $DB->count_records('data'));
|
||||
|
||||
$cm = get_coursemodule_from_instance('data', $data->id);
|
||||
@@ -52,16 +56,23 @@ class generator_test extends \advanced_testcase {
|
||||
$context = \context_module::instance($cm->id);
|
||||
$this->assertEquals($data->cmid, $context->instanceid);
|
||||
|
||||
// test gradebook integration using low level DB access - DO NOT USE IN PLUGIN CODE!
|
||||
$data = $generator->create_instance(array('course' => $course->id, 'assessed' => 1, 'scale' => 100));
|
||||
$gitem = $DB->get_record('grade_items', array('courseid' => $course->id, 'itemtype' => 'mod',
|
||||
'itemmodule' => 'data', 'iteminstance' => $data->id));
|
||||
// Test gradebook integration using low level DB access - DO NOT USE IN PLUGIN CODE!
|
||||
$data = $generator->create_instance(['course' => $course->id, 'assessed' => 1, 'scale' => 100]);
|
||||
$gitem = $DB->get_record('grade_items', [
|
||||
'courseid' => $course->id,
|
||||
'itemtype' => 'mod',
|
||||
'itemmodule' => 'data',
|
||||
'iteminstance' => $data->id,
|
||||
]);
|
||||
$this->assertNotEmpty($gitem);
|
||||
$this->assertEquals(100, $gitem->grademax);
|
||||
$this->assertEquals(0, $gitem->grademin);
|
||||
$this->assertEquals(GRADE_TYPE_VALUE, $gitem->gradetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create_field
|
||||
*/
|
||||
public function test_create_field() {
|
||||
global $DB;
|
||||
|
||||
@@ -77,7 +88,7 @@ class generator_test extends \advanced_testcase {
|
||||
$this->assertInstanceOf('mod_data_generator', $generator);
|
||||
$this->assertEquals('data', $generator->get_modulename());
|
||||
|
||||
$data = $generator->create_instance(array('course' => $course->id));
|
||||
$data = $generator->create_instance(['course' => $course->id]);
|
||||
$this->assertEquals(1, $DB->count_records('data'));
|
||||
|
||||
$cm = get_coursemodule_from_instance('data', $data->id);
|
||||
@@ -88,13 +99,12 @@ class generator_test extends \advanced_testcase {
|
||||
$context = \context_module::instance($cm->id);
|
||||
$this->assertEquals($data->cmid, $context->instanceid);
|
||||
|
||||
$fieldtypes = array('checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url');
|
||||
$fieldtypes = ['checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url'];
|
||||
|
||||
$count = 1;
|
||||
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $fieldtype) {
|
||||
|
||||
// Creating variables dynamically.
|
||||
$fieldname = 'field-' . $count;
|
||||
$record = new \stdClass();
|
||||
@@ -107,17 +117,22 @@ class generator_test extends \advanced_testcase {
|
||||
$count++;
|
||||
}
|
||||
|
||||
$this->assertEquals(count($fieldtypes), $DB->count_records('data_fields', array('dataid' => $data->id)));
|
||||
$this->assertEquals(count($fieldtypes), $DB->count_records('data_fields', ['dataid' => $data->id]));
|
||||
|
||||
$addtemplate = $DB->get_record('data', array('id' => $data->id), 'addtemplate');
|
||||
$addtemplate = $DB->get_record('data', ['id' => $data->id], 'addtemplate');
|
||||
$addtemplate = $addtemplate->addtemplate;
|
||||
|
||||
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;
|
||||
|
||||
@@ -130,15 +145,15 @@ class generator_test extends \advanced_testcase {
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
|
||||
|
||||
$groupa = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupA'));
|
||||
$this->getDataGenerator()->create_group_member(array('userid' => $user1->id, 'groupid' => $groupa->id));
|
||||
$groupa = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'groupA']);
|
||||
$this->getDataGenerator()->create_group_member(['userid' => $user1->id, 'groupid' => $groupa->id]);
|
||||
|
||||
/** @var mod_data_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$this->assertInstanceOf('mod_data_generator', $generator);
|
||||
$this->assertEquals('data', $generator->get_modulename());
|
||||
|
||||
$data = $generator->create_instance(array('course' => $course->id));
|
||||
$data = $generator->create_instance(['course' => $course->id]);
|
||||
$this->assertEquals(1, $DB->count_records('data'));
|
||||
|
||||
$cm = get_coursemodule_from_instance('data', $data->id);
|
||||
@@ -149,14 +164,14 @@ class generator_test extends \advanced_testcase {
|
||||
$context = \context_module::instance($cm->id);
|
||||
$this->assertEquals($data->cmid, $context->instanceid);
|
||||
|
||||
$fieldtypes = array('checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url',
|
||||
'latlong', 'file', 'picture');
|
||||
$fieldtypes = ['checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url',
|
||||
'latlong', 'file', 'picture',
|
||||
];
|
||||
|
||||
$count = 1;
|
||||
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $fieldtype) {
|
||||
|
||||
// Creating variables dynamically.
|
||||
$fieldname = 'field-' . $count;
|
||||
$record = new \stdClass();
|
||||
@@ -164,30 +179,27 @@ class generator_test 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', ['dataid' => $data->id], 'id');
|
||||
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $data->id), 'id');
|
||||
|
||||
$contents = array();
|
||||
$contents[] = array('opt1', 'opt2', 'opt3', 'opt4');
|
||||
$contents = [];
|
||||
$contents[] = ['opt1', 'opt2', 'opt3', 'opt4'];
|
||||
$contents[] = '01-01-2037'; // It should be lower than 2038, to avoid failing on 32-bit windows.
|
||||
$contents[] = 'menu1';
|
||||
$contents[] = array('multimenu1', 'multimenu2', 'multimenu3', 'multimenu4');
|
||||
$contents[] = ['multimenu1', 'multimenu2', 'multimenu3', 'multimenu4'];
|
||||
$contents[] = '12345';
|
||||
$contents[] = 'radioopt1';
|
||||
$contents[] = 'text for testing';
|
||||
$contents[] = '<p>text area testing<br /></p>';
|
||||
$contents[] = array('example.url', 'sampleurl');
|
||||
$contents[] = ['example.url', 'sampleurl'];
|
||||
$contents[] = [-31.9489873, 115.8382036]; // Latlong.
|
||||
$contents[] = 'Filename.pdf'; // File - filename.
|
||||
$contents[] = array('Cat1234.jpg', 'Cat'); // Picture - filename with alt text.
|
||||
$contents[] = ['Cat1234.jpg', 'Cat']; // Picture - filename with alt text.
|
||||
$count = 0;
|
||||
$fieldcontents = array();
|
||||
$fieldcontents = [];
|
||||
foreach ($fields as $fieldrecord) {
|
||||
$fieldcontents[$fieldrecord->id] = $contents[$count++];
|
||||
}
|
||||
@@ -195,16 +207,20 @@ class generator_test extends \advanced_testcase {
|
||||
$tags = ['Cats', 'mice'];
|
||||
|
||||
$this->setUser($user1);
|
||||
$datarecordid = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry($data,
|
||||
$fieldcontents, $groupa->id, $tags);
|
||||
$datarecordid = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry(
|
||||
$data,
|
||||
$fieldcontents,
|
||||
$groupa->id,
|
||||
$tags
|
||||
);
|
||||
|
||||
$this->assertEquals(1, $DB->count_records('data_records', array('dataid' => $data->id)));
|
||||
$this->assertEquals(count($contents), $DB->count_records('data_content', array('recordid' => $datarecordid)));
|
||||
$this->assertEquals(1, $DB->count_records('data_records', ['dataid' => $data->id]));
|
||||
$this->assertEquals(count($contents), $DB->count_records('data_content', ['recordid' => $datarecordid]));
|
||||
|
||||
$entry = $DB->get_record('data_records', array('id' => $datarecordid));
|
||||
$entry = $DB->get_record('data_records', ['id' => $datarecordid]);
|
||||
$this->assertEquals($entry->groupid, $groupa->id);
|
||||
|
||||
$contents = $DB->get_records('data_content', array('recordid' => $datarecordid), 'id');
|
||||
$contents = $DB->get_records('data_content', ['recordid' => $datarecordid], 'id');
|
||||
|
||||
$contentstartid = 0;
|
||||
$flag = 0;
|
||||
@@ -226,7 +242,9 @@ class generator_test extends \advanced_testcase {
|
||||
$this->assertEquals($contents[$contentstartid]->content1, '1');
|
||||
$this->assertEquals($contents[++$contentstartid]->content, 'http://example.url');
|
||||
$this->assertEquals($contents[$contentstartid]->content1, 'sampleurl');
|
||||
$this->assertEquals(array('Cats', 'mice'),
|
||||
array_values(\core_tag_tag::get_item_tags_array('mod_data', 'data_records', $datarecordid)));
|
||||
$this->assertEquals(
|
||||
['Cats', 'mice'],
|
||||
array_values(\core_tag_tag::get_item_tags_array('mod_data', 'data_records', $datarecordid))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ class maildigest_test 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);
|
||||
}
|
||||
@@ -693,7 +693,7 @@ class maildigest_test 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);
|
||||
@@ -746,7 +746,7 @@ class maildigest_test extends \advanced_testcase {
|
||||
$this->queue_tasks_and_assert($expect);
|
||||
|
||||
// There should now be two tasks queued.
|
||||
$tasks = $DB->get_records('task_adhoc');
|
||||
$tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
|
||||
$this->assertCount(2, $tasks);
|
||||
|
||||
// Add yet another another discussions to forum 1.
|
||||
@@ -762,7 +762,7 @@ class maildigest_test extends \advanced_testcase {
|
||||
$this->queue_tasks_and_assert($expect);
|
||||
|
||||
// There should still be two tasks queued.
|
||||
$tasks = $DB->get_records('task_adhoc');
|
||||
$tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
|
||||
$this->assertCount(2, $tasks);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -103,9 +103,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,
|
||||
@@ -120,12 +117,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
@mod @mod_scorm
|
||||
Feature: Scorm availability
|
||||
In order to control when a SCORM activity is available to students
|
||||
As a teacher
|
||||
I need be able to set availability dates for the SCORM
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@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 |
|
||||
And the following "activities" exist:
|
||||
| activity | course | name | packagefilepath | timeopen | timeclose |
|
||||
| scorm | C1 | Past SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##yesterday## | ##yesterday## |
|
||||
| scorm | C1 | Current SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##yesterday## | ##tomorrow## |
|
||||
| scorm | C1 | Future SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##tomorrow## | ##tomorrow## |
|
||||
|
||||
Scenario: Scorm activity with dates in the past should not be available.
|
||||
When I am on the "Past SCORM" "scorm activity" page logged in as "student1"
|
||||
Then the activity date in "Past SCORM" should contain "Opened:"
|
||||
And the activity date in "Past SCORM" should contain "##yesterday noon##%A, %d %B %Y, %I:%M##"
|
||||
And the activity date in "Past SCORM" should contain "Closed:"
|
||||
And the activity date in "Past SCORM" should contain "##yesterday noon##%A, %d %B %Y, %I:%M##"
|
||||
And "Enter" "button" should not exist
|
||||
And I should not see "Preview"
|
||||
And I am on the "Current SCORM" "scorm activity" page
|
||||
And the activity date in "Current SCORM" should contain "Opened:"
|
||||
And the activity date in "Current SCORM" should contain "##yesterday noon##%A, %d %B %Y, %I:%M##"
|
||||
And the activity date in "Current SCORM" should contain "Closes:"
|
||||
And the activity date in "Current SCORM" should contain "##tomorrow noon##%A, %d %B %Y, %I:%M##"
|
||||
And "Enter" "button" should exist
|
||||
And I should see "Preview"
|
||||
And I am on the "Future SCORM" "scorm activity" page
|
||||
And the activity date in "Future SCORM" should contain "Opens:"
|
||||
And the activity date in "Future SCORM" should contain "##tomorrow noon##%A, %d %B %Y, %I:%M##"
|
||||
And the activity date in "Future SCORM" should contain "Closes:"
|
||||
And the activity date in "Future SCORM" should contain "##tomorrow noon##%A, %d %B %Y, %I:%M##"
|
||||
And I should not see "Enter"
|
||||
And I should not see "Preview"
|
||||
@@ -20,24 +20,13 @@ Feature: A teacher can use activity completion to track a student progress
|
||||
|
||||
Scenario: Require survey view
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 |
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test survey name"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Survey type | Critical incidents |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| completionview | 1 |
|
||||
| completionsubmit | 0 |
|
||||
And I press "Save and return to course"
|
||||
And I follow "Test survey name"
|
||||
| activity | name | course | idnumber | template | completion | completionview | completionsubmit |
|
||||
| survey | Test survey name | C1 | survey1 | 5 | 2 | 1 | 0 |
|
||||
And I am on the "Test survey name" "survey activity" page
|
||||
# Teacher view.
|
||||
And "Test survey name" should have the "View" completion condition
|
||||
And I log out
|
||||
# Student view.
|
||||
When I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
When I am on the "Course 1" course page logged in as student1
|
||||
And the "View" completion condition of "Test survey name" is displayed as "todo"
|
||||
And I follow "Test survey name"
|
||||
And I am on "Course 1" course homepage
|
||||
@@ -45,24 +34,13 @@ Feature: A teacher can use activity completion to track a student progress
|
||||
|
||||
Scenario: Require survey submission
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 |
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test survey name"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Survey type | Critical incidents |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| completionview | 1 |
|
||||
| completionsubmit | 1 |
|
||||
And I press "Save and return to course"
|
||||
And I follow "Test survey name"
|
||||
| activity | name | course | idnumber | template | completion | completionview | completionsubmit |
|
||||
| survey | Test survey name | C1 | survey1 | 5 | 2 | 1 | 1 |
|
||||
And I am on the "Test survey name" "survey activity" page
|
||||
# Teacher view.
|
||||
And "Test survey name" should have the "Submit answers" completion condition
|
||||
And I log out
|
||||
# Student view.
|
||||
When I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
When I am on the "Course 1" course page logged in as student1
|
||||
And the "Submit answers" completion condition of "Test survey name" is displayed as "todo"
|
||||
And I follow "Test survey name"
|
||||
And the "Submit answers" completion condition of "Test survey name" is displayed as "todo"
|
||||
@@ -75,16 +53,13 @@ Feature: A teacher can use activity completion to track a student progress
|
||||
@javascript
|
||||
Scenario: Use manual completion
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | completion |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 | 1 |
|
||||
| activity | name | course | idnumber | completion |
|
||||
| survey | Test survey name | C1 | survey1 | 1 |
|
||||
And I am on "Course 1" course homepage
|
||||
# Teacher view.
|
||||
And the manual completion button for "Test survey name" should be disabled
|
||||
And I log out
|
||||
# Student view.
|
||||
When I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test survey name"
|
||||
When I am on the "Test survey name" "survey activity" page logged in as student1
|
||||
Then the manual completion button of "Test survey name" is displayed as "Mark as done"
|
||||
And I toggle the manual completion state of "Test survey name"
|
||||
And the manual completion button of "Test survey name" is displayed as "Done"
|
||||
|
||||
@@ -18,17 +18,11 @@ Feature: A teacher navigates to response reports of students
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 | 1 |
|
||||
| activity | name | course | idnumber | template |
|
||||
| survey | Test survey name | C1 | survey1 | 5 |
|
||||
|
||||
Scenario: Only questions and participants page should be available under response reports as teacher
|
||||
Given I am on the "Test survey name" "survey activity" page logged in as teacher1
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Survey type | Critical incidents |
|
||||
And I press "Save and return to course"
|
||||
And I log out
|
||||
And I am on the "Test survey name" "survey activity" page logged in as student1
|
||||
Given I am on the "Test survey name" "survey activity" page logged in as student1
|
||||
And I set the field "At what moment in class were you most engaged as a learner?" to "most engaged as student1"
|
||||
And I set the field "At what moment in class were you most distanced as a learner?" to "most distanced as student1"
|
||||
And I set the field "What action from anyone in the forums did you find most affirming or helpful?" to "most helpful student1"
|
||||
@@ -36,7 +30,6 @@ Feature: A teacher navigates to response reports of students
|
||||
And I set the field "What event surprised you most?" to "most surprised student1"
|
||||
And I press "Click here to continue"
|
||||
And I press "Continue"
|
||||
And I log out
|
||||
And I am on the "Test survey name" "survey activity" page logged in as student2
|
||||
And I set the field "At what moment in class were you most engaged as a learner?" to "most engaged as student2"
|
||||
And I set the field "At what moment in class were you most distanced as a learner?" to "most distanced as student2"
|
||||
@@ -45,7 +38,6 @@ Feature: A teacher navigates to response reports of students
|
||||
And I set the field "What event surprised you most?" to "most surprised student1"
|
||||
And I press "Click here to continue"
|
||||
And I press "Continue"
|
||||
And I log out
|
||||
When I am on the "Test survey name" "survey activity" page logged in as teacher1
|
||||
And "Summary" "link" should not exist in current page administration
|
||||
And "Scales" "link" should not exist in current page administration
|
||||
|
||||
@@ -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 |
|
||||
@@ -14,17 +14,16 @@ Feature: A teacher can set three types of survey activity
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | section |
|
||||
| survey | Test survey name | Test survey description | C1 | survey1 | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test survey name"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
|
||||
Scenario: Switching between the three survey types
|
||||
Given the following "activities" exist:
|
||||
| activity | name | course | idnumber |
|
||||
| survey | Test survey name | C1 | survey1 |
|
||||
And I am on the "Test survey name" "survey activity editing" page
|
||||
And I set the following fields to these values:
|
||||
| Survey type | ATTLS (20 item version) |
|
||||
And I press "Save and return to course"
|
||||
And I follow "Test survey name"
|
||||
And I press "Save and display"
|
||||
Then I should see "Attitudes Towards Thinking and Learning"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
@@ -37,3 +36,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 create 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 | ATTLS (20 item version) |
|
||||
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"
|
||||
|
||||
@@ -19,8 +19,8 @@ Feature: View activity completion information in the Workshop activity
|
||||
| student2 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | submissiontypefile | completion | completionview |
|
||||
| workshop | Music history | Test workshop description | C1 | 1 | 2 | 1 |
|
||||
| activity | name | course | submissiontypefile | completion | completionview |
|
||||
| workshop | Music history | C1 | 1 | 2 | 1 |
|
||||
And I am on the "Music history" "workshop activity editing" page logged in as teacher1
|
||||
And I set the following fields to these values:
|
||||
| Require grade | Submission |
|
||||
@@ -28,10 +28,9 @@ Feature: View activity completion information in the Workshop activity
|
||||
And I edit assessment form in workshop "Music history" as:"
|
||||
| id_description__idx_0_editor | Aspect1 |
|
||||
And I change phase in workshop "Music history" to "Submission phase"
|
||||
And I log out
|
||||
|
||||
Scenario: View automatic completion items as a teacher
|
||||
Given I am on the "Music history" "workshop activity" page logged in as teacher1
|
||||
Given I am on the "Music history" "workshop activity" page
|
||||
Then "Music history" should have the "Receive a grade" completion condition
|
||||
And "Music history" should have the "View" completion condition
|
||||
|
||||
@@ -44,28 +43,22 @@ Feature: View activity completion information in the Workshop activity
|
||||
And I set the field "Title" to "Pinch harmonics"
|
||||
And I set the field "Submission content" to "Satisfying to play"
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
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
|
||||
And I change phase in workshop "Music history" to "Assessment phase"
|
||||
And I allocate submissions in workshop "Music history" as:"
|
||||
| Participant | Reviewer |
|
||||
| Vinnie Student1 | Rex Student2 |
|
||||
And I log out
|
||||
# Assess the submission.
|
||||
And I am on the "Music history" "workshop activity" page logged in as student2
|
||||
And I assess submission "Pinch harmonics" in workshop "Music history" as:"
|
||||
| grade__idx_0 | 9 / 10 |
|
||||
| peercomment__idx_0 | Well done |
|
||||
And I log out
|
||||
# Evaluate and close the workshop so a grade is recorded for the student.
|
||||
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
|
||||
And I change phase in workshop "Music history" to "Grading evaluation phase"
|
||||
And I follow "Music history"
|
||||
And I click on "Re-calculate grades" "button"
|
||||
And I change phase in workshop "Music history" to "Closed"
|
||||
And I log out
|
||||
# Confirm completion condition is updated.
|
||||
When I am on the "Music history" "workshop activity" page logged in as student1
|
||||
Then the "View" completion condition of "Music history" is displayed as "done"
|
||||
@@ -73,14 +66,13 @@ Feature: View activity completion information in the Workshop activity
|
||||
|
||||
@javascript
|
||||
Scenario: Use manual completion
|
||||
Given I am on the "Music history" "workshop activity" page logged in as teacher1
|
||||
Given I am on the "Music history" "workshop activity" page
|
||||
And I am on the "Music history" "workshop activity editing" page
|
||||
And I expand all fieldsets
|
||||
And I set the field "Completion tracking" to "Students can manually mark the activity as completed"
|
||||
And I press "Save and display"
|
||||
# Teacher view
|
||||
And the manual completion button for "Music history" should be disabled
|
||||
And I log out
|
||||
# Student view.
|
||||
When I am on the "Music history" "workshop activity" page logged in as student1
|
||||
Then the manual completion button of "Music history" is displayed as "Mark as done"
|
||||
|
||||
@@ -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"
|
||||
@@ -139,7 +129,6 @@ Feature: Workshop submission and assessment
|
||||
And I should see "32" in the "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam1')]]/td[contains(concat(' ', normalize-space(@class), ' '), ' submissiongrade ')]" "xpath_element"
|
||||
And I should see "16" in the "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam1')]]/td[contains(concat(' ', normalize-space(@class), ' '), ' gradinggrade ')]" "xpath_element"
|
||||
And I change phase in workshop "TestWorkshop" to "Closed"
|
||||
And I log out
|
||||
|
||||
# student1 looks at the activity
|
||||
And I am on the TestWorkshop "workshop activity" page logged in as student1
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -241,3 +241,27 @@ Feature: Custom profile fields should be visible and editable by those with the
|
||||
And I should not see "notvisible_field_information"
|
||||
|
||||
And I should not see "Edit profile"
|
||||
|
||||
@javascript
|
||||
Scenario: Menu profile field's default data works as expected when editing user profile
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name | visible | param1 | defaultdata |
|
||||
| menu | menufield | Menu field | 2 | OptA\nOptB\nOptC | OptB |
|
||||
And I log in as "userwithinformation"
|
||||
When I follow "Profile" in the user menu
|
||||
And I click on "Edit profile" "link" in the "region-main" "region"
|
||||
Then the following fields match these values:
|
||||
| Menu field | OptB |
|
||||
|
||||
@javascript
|
||||
Scenario: Menu profile field successfully updated when editing user profile
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name | visible | param1 |
|
||||
| menu | menufield | Menu field | 2 | OptA\nOptB\nOptC |
|
||||
And I log in as "userwithinformation"
|
||||
When I follow "Profile" in the user menu
|
||||
And I click on "Edit profile" "link" in the "region-main" "region"
|
||||
And I set the following fields to these values:
|
||||
| Menu field | OptC |
|
||||
And I click on "Update profile" "button"
|
||||
Then I should see "OptC"
|
||||
|
||||
@@ -1629,4 +1629,36 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
$this->assertEquals('email', $user['extrafields'][0]['name']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = 2021051711.00; // 20210517 = branching date YYYYMMDD - do not modify!
|
||||
$version = 2021051712.00; // 20210517 = branching date YYYYMMDD - do not modify!
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '3.11.11 (Build: 20221114)';// Human-friendly version name
|
||||
$release = '3.11.12 (Build: 20230116)';// Human-friendly version name
|
||||
$branch = '311'; // This version's branch.
|
||||
$maturity = MATURITY_STABLE; // This version's maturity level.
|
||||
|
||||
Reference in New Issue
Block a user