MDL-38026 behat: New tests
[moodle.git] / lib / tests / behat / behat_forms.php
CommitLineData
23ebc481
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 * Steps definitions related with forms.
19 *
20 * @package core
21 * @category test
22 * @copyright 2012 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
28require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
29
30use Behat\Behat\Context\Step\Given as Given,
31 Behat\Behat\Context\Step\When as When,
32 Behat\Behat\Context\Step\Then as Then,
33 Behat\Gherkin\Node\TableNode as TableNode,
34 Behat\Mink\Element\NodeElement as NodeElement,
35 Behat\Mink\Exception\ExpectationException as ExpectationException,
36 Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
37
38/**
39 * Forms-related steps definitions.
40 *
41 * @package core
42 * @category test
43 * @copyright 2012 David MonllaĆ³
44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 */
46class behat_forms extends behat_base {
47
48 /**
49 * Presses button with specified id|name|title|alt|value.
50 *
23ebc481 51 * @When /^I press "(?P<button_string>(?:[^"]|\\")*)"$/
1f9ffbdb 52 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 53 * @param string $button
23ebc481
DM
54 */
55 public function press_button($button) {
1f9ffbdb
DM
56
57 // Ensures the button is present.
58 $buttonnode = $this->find_button($button);
59 $buttonnode->press();
23ebc481
DM
60 }
61
62 /**
63 * Fills a moodle form with field/value data.
64 *
23ebc481 65 * @Given /^I fill the moodle form with:$/
1f9ffbdb 66 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
67 * @param TableNode $data
68 */
69 public function i_fill_the_moodle_form_with(TableNode $data) {
70
71 $datahash = $data->getRowsHash();
72
73 // The action depends on the field type.
74 foreach ($datahash as $locator => $value) {
75
76 unset($fieldnode);
77
1f9ffbdb
DM
78 // Getting the NodeElement.
79 $fieldnode = $this->find_field($locator);
23ebc481
DM
80
81 // Gets the field type from a parent node.
82 $field = $this->get_field($fieldnode, $locator);
83
84 // Delegates to the field class.
23ebc481
DM
85 $field->set_value($value);
86 }
87 }
88
89 /**
90 * Fills in form field with specified id|name|label|value.
91 *
23ebc481 92 * @When /^I fill in "(?P<field_string>(?:[^"]|\\")*)" with "(?P<value_string>(?:[^"]|\\")*)"$/
1f9ffbdb 93 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
94 * @param string $field
95 * @param string $value
23ebc481
DM
96 */
97 public function fill_field($field, $value) {
1f9ffbdb
DM
98
99 $fieldnode = $this->find_field($field);
100 $fieldnode->setValue($value);
23ebc481
DM
101 }
102
103 /**
104 * Selects option in select field with specified id|name|label|value.
105 *
23ebc481 106 * @When /^I select "(?P<option_string>(?:[^"]|\\")*)" from "(?P<select_string>(?:[^"]|\\")*)"$/
1f9ffbdb 107 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
108 * @param string $option
109 * @param string $select
23ebc481
DM
110 */
111 public function select_option($option, $select) {
23ebc481 112
1f9ffbdb 113 $selectnode = $this->find_field($select);
23ebc481 114 $selectnode->selectOption($option);
1f9ffbdb
DM
115
116 // Adding a click as Selenium requires it to fire some JS events.
23ebc481
DM
117 $selectnode->click();
118 }
119
120 /**
121 * Checks checkbox with specified id|name|label|value.
122 *
23ebc481 123 * @When /^I check "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb 124 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 125 * @param string $option
23ebc481
DM
126 */
127 public function check_option($option) {
1f9ffbdb
DM
128
129 $checkboxnode = $this->find_field($option);
130 $checkboxnode->check();
23ebc481
DM
131 }
132
133 /**
134 * Unchecks checkbox with specified id|name|label|value.
135 *
23ebc481 136 * @When /^I uncheck "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb 137 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 138 * @param string $option
23ebc481
DM
139 */
140 public function uncheck_option($option) {
1f9ffbdb
DM
141
142 $checkboxnode = $this->find_field($option);
143 $checkboxnode->uncheck();
23ebc481
DM
144 }
145
146 /**
147 * Checks that the form element field have the specified value.
148 *
23ebc481 149 * @Then /^the "(?P<field_string>(?:[^"]|\\")*)" field should match "(?P<value_string>(?:[^"]|\\")*)" value$/
1f9ffbdb
DM
150 * @throws ExpectationException
151 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
152 * @param string $locator
153 * @param string $value
23ebc481
DM
154 */
155 public function the_field_should_match_value($locator, $value) {
156
1f9ffbdb 157 $fieldnode = $this->find_field($locator);
23ebc481
DM
158
159 // Gets the field instance.
160 $field = $this->get_field($fieldnode, $locator);
161
162 // Checks if the provided value matches the current field value.
163 if ($value != $field->get_value()) {
164 throw new ExpectationException(
165 'The \'' . $locator . '\' value is \'' . $field->get_value() . '\'' ,
166 $this->getSession()
167 );
168 }
169 }
170
171 /**
172 * Checks, that checkbox with specified in|name|label|value is checked.
173 *
23ebc481 174 * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should be checked$/
1f9ffbdb 175 * @see Behat\MinkExtension\Context\MinkContext
46ac40cd 176 * @param string $checkbox
23ebc481
DM
177 */
178 public function assert_checkbox_checked($checkbox) {
23ebc481
DM
179 $this->assertSession()->checkboxChecked($checkbox);
180 }
181
182 /**
183 * Checks, that checkbox with specified in|name|label|value is unchecked.
184 *
23ebc481 185 * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should not be checked$/
1f9ffbdb 186 * @see Behat\MinkExtension\Context\MinkContext
46ac40cd 187 * @param string $checkbox
23ebc481
DM
188 */
189 public function assert_checkbox_not_checked($checkbox) {
23ebc481
DM
190 $this->assertSession()->checkboxNotChecked($checkbox);
191 }
192
193 /**
194 * Checks, that given select box contains the specified option.
195 *
23ebc481 196 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
197 * @throws ExpectationException
198 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
199 * @param string $select The select element name
200 * @param string $option The option text/value
201 */
202 public function the_select_box_should_contain($select, $option) {
203
1f9ffbdb 204 $selectnode = $this->find_field($select);
23ebc481
DM
205
206 $regex = '/' . preg_quote($option, '/') . '/ui';
207 if (!preg_match($regex, $selectnode->getText())) {
208 throw new ExpectationException(
209 'The select box "' . $select . '" does not contains the option "' . $option . '"',
210 $this->getSession()
211 );
212 }
213
214 }
215
216 /**
217 * Checks, that given select box does not contain the specified option.
218 *
23ebc481 219 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should not contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
220 * @throws ExpectationException
221 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
222 * @param string $select The select element name
223 * @param string $option The option text/value
224 */
225 public function the_select_box_should_not_contain($select, $option) {
226
1f9ffbdb 227 $selectnode = $this->find_field($select);
23ebc481
DM
228
229 $regex = '/' . preg_quote($option, '/') . '/ui';
230 if (preg_match($regex, $selectnode->getText())) {
231 throw new ExpectationException(
232 'The select box "' . $select . '" contains the option "' . $option . '"',
233 $this->getSession()
234 );
235 }
236 }
237
238 /**
239 * Gets an instance of the form element field.
240 *
241 * @param NodeElement $fieldnode The current node
242 * @param string $locator Just to send an exception that makes sense for the user
243 * @return behat_form_field
244 */
245 protected function get_field(NodeElement $fieldnode, $locator) {
246 global $CFG;
247
23ebc481
DM
248 // Get the field type.
249 $type = $this->get_node_type($fieldnode, $locator);
250 $classname = 'behat_form_' . $type;
251
252 // Fallsback on the default form field if nothing specific exists.
253 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
254 if (!file_exists($classpath)) {
255 $classname = 'behat_form_field';
256 $classpath = $CFG->libdir . '/behat/form_field/' . $classname . '.php';
257 }
258
259 // Returns the instance.
260 require_once($classpath);
261 return new $classname($this->getSession(), $fieldnode);
262 }
263
264 /**
265 * Recursive method to find the field type.
266 *
267 * Depending on the field the felement class node is a level or in another. We
268 * look recursively for a parent node with a 'felement' class to find the field type.
269 *
270 * @throws ExpectationException
271 * @param NodeElement $fieldnode The current node
272 * @param string $locator Just to send an exception that makes sense for the user
273 * @return mixed String or NodeElement depending if we have reached the felement node
274 */
275 protected function get_node_type(NodeElement $fieldnode, $locator) {
276
23ebc481
DM
277 // We look for a parent node with 'felement' class.
278 if ($class = $fieldnode->getParent()->getAttribute('class')) {
279
280 if (strstr($class, 'felement') != false) {
281 // Remove 'felement f' from class value.
282 return substr($class, 10);
283 }
284
285 // Stop propagation through the DOM, something went wrong!.
286 if (strstr($class, 'fcontainer') != false) {
287 throw new ExpectationException('No field type for ' . $locator . ' found, ensure the field exists', $this->getSession());
288 }
289 }
290
291 return $this->get_node_type($fieldnode->getParent(), $locator);
292 }
293
294}