MDL-44619 behat: filemanager field manager
[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
8aff0eec
DM
83 // If the field is not part of a moodleform, we should still try to find out
84 // which field type are we dealing with.
85 if ($type == 'field' &&
86 $guessedtype = self::guess_field_type($fieldnode, $session)) {
87 $type = $guessedtype;
88 }
89
a4534dce
DM
90 $classname = 'behat_form_' . $type;
91
8aff0eec 92 // Fallsback on the type guesser if nothing specific exists.
a4534dce
DM
93 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
94 if (!file_exists($classpath)) {
95 $classname = 'behat_form_field';
96 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
97 }
98
99 // Returns the instance.
100 require_once($classpath);
101 return new $classname($session, $fieldnode);
102 }
103
8aff0eec
DM
104 /**
105 * Guesses a basic field type and returns it.
106 *
107 * This method is intended to detect HTML form fields when no
108 * moodleform-specific elements have been detected.
109 *
110 * @param NodeElement $fieldnode
111 * @param Session $session
112 * @return string|bool The field type or false.
113 */
114 public static function guess_field_type(NodeElement $fieldnode, Session $session) {
115
116 // Textareas are considered text based elements.
117 $tagname = strtolower($fieldnode->getTagName());
118 if ($tagname == 'textarea') {
119
120 // If there is an iframe with $id + _ifr there a TinyMCE editor loaded.
786ced99 121 $xpath = '//div[@id="' . $fieldnode->getAttribute('id') . 'editable"]';
8aff0eec
DM
122 if ($session->getPage()->find('xpath', $xpath)) {
123 return 'editor';
124 }
125 return 'textarea';
126
127 } else if ($tagname == 'input') {
128 $type = $fieldnode->getAttribute('type');
129 switch ($type) {
130 case 'text':
131 case 'password':
132 case 'email':
133 case 'file':
134 return 'text';
135 case 'checkbox':
136 return 'checkbox';
137 break;
138 case 'radio':
139 return 'radio';
140 break;
141 default:
142 // Here we return false because all text-based
143 // fields should be included in the first switch case.
144 return false;
145 }
146
147 } else if ($tagname == 'select') {
148 // Select tag.
149 return 'select';
150 }
151
152 // We can not provide a closer field type.
153 return false;
154 }
155
a4534dce
DM
156 /**
157 * Detects when the field is a moodleform field type.
158 *
159 * Note that there are fields inside moodleforms that are not
160 * moodleform element; this method can not detect this, this will
051e9663 161 * be managed by get_field_node_type, after failing to find the form
a4534dce
DM
162 * element element type.
163 *
164 * @param NodeElement $fieldnode
165 * @return bool
166 */
167 protected static function is_moodleform_field(NodeElement $fieldnode) {
168
169 // We already waited when getting the NodeElement and we don't want an exception if it's not part of a moodleform.
8aff0eec
DM
170 $parentformfound = $fieldnode->find('xpath',
171 "/ancestor::fieldset" .
172 "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]"
173 );
a4534dce
DM
174
175 return ($parentformfound != false);
176 }
177
178 /**
179 * Recursive method to find the field type.
180 *
051e9663 181 * Depending on the field the felement class node is in a level or in another. We
a4534dce
DM
182 * look recursively for a parent node with a 'felement' class to find the field type.
183 *
184 * @param NodeElement $fieldnode The current node.
a4534dce
DM
185 * @param Session $session The behat browser session
186 * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
187 */
051e9663 188 protected static function get_field_node_type(NodeElement $fieldnode, Session $session) {
a4534dce
DM
189
190 // We look for a parent node with 'felement' class.
191 if ($class = $fieldnode->getParent()->getAttribute('class')) {
192
193 if (strstr($class, 'felement') != false) {
194 // Remove 'felement f' from class value.
195 return substr($class, 10);
196 }
197
198 // Stop propagation through the DOM, if it does not have a felement is not part of a moodle form.
199 if (strstr($class, 'fcontainer') != false) {
200 return false;
201 }
202 }
203
051e9663
DM
204 return self::get_field_node_type($fieldnode->getParent(), $session);
205 }
206
207 /**
208 * Gets an instance of the form field.
209 *
210 * Not all the fields are part of a moodle form, in this
211 * cases it fallsback to the generic form field. Also note
212 * that this generic field type is using a generic setValue()
213 * method from the Behat API, which is not always good to set
214 * the value of form elements.
215 *
216 * @deprecated since Moodle 2.6 MDL-39634 - please do not use this function any more.
217 * @todo MDL-XXXXX This will be deleted in Moodle 2.8
218 * @see behat_field_manager::get_form_field()
219 * @param NodeElement $fieldnode
220 * @param Session $session The behat browser session
221 * @return behat_form_field
222 */
223 public static function get_field(NodeElement $fieldnode, $locator, Session $session) {
224 debugging('Function behat_field_manager::get_field() is deprecated, ' .
225 'please use function behat_field_manager::get_form_field() instead', DEBUG_DEVELOPER);
226
227 return self::get_form_field($fieldnode, $session);
228 }
229
230 /**
231 * Recursive method to find the field type.
232 *
233 * Depending on the field the felement class node is in a level or in another. We
234 * look recursively for a parent node with a 'felement' class to find the field type.
235 *
236 * @deprecated since Moodle 2.6 MDL-39634 - please do not use this function any more.
237 * @todo MDL-XXXXX This will be deleted in Moodle 2.8
238 * @see behat_field_manager::get_field_node_type()
239 * @param NodeElement $fieldnode The current node.
240 * @param Session $session The behat browser session
241 * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
242 */
243 protected static function get_node_type(NodeElement $fieldnode, $locator, Session $session) {
244 debugging('Function behat_field_manager::get_node_type() is deprecated, ' .
245 'please use function behat_field_manager::get_field_node_type() instead', DEBUG_DEVELOPER);
246
247 return self::get_field_node_type($fieldnode, $session);
a4534dce
DM
248 }
249
250}