diff --git a/lib/behat/behat_field_manager.php b/lib/behat/behat_field_manager.php new file mode 100644 index 00000000000..01cc96560f0 --- /dev/null +++ b/lib/behat/behat_field_manager.php @@ -0,0 +1,131 @@ +. + +/** + * Form fields helper. + * + * @package core + * @category test + * @copyright 2013 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. + +use Behat\Mink\Session as Session, + Behat\Mink\Element\NodeElement as NodeElement; + +/** + * Helper to interact with form fields. + * + * @package core + * @category test + * @copyright 2013 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_field_manager { + + /** + * Gets an instance of the form field. + * + * Not all the fields are part of a moodle form, in this + * cases it fallsback to the generic form field. Also note + * that this generic field type is using a generic setValue() + * method from the Behat API, which is not always good to set + * the value of form elements. + * + * @param NodeElement $fieldnode + * @param string $locator The locator to help give more info about the possible problem. + * @param Session $session The behat browser session + * @return behat_form_field + */ + public static function get_field(NodeElement $fieldnode, $locator, Session $session) { + global $CFG; + + // Get the field type if is part of a moodleform. + if (self::is_moodleform_field($fieldnode)) { + $type = self::get_node_type($fieldnode, $locator, $session); + } + + // If is not a moodleforms field use the base field type. + if (empty($type)) { + $type = 'field'; + } + + $classname = 'behat_form_' . $type; + + // Fallsback on the default form field if nothing specific exists. + $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php'; + if (!file_exists($classpath)) { + $classname = 'behat_form_field'; + $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php'; + } + + // Returns the instance. + require_once($classpath); + return new $classname($session, $fieldnode); + } + + /** + * Detects when the field is a moodleform field type. + * + * Note that there are fields inside moodleforms that are not + * moodleform element; this method can not detect this, this will + * be managed by get_node_type, after failing to find the form + * element element type. + * + * @param NodeElement $fieldnode + * @return bool + */ + 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"); + + return ($parentformfound != false); + } + + /** + * Recursive method to find the field type. + * + * Depending on the field the felement class node is a level or in another. We + * look recursively for a parent node with a 'felement' class to find the field type. + * + * @param NodeElement $fieldnode The current node. + * @param string $locator Just to send an exception that makes sense for the user. + * @param Session $session The behat browser session + * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done. + */ + protected static function get_node_type(NodeElement $fieldnode, $locator, Session $session) { + + // We look for a parent node with 'felement' class. + if ($class = $fieldnode->getParent()->getAttribute('class')) { + + if (strstr($class, 'felement') != false) { + // Remove 'felement f' from class value. + return substr($class, 10); + } + + // Stop propagation through the DOM, if it does not have a felement is not part of a moodle form. + if (strstr($class, 'fcontainer') != false) { + return false; + } + } + + return self::get_node_type($fieldnode->getParent(), $locator, $session); + } + +} diff --git a/lib/behat/form_field/behat_form_field.php b/lib/behat/form_field/behat_form_field.php index 5f19d59a53d..938bde631e8 100644 --- a/lib/behat/form_field/behat_form_field.php +++ b/lib/behat/form_field/behat_form_field.php @@ -48,7 +48,7 @@ class behat_form_field { /** * @var NodeElement The field DOM node to interact with. */ - protected $fieldnode; + protected $field; /** * General constructor with the node and the session to interact with. diff --git a/lib/tests/behat/behat_forms.php b/lib/tests/behat/behat_forms.php index 78cda2b7d0e..4ce80619172 100644 --- a/lib/tests/behat/behat_forms.php +++ b/lib/tests/behat/behat_forms.php @@ -26,6 +26,7 @@ // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); +require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php'); use Behat\Behat\Context\Step\Given as Given, Behat\Behat\Context\Step\When as When, @@ -76,13 +77,11 @@ class behat_forms extends behat_base { // The action depends on the field type. foreach ($datahash as $locator => $value) { - unset($fieldnode); - - // Getting the NodeElement. + // Getting the node element pointed by the label. $fieldnode = $this->find_field($locator); // Gets the field type from a parent node. - $field = $this->get_field($fieldnode, $locator); + $field = behat_field_manager::get_field($fieldnode, $locator, $this->getSession()); // Delegates to the field class. $field->set_value($value); @@ -220,7 +219,7 @@ class behat_forms extends behat_base { $fieldnode = $this->find_field($locator); // Get the field. - $field = $this->get_field($fieldnode, $locator); + $field = behat_field_manager::get_field($fieldnode, $locator, $this->getSession()); $fieldvalue = $field->get_value(); // Checks if the provided value matches the current field value. @@ -299,92 +298,4 @@ class behat_forms extends behat_base { } } - /** - * Gets an instance of the form field. - * - * Not all the fields are part of a moodle form, in this - * cases it fallsback to the generic form field. Also note - * that this generic field type is using a generic setValue() - * method from the Behat API, which is not always good to set - * the value of form elements. - * - * @param NodeElement $fieldnode The current node - * @param string $locator Just to send an exception that makes sense for the user - * @return behat_form_field - */ - protected function get_field(NodeElement $fieldnode, $locator) { - global $CFG; - - // Get the field type if is part of a moodleform. - if ($this->is_moodleform_field($fieldnode)) { - $type = $this->get_node_type($fieldnode, $locator); - } - - // If is not a moodleforms field use the base field type. - if (empty($type)) { - $type = 'field'; - } - - $classname = 'behat_form_' . $type; - - // Fallsback on the default form field if nothing specific exists. - $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php'; - if (!file_exists($classpath)) { - $classname = 'behat_form_field'; - $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php'; - } - - // Returns the instance. - require_once($classpath); - return new $classname($this->getSession(), $fieldnode); - } - - /** - * Detects when the field is a moodleform field type. - * - * Note that there are fields inside moodleforms that are not - * moodleform element; this method can not detect this, this will - * be managed by get_node_type, after failing to find the form - * element element type. - * - * @param NodeElement $fieldnode - * @return bool - */ - protected 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"); - - return ($parentformfound != false); - } - - /** - * Recursive method to find the field type. - * - * Depending on the field the felement class node is a level or in another. We - * look recursively for a parent node with a 'felement' class to find the field type. - * - * @param NodeElement $fieldnode The current node. - * @param string $locator Just to send an exception that makes sense for the user. - * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done. - */ - protected function get_node_type(NodeElement $fieldnode, $locator) { - - // We look for a parent node with 'felement' class. - if ($class = $fieldnode->getParent()->getAttribute('class')) { - - if (strstr($class, 'felement') != false) { - // Remove 'felement f' from class value. - return substr($class, 10); - } - - // Stop propagation through the DOM, if it does not have a felement is not part of a moodle form. - if (strstr($class, 'fcontainer') != false) { - return false; - } - } - - return $this->get_node_type($fieldnode->getParent(), $locator); - } - }