Skip to content

Commit

Permalink
MDL-62514 behat: Rewrite handling of autocomplete
Browse files Browse the repository at this point in the history
This includes a minor restructure of the autocomplete JS to make use of
promises and improve tracking of pending JS.

In particular it improves the way in which throttled text input is
handled to ensure that the behat does not continue until:
- typing is fully complete; and
- all possible ajax requests have been sent; and
- all possible ajax requests complete; and
- the suggestions are updated.

A number of conditions existed where behat would move on to the next
step too early in a race condition effect between Behat and Autocomplete.
  • Loading branch information
andrewnicols committed Jan 30, 2019
1 parent 7bfb575 commit e994dea
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 150 deletions.
2 changes: 1 addition & 1 deletion lib/amd/build/form-autocomplete.min.js

Large diffs are not rendered by default.

396 changes: 261 additions & 135 deletions lib/amd/src/form-autocomplete.js

Large diffs are not rendered by default.

48 changes: 40 additions & 8 deletions lib/behat/form_field/behat_form_autocomplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,45 @@ public function set_value($value) {
if (!$this->running_javascript()) {
throw new coding_exception('Setting the valid of an autocomplete field requires javascript.');
}
$this->field->setValue($value);
// After the value is set, there is a 400ms throttle and then search. So adding 2 sec. delay to ensure both
// throttle + search finishes.
sleep(2);
$id = $this->field->getAttribute('id');
$js = ' require(["jquery"], function($) { $(document.getElementById("'.$id.'")).trigger("behat:set-value"); }); ';
$this->session->executeScript($js);
$this->key_press(27);

// Set the value of the autocomplete's input.
// If this autocomplete offers suggestions then these should be fetched by setting the value and waiting for the
// JS to finish fetching those suggestions.

$istagelement = $this->field->hasAttribute('data-tags') && $this->field->getAttribute('data-tags');

if ($istagelement && false !== strpos($value, ',')) {
// Commas have a special meaning as a value separator in 'tag' autocomplete elements.
// To handle this we break the value up by comma, and enter it in chunks.
$values = explode(',', $value);

while ($value = array_shift($values)) {
$this->set_value($value);
}
} else {
$this->field->setValue($value);
$this->wait_for_pending_js();

// If the autocomplete found suggestions, then it will have:
// 1) marked itself as expanded; and
// 2) have an aria-selected suggestion in the list.
$expanded = $this->field->getAttribute('aria-expanded');
$suggestion = $this->field->getParent()->find('css', '.form-autocomplete-suggestions > [aria-selected="true"]');

if ($expanded && null !== $suggestion) {
// A suggestion was found.
// Click on the first item in the list.
$suggestion->click();
} else {
// Press the return key to create a new tag.
// Note: We cannot use $this->key_press() because the keyPress action, in combination with the keyDown
// submits the form.
$this->field->keyDown(13);
$this->field->keyUp(13);
}

$this->wait_for_pending_js();
$this->key_press(27);
}
}
}
2 changes: 1 addition & 1 deletion lib/templates/form_autocomplete_input.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{ "inputID": 1, "suggestionsId": 2, "selectionId": 3, "downArrowId": 4, "placeholder": "Select something" }
}}
{{#showSuggestions}}
<input type="text" id="{{inputId}}" list="{{suggestionsId}}" placeholder="{{placeholder}}" role="combobox" aria-expanded="false" autocomplete="off" autocorrect="off" autocapitalize="off" aria-autocomplete="list" aria-owns="{{suggestionsId}} {{selectionId}}"/><span class="form-autocomplete-downarrow" id="{{downArrowId}}">&#x25BC;</span>
<input type="text" id="{{inputId}}" list="{{suggestionsId}}" placeholder="{{placeholder}}" role="combobox" aria-expanded="false" autocomplete="off" autocorrect="off" autocapitalize="off" aria-autocomplete="list" aria-owns="{{suggestionsId}} {{selectionId}}" {{#tags}}data-tags="1"{{/tags}}/><span class="form-autocomplete-downarrow" id="{{downArrowId}}">&#x25BC;</span>
{{/showSuggestions}}
{{^showSuggestions}}
<input type="text" id="{{inputId}}" placeholder="{{placeholder}}" role="textbox" aria-owns="{{selectionId}}"/>
Expand Down
4 changes: 0 additions & 4 deletions mod/feedback/tests/behat/coursemapping.feature
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,6 @@ Feature: Mapping courses in a feedback
And I follow "Map feedback to courses"
And I set the field "Courses" to "Course 2"
And I set the field "Courses" to "Course 3"
# Weird solution to make the editable field to lose the focus
# but with the focus, "save changes" uses to fail because of
# the suggestions hiding the button.
And I press key "27" in the field "Courses"
And I press "Save changes"
And I should see "Course mapping has been changed"
And I log out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{ "inputID": 1, "suggestionsId": 2, "selectionId": 3, "downArrowId": 4, "placeholder": "Select something" }
}}
{{#showSuggestions}}
<input type="text" id="{{inputId}}" class="form-control" list="{{suggestionsId}}" placeholder="{{placeholder}}" role="combobox" aria-expanded="false" autocomplete="off" autocorrect="off" autocapitalize="off" aria-autocomplete="list" aria-owns="{{suggestionsId}} {{selectionId}}"/><span class="form-autocomplete-downarrow" id="{{downArrowId}}">&#x25BC;</span>
<input type="text" id="{{inputId}}" class="form-control" list="{{suggestionsId}}" placeholder="{{placeholder}}" role="combobox" aria-expanded="false" autocomplete="off" autocorrect="off" autocapitalize="off" aria-autocomplete="list" aria-owns="{{suggestionsId}} {{selectionId}}" {{#tags}}data-tags="1"{{/tags}}/><span class="form-autocomplete-downarrow" id="{{downArrowId}}">&#x25BC;</span>
{{/showSuggestions}}
{{^showSuggestions}}
<input type="text" id="{{inputId}}" placeholder="{{placeholder}}" role="textbox" aria-owns="{{selectionId}}"/>
Expand Down
3 changes: 3 additions & 0 deletions theme/upgrade.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
This files describes API changes in /theme/* themes,
information provided here is intended especially for theme designer.

=== 3.7 ===
* The core/form_autocompelte_input template now has a `data-tags` attribute.

=== 3.6 ===

* A new callback has been added to the theme layout files allowing plugins to inject their content
Expand Down

0 comments on commit e994dea

Please sign in to comment.