See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 403]
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 28 require_once (__DIR__ . '/../../../lib/behat/behat_base.php'); 29 require_once (__DIR__ . '/../../../lib/behat/behat_field_manager.php'); 30 31 use Behat\Gherkin\Node\{TableNode, PyStringNode}; 32 use Behat\Mink\Element\NodeElement; 33 use Behat\Mink\Exception\{ElementNotFoundException, ExpectationException}; 34 35 /** 36 * Forms-related steps definitions. 37 * 38 * Note, Behat tests to verify that the steps defined here work as advertised 39 * are kept in admin/tool/behat/tests/behat. 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 */ 46 class behat_forms extends behat_base { 47 48 /** 49 * Presses button with specified id|name|title|alt|value. 50 * 51 * @When /^I press "(?P<button_string>(?:[^"]|\\")*)"$/ 52 * @throws ElementNotFoundException Thrown by behat_base::find 53 * @param string $button 54 */ 55 public function press_button($button) { 56 $this->execute('behat_general::i_click_on', [$button, 'button']); 57 } 58 59 /** 60 * Press button with specified id|name|title|alt|value and switch to main window. 61 * 62 * @When /^I press "(?P<button_string>(?:[^"]|\\")*)" and switch to main window$/ 63 * @throws ElementNotFoundException Thrown by behat_base::find 64 * @param string $button 65 */ 66 public function press_button_and_switch_to_main_window($button) { 67 // Ensures the button is present, before pressing. 68 $buttonnode = $this->find_button($button); 69 $buttonnode->press(); 70 $this->wait_for_pending_js(); 71 $this->look_for_exceptions(); 72 73 // Switch to main window. 74 $this->execute('behat_general::switch_to_the_main_window'); 75 } 76 77 /** 78 * Fills a form with field/value data. 79 * 80 * @Given /^I set the following fields to these values:$/ 81 * @throws ElementNotFoundException Thrown by behat_base::find 82 * @param TableNode $data 83 */ 84 public function i_set_the_following_fields_to_these_values(TableNode $data) { 85 86 // Expand all fields in case we have. 87 $this->expand_all_fields(); 88 89 $datahash = $data->getRowsHash(); 90 91 // The action depends on the field type. 92 foreach ($datahash as $locator => $value) { 93 $this->set_field_value($locator, $value); 94 } 95 } 96 97 /** 98 * Fills a form with field/value data. 99 * 100 * @Given /^I set the following fields in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" to these values:$/ 101 * @throws ElementNotFoundException Thrown by behat_base::find 102 * @param string $containerelement Element we look in 103 * @param string $containerselectortype The type of selector where we look in 104 * @param TableNode $data 105 */ 106 public function i_set_the_following_fields_in_container_to_these_values( 107 $containerelement, $containerselectortype, TableNode $data) { 108 109 // Expand all fields in case we have. 110 $this->expand_all_fields(); 111 112 $datahash = $data->getRowsHash(); 113 114 // The action depends on the field type. 115 foreach ($datahash as $locator => $value) { 116 $this->set_field_value_in_container($locator, $value, $containerselectortype, $containerelement); 117 } 118 } 119 120 /** 121 * Expands all moodleform's fields, including collapsed fieldsets and advanced fields if they are present. 122 * @Given /^I expand all fieldsets$/ 123 */ 124 public function i_expand_all_fieldsets() { 125 $this->expand_all_fields(); 126 } 127 128 /** 129 * Expands all moodle form fieldsets if they exists. 130 * 131 * Externalized from i_expand_all_fields to call it from 132 * other form-related steps without having to use steps-group calls. 133 * 134 * @throws ElementNotFoundException Thrown by behat_base::find_all 135 * @return void 136 */ 137 protected function expand_all_fields() { 138 // Expand only if JS mode, else not needed. 139 if (!$this->running_javascript()) { 140 return; 141 } 142 143 // We already know that we waited for the DOM and the JS to be loaded, even the editor 144 // so, we will use the reduced timeout as it is a common task and we should save time. 145 try { 146 $this->wait_for_pending_js(); 147 // Expand all fieldsets link - which will only be there if there is more than one collapsible section. 148 $expandallxpath = "//div[@class='collapsible-actions']" . 149 "//a[contains(concat(' ', @class, ' '), ' collapsed ')]" . 150 "//span[contains(concat(' ', @class, ' '), ' expandall ')]"; 151 // Else, look for the first expand fieldset link (old theme structure). 152 $expandsectionold = "//legend[@class='ftoggler']" . 153 "//a[contains(concat(' ', @class, ' '), ' icons-collapse-expand ') and @aria-expanded = 'false']"; 154 // Else, look for the first expand fieldset link (current theme structure). 155 $expandsectioncurrent = "//fieldset//div[contains(concat(' ', @class, ' '), ' ftoggler ')]" . 156 "//a[contains(concat(' ', @class, ' '), ' icons-collapse-expand ') and @aria-expanded = 'false']"; 157 158 $collapseexpandlink = $this->find('xpath', $expandallxpath . '|' . $expandsectionold . '|' . $expandsectioncurrent, 159 false, false, behat_base::get_reduced_timeout()); 160 $collapseexpandlink->click(); 161 $this->wait_for_pending_js(); 162 163 } catch (ElementNotFoundException $e) { 164 // The behat_base::find() method throws an exception if there are no elements, 165 // we should not fail a test because of this. We continue if there are not expandable fields. 166 } 167 168 // Different try & catch as we can have expanded fieldsets with advanced fields on them. 169 try { 170 171 // Expand all fields xpath. 172 $showmorexpath = "//a[normalize-space(.)='" . get_string('showmore', 'form') . "']" . 173 "[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler')]"; 174 175 // We don't wait here as we already waited when getting the expand fieldsets links. 176 if (!$showmores = $this->getSession()->getPage()->findAll('xpath', $showmorexpath)) { 177 return; 178 } 179 180 if ($this->getSession()->getDriver() instanceof \DMore\ChromeDriver\ChromeDriver) { 181 // Chrome Driver produces unique xpaths for each element. 182 foreach ($showmores as $showmore) { 183 $showmore->click(); 184 } 185 } else { 186 // Funny thing about this, with findAll() we specify a pattern and each element matching the pattern 187 // is added to the array with of xpaths with a [0], [1]... sufix, but when we click on an element it 188 // does not matches the specified xpath anymore (now is a "Show less..." link) so [1] becomes [0], 189 // that's why we always click on the first XPath match, will be always the next one. 190 $iterations = count($showmores); 191 for ($i = 0; $i < $iterations; $i++) { 192 $showmores[0]->click(); 193 } 194 } 195 196 } catch (ElementNotFoundException $e) { 197 // We continue with the test. 198 } 199 200 } 201 202 /** 203 * Sets the field to wwwroot plus the given path. Include the first slash. 204 * 205 * @Given /^I set the field "(?P<field_string>(?:[^"]|\\")*)" to local url "(?P<field_path_string>(?:[^"]|\\")*)"$/ 206 * @throws ElementNotFoundException Thrown by behat_base::find 207 * @param string $field 208 * @param string $path 209 * @return void 210 */ 211 public function i_set_the_field_to_local_url($field, $path) { 212 global $CFG; 213 $this->set_field_value($field, $CFG->wwwroot . $path); 214 } 215 216 /** 217 * Sets the specified value to the field. 218 * 219 * @Given /^I set the field "(?P<field_string>(?:[^"]|\\")*)" to "(?P<field_value_string>(?:[^"]|\\")*)"$/ 220 * @throws ElementNotFoundException Thrown by behat_base::find 221 * @param string $field 222 * @param string $value 223 * @return void 224 */ 225 public function i_set_the_field_to($field, $value) { 226 $this->set_field_value($field, $value); 227 } 228 229 /** 230 * Sets the specified value to the field. 231 * 232 * @Given /^I set the field "(?P<field_string>(?:[^"]|\\")*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" to "(?P<field_value_string>(?:[^"]|\\")*)"$/ 233 * @throws ElementNotFoundException Thrown by behat_base::find 234 * @param string $field 235 * @param string $containerelement Element we look in 236 * @param string $containerselectortype The type of selector where we look in 237 * @param string $value 238 */ 239 public function i_set_the_field_in_container_to($field, $containerelement, $containerselectortype, $value) { 240 $this->set_field_value_in_container($field, $value, $containerselectortype, $containerelement); 241 } 242 243 /** 244 * Press the key in the field to trigger the javascript keypress event 245 * 246 * Note that the character key will not actually be typed in the input field 247 * 248 * @Given /^I press key "(?P<key_string>(?:[^"]|\\")*)" in the field "(?P<field_string>(?:[^"]|\\")*)"$/ 249 * @throws ElementNotFoundException Thrown by behat_base::find 250 * @param string $key either char-code or character itself, 251 * may optionally be prefixed with ctrl-, alt-, shift- or meta- 252 * @param string $field 253 * @return void 254 */ 255 public function i_press_key_in_the_field($key, $field) { 256 if (!$this->running_javascript()) { 257 throw new DriverException('Key press step is not available with Javascript disabled'); 258 } 259 $fld = behat_field_manager::get_form_field_from_label($field, $this); 260 $modifier = null; 261 $char = $key; 262 if (preg_match('/-/', $key)) { 263 list($modifier, $char) = preg_split('/-/', $key, 2); 264 } 265 if (is_numeric($char)) { 266 $char = (int)$char; 267 } 268 $fld->key_press($char, $modifier); 269 } 270 271 /** 272 * Sets the specified value to the field. 273 * 274 * @Given /^I set the field "(?P<field_string>(?:[^"]|\\")*)" to multiline:$/ 275 * @throws ElementNotFoundException Thrown by behat_base::find 276 * @param string $field 277 * @param PyStringNode $value 278 * @return void 279 */ 280 public function i_set_the_field_to_multiline($field, PyStringNode $value) { 281 $this->set_field_value($field, (string)$value); 282 } 283 284 /** 285 * Sets the specified value to the field with xpath. 286 * 287 * @Given /^I set the field with xpath "(?P<fieldxpath_string>(?:[^"]|\\")*)" to "(?P<field_value_string>(?:[^"]|\\")*)"$/ 288 * @throws ElementNotFoundException Thrown by behat_base::find 289 * @param string $field 290 * @param string $value 291 * @return void 292 */ 293 public function i_set_the_field_with_xpath_to($fieldxpath, $value) { 294 $this->set_field_node_value($this->find('xpath', $fieldxpath), $value); 295 } 296 297 /** 298 * Checks, the field matches the value. 299 * 300 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" matches value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 301 * @throws ElementNotFoundException Thrown by behat_base::find 302 * @param string $field 303 * @param string $value 304 * @return void 305 */ 306 public function the_field_matches_value($field, $value) { 307 308 // Get the field. 309 $formfield = behat_field_manager::get_form_field_from_label($field, $this); 310 311 // Checks if the provided value matches the current field value. 312 if (!$formfield->matches($value)) { 313 $fieldvalue = $formfield->get_value(); 314 throw new ExpectationException( 315 'The \'' . $field . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' , 316 $this->getSession() 317 ); 318 } 319 } 320 321 /** 322 * Checks, the field matches the value. 323 * 324 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" matches multiline:$/ 325 * @throws ElementNotFoundException Thrown by behat_base::find 326 * @param string $field 327 * @param PyStringNode $value 328 * @return void 329 */ 330 public function the_field_matches_multiline($field, PyStringNode $value) { 331 $this->the_field_matches_value($field, (string)$value); 332 } 333 334 /** 335 * Checks, the field does not match the value. 336 * 337 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" does not match value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 338 * @throws ExpectationException 339 * @throws ElementNotFoundException Thrown by behat_base::find 340 * @param string $field 341 * @param string $value 342 */ 343 public function the_field_does_not_match_value($field, $value) { 344 345 // Get the field. 346 $formfield = behat_field_manager::get_form_field_from_label($field, $this); 347 348 // Checks if the provided value matches the current field value. 349 if ($formfield->matches($value)) { 350 throw new ExpectationException( 351 'The \'' . $field . '\' value matches \'' . $value . '\' and it should not match it' , 352 $this->getSession() 353 ); 354 } 355 } 356 357 /** 358 * Checks, the field matches the value. 359 * 360 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" matches value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 361 * @throws ElementNotFoundException Thrown by behat_base::find 362 * @param string $field 363 * @param string $containerelement Element we look in 364 * @param string $containerselectortype The type of selector where we look in 365 * @param string $value 366 */ 367 public function the_field_in_container_matches_value($field, $containerelement, $containerselectortype, $value) { 368 369 // Get the field. 370 $node = $this->get_node_in_container('field', $field, $containerselectortype, $containerelement); 371 $formfield = behat_field_manager::get_form_field($node, $this->getSession()); 372 373 // Checks if the provided value matches the current field value. 374 if (!$formfield->matches($value)) { 375 $fieldvalue = $formfield->get_value(); 376 throw new ExpectationException( 377 'The \'' . $field . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' , 378 $this->getSession() 379 ); 380 } 381 } 382 383 /** 384 * Checks, the field does not match the value. 385 * 386 * @Then /^the field "(?P<field_string>(?:[^"]|\\")*)" in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" does not match value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 387 * @throws ExpectationException 388 * @throws ElementNotFoundException Thrown by behat_base::find 389 * @param string $field 390 * @param string $containerelement Element we look in 391 * @param string $containerselectortype The type of selector where we look in 392 * @param string $value 393 */ 394 public function the_field_in_container_does_not_match_value($field, $containerelement, $containerselectortype, $value) { 395 396 // Get the field. 397 $node = $this->get_node_in_container('field', $field, $containerselectortype, $containerelement); 398 $formfield = behat_field_manager::get_form_field($node, $this->getSession()); 399 400 // Checks if the provided value matches the current field value. 401 if ($formfield->matches($value)) { 402 throw new ExpectationException( 403 'The \'' . $field . '\' value matches \'' . $value . '\' and it should not match it' , 404 $this->getSession() 405 ); 406 } 407 } 408 409 /** 410 * Checks, the field matches the value. 411 * 412 * @Then /^the field with xpath "(?P<xpath_string>(?:[^"]|\\")*)" matches value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 413 * @throws ExpectationException 414 * @throws ElementNotFoundException Thrown by behat_base::find 415 * @param string $fieldxpath 416 * @param string $value 417 * @return void 418 */ 419 public function the_field_with_xpath_matches_value($fieldxpath, $value) { 420 421 // Get the field. 422 $fieldnode = $this->find('xpath', $fieldxpath); 423 $formfield = behat_field_manager::get_form_field($fieldnode, $this->getSession()); 424 425 // Checks if the provided value matches the current field value. 426 if (!$formfield->matches($value)) { 427 $fieldvalue = $formfield->get_value(); 428 throw new ExpectationException( 429 'The \'' . $fieldxpath . '\' value is \'' . $fieldvalue . '\', \'' . $value . '\' expected' , 430 $this->getSession() 431 ); 432 } 433 } 434 435 /** 436 * Checks, the field does not match the value. 437 * 438 * @Then /^the field with xpath "(?P<xpath_string>(?:[^"]|\\")*)" does not match value "(?P<field_value_string>(?:[^"]|\\")*)"$/ 439 * @throws ExpectationException 440 * @throws ElementNotFoundException Thrown by behat_base::find 441 * @param string $fieldxpath 442 * @param string $value 443 * @return void 444 */ 445 public function the_field_with_xpath_does_not_match_value($fieldxpath, $value) { 446 447 // Get the field. 448 $fieldnode = $this->find('xpath', $fieldxpath); 449 $formfield = behat_field_manager::get_form_field($fieldnode, $this->getSession()); 450 451 // Checks if the provided value matches the current field value. 452 if ($formfield->matches($value)) { 453 throw new ExpectationException( 454 'The \'' . $fieldxpath . '\' value matches \'' . $value . '\' and it should not match it' , 455 $this->getSession() 456 ); 457 } 458 } 459 460 /** 461 * Checks, the provided field/value matches. 462 * 463 * @Then /^the following fields match these values:$/ 464 * @throws ExpectationException 465 * @param TableNode $data Pairs of | field | value | 466 */ 467 public function the_following_fields_match_these_values(TableNode $data) { 468 469 // Expand all fields in case we have. 470 $this->expand_all_fields(); 471 472 $datahash = $data->getRowsHash(); 473 474 // The action depends on the field type. 475 foreach ($datahash as $locator => $value) { 476 $this->the_field_matches_value($locator, $value); 477 } 478 } 479 480 /** 481 * Checks that the provided field/value pairs don't match. 482 * 483 * @Then /^the following fields do not match these values:$/ 484 * @throws ExpectationException 485 * @param TableNode $data Pairs of | field | value | 486 */ 487 public function the_following_fields_do_not_match_these_values(TableNode $data) { 488 489 // Expand all fields in case we have. 490 $this->expand_all_fields(); 491 492 $datahash = $data->getRowsHash(); 493 494 // The action depends on the field type. 495 foreach ($datahash as $locator => $value) { 496 $this->the_field_does_not_match_value($locator, $value); 497 } 498 } 499 500 /** 501 * Checks, the provided field/value matches. 502 * 503 * @Then /^the following fields in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" match these values:$/ 504 * @throws ExpectationException 505 * @param string $containerelement Element we look in 506 * @param string $containerselectortype The type of selector where we look in 507 * @param TableNode $data Pairs of | field | value | 508 */ 509 public function the_following_fields_in_container_match_these_values( 510 $containerelement, $containerselectortype, TableNode $data) { 511 512 // Expand all fields in case we have. 513 $this->expand_all_fields(); 514 515 $datahash = $data->getRowsHash(); 516 517 // The action depends on the field type. 518 foreach ($datahash as $locator => $value) { 519 $this->the_field_in_container_matches_value($locator, $containerelement, $containerselectortype, $value); 520 } 521 } 522 523 /** 524 * Checks that the provided field/value pairs don't match. 525 * 526 * @Then /^the following fields in the "(?P<element_container_string>(?:[^"]|\\")*)" "(?P<text_selector_string>[^"]*)" do not match these values:$/ 527 * @throws ExpectationException 528 * @param string $containerelement Element we look in 529 * @param string $containerselectortype The type of selector where we look in 530 * @param TableNode $data Pairs of | field | value | 531 */ 532 public function the_following_fields_in_container_do_not_match_these_values( 533 $containerelement, $containerselectortype, TableNode $data) { 534 535 // Expand all fields in case we have. 536 $this->expand_all_fields(); 537 538 $datahash = $data->getRowsHash(); 539 540 // The action depends on the field type. 541 foreach ($datahash as $locator => $value) { 542 $this->the_field_in_container_does_not_match_value($locator, $containerelement, $containerselectortype, $value); 543 } 544 } 545 546 /** 547 * Checks, that given select box contains the specified option. 548 * 549 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should contain "(?P<option_string>(?:[^"]|\\")*)"$/ 550 * @throws ExpectationException 551 * @throws ElementNotFoundException Thrown by behat_base::find 552 * @param string $select The select element name 553 * @param string $option The option text/value. Plain value or comma separated 554 * values if multiple. Commas in multiple values escaped with backslash. 555 */ 556 public function the_select_box_should_contain($select, $option) { 557 558 $selectnode = $this->find_field($select); 559 $multiple = $selectnode->hasAttribute('multiple'); 560 $optionsarr = array(); // Array of passed value/text options to test. 561 562 if ($multiple) { 563 // Can pass multiple comma separated, with valuable commas escaped with backslash. 564 foreach (preg_replace('/\\\,/', ',', preg_split('/(?<!\\\),/', $option)) as $opt) { 565 $optionsarr[] = trim($opt); 566 } 567 } else { 568 // Only one option has been passed. 569 $optionsarr[] = trim($option); 570 } 571 572 // Now get all the values and texts in the select. 573 $options = $selectnode->findAll('xpath', '//option'); 574 $values = array(); 575 foreach ($options as $opt) { 576 $values[trim($opt->getValue())] = trim($opt->getText()); 577 } 578 579 foreach ($optionsarr as $opt) { 580 // Verify every option is a valid text or value. 581 if (!in_array($opt, $values) && !array_key_exists($opt, $values)) { 582 throw new ExpectationException( 583 'The select box "' . $select . '" does not contain the option "' . $opt . '"', 584 $this->getSession() 585 ); 586 } 587 } 588 } 589 590 /** 591 * Checks, that given select box does not contain the specified option. 592 * 593 * @Then /^the "(?P<select_string>(?:[^"]|\\")*)" select box should not contain "(?P<option_string>(?:[^"]|\\")*)"$/ 594 * @throws ExpectationException 595 * @throws ElementNotFoundException Thrown by behat_base::find 596 * @param string $select The select element name 597 * @param string $option The option text/value. Plain value or comma separated 598 * values if multiple. Commas in multiple values escaped with backslash. 599 */ 600 public function the_select_box_should_not_contain($select, $option) { 601 602 $selectnode = $this->find_field($select); 603 $multiple = $selectnode->hasAttribute('multiple'); 604 $optionsarr = array(); // Array of passed value/text options to test. 605 606 if ($multiple) { 607 // Can pass multiple comma separated, with valuable commas escaped with backslash. 608 foreach (preg_replace('/\\\,/', ',', preg_split('/(?<!\\\),/', $option)) as $opt) { 609 $optionsarr[] = trim($opt); 610 } 611 } else { 612 // Only one option has been passed. 613 $optionsarr[] = trim($option); 614 } 615 616 // Now get all the values and texts in the select. 617 $options = $selectnode->findAll('xpath', '//option'); 618 $values = array(); 619 foreach ($options as $opt) { 620 $values[trim($opt->getValue())] = trim($opt->getText()); 621 } 622 623 foreach ($optionsarr as $opt) { 624 // Verify every option is not a valid text or value. 625 if (in_array($opt, $values) || array_key_exists($opt, $values)) { 626 throw new ExpectationException( 627 'The select box "' . $select . '" contains the option "' . $opt . '"', 628 $this->getSession() 629 ); 630 } 631 } 632 } 633 634 /** 635 * Generic field setter. 636 * 637 * Internal API method, a generic *I set "VALUE" to "FIELD" field* 638 * could be created based on it. 639 * 640 * @param string $fieldlocator The pointer to the field, it will depend on the field type. 641 * @param string $value 642 * @return void 643 */ 644 protected function set_field_value($fieldlocator, $value) { 645 // We delegate to behat_form_field class, it will 646 // guess the type properly as it is a select tag. 647 $field = behat_field_manager::get_form_field_from_label($fieldlocator, $this); 648 $field->set_value($value); 649 } 650 651 /** 652 * Generic field setter to be used by chainable steps. 653 * 654 * @param NodeElement $fieldnode 655 * @param string $value 656 */ 657 public function set_field_node_value(NodeElement $fieldnode, string $value): void { 658 $field = behat_field_manager::get_form_field($fieldnode, $this->getSession()); 659 $field->set_value($value); 660 } 661 662 /** 663 * Generic field setter. 664 * 665 * Internal API method, a generic *I set "VALUE" to "FIELD" field* 666 * could be created based on it. 667 * 668 * @param string $fieldlocator The pointer to the field, it will depend on the field type. 669 * @param string $value the value to set 670 * @param string $containerselectortype The type of selector where we look in 671 * @param string $containerelement Element we look in 672 */ 673 protected function set_field_value_in_container($fieldlocator, $value, $containerselectortype, $containerelement) { 674 $node = $this->get_node_in_container('field', $fieldlocator, $containerselectortype, $containerelement); 675 $this->set_field_node_value($node, $value); 676 } 677 678 /** 679 * Select a value from single select and redirect. 680 * 681 * @Given /^I select "(?P<singleselect_option_string>(?:[^"]|\\")*)" from the "(?P<singleselect_name_string>(?:[^"]|\\")*)" singleselect$/ 682 */ 683 public function i_select_from_the_singleselect($option, $singleselect) { 684 685 $this->execute('behat_forms::i_set_the_field_to', array($this->escape($singleselect), $this->escape($option))); 686 687 if (!$this->running_javascript()) { 688 // Press button in the specified select container. 689 $containerxpath = "//div[" . 690 "(contains(concat(' ', normalize-space(@class), ' '), ' singleselect ') " . 691 "or contains(concat(' ', normalize-space(@class), ' '), ' urlselect ')". 692 ") and ( 693 .//label[contains(normalize-space(string(.)), '" . $singleselect . "')] " . 694 "or .//select[(./@name='" . $singleselect . "' or ./@id='". $singleselect . "')]" . 695 ")]"; 696 697 $this->execute('behat_general::i_click_on_in_the', 698 array(get_string('go'), "button", $containerxpath, "xpath_element") 699 ); 700 } 701 } 702 703 /** 704 * Select item from autocomplete list. 705 * 706 * @Given /^I click on "([^"]*)" item in the autocomplete list$/ 707 * 708 * @param string $item 709 */ 710 public function i_click_on_item_in_the_autocomplete_list($item) { 711 $xpathtarget = "//ul[@class='form-autocomplete-suggestions']//*[contains(concat('|', string(.), '|'),'|" . $item . "|')]"; 712 713 $this->execute('behat_general::i_click_on', [$xpathtarget, 'xpath_element']); 714 } 715 716 /** 717 * Open the auto-complete suggestions list (Assuming there is only one on the page.). 718 * 719 * @Given I open the autocomplete suggestions list 720 * @Given I open the autocomplete suggestions list in the :container :containertype 721 */ 722 public function i_open_the_autocomplete_suggestions_list($container = null, $containertype = null) { 723 $csstarget = ".form-autocomplete-downarrow"; 724 if ($container && $containertype) { 725 $this->execute('behat_general::i_click_on_in_the', [$csstarget, 'css_element', $container, $containertype]); 726 } else { 727 $this->execute('behat_general::i_click_on', [$csstarget, 'css_element']); 728 } 729 } 730 731 /** 732 * Expand the given autocomplete list 733 * 734 * @Given /^I expand the "(?P<field_string>(?:[^"]|\\")*)" autocomplete$/ 735 * 736 * @param string $field Field name 737 */ 738 public function i_expand_the_autocomplete($field) { 739 $csstarget = '.form-autocomplete-downarrow'; 740 $node = $this->get_node_in_container('css_element', $csstarget, 'form_row', $field); 741 $this->ensure_node_is_visible($node); 742 $node->click(); 743 } 744 745 /** 746 * Assert the given option exist in the given autocomplete list 747 * 748 * @Given /^I should see "(?P<option_string>(?:[^"]|\\")*)" in the list of options for the "(?P<field_string>(?:[^"]|\\")*)" autocomplete$$/ 749 * 750 * @param string $option Name of option 751 * @param string $field Field name 752 */ 753 public function i_should_see_in_the_list_of_option_for_the_autocomplete($option, $field) { 754 $xpathtarget = "//div[contains(@class, 'form-autocomplete-selection') and contains(.//div, '" . $option . "')]"; 755 $node = $this->get_node_in_container('xpath_element', $xpathtarget, 'form_row', $field); 756 $this->ensure_node_is_visible($node); 757 } 758 759 /** 760 * Checks whether the select menu contains an option with specified text or not. 761 * 762 * @Then the :name select menu should contain :option 763 * @Then the :name select menu should :not contain :option 764 * 765 * @throws ExpectationException When the expectation is not satisfied 766 * @param string $label The label of the select menu element 767 * @param string $option The string that is used to identify an option within the select menu. If the string 768 * has two items separated by '>' (ex. "Group > Option"), the first item ("Group") will be 769 * used to identify a particular group within the select menu, while the second ("Option") 770 * will be used to identify an option within that group. Otherwise, a string with a single 771 * item (ex. "Option") will be used to identify an option within the select menu regardless 772 * of any existing groups. 773 * @param string|null $not If set, the select menu should not contain the specified option. If null, the option 774 * should be present. 775 */ 776 public function the_select_menu_should_contain(string $label, string $option, ?string $not = null) { 777 778 $field = behat_field_manager::get_form_field_from_label($label, $this); 779 780 if (!method_exists($field, 'has_option')) { 781 throw new coding_exception('Field does not support the has_option function.'); 782 } 783 784 // If the select menu contains the specified option but it should not. 785 if ($field->has_option($option) && $not) { 786 throw new ExpectationException( 787 "The select menu should not contain \"{$option}\" but it does.", 788 $this->getSession() 789 ); 790 } 791 // If the select menu does not contain the specified option but it should. 792 if (!$field->has_option($option) && !$not) { 793 throw new ExpectationException( 794 "The select menu should contain \"{$option}\" but it does not.", 795 $this->getSession() 796 ); 797 } 798 } 799 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body