weekly release 2.6dev
[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
51 * @param string $locator The locator to help give more info about the possible problem.
52 * @param Session $session The behat browser session
53 * @return behat_form_field
54 */
55 public static function get_field(NodeElement $fieldnode, $locator, Session $session) {
a4534dce
DM
56
57 // Get the field type if is part of a moodleform.
58 if (self::is_moodleform_field($fieldnode)) {
59 $type = self::get_node_type($fieldnode, $locator, $session);
60 }
61
62 // If is not a moodleforms field use the base field type.
63 if (empty($type)) {
64 $type = 'field';
65 }
66
3a4d76ac
DM
67 return self::get_field_instance($type, $fieldnode, $session);
68 }
69
70 /**
71 * Returns the appropiate behat_form_field according to the provided type.
72 *
73 * It defaults to behat_form_field.
74 *
75 * @param string $type The field type (checkbox, date_selector, text...)
76 * @param NodeElement $fieldnode
77 * @param Session $session The behat session
78 * @return behat_form_field
79 */
80 public static function get_field_instance($type, NodeElement $fieldnode, Session $session) {
81
82 global $CFG;
83
a4534dce
DM
84 $classname = 'behat_form_' . $type;
85
86 // Fallsback on the default form field if nothing specific exists.
87 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
88 if (!file_exists($classpath)) {
89 $classname = 'behat_form_field';
90 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
91 }
92
93 // Returns the instance.
94 require_once($classpath);
95 return new $classname($session, $fieldnode);
96 }
97
98 /**
99 * Detects when the field is a moodleform field type.
100 *
101 * Note that there are fields inside moodleforms that are not
102 * moodleform element; this method can not detect this, this will
103 * be managed by get_node_type, after failing to find the form
104 * element element type.
105 *
106 * @param NodeElement $fieldnode
107 * @return bool
108 */
109 protected static function is_moodleform_field(NodeElement $fieldnode) {
110
111 // We already waited when getting the NodeElement and we don't want an exception if it's not part of a moodleform.
112 $parentformfound = $fieldnode->find('xpath', "/ancestor::form[contains(concat(' ', normalize-space(@class), ' '), ' mform ')]/fieldset");
113
114 return ($parentformfound != false);
115 }
116
117 /**
118 * Recursive method to find the field type.
119 *
120 * Depending on the field the felement class node is a level or in another. We
121 * look recursively for a parent node with a 'felement' class to find the field type.
122 *
123 * @param NodeElement $fieldnode The current node.
124 * @param string $locator Just to send an exception that makes sense for the user.
125 * @param Session $session The behat browser session
126 * @return mixed A NodeElement if we continue looking for the element type and String or false when we are done.
127 */
128 protected static function get_node_type(NodeElement $fieldnode, $locator, Session $session) {
129
130 // We look for a parent node with 'felement' class.
131 if ($class = $fieldnode->getParent()->getAttribute('class')) {
132
133 if (strstr($class, 'felement') != false) {
134 // Remove 'felement f' from class value.
135 return substr($class, 10);
136 }
137
138 // Stop propagation through the DOM, if it does not have a felement is not part of a moodle form.
139 if (strstr($class, 'fcontainer') != false) {
140 return false;
141 }
142 }
143
144 return self::get_node_type($fieldnode->getParent(), $locator, $session);
145 }
146
147}