MDL-39635 behat: XPath cleanups
[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');
a4534dce 29require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php');
23ebc481
DM
30
31use Behat\Behat\Context\Step\Given as Given,
32 Behat\Behat\Context\Step\When as When,
33 Behat\Behat\Context\Step\Then as Then,
34 Behat\Gherkin\Node\TableNode as TableNode,
35 Behat\Mink\Element\NodeElement as NodeElement,
36 Behat\Mink\Exception\ExpectationException as ExpectationException,
37 Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
38
39/**
40 * Forms-related steps definitions.
41 *
42 * @package core
43 * @category test
44 * @copyright 2012 David MonllaĆ³
45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46 */
47class behat_forms extends behat_base {
48
49 /**
50 * Presses button with specified id|name|title|alt|value.
51 *
23ebc481 52 * @When /^I press "(?P<button_string>(?:[^"]|\\")*)"$/
1f9ffbdb 53 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 54 * @param string $button
23ebc481
DM
55 */
56 public function press_button($button) {
1f9ffbdb
DM
57
58 // Ensures the button is present.
59 $buttonnode = $this->find_button($button);
60 $buttonnode->press();
23ebc481
DM
61 }
62
63 /**
64 * Fills a moodle form with field/value data.
65 *
23ebc481 66 * @Given /^I fill the moodle form with:$/
1f9ffbdb 67 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
68 * @param TableNode $data
69 */
70 public function i_fill_the_moodle_form_with(TableNode $data) {
71
f8f1bdc3
DM
72 // Expand all fields in case we have.
73 $this->expand_all_fields();
74
23ebc481
DM
75 $datahash = $data->getRowsHash();
76
77 // The action depends on the field type.
78 foreach ($datahash as $locator => $value) {
79
a4534dce 80 // Getting the node element pointed by the label.
1f9ffbdb 81 $fieldnode = $this->find_field($locator);
23ebc481
DM
82
83 // Gets the field type from a parent node.
051e9663 84 $field = behat_field_manager::get_form_field($fieldnode, $this->getSession());
23ebc481
DM
85
86 // Delegates to the field class.
23ebc481
DM
87 $field->set_value($value);
88 }
89 }
90
f8f1bdc3
DM
91 /**
92 * Expands all moodleform's fields, including collapsed fieldsets and advanced fields if they are present.
93 * @Given /^I expand all fieldsets$/
94 */
95 public function i_expand_all_fieldsets() {
96 $this->expand_all_fields();
97 }
98
99 /**
100 * Expands all moodle form fieldsets if they exists.
101 *
102 * Externalized from i_expand_all_fields to call it from
103 * other form-related steps without having to use steps-group calls.
104 *
105 * @throws ElementNotFoundException Thrown by behat_base::find_all
106 * @return void
107 */
108 protected function expand_all_fields() {
109
110 // behat_base::find() throws an exception if there are no elements, we should not fail a test because of this.
111 try {
112
113 // Expand fieldsets.
0b8bb3fe 114 $fieldsets = $this->find_all('css', 'fieldset.collapsed a.fheader');
f8f1bdc3
DM
115
116 // We are supposed to have fieldsets here, otherwise exception.
117
118 // Funny thing about this, with find_all() we specify a pattern and each element matching the pattern is added to the array
119 // with of xpaths with a [0], [1]... sufix, but when we click on an element it does not matches the specified xpath
120 // anymore (is not collapsed) so [1] becomes [0], that's why we always click on the first XPath match, will be always the next one.
121 $iterations = count($fieldsets);
122 for ($i = 0; $i < $iterations; $i++) {
123 $fieldsets[0]->click();
124 }
125
126 } catch (ElementNotFoundException $e) {
127 // We continue if there are not expanded fields.
128 }
129
130 // Different try & catch as we can have expanded fieldsets with advanced fields on them.
131 try {
132
133 // Show all fields.
134 $showmorestr = get_string('showmore', 'form');
38976081
DM
135 $showmores = $this->find_all('xpath', "//a[normalize-space(.)='" . $showmorestr . "']" .
136 "[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler ')]");
f8f1bdc3
DM
137
138 // We are supposed to have 'show more's here, otherwise exception.
139
140 // Same funny case, after clicking on the element the [1] showmore link becomes the [0].
141 $iterations = count($showmores);
142 for ($i = 0; $i < $iterations; $i++) {
143 $showmores[0]->click();
144 }
145
146 } catch (ElementNotFoundException $e) {
147 // We continue with the test.
148 }
149
150 }
151
23ebc481
DM
152 /**
153 * Fills in form field with specified id|name|label|value.
154 *
23ebc481 155 * @When /^I fill in "(?P<field_string>(?:[^"]|\\")*)" with "(?P<value_string>(?:[^"]|\\")*)"$/
1f9ffbdb 156 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
157 * @param string $field
158 * @param string $value
23ebc481
DM
159 */
160 public function fill_field($field, $value) {
1f9ffbdb
DM
161
162 $fieldnode = $this->find_field($field);
163 $fieldnode->setValue($value);
23ebc481
DM
164 }
165
166 /**
167 * Selects option in select field with specified id|name|label|value.
168 *
23ebc481 169 * @When /^I select "(?P<option_string>(?:[^"]|\\")*)" from "(?P<select_string>(?:[^"]|\\")*)"$/
1f9ffbdb 170 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
171 * @param string $option
172 * @param string $select
23ebc481
DM
173 */
174 public function select_option($option, $select) {
23ebc481 175
1f9ffbdb 176 $selectnode = $this->find_field($select);
23ebc481 177 $selectnode->selectOption($option);
1f9ffbdb
DM
178
179 // Adding a click as Selenium requires it to fire some JS events.
cd7ea8f0 180 if ($this->running_javascript()) {
28abad1a 181
1fb97157
DM
182 // In some browsers the selectOption actions can perform a page reload
183 // so we need to ensure the element is still available to continue interacting
184 // with it. We don't wait here.
185 if (!$this->getSession()->getDriver()->find($selectnode->getXpath())) {
186 return;
187 }
188
38976081 189 // Single select needs an extra click in the option.
28abad1a 190 if (!$selectnode->hasAttribute('multiple')) {
38976081
DM
191
192 // Avoid quotes problems.
193 $option = $this->getSession()->getSelectorsHandler()->xpathLiteral($option);
194 $xpath = "//option[(./@value=$option or normalize-space(.)=$option)]";
28abad1a
DM
195 $optionnode = $this->find('xpath', $xpath, false, $selectnode);
196 $optionnode->click();
197 } else {
198 // Multiple ones needs the click in the select.
199 $selectnode->click();
200 }
cd7ea8f0 201 }
23ebc481
DM
202 }
203
fb624374
DM
204 /**
205 * Selects the specified id|name|label from the specified radio button.
206 *
207 * @When /^I select "(?P<radio_button_string>(?:[^"]|\\")*)" radio button$/
208 * @throws ElementNotFoundException Thrown by behat_base::find
5cde7298 209 * @param string $radio The radio button id, name or label value
fb624374
DM
210 */
211 public function select_radio($radio) {
212
213 $radionode = $this->find_radio($radio);
214 $radionode->check();
215
216 // Adding a click as Selenium requires it to fire some JS events.
cd7ea8f0
DM
217 if ($this->running_javascript()) {
218 $radionode->click();
219 }
fb624374
DM
220 }
221
23ebc481
DM
222 /**
223 * Checks checkbox with specified id|name|label|value.
224 *
23ebc481 225 * @When /^I check "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb 226 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 227 * @param string $option
23ebc481
DM
228 */
229 public function check_option($option) {
1f9ffbdb
DM
230
231 $checkboxnode = $this->find_field($option);
232 $checkboxnode->check();
23ebc481
DM
233 }
234
235 /**
236 * Unchecks checkbox with specified id|name|label|value.
237 *
23ebc481 238 * @When /^I uncheck "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb 239 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd 240 * @param string $option
23ebc481
DM
241 */
242 public function uncheck_option($option) {
1f9ffbdb
DM
243
244 $checkboxnode = $this->find_field($option);
245 $checkboxnode->uncheck();
23ebc481
DM
246 }
247
248 /**
249 * Checks that the form element field have the specified value.
250 *
23ebc481 251 * @Then /^the "(?P<field_string>(?:[^"]|\\")*)" field should match "(?P<value_string>(?:[^"]|\\")*)" value$/
1f9ffbdb
DM
252 * @throws ExpectationException
253 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
254 * @param string $locator
255 * @param string $value
23ebc481
DM
256 */
257 public function the_field_should_match_value($locator, $value) {
258
1f9ffbdb 259 $fieldnode = $this->find_field($locator);
23ebc481 260
49d91129 261 // Get the field.
051e9663 262 $field = behat_field_manager::get_form_field($fieldnode, $this->getSession());
49d91129 263 $fieldvalue = $field->get_value();
23ebc481
DM
264
265 // Checks if the provided value matches the current field value.
15c7fb4a 266 if (trim($value) != trim($fieldvalue)) {
23ebc481 267 throw new ExpectationException(
49d91129 268 'The \'' . $locator . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' ,
23ebc481
DM
269 $this->getSession()
270 );
271 }
272 }
273
274 /**
275 * Checks, that checkbox with specified in|name|label|value is checked.
276 *
23ebc481 277 * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should be checked$/
1f9ffbdb 278 * @see Behat\MinkExtension\Context\MinkContext
46ac40cd 279 * @param string $checkbox
23ebc481
DM
280 */
281 public function assert_checkbox_checked($checkbox) {
23ebc481
DM
282 $this->assertSession()->checkboxChecked($checkbox);
283 }
284
285 /**
286 * Checks, that checkbox with specified in|name|label|value is unchecked.
287 *
23ebc481 288 * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should not be checked$/
1f9ffbdb 289 * @see Behat\MinkExtension\Context\MinkContext
46ac40cd 290 * @param string $checkbox
23ebc481
DM
291 */
292 public function assert_checkbox_not_checked($checkbox) {
23ebc481
DM
293 $this->assertSession()->checkboxNotChecked($checkbox);
294 }
295
296 /**
297 * Checks, that given select box contains the specified option.
298 *
23ebc481 299 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
300 * @throws ExpectationException
301 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
302 * @param string $select The select element name
303 * @param string $option The option text/value
304 */
305 public function the_select_box_should_contain($select, $option) {
306
1f9ffbdb 307 $selectnode = $this->find_field($select);
23ebc481
DM
308
309 $regex = '/' . preg_quote($option, '/') . '/ui';
310 if (!preg_match($regex, $selectnode->getText())) {
311 throw new ExpectationException(
312 'The select box "' . $select . '" does not contains the option "' . $option . '"',
313 $this->getSession()
314 );
315 }
316
317 }
318
319 /**
320 * Checks, that given select box does not contain the specified option.
321 *
23ebc481 322 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should not contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
323 * @throws ExpectationException
324 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
325 * @param string $select The select element name
326 * @param string $option The option text/value
327 */
328 public function the_select_box_should_not_contain($select, $option) {
329
1f9ffbdb 330 $selectnode = $this->find_field($select);
23ebc481
DM
331
332 $regex = '/' . preg_quote($option, '/') . '/ui';
333 if (preg_match($regex, $selectnode->getText())) {
334 throw new ExpectationException(
335 'The select box "' . $select . '" contains the option "' . $option . '"',
336 $this->getSession()
337 );
338 }
339 }
340
23ebc481 341}