MDL-67668 behat: Add inplace editable field type

This commit promotes the Inplace Editable field to a first-class form
element by introducing a new partial selector for inplace editable
fields, and teaching the field manager how to recognise these, then
introducing a new field type which can handle setting values for this
field.
This commit is contained in:
Andrew Nicols 2020-06-17 13:45:15 +08:00
parent 548da2ce97
commit fd71823ec7
5 changed files with 130 additions and 5 deletions

View File

@ -0,0 +1,30 @@
@tool_behat
Feature: Verify that the inplace editable field works as expected
In order to use behat step definitions
As a test write
I need to ensure that the inplace editable works in forms
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
And the following "activities" exist:
| activity | course | name | idnumber |
| forum | C1 | My first forum | forum1 |
| assign | C1 | My first assignment | assign1 |
| quiz | C1 | My first quiz | quiz1 |
And I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
@javascript
Scenario: Using an inplace editable updates the name of an activity
When I set the field "Edit title" in the "My first assignment" "activity" to "Coursework submission"
Then I should see "Coursework submission"
And I should not see "My first assignment"
But I should see "My first forum"
And I should see "My first quiz"
And I set the field "Edit title" in the "Coursework submission" "activity" to "My first assignment"
And I should not see "Coursework submission"
But I should see "My first assignment"
And I should see "My first forum"
And I should see "My first quiz"

View File

@ -48,7 +48,6 @@ class behat_field_manager {
* @return behat_form_field
*/
public static function get_form_field_from_label($label, RawMinkContext $context) {
// There are moodle form elements that are not directly related with
// a basic HTML form field, we should also take care of them.
// The DOM node.
@ -172,6 +171,10 @@ class behat_field_manager {
} else if ($tagname == 'select') {
// Select tag.
return 'select';
} else if ($tagname == 'span') {
if ($fieldnode->hasAttribute('data-inplaceeditable') && $fieldnode->getAttribute('data-inplaceeditable')) {
return 'inplaceeditable';
}
}
// We can not provide a closer field type.

View File

@ -135,7 +135,7 @@ class behat_partial_named_selector extends \Behat\Mink\Selector\PartialNamedSele
*/
protected static $moodleselectors = array(
'activity' => <<<XPATH
.//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][normalize-space(.) = %locator% ]
.//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][descendant::*[contains(normalize-space(.), %locator%)]]
XPATH
, 'block' => <<<XPATH
.//*[@data-block][contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' ')) or
@ -262,6 +262,11 @@ XPATH
.//*[@data-passwordunmask='wrapper']
/descendant::input[@id = %locator% or @id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
XPATH
,
'inplaceeditable' => <<<XPATH
.//descendant::span[@data-inplaceeditable][descendant::a[%titleMatch%]]
XPATH
,
],
];

View File

@ -25,8 +25,8 @@
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
use Behat\Mink\Session as Session,
Behat\Mink\Element\NodeElement as NodeElement;
use Behat\Mink\Element\NodeElement;
use Behat\Mink\Session;
/**
* Representation of a form field.
@ -38,7 +38,10 @@ use Behat\Mink\Session as Session,
* @copyright 2012 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_form_field {
class behat_form_field implements behat_session_interface {
// All of the functionality of behat_base is shared with form fields via the behat_session_trait trait.
use behat_session_trait;
/**
* @var Session Behat session.
@ -55,6 +58,16 @@ class behat_form_field {
*/
protected $fieldlocator = false;
/**
* Returns the Mink session.
*
* @param string|null $name name of the session OR active session will be used
* @return \Behat\Mink\Session
*/
public function getSession($name = null) {
return $this->session;
}
/**
* General constructor with the node and the session to interact with.

View File

@ -0,0 +1,74 @@
<?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/>.
/**
* Custom interaction with inplace editable elements.
*
* @package core_form
* @category test
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/behat_form_text.php');
/**
* Custom interaction with inplace editable elements.
*
* @package core_form
* @category test
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_form_inplaceeditable extends behat_form_text {
/**
* Sets the value to a field.
*
* @param string $value
* @return void
*/
public function set_value($value) {
// Require JS to run this step.
self::require_javascript();
// Click to enable editing.
self::execute(
'behat_general::i_click_on_in_the',
[
'[data-inplaceeditablelink]',
'css_element',
$this->field,
'NodeElement',
]
);
// Note: It is not possible to use the NodeElement->keyDown() and related functions because
// this can trigger a focusOnElement call each time.
// Instead use the behat_base::type_keys() function.
// The inplace editable selects all existing content on focus.
// Clear the existing value.
self::type_keys($this->session, [behat_keys::BACKSPACE]);
// Type in the new value, followed by ENTER to save the value.
self::type_keys($this->session, array_merge(
str_split($value),
[behat_keys::ENTER]
));
}
}