MDL-43738 behat: More info about how to get/set fields
[moodle.git] / lib / behat / behat_field_manager.php
CommitLineData
a4534dce
DM
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Form fields helper.
19 *
20 * @package core
21 * @category test
22 * @copyright 2013 David MonllaĆ³
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
27
28use Behat\Mink\Session as Session,
29 Behat\Mink\Element\NodeElement as NodeElement;
30
31/**
32 * Helper to interact with form fields.
33 *
34 * @package core
35 * @category test
36 * @copyright 2013 David MonllaĆ³
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class behat_field_manager {
40
41 /**
42 * Gets an instance of the form field.
43 *
44 * Not all the fields are part of a moodle form, in this
45 * cases it fallsback to the generic form field. Also note
46 * that this generic field type is using a generic setValue()
47 * method from the Behat API, which is not always good to set
48 * the value of form elements.
49 *
50 * @param NodeElement $fieldnode
a4534dce
DM
51 * @param Session $session The behat browser session
52 * @return behat_form_field
53 */
051e9663 54 public static function get_form_field(NodeElement $fieldnode, Session $session) {
a4534dce
DM
55
56 // Get the field type if is part of a moodleform.
57 if (self::is_moodleform_field($fieldnode)) {
051e9663 58 $type = self::get_field_node_type($fieldnode, $session);
a4534dce
DM
59 }
60
61 // If is not a moodleforms field use the base field type.
62 if (empty($type)) {
63 $type = 'field';
64 }
65
3a4d76ac
DM
66 return self::get_field_instance($type, $fieldnode, $session);
67 }
68
69 /**
70 * Returns the appropiate behat_form_field according to the provided type.
71 *
72 * It defaults to behat_form_field.
73 *
74 * @param string $type The field type (checkbox, date_selector, text...)
75 * @param NodeElement $fieldnode
76 * @param Session $session The behat session
77 * @return behat_form_field
78 */
79 public static function get_field_instance($type, NodeElement $fieldnode, Session $session) {
80
81 global $CFG;
82
a4534dce
DM
83 $classname = 'behat_form_' . $type;
84
85 // Fallsback on the default form field if nothing specific exists.
86 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
87 if (!file_exists($classpath)) {
88 $classname = 'behat_form_field';
89 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
90 }
91
92 // Returns the instance.
93 require_once($classpath);
94 return new $classname($session, $fieldnode);
95 }
96
97 /**
98 * Detects when the field is a moodleform field type.
99 *
100 * Note that there are fields inside moodleforms that are not
101 * moodleform element; this method can not detect this, this will
051e9663 102 * be managed by get_field_node_type, after failing to find the form
a4534dce
DM
103 * element element type.
104 *
105 * @param NodeElement $fieldnode
106 * @return bool
107 */
108 protected static function is_moodleform_field(NodeElement $fieldnode) {
109
110 // We already waited when getting the NodeElement and we don't want an exception if it's not part of a moodleform.
111 $parentformfound = $fieldnode->find('xpath', "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]/fieldset");
112
113 return ($parentformfound != false);
114 }
115
116 /**
117 * Recursive method to find the field type.
118 *
051e9663 119 * Depending on the field the felement class node is in a level or in another. We
a4534dce
DM
120 * look recursively for a parent node with a 'felement' class to find the field type.
121 *
122 * @param NodeElement $fieldnode The current node.
a4534dce
DM
123 * @param Session $session The behat browser session
124 * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
125 */
051e9663 126 protected static function get_field_node_type(NodeElement $fieldnode, Session $session) {
a4534dce
DM
127
128 // We look for a parent node with 'felement' class.
129 if ($class = $fieldnode->getParent()->getAttribute('class')) {
130
131 if (strstr($class, 'felement') != false) {
132 // Remove 'felement f' from class value.
133 return substr($class, 10);
134 }
135
136 // Stop propagation through the DOM, if it does not have a felement is not part of a moodle form.
137 if (strstr($class, 'fcontainer') != false) {
138 return false;
139 }
140 }
141
051e9663
DM
142 return self::get_field_node_type($fieldnode->getParent(), $session);
143 }
144
145 /**
146 * Gets an instance of the form field.
147 *
148 * Not all the fields are part of a moodle form, in this
149 * cases it fallsback to the generic form field. Also note
150 * that this generic field type is using a generic setValue()
151 * method from the Behat API, which is not always good to set
152 * the value of form elements.
153 *
154 * @deprecated since Moodle 2.6 MDL-39634 - please do not use this function any more.
155 * @todo MDL-XXXXX This will be deleted in Moodle 2.8
156 * @see behat_field_manager::get_form_field()
157 * @param NodeElement $fieldnode
158 * @param Session $session The behat browser session
159 * @return behat_form_field
160 */
161 public static function get_field(NodeElement $fieldnode, $locator, Session $session) {
162 debugging('Function behat_field_manager::get_field() is deprecated, ' .
163 'please use function behat_field_manager::get_form_field() instead', DEBUG_DEVELOPER);
164
165 return self::get_form_field($fieldnode, $session);
166 }
167
168 /**
169 * Recursive method to find the field type.
170 *
171 * Depending on the field the felement class node is in a level or in another. We
172 * look recursively for a parent node with a 'felement' class to find the field type.
173 *
174 * @deprecated since Moodle 2.6 MDL-39634 - please do not use this function any more.
175 * @todo MDL-XXXXX This will be deleted in Moodle 2.8
176 * @see behat_field_manager::get_field_node_type()
177 * @param NodeElement $fieldnode The current node.
178 * @param Session $session The behat browser session
179 * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
180 */
181 protected static function get_node_type(NodeElement $fieldnode, $locator, Session $session) {
182 debugging('Function behat_field_manager::get_node_type() is deprecated, ' .
183 'please use function behat_field_manager::get_field_node_type() instead', DEBUG_DEVELOPER);
184
185 return self::get_field_node_type($fieldnode, $session);
a4534dce
DM
186 }
187
188}