Merge branch 'MDL-82373-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE

This commit is contained in:
Jun Pataleta 2024-07-25 11:31:43 +08:00
commit e18333d842
No known key found for this signature in database
GPG Key ID: F83510526D99E2C7
20 changed files with 161 additions and 89 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,6 +37,7 @@ import {eventTypes} from './events';
import {getString} from 'core/str';
import {prefetchStrings} from 'core/prefetch';
import {notifyFilterContentUpdated} from 'core/event';
import PendingPromise from 'core/pending';
/**
* The minimum spacing for tour step to display.
@ -486,14 +487,22 @@ const Tour = class {
return this.endTour();
}
const pendingPromise = new PendingPromise(`tool_usertours/tour:_gotoStep-${stepConfig.stepNumber}`);
if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {
stepConfig.delayed = true;
window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);
window.setTimeout(function(stepConfig, direction) {
this._gotoStep(stepConfig, direction);
pendingPromise.resolve();
}, stepConfig.delay, stepConfig, direction);
return this;
} else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {
let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
return this.gotoStep(this[fn](stepConfig.stepNumber), direction);
const fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
this.gotoStep(this[fn](stepConfig.stepNumber), direction);
pendingPromise.resolve();
return this;
}
this.hide();
@ -504,6 +513,7 @@ const Tour = class {
this.dispatchEvent(eventTypes.stepRendered, {stepConfig});
}
pendingPromise.resolve();
return this;
}
@ -823,12 +833,14 @@ const Tour = class {
left: 0,
});
const pendingPromise = new PendingPromise(`tool_usertours/tour:addStepToPage-${stepConfig.stepNumber}`);
animationTarget
.animate({
scrollTop: this.calculateScrollTop(stepConfig),
}).promise().then(function() {
this.positionStep(stepConfig);
this.revealStep(stepConfig);
pendingPromise.resolve();
return;
}.bind(this))
.catch(function() {
@ -900,6 +912,7 @@ const Tour = class {
*/
revealStep(stepConfig) {
// Fade the step in.
const pendingPromise = new PendingPromise(`tool_usertours/tour:revealStep-${stepConfig.stepNumber}`);
this.currentStepNode.fadeIn('', $.proxy(function() {
// Announce via ARIA.
this.announceStep(stepConfig);
@ -913,6 +926,7 @@ const Tour = class {
if (this.currentStepNode) {
this.currentStepNode.focus();
}
pendingPromise.resolve();
}, this), 100);
}, this));
@ -1160,6 +1174,7 @@ const Tour = class {
return this;
}
const pendingPromise = new PendingPromise('tool_usertours/tour:hide');
if (this.currentStepNode && this.currentStepNode.length) {
this.currentStepNode.hide();
if (this.currentStepPopper) {
@ -1194,17 +1209,22 @@ const Tour = class {
this.currentStepConfig = null;
}
let fadeTime = 0;
if (transition) {
fadeTime = 400;
}
// Remove the backdrop features.
$('[data-flexitour="step-background"]').remove();
$('[data-flexitour="step-backdrop"]').removeAttr('data-flexitour');
$('[data-flexitour="backdrop"]').fadeOut(fadeTime, function() {
$(this).remove();
});
const backdrop = $('[data-flexitour="backdrop"]');
if (backdrop.length) {
if (transition) {
const backdropRemovalPromise = new PendingPromise('tool_usertours/tour:hide:backdrop');
backdrop.fadeOut(400, function() {
$(this).remove();
backdropRemovalPromise.resolve();
});
} else {
backdrop.remove();
}
}
// Remove aria-describedby and tabindex attributes.
if (this.currentStepNode && this.currentStepNode.length) {
@ -1225,6 +1245,8 @@ const Tour = class {
this.currentStepNode = null;
this.currentStepPopper = null;
pendingPromise.resolve();
return this;
}

View File

@ -12,17 +12,7 @@ Feature: Delete H5P file from the content bank
And I follow "Manage private files..."
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "Files" filemanager
And I click on "Save changes" "button"
And I am on site homepage
And I turn editing mode on
And the following config values are set as admin:
| unaddableblocks | | theme_boost|
And I add the "Navigation" block if not present
And I configure the "Navigation" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
And I press "Save changes"
And I click on "Site pages" "list_item" in the "Navigation" "block"
And I click on "Content bank" "link" in the "Navigation" "block"
And I am on the "Content bank" page
And I click on "Upload" "link"
And I click on "Choose a file..." "button"
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
@ -32,14 +22,16 @@ Feature: Delete H5P file from the content bank
And I click on "Save changes" "button"
Scenario: Admins can delete content from the content bank
Given I click on "More" "button"
Given I wait "2" seconds
And I click on "More" "button"
And I should see "Delete"
And I click on "Delete" "link" in the ".cb-toolbar-container" "css_element"
And I click on "Delete" "link"
And I should see "Are you sure you want to delete the content 'content2delete.h5p'"
And I should not see "The content will only be deleted from the content bank"
And I click on "Cancel" "button" in the "Delete content" "dialogue"
Then I should see "content2delete.h5p"
And I click on "More" "button"
And I wait "2" seconds
And I click on "More" "button"
And I click on "Delete" "link" in the ".cb-toolbar-container" "css_element"
And I click on "Delete" "button" in the "Delete content" "dialogue"
And I wait until the page is ready
@ -61,20 +53,21 @@ Feature: Delete H5P file from the content bank
And I follow "Manage private files..."
And I upload "h5p/tests/fixtures/find-the-words.h5p" file to "Files" filemanager
And I click on "Save changes" "button"
When I click on "Site pages" "list_item" in the "Navigation" "block"
And I click on "Content bank" "link" in the "Navigation" "block"
When I am on the "Content bank" page
And I should see "content2delete.h5p"
And I follow "content2delete.h5p"
And I wait "2" seconds
And I click on "More" "button"
Then I should not see "Delete"
And I click on "Content bank" "link"
And I am on the "Content bank" page
And I click on "Upload" "link"
And I click on "Choose a file..." "button"
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
And I click on "find-the-words.h5p" "link"
And I click on "Select this file" "button"
And I click on "Save changes" "button"
And I click on "More" "button"
And I wait "2" seconds
And I click on "More" "button"
And I should see "Delete"
Scenario: The number of times a content is used is displayed before removing it
@ -86,10 +79,10 @@ Feature: Delete H5P file from the content bank
And I click on "Link to the file" "radio"
And I click on "Select this file" "button"
And I click on "Save changes" "button"
When I click on "Site pages" "list_item" in the "Navigation" "block"
And I click on "Content bank" "link" in the "Navigation" "block"
And I am on the "Content bank" page
And I follow "content2delete.h5p"
And I click on "More" "button"
And I wait "2" seconds
And I click on "More" "button"
And I click on "Delete" "link" in the ".cb-toolbar-container" "css_element"
Then I should see "Are you sure you want to delete the content 'content2delete.h5p'"
And I should see "The content will only be deleted from the content bank"

View File

@ -1,10 +1,10 @@
define("core_grades/gradebooksetup_forms",["exports","core_form/modalform","core/str","core/notification","core_form/changechecker"],(function(_exports,_modalform,_str,_notification,FormChangeChecker){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
define("core_grades/gradebooksetup_forms",["exports","core_form/modalform","core/str","core/notification","core_form/changechecker","core/pending"],(function(_exports,_modalform,_str,_notification,FormChangeChecker,_pending){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Prints the add item gradebook form
*
* @module core_grades
* @copyright 2023 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_notification=_interopRequireDefault(_notification),FormChangeChecker=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(FormChangeChecker);const Selectors_advancedFormLink="a.showadvancedform";_exports.init=()=>{document.addEventListener("click",(event=>{const args={};let formClass=null,title=null,trigger=null;if(event.target.closest('[data-trigger="add-item-form"]')?(event.preventDefault(),trigger=event.target.closest('[data-trigger="add-item-form"]'),formClass="core_grades\\form\\add_item",title="-1"===trigger.getAttribute("data-itemid")?(0,_str.getString)("newitem","core_grades"):(0,_str.getString)("itemsedit","core_grades"),args.itemid=trigger.getAttribute("data-itemid")):event.target.closest('[data-trigger="add-category-form"]')?(event.preventDefault(),trigger=event.target.closest('[data-trigger="add-category-form"]'),formClass="core_grades\\form\\add_category",title="-1"===trigger.getAttribute("data-category")?(0,_str.getString)("newcategory","core_grades"):(0,_str.getString)("categoryedit","core_grades"),args.category=trigger.getAttribute("data-category")):event.target.closest('[data-trigger="add-outcome-form"]')&&(event.preventDefault(),trigger=event.target.closest('[data-trigger="add-outcome-form"]'),formClass="core_grades\\form\\add_outcome",title="-1"===trigger.getAttribute("data-itemid")?(0,_str.getString)("newoutcomeitem","core_grades"):(0,_str.getString)("outcomeitemsedit","core_grades"),args.itemid=trigger.getAttribute("data-itemid")),trigger){args.courseid=trigger.getAttribute("data-courseid"),args.gpr_plugin=trigger.getAttribute("data-gprplugin");const modalForm=new _modalform.default({modalConfig:{title:title},formClass:formClass,args:args,saveButtonText:(0,_str.getString)("save","core"),returnFocus:trigger});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{event.detail.result?window.location.assign(event.detail.url):_notification.default.addNotification({type:"error",message:(0,_str.getString)("saving_failed","core_grades")})})),modalForm.show()}const showAdvancedForm=event.target.closest(Selectors_advancedFormLink);if(showAdvancedForm){event.preventDefault();const form=event.target.closest("form");form.action=showAdvancedForm.href,FormChangeChecker.disableAllChecks(),form.submit()}}))}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_notification=_interopRequireDefault(_notification),FormChangeChecker=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(FormChangeChecker),_pending=_interopRequireDefault(_pending);const Selectors_advancedFormLink="a.showadvancedform";_exports.init=()=>{document.addEventListener("click",(event=>{const triggerData=(event=>{if(event.target.closest('[data-trigger="add-item-form"]')){const trigger=event.target.closest('[data-trigger="add-item-form"]');return{trigger:trigger,formClass:"core_grades\\form\\add_item",titleKey:"-1"===trigger.getAttribute("data-itemid")?"newitem":"itemsedit",args:{itemid:trigger.getAttribute("data-itemid")}}}if(event.target.closest('[data-trigger="add-category-form"]')){const trigger=event.target.closest('[data-trigger="add-category-form"]');return{trigger:trigger,formClass:"core_grades\\form\\add_category",titleKey:"-1"===trigger.getAttribute("data-category")?"newcategory":"categoryedit",args:{category:trigger.getAttribute("data-category")}}}if(event.target.closest('[data-trigger="add-outcome-form"]')){const trigger=event.target.closest('[data-trigger="add-outcome-form"]');return{trigger:trigger,formClass:"core_grades\\form\\add_outcome",titleKey:"-1"===trigger.getAttribute("data-itemid")?"newoutcomeitem":"outcomeitemsedit",args:{itemid:trigger.getAttribute("data-itemid")}}}return null})(event);if(triggerData){event.preventDefault();const pendingPromise=new _pending.default("core_grades:add_item:".concat(triggerData.args.itemid)),{trigger:trigger,formClass:formClass,titleKey:titleKey,args:args}=triggerData;args.courseid=trigger.getAttribute("data-courseid"),args.gpr_plugin=trigger.getAttribute("data-gprplugin");const modalForm=new _modalform.default({modalConfig:{title:(0,_str.getString)(titleKey,"core_grades")},formClass:formClass,args:args,saveButtonText:(0,_str.getString)("save","core"),returnFocus:trigger});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{event.detail.result?(new _pending.default("core_grades:form_submitted"),window.location.assign(event.detail.url)):_notification.default.addNotification({type:"error",message:(0,_str.getString)("saving_failed","core_grades")})})),modalForm.show(),pendingPromise.resolve()}const showAdvancedForm=event.target.closest(Selectors_advancedFormLink);if(showAdvancedForm){event.preventDefault(),new _pending.default("core_grades:show_advanced_form");const form=event.target.closest("form");form.action=showAdvancedForm.href,FormChangeChecker.disableAllChecks(),form.submit()}}))}}));
//# sourceMappingURL=gradebooksetup_forms.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -25,52 +25,68 @@ import ModalForm from 'core_form/modalform';
import {getString} from 'core/str';
import Notification from 'core/notification';
import * as FormChangeChecker from 'core_form/changechecker';
import PendingPromise from 'core/pending';
const Selectors = {
advancedFormLink: 'a.showadvancedform'
};
const getDetailsFromEvent = (event) => {
if (event.target.closest('[data-trigger="add-item-form"]')) {
const trigger = event.target.closest('[data-trigger="add-item-form"]');
return {
trigger,
formClass: 'core_grades\\form\\add_item',
titleKey: trigger.getAttribute('data-itemid') === '-1' ? 'newitem' : 'itemsedit',
args: {
itemid: trigger.getAttribute('data-itemid'),
},
};
} else if (event.target.closest('[data-trigger="add-category-form"]')) {
const trigger = event.target.closest('[data-trigger="add-category-form"]');
return {
trigger,
formClass: 'core_grades\\form\\add_category',
titleKey: trigger.getAttribute('data-category') === '-1' ? 'newcategory' : 'categoryedit',
args: {
category: trigger.getAttribute('data-category'),
},
};
} else if (event.target.closest('[data-trigger="add-outcome-form"]')) {
const trigger = event.target.closest('[data-trigger="add-outcome-form"]');
return {
trigger,
formClass: 'core_grades\\form\\add_outcome',
titleKey: trigger.getAttribute('data-itemid') === '-1' ? 'newoutcomeitem' : 'outcomeitemsedit',
args: {
itemid: trigger.getAttribute('data-itemid'),
},
};
}
return null;
};
/**
* Initialize module
*/
export const init = () => {
// Sometimes the trigger does not exist, so lets conditionally add it.
document.addEventListener('click', event => {
const args = {};
const triggerData = getDetailsFromEvent(event);
let formClass = null;
let title = null;
let trigger = null;
if (event.target.closest('[data-trigger="add-item-form"]')) {
if (triggerData) {
event.preventDefault();
trigger = event.target.closest('[data-trigger="add-item-form"]');
formClass = 'core_grades\\form\\add_item';
title = trigger.getAttribute('data-itemid') === '-1' ?
getString('newitem', 'core_grades') : getString('itemsedit', 'core_grades');
args.itemid = trigger.getAttribute('data-itemid');
} else if (event.target.closest('[data-trigger="add-category-form"]')) {
event.preventDefault();
trigger = event.target.closest('[data-trigger="add-category-form"]');
formClass = 'core_grades\\form\\add_category';
title = trigger.getAttribute('data-category') === '-1' ?
getString('newcategory', 'core_grades') : getString('categoryedit', 'core_grades');
args.category = trigger.getAttribute('data-category');
} else if (event.target.closest('[data-trigger="add-outcome-form"]')) {
event.preventDefault();
trigger = event.target.closest('[data-trigger="add-outcome-form"]');
formClass = 'core_grades\\form\\add_outcome';
title = trigger.getAttribute('data-itemid') === '-1' ?
getString('newoutcomeitem', 'core_grades') : getString('outcomeitemsedit', 'core_grades');
args.itemid = trigger.getAttribute('data-itemid');
}
const pendingPromise = new PendingPromise(`core_grades:add_item:${triggerData.args.itemid}`);
if (trigger) {
const {trigger, formClass, titleKey, args} = triggerData;
args.courseid = trigger.getAttribute('data-courseid');
args.gpr_plugin = trigger.getAttribute('data-gprplugin');
const modalForm = new ModalForm({
modalConfig: {
title: title,
title: getString(titleKey, 'core_grades'),
},
formClass: formClass,
args: args,
@ -81,6 +97,7 @@ export const init = () => {
// Show a toast notification when the form is submitted.
modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {
if (event.detail.result) {
new PendingPromise('core_grades:form_submitted');
window.location.assign(event.detail.url);
} else {
Notification.addNotification({
@ -91,11 +108,16 @@ export const init = () => {
});
modalForm.show();
pendingPromise.resolve();
}
const showAdvancedForm = event.target.closest(Selectors.advancedFormLink);
if (showAdvancedForm) { // Navigate to the advanced form page and cary over any entered data.
if (showAdvancedForm) {
// Navigate to the advanced form page and cary over any entered data.
event.preventDefault();
// Do not resolve this pendingPromise - it will be cleared when the page changes.
new PendingPromise('core_grades:show_advanced_form');
const form = event.target.closest('form');
form.action = showAdvancedForm.href;
// Disable the form change checker as we are going to carry over the data to the advanced form.

View File

@ -74,11 +74,16 @@ class behat_grade extends behat_base {
'link', '.modal-dialog', 'css_element']);
}
$this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
if ($this->getSession()->getPage()->find('xpath', './/button[@data-action="save"]')) {
$container = $this->get_selected_node("core_grades > gradeitem modal", "form");
$node = $this->find('xpath', './/button[@data-action="save"]', false, $container);
$node->press();
$this->execute('behat_general::i_click_on_in_the', [
'.//button[@data-action="save"]',
'xpath',
$container,
'NodeElement',
]);
} else {
$savechanges = get_string('savechanges', 'grades');
$this->execute('behat_forms::press_button', $this->escape($savechanges));

View File

@ -645,7 +645,6 @@ trait behat_session_trait {
* @return void Throws an exception if it times out without the element being visible
*/
protected function ensure_node_is_visible($node) {
if (!$this->running_javascript()) {
return;
}
@ -715,7 +714,6 @@ trait behat_session_trait {
* @return NodeElement Throws an exception if it times out without being visible
*/
protected function ensure_element_is_visible($element, $selectortype) {
if (!$this->running_javascript()) {
return;
}

View File

@ -16,6 +16,7 @@
namespace Moodle\BehatExtension\Driver;
use Behat\Mink\Exception\DriverException;
use OAndreyev\Mink\Driver\WebDriver as UpstreamDriver;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
@ -79,4 +80,14 @@ class WebDriver extends UpstreamDriver {
public function post_key($key, $xpath) {
throw new \Exception('No longer used - please use keyDown and keyUp');
}
#[\Override]
public function stop(): void {
try {
parent::stop();
} catch (DriverException $e) {
error_log($e->getMessage());
$this->webDriver = null;
}
}
}

View File

@ -134,6 +134,10 @@ M.util.CollapsibleRegion = function(Y, id, userpref, strtooltip) {
from: {height:height}
});
animation.on('start', () => M.util.js_pending('CollapsibleRegion'));
animation.on('resume', () => M.util.js_pending('CollapsibleRegion'));
animation.on('pause', () => M.util.js_complete('CollapsibleRegion'));
// Handler for the animation finishing.
animation.on('end', function() {
this.div.toggleClass('collapsed');
@ -148,6 +152,8 @@ M.util.CollapsibleRegion = function(Y, id, userpref, strtooltip) {
} else {
this.icon.set('src', M.util.image_url('t/expanded', 'moodle'));
}
M.util.js_complete('CollapsibleRegion');
}, this);
// Hook up the event handler.

View File

@ -62,7 +62,6 @@ class behat_action_menu extends behat_base {
return;
}
$this->ensure_node_is_visible($node);
$node->click();
}
@ -87,7 +86,6 @@ class behat_action_menu extends behat_base {
// Gets the node based on the requested selector type and locator.
$menuselector = ".moodle-actionmenu .dropdown.show .dropdown-menu";
$node = $this->get_node_in_container("link", trim($menuitem), "css_element", $menuselector);
$this->ensure_node_is_visible($node);
$node->click();
}

View File

@ -777,7 +777,6 @@ class behat_forms extends behat_base {
public function i_expand_the_autocomplete($field) {
$csstarget = '.form-autocomplete-downarrow';
$node = $this->get_node_in_container('css_element', $csstarget, 'form_row', $field);
$this->ensure_node_is_visible($node);
$node->click();
}

View File

@ -32,8 +32,11 @@ use Behat\Mink\Element\NodeElement;
use Behat\Mink\Exception\DriverException;
use Behat\Mink\Exception\ElementNotFoundException;
use Behat\Mink\Exception\ExpectationException;
use Facebook\WebDriver\Exception\NoSuchAlertException;
use Facebook\WebDriver\Exception\NoSuchElementException;
use Facebook\WebDriver\Exception\StaleElementReferenceException;
use Facebook\WebDriver\WebDriverAlert;
use Facebook\WebDriver\WebDriverExpectedCondition;
/**
* Cross component steps definitions.
@ -262,12 +265,25 @@ class behat_general extends behat_base {
$this->getSession()->switchToWindow($names[0]);
}
/**
* Wait for an alert to be displayed.
*
* @return WebDriverAlert
*/
public function wait_for_alert(): WebDriverAlert {
$webdriver = $this->getSession()->getDriver()->getWebdriver();
$webdriver->wait()->until(WebDriverExpectedCondition::alertIsPresent());
return $webdriver->switchTo()->alert();
}
/**
* Accepts the currently displayed alert dialog. This step does not work in all the browsers, consider it experimental.
* @Given /^I accept the currently displayed dialog$/
*/
public function accept_currently_displayed_alert_dialog() {
$this->getSession()->getDriver()->getWebDriver()->switchTo()->alert()->accept();
$alert = $this->wait_for_alert();
$alert->accept();
}
/**
@ -275,7 +291,8 @@ class behat_general extends behat_base {
* @Given /^I dismiss the currently displayed dialog$/
*/
public function dismiss_currently_displayed_alert_dialog() {
$this->getSession()->getDriver()->getWebDriver()->switchTo()->alert()->dismiss();
$alert = $this->wait_for_alert();
$alert->dismiss();
}
/**
@ -286,9 +303,7 @@ class behat_general extends behat_base {
* @param string $link
*/
public function click_link($link) {
$linknode = $this->find_link($link);
$this->ensure_node_is_visible($linknode);
$linknode->click();
}
@ -393,11 +408,8 @@ class behat_general extends behat_base {
* @param string $selectortype The type of what we look for
*/
public function i_click_on($element, $selectortype) {
// Gets the node based on the requested selector type and locator.
$node = $this->get_selected_node($selectortype, $element);
$this->ensure_node_is_visible($node);
$node->click();
$this->get_selected_node($selectortype, $element)->click();
}
/**
@ -458,9 +470,7 @@ class behat_general extends behat_base {
* @param string $nodeselectortype The type of selector where we look in
*/
public function i_click_on_in_the($element, $selectortype, $nodeelement, $nodeselectortype) {
$node = $this->get_node_in_container($selectortype, $element, $nodeselectortype, $nodeelement);
$this->ensure_node_is_visible($node);
$node->click();
}
@ -502,7 +512,6 @@ class behat_general extends behat_base {
}
$node = $this->get_node_in_container($selectortype, $element, $nodeselectortype, $nodeelement);
$this->ensure_node_is_visible($node);
// KeyUP and KeyDown require the element to be displayed in the current window.
$this->execute_js_on_node($node, '{{ELEMENT}}.scrollIntoView();');

View File

@ -725,6 +725,9 @@ class behat_navigation extends behat_base {
case 'Admin notifications':
return new moodle_url('/admin/');
case 'Content bank':
return new moodle_url('/contentbank/');
case 'My private files':
return new moodle_url('/user/files.php');

View File

@ -96,6 +96,7 @@ Feature: In a lesson activity, students can not re-attempt a question more than
And I press the "back" button in the browser
And I press the "back" button in the browser
And I press the "back" button in the browser
And I reload the page
And I should see "Paper is made from trees"
And I set the following fields to these values:
| True | 1 |
@ -117,6 +118,7 @@ Feature: In a lesson activity, students can not re-attempt a question more than
And I press "Submit"
And I should see "Wrong"
And I press the "back" button in the browser
And I reload the page
And I set the following fields to these values:
| True | 1 |
When I press "Submit"
@ -141,6 +143,7 @@ Feature: In a lesson activity, students can not re-attempt a question more than
And I press "Submit"
And I should see "Correct"
And I press the "back" button in the browser
And I reload the page
And I set the following fields to these values:
| False | 1 |
And I press "Submit"

View File

@ -149,6 +149,9 @@ class behat_mod_quiz extends behat_question_base {
return new moodle_url('/mod/quiz/review.php', ['attempt' => $attempt->id]);
case 'question bank':
// The question bank does not handle fields at the edge of the viewport well.
// Increase the size to avoid this.
$this->execute('behat_general::i_change_window_size_to', ['window', 'large']);
return new moodle_url('/question/edit.php', [
'cmid' => $this->get_cm_by_quiz_name($identifier)->id,
]);
@ -626,7 +629,6 @@ class behat_mod_quiz extends behat_question_base {
public function i_click_on_shuffle_for_section($heading) {
$xpath = $this->get_xpath_for_shuffle_checkbox($heading);
$checkbox = $this->find('xpath', $xpath);
$this->ensure_node_is_visible($checkbox);
$checkbox->click();
}

View File

@ -68,8 +68,12 @@ class behat_core_question extends behat_question_base {
protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
switch (strtolower($type)) {
case 'course question bank':
return new moodle_url('/question/edit.php',
['courseid' => $this->get_course_id($identifier)]);
// The question bank does not handle fields at the edge of the viewport well.
// Increase the size to avoid this.
$this->execute('behat_general::i_change_window_size_to', ['window', 'large']);
return new moodle_url('/question/edit.php', [
'courseid' => $this->get_course_id($identifier),
]);
case 'course question categories':
return new moodle_url('/question/bank/managecategories/category.php',

View File

@ -289,7 +289,6 @@ class behat_filepicker extends behat_base {
}
$selectfilebutton = $this->find_button(get_string('getfile', 'repository'));
$this->ensure_node_is_visible($selectfilebutton);
$selectfilebutton->click();
// We wait for all the JS to finish as it is performing an action.
@ -297,7 +296,6 @@ class behat_filepicker extends behat_base {
if ($overwriteaction !== false) {
$overwritebutton = $this->find_button($overwriteaction);
$this->ensure_node_is_visible($overwritebutton);
$overwritebutton->click();
// We wait for all the JS to finish.

View File

@ -175,7 +175,6 @@ class behat_repository_upload extends behat_base {
if ($overwriteaction !== false) {
$overwritebutton = $this->find_button($overwriteaction);
$this->ensure_node_is_visible($overwritebutton);
$overwritebutton->click();
// We wait for all the JS to finish.