Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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  declare(strict_types=1);
  18  
  19  require_once (__DIR__  . '/behat_form_field.php');
  20  
  21  use \Behat\Mink\Element\NodeElement;
  22  
  23  /**
  24   * Custom interaction with select_menu elements
  25   *
  26   * @package   core_form
  27   * @copyright 2022 Shamim Rezaie <shamim@moodle.com>
  28   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29   */
  30  class behat_form_select_menu extends behat_form_field {
  31  
  32      /**
  33       * Sets the value of the select menu field.
  34       *
  35       * @param string $value The string that is used to identify an option within the select menu. If the string
  36       *                      has two items separated by '>' (ex. "Group > Option"), the first item ("Group") will be
  37       *                      used to identify a particular group within the select menu, while the second ("Option")
  38       *                      will be used to identify an option within that group. Otherwise, a string with a single
  39       *                      item (ex. "Option") will be used to identify an option within the select menu regardless
  40       *                      of any existing groups.
  41       */
  42      public function set_value($value) {
  43          self::require_javascript();
  44  
  45          $this->field->click();
  46          $option = $this->find_option($value);
  47          $option->click();
  48      }
  49  
  50      public function get_value() {
  51          $rootnode = $this->field->getParent();
  52          $input = $rootnode->find('css', 'input');
  53          return $input->getValue();
  54      }
  55  
  56      /**
  57       * Checks whether a given option exists in the select menu field.
  58       *
  59       * @param string $option The string that is used to identify an option within the select menu. If the string
  60       *                       has two items separated by '>' (ex. "Group > Option"), the first item ("Group") will be
  61       *                       used to identify a particular group within the select menu, while the second ("Option")
  62       *                       will be used to identify an option within that group. Otherwise, a string with a single
  63       *                       item (ex. "Option") will be used to identify an option within the select menu regardless
  64       *                       of any existing groups.
  65       * @return bool Whether the option exists in the select menu field or not.
  66       */
  67      public function has_option(string $option): bool {
  68          if ($this->find_option($option)) {
  69              return true;
  70          }
  71          return false;
  72      }
  73  
  74      /**
  75       * Finds and returns a given option from the select menu field.
  76       *
  77       * @param string $option The string that is used to identify an option within the select menu. If the string
  78       *                       has two items separated by '>' (ex. "Group > Option"), the first item ("Group") will be
  79       *                       used to identify a particular group within the select menu, while the second ("Option")
  80       *                       will be used to identify an option within that group. Otherwise, a string with a single
  81       *                       item (ex. "Option") will be used to identify an option within the select menu regardless
  82       *                       of any existing groups.
  83       * @return NodeElement|null The option element or null if it cannot be found.
  84       */
  85      private function find_option(string $option): ?NodeElement {
  86          // Split the value string by ">" to determine whether a group has been specified.
  87          $path = preg_split('/\s*>\s*/', trim($option));
  88  
  89          if (count($path) > 1) { // Group has been specified.
  90              $optionxpath = '//li[contains(@role, "presentation") and normalize-space(text()) = "' .
  91                  $this->escape($path[0]) . '"]' .
  92                  '/following-sibling::li[contains(@role, "option") and normalize-space(text()) = "' .
  93                  $this->escape($path[1]) . '"]';
  94          } else { // Group has not been specified.
  95              $optionxpath = '//li[contains(@role, "option") and normalize-space(text()) = "' .
  96                  $this->escape($path[0]) . '"]';
  97          }
  98  
  99          return $this->field->getParent()->find('xpath', $optionxpath);
 100      }
 101  }