[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/behat/form_field/ -> behat_form_select.php (source)

   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   * Single select form field class.
  19   *
  20   * @package    core_form
  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__  . '/behat_form_field.php');
  29  
  30  /**
  31   * Single select form field.
  32   *
  33   * @package    core_form
  34   * @category   test
  35   * @copyright  2012 David Monllaó
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class behat_form_select extends behat_form_field {
  39  
  40      /**
  41       * Sets the value(s) of a select element.
  42       *
  43       * Seems an easy select, but there are lots of combinations
  44       * of browsers and operative systems and each one manages the
  45       * autosubmits and the multiple option selects in a different way.
  46       *
  47       * @param string $value plain value or comma separated values if multiple. Commas in values escaped with backslash.
  48       * @return void
  49       */
  50      public function set_value($value) {
  51  
  52          // Is the select multiple?
  53          $multiple = $this->field->hasAttribute('multiple');
  54          $singleselect = ($this->field->hasClass('singleselect') || $this->field->hasClass('urlselect'));
  55  
  56          // Here we select the option(s).
  57          if ($multiple) {
  58              // Split and decode values. Comma separated list of values allowed. With valuable commas escaped with backslash.
  59              $options = preg_replace('/\\\,/', ',',  preg_split('/(?<!\\\),/', trim($value)));
  60              // This is a multiple select, let's pass the multiple flag after first option.
  61              $afterfirstoption = false;
  62              foreach ($options as $option) {
  63                  $this->field->selectOption(trim($option), $afterfirstoption);
  64                  $afterfirstoption = true;
  65              }
  66          } else {
  67             // By default, assume the passed value is a non-multiple option.
  68              $this->field->selectOption(trim($value));
  69         }
  70  
  71          // Wait for all the possible AJAX requests that have been
  72          // already triggered by selectOption() to be finished.
  73          if ($this->running_javascript()) {
  74              // Trigger change event and click on first skip link, as some OS/browsers (Phantomjs, Mac-FF),
  75              // don't close select option field and trigger event.
  76              if (!$singleselect) {
  77                  $dialoguexpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue-focused ')]";
  78                  if (!$node = $this->session->getDriver()->find($dialoguexpath)) {
  79                      $script = "Syn.trigger('change', {}, {{ELEMENT}})";
  80                      try {
  81                          $this->session->getDriver()->triggerSynScript($this->field->getXpath(), $script);
  82                          $this->session->getDriver()->click('//body//div[@class="skiplinks"]');
  83                      } catch (\Exception $e) {
  84                          return;
  85                      }
  86                  } else {
  87                      try {
  88                          $this->session->getDriver()->click($dialoguexpath);
  89                      } catch (\Exception $e) {
  90                          return;
  91                      }
  92                  }
  93              }
  94              $this->session->wait(behat_base::TIMEOUT * 1000, behat_base::PAGE_READY_JS);
  95          }
  96      }
  97  
  98      /**
  99       * Returns the text of the currently selected options.
 100       *
 101       * @return string Comma separated if multiple options are selected. Commas in option texts escaped with backslash.
 102       */
 103      public function get_value() {
 104          return $this->get_selected_options();
 105      }
 106  
 107      /**
 108       * Returns whether the provided argument matches the current value.
 109       *
 110       * @param mixed $expectedvalue
 111       * @return bool
 112       */
 113      public function matches($expectedvalue) {
 114  
 115          $multiple = $this->field->hasAttribute('multiple');
 116  
 117          // Same implementation as the parent if it is a single select.
 118          if (!$multiple) {
 119              $cleanexpectedvalue = trim($expectedvalue);
 120              $selectedtext = trim($this->get_selected_options());
 121              $selectedvalue = trim($this->get_selected_options(false));
 122              if ($cleanexpectedvalue != $selectedvalue && $cleanexpectedvalue != $selectedtext) {
 123                  return false;
 124              }
 125              return true;
 126          }
 127  
 128          // We are dealing with a multi-select.
 129  
 130          // Unescape + trim all options and flip it to have the expected values as keys.
 131          $expectedoptions = $this->get_unescaped_options($expectedvalue);
 132  
 133          // Get currently selected option's texts.
 134          $texts = $this->get_selected_options(true);
 135          $selectedoptiontexts = $this->get_unescaped_options($texts);
 136  
 137          // Get currently selected option's values.
 138          $values = $this->get_selected_options(false);
 139          $selectedoptionvalues = $this->get_unescaped_options($values);
 140  
 141          // Precheck to speed things up.
 142          if (count($expectedoptions) !== count($selectedoptiontexts) ||
 143                  count($expectedoptions) !== count($selectedoptionvalues)) {
 144              return false;
 145          }
 146  
 147          // We check against string-ordered lists of options.
 148          if ($expectedoptions != $selectedoptiontexts &&
 149                  $expectedoptions != $selectedoptionvalues) {
 150              return false;
 151          }
 152  
 153          return true;
 154      }
 155  
 156      /**
 157       * Cleans the list of options and returns it as a string separating options with |||.
 158       *
 159       * @param string $value The string containing the escaped options.
 160       * @return string The options
 161       */
 162      protected function get_unescaped_options($value) {
 163  
 164          // Can be multiple comma separated, with valuable commas escaped with backslash.
 165          $optionsarray = array_map(
 166              'trim',
 167              preg_replace('/\\\,/', ',',
 168                  preg_split('/(?<!\\\),/', $value)
 169             )
 170          );
 171  
 172          // Sort by value (keeping the keys is irrelevant).
 173          core_collator::asort($optionsarray, SORT_STRING);
 174  
 175          // Returning it as a string which is easier to match against other values.
 176          return implode('|||', $optionsarray);
 177      }
 178  
 179      /**
 180       * Returns the field selected values.
 181       *
 182       * Externalized from the common behat_form_field API method get_value() as
 183       * matches() needs to check against both values and texts.
 184       *
 185       * @param bool $returntexts Returns the options texts or the options values.
 186       * @return string
 187       */
 188      protected function get_selected_options($returntexts = true) {
 189  
 190          $method = 'getHtml';
 191          if ($returntexts === false) {
 192              $method = 'getValue';
 193          }
 194  
 195          // Is the select multiple?
 196          $multiple = $this->field->hasAttribute('multiple');
 197  
 198          $selectedoptions = array(); // To accumulate found selected options.
 199  
 200          // Driver returns the values as an array or as a string depending
 201          // on whether multiple options are selected or not.
 202          $values = $this->field->getValue();
 203          if (!is_array($values)) {
 204              $values = array($values);
 205          }
 206  
 207          // Get all the options in the select and extract their value/text pairs.
 208          $alloptions = $this->field->findAll('xpath', '//option');
 209          foreach ($alloptions as $option) {
 210              // Is it selected?
 211              if (in_array($option->getValue(), $values)) {
 212                  if ($multiple) {
 213                      // If the select is multiple, text commas must be encoded.
 214                      $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}()));
 215                  } else {
 216                      $selectedoptions[] = trim($option->{$method}());
 217                  }
 218              }
 219          }
 220  
 221          return implode(', ', $selectedoptions);
 222      }
 223  
 224      /**
 225       * Returns the opton XPath based on it's select xpath.
 226       *
 227       * @param string $option
 228       * @param string $selectxpath
 229       * @return string xpath
 230       */
 231      protected function get_option_xpath($option, $selectxpath) {
 232          $valueliteral = behat_context_helper::escape(trim($option));
 233          return $selectxpath . "/descendant::option[(./@value=$valueliteral or normalize-space(.)=$valueliteral)]";
 234      }
 235  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1