MDL-43835 behat: Fixed backup behat test
[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 /**
a5254141 64 * Fills a form with field/value data. More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps.
23ebc481 65 *
a5254141 66 * @Given /^I set the following fields to these values:$/
1f9ffbdb 67 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481
DM
68 * @param TableNode $data
69 */
a5254141 70 public function i_set_the_following_fields_to_these_values(TableNode $data) {
23ebc481 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) {
a5254141 79 $this->set_field_value($locator, $value);
23ebc481
DM
80 }
81 }
82
f8f1bdc3
DM
83 /**
84 * Expands all moodleform's fields, including collapsed fieldsets and advanced fields if they are present.
85 * @Given /^I expand all fieldsets$/
86 */
87 public function i_expand_all_fieldsets() {
88 $this->expand_all_fields();
89 }
90
91 /**
92 * Expands all moodle form fieldsets if they exists.
93 *
94 * Externalized from i_expand_all_fields to call it from
95 * other form-related steps without having to use steps-group calls.
96 *
97 * @throws ElementNotFoundException Thrown by behat_base::find_all
98 * @return void
99 */
100 protected function expand_all_fields() {
101
74c78e74
DM
102 // We already know that we waited for the DOM and the JS to be loaded, even the editor
103 // so, we will use the reduced timeout as it is a common task and we should save time.
f8f1bdc3
DM
104 try {
105
8cda2e6f 106 // Expand fieldsets link.
74c78e74 107 $xpath = "//div[@class='collapsible-actions']" .
8cda2e6f 108 "/descendant::a[contains(concat(' ', @class, ' '), ' collapseexpand ')]" .
74c78e74
DM
109 "[not(contains(concat(' ', @class, ' '), ' collapse-all '))]";
110 $collapseexpandlink = $this->find('xpath', $xpath, false, false, self::REDUCED_TIMEOUT);
8cda2e6f 111 $collapseexpandlink->click();
f8f1bdc3
DM
112
113 } catch (ElementNotFoundException $e) {
74c78e74
DM
114 // The behat_base::find() method throws an exception if there are no elements,
115 // we should not fail a test because of this. We continue if there are not expandable fields.
f8f1bdc3
DM
116 }
117
118 // Different try & catch as we can have expanded fieldsets with advanced fields on them.
119 try {
120
8cda2e6f
DM
121 // Expand all fields xpath.
122 $showmorexpath = "//a[normalize-space(.)='" . get_string('showmore', 'form') . "']" .
123 "[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler')]";
f8f1bdc3 124
8cda2e6f 125 // We don't wait here as we already waited when getting the expand fieldsets links.
74c78e74
DM
126 if (!$showmores = $this->getSession()->getPage()->findAll('xpath', $showmorexpath)) {
127 return;
128 }
f8f1bdc3 129
8cda2e6f
DM
130 // Funny thing about this, with findAll() we specify a pattern and each element matching the pattern is added to the array
131 // with of xpaths with a [0], [1]... sufix, but when we click on an element it does not matches the specified xpath
132 // anymore (now is a "Show less..." link) so [1] becomes [0], that's why we always click on the first XPath match,
133 // will be always the next one.
f8f1bdc3
DM
134 $iterations = count($showmores);
135 for ($i = 0; $i < $iterations; $i++) {
136 $showmores[0]->click();
137 }
138
139 } catch (ElementNotFoundException $e) {
140 // We continue with the test.
141 }
142
143 }
144
23ebc481 145 /**
a5254141 146 * Sets the specified value to the field.
23ebc481 147 *
decf1e14 148 * @Given /^I set the field "(?P<field_string>(?:[^"]|\\")*)" to "(?P<field_value_string>(?:[^"]|\\")*)"$/
1f9ffbdb 149 * @throws ElementNotFoundException Thrown by behat_base::find
46ac40cd
DM
150 * @param string $field
151 * @param string $value
a5254141 152 * @return void
23ebc481 153 */
a5254141 154 public function i_set_the_field_to($field, $value) {
c3f1e953 155 $this->set_field_value($field, $value);
23ebc481
DM
156 }
157
158 /**
a5254141 159 * Checks, the field matches the value. More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps.
23ebc481 160 *
decf1e14 161 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" matches value "(?P<field_value_string>(?:[^"]|\\")*)"$/
1f9ffbdb 162 * @throws ElementNotFoundException Thrown by behat_base::find
a5254141 163 * @param string $field
46ac40cd 164 * @param string $value
a5254141 165 * @return void
23ebc481 166 */
a5254141 167 public function the_field_matches_value($field, $value) {
23ebc481 168
49d91129 169 // Get the field.
af4830a2 170 $formfield = behat_field_manager::get_form_field_from_label($field, $this);
23ebc481
DM
171
172 // Checks if the provided value matches the current field value.
a5254141
DM
173 if (!$formfield->matches($value)) {
174 $fieldvalue = $formfield->get_value();
23ebc481 175 throw new ExpectationException(
a5254141 176 'The \'' . $field . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' ,
23ebc481
DM
177 $this->getSession()
178 );
179 }
180 }
181
c3f1e953 182 /**
a5254141 183 * Checks, the field does not match the value. More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps.
c3f1e953 184 *
decf1e14 185 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" does not match value "(?P<field_value_string>(?:[^"]|\\")*)"$/
c3f1e953
DM
186 * @throws ExpectationException
187 * @throws ElementNotFoundException Thrown by behat_base::find
188 * @param string $field
189 * @param string $value
190 * @return void
191 */
192 public function the_field_does_not_match_value($field, $value) {
193
c3f1e953 194 // Get the field.
af4830a2 195 $formfield = behat_field_manager::get_form_field_from_label($field, $this);
c3f1e953
DM
196
197 // Checks if the provided value matches the current field value.
a5254141
DM
198 if ($formfield->matches($value)) {
199 $fieldvalue = $formfield->get_value();
c3f1e953
DM
200 throw new ExpectationException(
201 'The \'' . $field . '\' value matches \'' . $value . '\' and it should not match it' ,
202 $this->getSession()
203 );
204 }
205 }
206
207 /**
a5254141 208 * Checks, the provided field/value matches. More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps.
c3f1e953
DM
209 *
210 * @Then /^the following fields match these values:$/
211 * @throws ExpectationException
a5254141 212 * @param TableNode $data Pairs of | field | value |
c3f1e953
DM
213 */
214 public function the_following_fields_match_these_values(TableNode $data) {
215
216 // Expand all fields in case we have.
217 $this->expand_all_fields();
218
219 $datahash = $data->getRowsHash();
220
221 // The action depends on the field type.
222 foreach ($datahash as $locator => $value) {
a5254141 223 $this->the_field_matches_value($locator, $value);
c3f1e953
DM
224 }
225 }
226
227 /**
decf1e14 228 * Checks that the provided field/value pairs don't match. More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps.
c3f1e953
DM
229 *
230 * @Then /^the following fields do not match these values:$/
231 * @throws ExpectationException
a5254141 232 * @param TableNode $data Pairs of | field | value |
c3f1e953
DM
233 */
234 public function the_following_fields_do_not_match_these_values(TableNode $data) {
235
236 // Expand all fields in case we have.
237 $this->expand_all_fields();
238
239 $datahash = $data->getRowsHash();
240
241 // The action depends on the field type.
242 foreach ($datahash as $locator => $value) {
243 $this->the_field_does_not_match_value($locator, $value);
244 }
245 }
246
23ebc481
DM
247 /**
248 * Checks, that given select box contains the specified option.
249 *
23ebc481 250 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
251 * @throws ExpectationException
252 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481 253 * @param string $select The select element name
5f66d46e
EL
254 * @param string $option The option text/value. Plain value or comma separated
255 * values if multiple. Commas in multiple values escaped with backslash.
23ebc481
DM
256 */
257 public function the_select_box_should_contain($select, $option) {
258
1f9ffbdb 259 $selectnode = $this->find_field($select);
5f66d46e
EL
260 $multiple = $selectnode->hasAttribute('multiple');
261 $optionsarr = array(); // Array of passed value/text options to test.
23ebc481 262
5f66d46e
EL
263 if ($multiple) {
264 // Can pass multiple comma separated, with valuable commas escaped with backslash.
265 foreach (preg_replace('/\\\,/', ',', preg_split('/(?<!\\\),/', $option)) as $opt) {
266 $optionsarr[] = trim($opt);
267 }
268 } else {
269 // Only one option has been passed.
270 $optionsarr[] = trim($option);
271 }
272
273 // Now get all the values and texts in the select.
274 $options = $selectnode->findAll('xpath', '//option');
275 $values = array();
276 foreach ($options as $opt) {
277 $values[trim($opt->getValue())] = trim($opt->getText());
23ebc481
DM
278 }
279
5f66d46e
EL
280 foreach ($optionsarr as $opt) {
281 // Verify every option is a valid text or value.
282 if (!in_array($opt, $values) && !array_key_exists($opt, $values)) {
283 throw new ExpectationException(
284 'The select box "' . $select . '" does not contain the option "' . $opt . '"',
285 $this->getSession()
286 );
287 }
288 }
23ebc481
DM
289 }
290
291 /**
292 * Checks, that given select box does not contain the specified option.
293 *
23ebc481 294 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should not contain "(?P<option_string>(?:[^"]|\\")*)"$/
1f9ffbdb
DM
295 * @throws ExpectationException
296 * @throws ElementNotFoundException Thrown by behat_base::find
23ebc481 297 * @param string $select The select element name
5f66d46e
EL
298 * @param string $option The option text/value. Plain value or comma separated
299 * values if multiple. Commas in multiple values escaped with backslash.
23ebc481
DM
300 */
301 public function the_select_box_should_not_contain($select, $option) {
302
1f9ffbdb 303 $selectnode = $this->find_field($select);
5f66d46e
EL
304 $multiple = $selectnode->hasAttribute('multiple');
305 $optionsarr = array(); // Array of passed value/text options to test.
23ebc481 306
5f66d46e
EL
307 if ($multiple) {
308 // Can pass multiple comma separated, with valuable commas escaped with backslash.
309 foreach (preg_replace('/\\\,/', ',', preg_split('/(?<!\\\),/', $option)) as $opt) {
310 $optionsarr[] = trim($opt);
311 }
312 } else {
313 // Only one option has been passed.
314 $optionsarr[] = trim($option);
315 }
316
317 // Now get all the values and texts in the select.
318 $options = $selectnode->findAll('xpath', '//option');
319 $values = array();
320 foreach ($options as $opt) {
321 $values[trim($opt->getValue())] = trim($opt->getText());
322 }
323
324 foreach ($optionsarr as $opt) {
325 // Verify every option is not a valid text or value.
326 if (in_array($opt, $values) || array_key_exists($opt, $values)) {
327 throw new ExpectationException(
328 'The select box "' . $select . '" contains the option "' . $opt . '"',
329 $this->getSession()
330 );
331 }
332 }
333 }
334
335 /**
c3f1e953 336 * Generic field setter.
5f66d46e 337 *
c3f1e953
DM
338 * Internal API method, a generic *I set "VALUE" to "FIELD" field*
339 * could be created based on it.
5f66d46e 340 *
c3f1e953
DM
341 * @param string $fieldlocator The pointer to the field, it will depend on the field type.
342 * @param string $value
343 * @return void
5f66d46e 344 */
c3f1e953 345 protected function set_field_value($fieldlocator, $value) {
5f66d46e 346
c3f1e953
DM
347 // We delegate to behat_form_field class, it will
348 // guess the type properly as it is a select tag.
af4830a2 349 $field = behat_field_manager::get_form_field_from_label($fieldlocator, $this);
c3f1e953 350 $field->set_value($value);
23ebc481
DM
351 }
352
23ebc481 353}