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