Merge branch 'MDL-78779-master' of https://github.com/andrewnicols/moodle
This commit is contained in:
@@ -46,7 +46,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
| -1- |
|
||||
| Teacher 1 |
|
||||
When I set the field "Search users" to "Turtle"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I confirm "Turtle Manatee" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget does not exist
|
||||
And I click on "Turtle Manatee" "list_item"
|
||||
@@ -63,7 +63,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
| User Test |
|
||||
| Dummy User |
|
||||
And I set the field "Search users" to "Turt"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I click on "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And "View all results (5)" "option_role" should not be visible
|
||||
|
||||
@@ -98,7 +98,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
# Case: Multiple users found and select only one result.
|
||||
Then I set the field "Search users" to "User"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
@@ -124,7 +124,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
# Business case cont. When pressing enter with multiple partial matches, behave like when you select the "View all results for (Bob)"
|
||||
# Case: Multiple users found and select all partial matches.
|
||||
And I set the field "Search users" to "User"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I click on "View all results (5)" "option_role"
|
||||
And I wait until the page is ready
|
||||
And the following should exist in the "user-grades" table:
|
||||
@@ -164,10 +164,10 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
Scenario: A teacher can search for values besides the users' name
|
||||
Given I set the field "Search users" to "student5@example.com"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And "Turtle Manatee" "list_item" should exist
|
||||
And I set the field "Search users" to "@example.com"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
# Note: All learners match this email & showing emails is current default.
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
@@ -177,7 +177,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
# Search on the country field.
|
||||
When I set the field "Search users" to "JP"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I wait until "Turtle Manatee" "list_item" does not exist
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
@@ -189,7 +189,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
# Search on the institution field.
|
||||
And I set the field "Search users" to "ABCD"
|
||||
And I wait until "Dummy User" "list_item" exists
|
||||
And "Dummy User" "list_item" should exist
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
And I confirm "Student 1" in "user" search within the gradebook widget exists
|
||||
@@ -213,7 +213,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
# Search on the institution field then press enter to show the record set.
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "list_item" exists
|
||||
And "Turtle Manatee" "list_item" should exist
|
||||
And I confirm "Dummy User" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Example" in "user" search within the gradebook widget exists
|
||||
And I confirm "User Test" in "user" search within the gradebook widget exists
|
||||
@@ -239,7 +239,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
And the page should meet "wcag131, wcag141, wcag412" accessibility standards
|
||||
And the page should meet accessibility standards with "wcag131, wcag141, wcag412" extra tests
|
||||
# Move onto general keyboard navigation testing.
|
||||
When I wait until "Turtle Manatee" "option_role" exists
|
||||
When "Turtle Manatee" "option_role" should exist
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
And I press the end key
|
||||
@@ -258,13 +258,13 @@ Feature: Within the User report, a teacher can search for users.
|
||||
|
||||
And I navigate to "View > User report" in the course gradebook
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "option_role" exists
|
||||
And "Turtle Manatee" "option_role" should exist
|
||||
And I press the down key
|
||||
And the focused element is "Student 1" "option_role"
|
||||
|
||||
# Lets check the tabbing order.
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "View all results (5)" "option_role" exists
|
||||
And "View all results (5)" "option_role" should exist
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And I press the tab key
|
||||
@@ -289,7 +289,7 @@ Feature: Within the User report, a teacher can search for users.
|
||||
# Sometimes with behat we get unattached nodes causing spurious failures.
|
||||
And I wait "1" seconds
|
||||
And I set the field "Search users" to "ABC"
|
||||
And I wait until "Turtle Manatee" "option_role" exists
|
||||
And "Turtle Manatee" "option_role" should exist
|
||||
And I press the tab key
|
||||
And the focused element is "Clear search input" "button" in the ".user-search" "css_element"
|
||||
And I press the enter key
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
||||
define("core/utils",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.throttle=_exports.getNormalisedComponent=_exports.debounce=void 0;_exports.throttle=(func,wait)=>{let onCooldown=!1,runAgain=null;const run=function(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];runAgain=null!==runAgain,onCooldown||(func.apply(this,args),onCooldown=!0,setTimeout((()=>{const recurse=runAgain;onCooldown=!1,runAgain=null,recurse&&run(args)}),wait))};return run};_exports.debounce=(func,wait)=>{let timeout=null;return function(){for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++)args[_key2]=arguments[_key2];clearTimeout(timeout),timeout=setTimeout((()=>{func.apply(this,args)}),wait)}};_exports.getNormalisedComponent=component=>component&&"moodle"!==component&&"core"!==component?component:"core"}));
|
||||
define("core/utils",["exports","core/pending"],(function(_exports,_pending){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.throttle=_exports.getNormalisedComponent=_exports.debounce=void 0,_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};_exports.throttle=(func,wait)=>{let onCooldown=!1,runAgain=null;const run=function(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];runAgain=null!==runAgain,onCooldown||(func.apply(this,args),onCooldown=!0,setTimeout((()=>{const recurse=runAgain;onCooldown=!1,runAgain=null,recurse&&run(args)}),wait))};return run};const debounceMap=new Map;_exports.debounce=function(func,wait){let{pending:pending=!1}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},timeout=null;const returnedFunction=function(){for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++)args[_key2]=arguments[_key2];pending&&!debounceMap.has(returnedFunction)&&debounceMap.set(returnedFunction,new _pending.default("core/utils:debounce")),clearTimeout(timeout),timeout=setTimeout((async()=>{const pendingPromise=debounceMap.get(returnedFunction);debounceMap.delete(returnedFunction),await func.apply(undefined,args),null==pendingPromise||pendingPromise.resolve()}),wait)};return returnedFunction};_exports.getNormalisedComponent=component=>component&&"moodle"!==component&&"core"!==component?component:"core"}));
|
||||
|
||||
//# sourceMappingURL=utils.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -237,6 +237,17 @@ export default class {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether search results are currently visible.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
searchResultsVisible() {
|
||||
const {searchDropdown} = this.getHTMLElements();
|
||||
// If a Node is not visible, then the offsetParent is null.
|
||||
return searchDropdown.offsetParent !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When called, update the dropdown fields.
|
||||
*
|
||||
@@ -291,6 +302,11 @@ export default class {
|
||||
registerInputHandlers() {
|
||||
// Register & handle the text input.
|
||||
this.searchInput.addEventListener('input', debounce(async() => {
|
||||
if (this.getSearchTerm() === this.searchInput.value && this.searchResultsVisible()) {
|
||||
window.console.warn(`Search term matches input value - skipping`);
|
||||
// The debounce canhappen multiple times quickly. GRrargh
|
||||
return;
|
||||
}
|
||||
this.setSearchTerms(this.searchInput.value);
|
||||
// We can also require a set amount of input before search.
|
||||
if (this.getSearchTerm() === '') {
|
||||
@@ -302,12 +318,13 @@ export default class {
|
||||
await this.renderAndShow().then(() => {
|
||||
// Display the "clear" search button in the search bar.
|
||||
this.clearSearchButton.classList.remove('d-none');
|
||||
return;
|
||||
}).then(() => {
|
||||
pendingPromise.resolve();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}, 300));
|
||||
}, 300, {pending: true}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+36
-4
@@ -21,6 +21,8 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import Pending from 'core/pending';
|
||||
|
||||
/**
|
||||
* Create a wrapper function to throttle the execution of the given
|
||||
*
|
||||
@@ -70,6 +72,11 @@ export const throttle = (func, wait) => {
|
||||
return run;
|
||||
};
|
||||
|
||||
/**
|
||||
* @property {Map} debounceMap A map of functions to their debounced pending promises.
|
||||
*/
|
||||
const debounceMap = new Map();
|
||||
|
||||
/**
|
||||
* Create a wrapper function to debounce the execution of the given
|
||||
* function. Each attempt to execute the function will reset the cooldown
|
||||
@@ -78,16 +85,41 @@ export const throttle = (func, wait) => {
|
||||
* @method
|
||||
* @param {Function} func The function to debounce
|
||||
* @param {Number} wait The number of milliseconds to wait after the final attempt to execute
|
||||
* @param {Object} [options]
|
||||
* @param {boolean} [options.pending=false] Whether to wrap the debounced method in a pending promise
|
||||
* @return {Function}
|
||||
*/
|
||||
export const debounce = (func, wait) => {
|
||||
export const debounce = (
|
||||
func,
|
||||
wait,
|
||||
{
|
||||
pending = false,
|
||||
} = {},
|
||||
) => {
|
||||
let timeout = null;
|
||||
return function(...args) {
|
||||
|
||||
const returnedFunction = (...args) => {
|
||||
if (pending && !debounceMap.has(returnedFunction)) {
|
||||
debounceMap.set(returnedFunction, new Pending('core/utils:debounce'));
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
func.apply(this, args);
|
||||
timeout = setTimeout(async () => {
|
||||
// Get the current pending promise and immediately empty it.
|
||||
// This is important to allow the function to be debounced again as soon as possible.
|
||||
// We do not resolve it until later - but that's fine because the promise is appropriately scoped.
|
||||
const pendingPromise = debounceMap.get(returnedFunction);
|
||||
debounceMap.delete(returnedFunction);
|
||||
|
||||
// Allow the debounced function to return a Promise.
|
||||
// This ensures that Behat will not continue until the function has finished executing.
|
||||
await func.apply(this, args);
|
||||
|
||||
// Resolve the pending promise if it exists.
|
||||
pendingPromise?.resolve();
|
||||
}, wait);
|
||||
};
|
||||
|
||||
return returnedFunction;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user