From 39ce052c66ed2d0bbadcf3ca6f0533ffeb8bf012 Mon Sep 17 00:00:00 2001 From: David Monllao Date: Thu, 27 Feb 2014 16:39:25 +0800 Subject: [PATCH] MDL-43738 behat: Refactoring the field type guesser The previous behaviour delegates the responsability of overwriting the 3 public methods to the child classes, now the field type or moodleform field is guessed earlier in the execution flow. Other changes introduced here: - Fix wrong moodleform detection when there is a form in the page but the field we are dealing with is not inside it. - Some coding style changes. --- lib/behat/behat_field_manager.php | 66 +++++++++++- .../form_field/behat_form_date_selector.php | 3 - lib/behat/form_field/behat_form_editor.php | 4 +- lib/behat/form_field/behat_form_field.php | 100 ++++++------------ lib/behat/form_field/behat_form_group.php | 5 +- .../form_field/behat_form_modvisible.php | 3 +- lib/behat/form_field/behat_form_radio.php | 5 +- lib/behat/form_field/behat_form_select.php | 5 +- .../form_field/behat_form_selectyesno.php | 3 +- lib/behat/form_field/behat_form_text.php | 69 ++++++++++++ lib/behat/form_field/behat_form_textarea.php | 39 +++++++ 11 files changed, 218 insertions(+), 84 deletions(-) create mode 100644 lib/behat/form_field/behat_form_text.php create mode 100644 lib/behat/form_field/behat_form_textarea.php diff --git a/lib/behat/behat_field_manager.php b/lib/behat/behat_field_manager.php index b83b18e2b90..7454da8890c 100644 --- a/lib/behat/behat_field_manager.php +++ b/lib/behat/behat_field_manager.php @@ -80,9 +80,16 @@ class behat_field_manager { global $CFG; + // If the field is not part of a moodleform, we should still try to find out + // which field type are we dealing with. + if ($type == 'field' && + $guessedtype = self::guess_field_type($fieldnode, $session)) { + $type = $guessedtype; + } + $classname = 'behat_form_' . $type; - // Fallsback on the default form field if nothing specific exists. + // Fallsback on the type guesser if nothing specific exists. $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php'; if (!file_exists($classpath)) { $classname = 'behat_form_field'; @@ -94,6 +101,58 @@ class behat_field_manager { return new $classname($session, $fieldnode); } + /** + * Guesses a basic field type and returns it. + * + * This method is intended to detect HTML form fields when no + * moodleform-specific elements have been detected. + * + * @param NodeElement $fieldnode + * @param Session $session + * @return string|bool The field type or false. + */ + public static function guess_field_type(NodeElement $fieldnode, Session $session) { + + // Textareas are considered text based elements. + $tagname = strtolower($fieldnode->getTagName()); + if ($tagname == 'textarea') { + + // If there is an iframe with $id + _ifr there a TinyMCE editor loaded. + $xpath = '//iframe[@id="' . $fieldnode->getAttribute('id') . '_ifr"]'; + if ($session->getPage()->find('xpath', $xpath)) { + return 'editor'; + } + return 'textarea'; + + } else if ($tagname == 'input') { + $type = $fieldnode->getAttribute('type'); + switch ($type) { + case 'text': + case 'password': + case 'email': + case 'file': + return 'text'; + case 'checkbox': + return 'checkbox'; + break; + case 'radio': + return 'radio'; + break; + default: + // Here we return false because all text-based + // fields should be included in the first switch case. + return false; + } + + } else if ($tagname == 'select') { + // Select tag. + return 'select'; + } + + // We can not provide a closer field type. + return false; + } + /** * Detects when the field is a moodleform field type. * @@ -108,7 +167,10 @@ class behat_field_manager { protected static function is_moodleform_field(NodeElement $fieldnode) { // We already waited when getting the NodeElement and we don't want an exception if it's not part of a moodleform. - $parentformfound = $fieldnode->find('xpath', "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]/fieldset"); + $parentformfound = $fieldnode->find('xpath', + "/ancestor::fieldset" . + "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]" + ); return ($parentformfound != false); } diff --git a/lib/behat/form_field/behat_form_date_selector.php b/lib/behat/form_field/behat_form_date_selector.php index 4fc8e47646b..71c477c9596 100644 --- a/lib/behat/form_field/behat_form_date_selector.php +++ b/lib/behat/form_field/behat_form_date_selector.php @@ -30,9 +30,6 @@ require_once(__DIR__ . '/behat_form_group.php'); /** * Date form field. * - * Simple extension of behat_form_group to allow the different - * date_selector fields to be filled according to it's type. - * * This class will be refactored in case we are interested in * creating more complex formats to fill date and date-time fields. * diff --git a/lib/behat/form_field/behat_form_editor.php b/lib/behat/form_field/behat_form_editor.php index 5c82bcfc6ca..457a8867464 100644 --- a/lib/behat/form_field/behat_form_editor.php +++ b/lib/behat/form_field/behat_form_editor.php @@ -27,7 +27,7 @@ use Behat\Mink\Element\NodeElement as NodeElement; -require_once(__DIR__ . '/behat_form_field.php'); +require_once(__DIR__ . '/behat_form_textarea.php'); /** * Moodle editor field. @@ -38,7 +38,7 @@ require_once(__DIR__ . '/behat_form_field.php'); * @copyright 2012 David Monllaó * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class behat_form_editor extends behat_form_field { +class behat_form_editor extends behat_form_textarea { /** * Sets the value to a field. diff --git a/lib/behat/form_field/behat_form_field.php b/lib/behat/form_field/behat_form_field.php index 5951defb84e..4d3f1b497fa 100644 --- a/lib/behat/form_field/behat_form_field.php +++ b/lib/behat/form_field/behat_form_field.php @@ -69,14 +69,11 @@ class behat_form_field { * @return void */ public function set_value($value) { - - // If we are not dealing with a text-based tag try to find the most appropiate - // behat_form_* class to deal with it. - if ($instance = $this->guess_type()) { - $instance->set_value($value); - } else { - $this->field->setValue($value); - } + // We delegate to the best guess, if we arrived here + // using the generic behat_form_field is because we are + // dealing with a fgroup element. + $instance = $this->guess_type(); + return $instance->set_value($value); } /** @@ -85,14 +82,11 @@ class behat_form_field { * @return string */ public function get_value() { - - // If we are not dealing with a text-based tag try to find the most appropiate - // behat_form_* class to deal with it. - if ($instance = $this->guess_type()) { - return $instance->get_value(); - } else { - return $this->field->getValue(); - } + // We delegate to the best guess, if we arrived here + // using the generic behat_form_field is because we are + // dealing with a fgroup element. + $instance = $this->guess_type(); + return $instance->get_value(); } /** @@ -105,18 +99,11 @@ class behat_form_field { * @return bool The provided value matches the field value? */ public function matches($expectedvalue) { - - // If we are not dealing with a text-based tag try to find the most appropiate - // behat_form_* class to deal with it. - if ($instance = $this->guess_type()) { - return $instance->matches($expectedvalue); - } - - // Text-based comparison. - if (trim($expectedvalue) != trim($this->get_value())) { - return false; - } - return true; + // We delegate to the best guess, if we arrived here + // using the generic behat_form_field is because we are + // dealing with a fgroup element. + $instance = $this->guess_type(); + return $instance->matches($expectedvalue); } /** @@ -130,52 +117,17 @@ class behat_form_field { * moodle form elements we will need to refactor this simple HTML elements * guess method. * - * @return mixed False if no need for an special behat_form_*, otherwise the behat_form_* + * @return behat_form_field */ private function guess_type() { global $CFG; - // Textareas are considered text based elements. - $tagname = strtolower($this->field->getTagName()); - if ($tagname == 'textarea') { - - if (!$this->running_javascript()) { - return false; - } - - // If there is an iframe with $id + _ifr there a TinyMCE editor loaded. - $xpath = '//iframe[@id="' . $this->field->getAttribute('id') . '_ifr"]'; - if (!$this->session->getPage()->find('xpath', $xpath)) { - - // Generic one if it is a normal textarea. - return false; - } - - $classname = 'behat_form_editor'; - - } else if ($tagname == 'input') { - $type = $this->field->getAttribute('type'); - switch ($type) { - case 'text': - return false; - case 'checkbox': - $classname = 'behat_form_checkbox'; - break; - case 'radio': - $classname = 'behat_form_radio'; - break; - default: - return false; - } - - } else if ($tagname == 'select') { - // Select tag. - $classname = 'behat_form_select'; - - } else { - return false; + // We default to the text-based field if nothing was detected. + if (!$type = behat_field_manager::guess_field_type($this->field, $this->session)) { + $type = 'text'; } + $classname = 'behat_form_' . $type; $classpath = $CFG->dirroot . '/lib/behat/form_field/' . $classname . '.php'; require_once($classpath); return new $classname($this->session, $this->field); @@ -207,4 +159,16 @@ class behat_form_field { return $this->session->getDriver()->getWebDriverSession()->element('xpath', $this->field->getXPath())->getID(); } + /** + * Checks if the provided text matches the field value. + * + * @param string $expectedvalue + * @return bool + */ + protected function text_matches($expectedvalue) { + if (trim($expectedvalue) != trim($this->get_value())) { + return false; + } + return true; + } } diff --git a/lib/behat/form_field/behat_form_group.php b/lib/behat/form_field/behat_form_group.php index 533a787cd7e..3e8b2e58fd8 100644 --- a/lib/behat/form_field/behat_form_group.php +++ b/lib/behat/form_field/behat_form_group.php @@ -30,8 +30,9 @@ require_once(__DIR__ . '/behat_form_field.php'); /** * Class to re-guess the field type as grouped fields can have different field types. * - * When filling fields in a fgroup field element we don't know what kind - * of field are we dealing with, so we should re-guess it. + * When filling fields inside a fgroup field element we don't know what kind + * of field are we dealing with, so we should re-guess it as behat_form_field + * does. * * @package core_form * @category test diff --git a/lib/behat/form_field/behat_form_modvisible.php b/lib/behat/form_field/behat_form_modvisible.php index 04e65ffa634..74752b91d17 100644 --- a/lib/behat/form_field/behat_form_modvisible.php +++ b/lib/behat/form_field/behat_form_modvisible.php @@ -38,4 +38,5 @@ require_once(__DIR__ . '/behat_form_select.php'); * @copyright 2013 David Monllaó * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class behat_form_modvisible extends behat_form_select {} +class behat_form_modvisible extends behat_form_select { +} diff --git a/lib/behat/form_field/behat_form_radio.php b/lib/behat/form_field/behat_form_radio.php index 27b5d005631..8304133dae6 100644 --- a/lib/behat/form_field/behat_form_radio.php +++ b/lib/behat/form_field/behat_form_radio.php @@ -89,9 +89,6 @@ class behat_form_radio extends behat_form_checkbox { * @return bool */ public function matches($expectedvalue = false) { - if (trim($expectedvalue) != trim($this->get_value())) { - return false; - } - return true; + return $this->text_matches($expectedvalue); } } diff --git a/lib/behat/form_field/behat_form_select.php b/lib/behat/form_field/behat_form_select.php index d0911d6c8b2..dcc6acef7dd 100644 --- a/lib/behat/form_field/behat_form_select.php +++ b/lib/behat/form_field/behat_form_select.php @@ -204,7 +204,10 @@ class behat_form_select extends behat_form_field { // Same implementation as the parent if it is a single select. if (!$multiple) { - if (trim($expectedvalue) != trim($this->get_value())) { + $cleanexpectedvalue = trim($expectedvalue); + $selectedtext = trim($this->get_selected_options()); + $selectedvalue = trim($this->get_selected_options(false)); + if ($cleanexpectedvalue != $selectedvalue && $cleanexpectedvalue != $selectedtext) { return false; } return true; diff --git a/lib/behat/form_field/behat_form_selectyesno.php b/lib/behat/form_field/behat_form_selectyesno.php index 3759a17a21e..73f8bef779e 100644 --- a/lib/behat/form_field/behat_form_selectyesno.php +++ b/lib/behat/form_field/behat_form_selectyesno.php @@ -38,4 +38,5 @@ require_once(__DIR__ . '/behat_form_select.php'); * @copyright 2013 David Monllaó * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class behat_form_selectyesno extends behat_form_select {} +class behat_form_selectyesno extends behat_form_select { +} diff --git a/lib/behat/form_field/behat_form_text.php b/lib/behat/form_field/behat_form_text.php new file mode 100644 index 00000000000..dffdf86ffa2 --- /dev/null +++ b/lib/behat/form_field/behat_form_text.php @@ -0,0 +1,69 @@ +. + +/** + * Text field class. + * + * @package core_form + * @category test + * @copyright 2014 David Monllaó + * @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_field.php'); + +/** + * Class for test-based fields. + * + * @package core_form + * @category test + * @copyright 2014 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_form_text extends behat_form_field { + + /** + * Sets the value to a field. + * + * @param string $value + * @return void + */ + public function set_value($value) { + $this->field->setValue($value); + } + + /** + * Returns the current value of the element. + * + * @return string + */ + public function get_value() { + return $this->field->getValue(); + } + + /** + * Matches the provided value against the current field value. + * + * @param string $expectedvalue + * @return bool The provided value matches the field value? + */ + public function matches($expectedvalue) { + return $this->text_matches($expectedvalue); + } + +} diff --git a/lib/behat/form_field/behat_form_textarea.php b/lib/behat/form_field/behat_form_textarea.php new file mode 100644 index 00000000000..c1730c287f9 --- /dev/null +++ b/lib/behat/form_field/behat_form_textarea.php @@ -0,0 +1,39 @@ +. + +/** + * Textarea field class. + * + * @package core_form + * @category test + * @copyright 2014 David Monllaó + * @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'); + +/** + * Textarea field class. + * + * @package core_form + * @category test + * @copyright 2014 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_form_textarea extends behat_form_text { +}