f3fdf3757a56aa55f69de8e3ebd90157ddbe8df0
[moodle.git] / lib / tests / behat / behat_forms.php
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/>.
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  */
26 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
28 require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
29 require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php');
31 use 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;
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  */
47 class behat_forms extends behat_base {
49     /**
50      * Presses button with specified id|name|title|alt|value.
51      *
52      * @When /^I press "(?P<button_string>(?:[^"]|\\")*)"$/
53      * @throws ElementNotFoundException Thrown by behat_base::find
54      * @param string $button
55      */
56     public function press_button($button) {
58         // Ensures the button is present.
59         $buttonnode = $this->find_button($button);
60         $buttonnode->press();
61     }
63     /**
64      * Fills a moodle form with field/value data.
65      *
66      * @Given /^I fill the moodle form with:$/
67      * @throws ElementNotFoundException Thrown by behat_base::find
68      * @param TableNode $data
69      */
70     public function i_fill_the_moodle_form_with(TableNode $data) {
72         // Expand all fields in case we have.
73         $this->expand_all_fields();
75         $datahash = $data->getRowsHash();
77         // The action depends on the field type.
78         foreach ($datahash as $locator => $value) {
80             // Getting the node element pointed by the label.
81             $fieldnode = $this->find_field($locator);
83             // Gets the field type from a parent node.
84             $field = behat_field_manager::get_form_field($fieldnode, $this->getSession());
86             // Delegates to the field class.
87             $field->set_value($value);
88         }
89     }
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     }
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() {
110         // We ensure that all the editors are loaded and we can interact with them.
111         $this->ensure_editors_are_loaded();
113         // We already know that we waited for the DOM and the JS to be loaded, even the editor
114         // so, we will use the reduced timeout as it is a common task and we should save time.
115         try {
117             // Expand fieldsets link.
118             $xpath = "//div[@class='collapsible-actions']" .
119                 "/descendant::a[contains(concat(' ', @class, ' '), ' collapseexpand ')]" .
120                 "[not(contains(concat(' ', @class, ' '), ' collapse-all '))]";
121             $collapseexpandlink = $this->find('xpath', $xpath, false, false, self::REDUCED_TIMEOUT);
122             $collapseexpandlink->click();
124         } catch (ElementNotFoundException $e) {
125             // The behat_base::find() method throws an exception if there are no elements,
126             // we should not fail a test because of this. We continue if there are not expandable fields.
127         }
129         // Different try & catch as we can have expanded fieldsets with advanced fields on them.
130         try {
132             // Expand all fields xpath.
133             $showmorexpath = "//a[normalize-space(.)='" . get_string('showmore', 'form') . "']" .
134                 "[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler')]";
136             // We don't wait here as we already waited when getting the expand fieldsets links.
137             if (!$showmores = $this->getSession()->getPage()->findAll('xpath', $showmorexpath)) {
138                 return;
139             }
141             // Funny thing about this, with findAll() we specify a pattern and each element matching the pattern is added to the array
142             // with of xpaths with a [0], [1]... sufix, but when we click on an element it does not matches the specified xpath
143             // anymore (now is a "Show less..." link) so [1] becomes [0], that's why we always click on the first XPath match,
144             // will be always the next one.
145             $iterations = count($showmores);
146             for ($i = 0; $i < $iterations; $i++) {
147                 $showmores[0]->click();
148             }
150         } catch (ElementNotFoundException $e) {
151             // We continue with the test.
152         }
154     }
156     /**
157      * Fills in form field with specified id|name|label|value.
158      *
159      * @When /^I fill in "(?P<field_string>(?:[^"]|\\")*)" with "(?P<value_string>(?:[^"]|\\")*)"$/
160      * @throws ElementNotFoundException Thrown by behat_base::find
161      * @param string $field
162      * @param string $value
163      */
164     public function fill_field($field, $value) {
166         $fieldnode = $this->find_field($field);
167         $fieldnode->setValue($value);
168     }
170     /**
171      * Selects option in select field with specified id|name|label|value.
172      *
173      * @When /^I select "(?P<option_string>(?:[^"]|\\")*)" from "(?P<select_string>(?:[^"]|\\")*)"$/
174      * @throws ElementNotFoundException Thrown by behat_base::find
175      * @param string $option
176      * @param string $select
177      */
178     public function select_option($option, $select) {
180         $selectnode = $this->find_field($select);
182         // We delegate to behat_form_field class, it will
183         // guess the type properly as it is a select tag.
184         $selectformfield = behat_field_manager::get_form_field($selectnode, $this->getSession());
185         $selectformfield->set_value($option);
186     }
188     /**
189      * Selects the specified id|name|label from the specified radio button.
190      *
191      * @When /^I select "(?P<radio_button_string>(?:[^"]|\\")*)" radio button$/
192      * @throws ElementNotFoundException Thrown by behat_base::find
193      * @param string $radio The radio button id, name or label value
194      */
195     public function select_radio($radio) {
197         $radionode = $this->find_radio($radio);
198         $radionode->check();
200         // Adding a click as Selenium requires it to fire some JS events.
201         if ($this->running_javascript()) {
202             $radionode->click();
203         }
204     }
206     /**
207      * Checks checkbox with specified id|name|label|value.
208      *
209      * @When /^I check "(?P<option_string>(?:[^"]|\\")*)"$/
210      * @throws ElementNotFoundException Thrown by behat_base::find
211      * @param string $option
212      */
213     public function check_option($option) {
215         // We don't delegate to behat_form_checkbox as the
216         // step is explicitly saying I check.
217         $checkboxnode = $this->find_field($option);
218         $checkboxnode->check();
219     }
221     /**
222      * Unchecks checkbox with specified id|name|label|value.
223      *
224      * @When /^I uncheck "(?P<option_string>(?:[^"]|\\")*)"$/
225      * @throws ElementNotFoundException Thrown by behat_base::find
226      * @param string $option
227      */
228     public function uncheck_option($option) {
230         // We don't delegate to behat_form_checkbox as the
231         // step is explicitly saying I uncheck.
232         $checkboxnode = $this->find_field($option);
233         $checkboxnode->uncheck();
234     }
236     /**
237      * Checks that the form element field have the specified value.
238      *
239      * @Then /^the "(?P<field_string>(?:[^"]|\\")*)" field should match "(?P<value_string>(?:[^"]|\\")*)" value$/
240      * @throws ExpectationException
241      * @throws ElementNotFoundException Thrown by behat_base::find
242      * @param string $locator
243      * @param string $value
244      */
245     public function the_field_should_match_value($locator, $value) {
247         $fieldnode = $this->find_field($locator);
249         // Get the field.
250         $field = behat_field_manager::get_form_field($fieldnode, $this->getSession());
251         $fieldvalue = $field->get_value();
253         // Checks if the provided value matches the current field value.
254         if (trim($value) != trim($fieldvalue)) {
255             throw new ExpectationException(
256                 'The \'' . $locator . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' ,
257                 $this->getSession()
258             );
259         }
260     }
262     /**
263      * Checks, that checkbox with specified in|name|label|value is checked.
264      *
265      * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should be checked$/
266      * @see Behat\MinkExtension\Context\MinkContext
267      * @param string $checkbox
268      */
269     public function assert_checkbox_checked($checkbox) {
270         $this->assertSession()->checkboxChecked($checkbox);
271     }
273     /**
274      * Checks, that checkbox with specified in|name|label|value is unchecked.
275      *
276      * @Then /^the "(?P<checkbox_string>(?:[^"]|\\")*)" checkbox should not be checked$/
277      * @see Behat\MinkExtension\Context\MinkContext
278      * @param string $checkbox
279      */
280     public function assert_checkbox_not_checked($checkbox) {
281         $this->assertSession()->checkboxNotChecked($checkbox);
282     }
284     /**
285      * Checks, that given select box contains the specified option.
286      *
287      * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should contain "(?P<option_string>(?:[^"]|\\")*)"$/
288      * @throws ExpectationException
289      * @throws ElementNotFoundException Thrown by behat_base::find
290      * @param string $select The select element name
291      * @param string $option The option text/value
292      */
293     public function the_select_box_should_contain($select, $option) {
295         $selectnode = $this->find_field($select);
297         $regex = '/' . preg_quote($option, '/') . '/ui';
298         if (!preg_match($regex, $selectnode->getText())) {
299             throw new ExpectationException(
300                 'The select box "' . $select . '" does not contains the option "' . $option . '"',
301                 $this->getSession()
302             );
303         }
305     }
307     /**
308      * Checks, that given select box does not contain the specified option.
309      *
310      * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should not contain "(?P<option_string>(?:[^"]|\\")*)"$/
311      * @throws ExpectationException
312      * @throws ElementNotFoundException Thrown by behat_base::find
313      * @param string $select The select element name
314      * @param string $option The option text/value
315      */
316     public function the_select_box_should_not_contain($select, $option) {
318         $selectnode = $this->find_field($select);
320         $regex = '/' . preg_quote($option, '/') . '/ui';
321         if (preg_match($regex, $selectnode->getText())) {
322             throw new ExpectationException(
323                 'The select box "' . $select . '" contains the option "' . $option . '"',
324                 $this->getSession()
325             );
326         }
327     }