[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/tests/behat/ -> behat_navigation.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   * Navigation steps definitions.
  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__ . '/../../behat/behat_base.php');
  29  
  30  use Behat\Behat\Context\Step\Given as Given,
  31      Behat\Mink\Exception\ExpectationException as ExpectationException;
  32  
  33  /**
  34   * Steps definitions to navigate through the navigation tree nodes.
  35   *
  36   * @package    core
  37   * @category   test
  38   * @copyright  2012 David Monllaó
  39   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class behat_navigation extends behat_base {
  42  
  43      /**
  44       * Helper function to get a navigation nodes text element given its text from within the navigation block.
  45       *
  46       * This function finds the node with the given text from within the navigation block.
  47       * It checks to make sure the node is visible, and then returns it.
  48       *
  49       * @param string $text
  50       * @param bool $branch Set this true if you're only interested in the node if its a branch.
  51       * @param null|bool $collapsed Set this to true or false if you want the node to either be collapsed or not.
  52       *    If its left as null then we don't worry about it.
  53       * @param null|string|Exception|false $exception The exception to throw if the node is not found.
  54       * @return \Behat\Mink\Element\NodeElement
  55       */
  56      protected function get_node_text_node($text, $branch = false, $collapsed = null, $exception = null) {
  57          if ($exception === null) {
  58              $exception = new ExpectationException('The "' . $text . '" node could not be found', $this->getSession());
  59          } else if (is_string($exception)) {
  60              $exception = new ExpectationException($exception, $this->getSession());
  61          }
  62  
  63          $nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($text);
  64          $hasblocktree = "[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]";
  65          $hasbranch = "[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]";
  66          $hascollapsed = "li[contains(concat(' ', normalize-space(@class), ' '), ' collapsed ') or @data-expandable='1']";
  67          $notcollapsed = "li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed '))]";
  68          $match = "[normalize-space(.)={$nodetextliteral}]";
  69  
  70          // Avoid problems with quotes.
  71          $isbranch = ($branch) ? $hasbranch : '';
  72          if ($collapsed === true) {
  73              $iscollapsed = $hascollapsed;
  74          } else if ($collapsed === false) {
  75              $iscollapsed = $notcollapsed;
  76          } else {
  77              $iscollapsed = 'li';
  78          }
  79  
  80          // First check root nodes.
  81          $xpath  = "//ul{$hasblocktree}/$hascollapsed/p{$isbranch}/span{$match}|";
  82          // Next search for the node containing the text within a link.
  83          $xpath .= "//ul{$hasblocktree}//{$notcollapsed}/ul/{$iscollapsed}/p{$isbranch}/a{$match}|";
  84          // Finally search for the node containing the text within a span.
  85          $xpath .= "//ul{$hasblocktree}//{$notcollapsed}/ul/{$iscollapsed}/p{$isbranch}/span{$match}";
  86  
  87          $node = $this->find('xpath', $xpath, $exception);
  88          $this->ensure_node_is_visible($node);
  89          return $node;
  90      }
  91  
  92      /**
  93       * Returns true if the navigation node with the given text is expandable.
  94       *
  95       * @Given /^navigation node "([^"]*)" should be expandable$/
  96       *
  97       * @throws ExpectationException
  98       * @param string $nodetext
  99       * @return bool
 100       */
 101      public function navigation_node_should_be_expandable($nodetext) {
 102          if (!$this->running_javascript()) {
 103              // Nodes are only expandable when JavaScript is enabled.
 104              return false;
 105          }
 106  
 107          $node = $this->get_node_text_node($nodetext, true);
 108          $node = $node->getParent();
 109          if ($node->hasAttribute('data-expandable') && $node->getAttribute('data-expandable')) {
 110              return true;
 111          }
 112          throw new ExpectationException('The "' . $nodetext . '" node is not expandable', $this->getSession());
 113      }
 114  
 115      /**
 116       * Returns true if the navigation node with the given text is not expandable.
 117       *
 118       * @Given /^navigation node "([^"]*)" should not be expandable$/
 119       *
 120       * @throws ExpectationException
 121       * @param string $nodetext
 122       * @return bool
 123       */
 124      public function navigation_node_should_not_be_expandable($nodetext) {
 125          if (!$this->running_javascript()) {
 126              // Nodes are only expandable when JavaScript is enabled.
 127              return false;
 128          }
 129  
 130          $node = $this->get_node_text_node($nodetext);
 131          $node = $node->getParent();
 132          if ($node->hasAttribute('data-expandable') && $node->getAttribute('data-expandable')) {
 133              throw new ExpectationException('The "' . $nodetext . '" node is expandable', $this->getSession());
 134          }
 135          return true;
 136      }
 137  
 138      /**
 139       * Expands the selected node of the navigation tree that matches the text.
 140       * @Given /^I expand "(?P<nodetext_string>(?:[^"]|\\")*)" node$/
 141       *
 142       * @throws ExpectationException
 143       * @param string $nodetext
 144       * @return bool|void
 145       */
 146      public function i_expand_node($nodetext) {
 147  
 148          // This step is useless with Javascript disabled as Moodle auto expands
 149          // all of tree's nodes; adding this because of scenarios that shares the
 150          // same steps with and without Javascript enabled.
 151          if (!$this->running_javascript()) {
 152              if ($nodetext === get_string('administrationsite')) {
 153                  // Administration menu is not loaded by default any more. Click the link to expand.
 154                  return new Given('I click on "'.$nodetext.'" "link" in the "'.get_string('administration').'" "block"');
 155              }
 156              return true;
 157          }
 158  
 159          $node = $this->get_node_text_node($nodetext, true, true, 'The "' . $nodetext . '" node can not be expanded');
 160          // Check if the node is a link AND a branch.
 161          if (strtolower($node->getTagName()) === 'a') {
 162              // We just want to expand the node, we don't want to follow it.
 163              $node = $node->getParent();
 164          }
 165          $node->click();
 166      }
 167  
 168      /**
 169       * Collapses the selected node of the navigation tree that matches the text.
 170       *
 171       * @Given /^I collapse "(?P<nodetext_string>(?:[^"]|\\")*)" node$/
 172       * @throws ExpectationException
 173       * @param string $nodetext
 174       * @return bool|void
 175       */
 176      public function i_collapse_node($nodetext) {
 177  
 178          // No collapsible nodes with non-JS browsers.
 179          if (!$this->running_javascript()) {
 180              return true;
 181          }
 182  
 183          $node = $this->get_node_text_node($nodetext, true, false, 'The "' . $nodetext . '" node can not be collapsed');
 184          // Check if the node is a link AND a branch.
 185          if (strtolower($node->getTagName()) === 'a') {
 186              // We just want to expand the node, we don't want to follow it.
 187              $node = $node->getParent();
 188          }
 189          $node->click();
 190      }
 191  
 192      /**
 193       * Click link in navigation tree that matches the text in parentnode/s (seperated using greater-than character if more than one)
 194       *
 195       * @Given /^I navigate to "(?P<nodetext_string>(?:[^"]|\\")*)" node in "(?P<parentnodes_string>(?:[^"]|\\")*)"$/
 196       *
 197       * @throws ExpectationException
 198       * @param string $nodetext navigation node to click.
 199       * @param string $parentnodes comma seperated list of parent nodes.
 200       * @return void
 201       */
 202      public function i_navigate_to_node_in($nodetext, $parentnodes) {
 203  
 204          // Site admin is different and needs special treatment.
 205          $siteadminstr = get_string('administrationsite');
 206  
 207          // Create array of all parentnodes.
 208          $parentnodes = array_map('trim', explode('>', $parentnodes));
 209          $countparentnode = count($parentnodes);
 210  
 211          // If JS is disabled and Site administration is not expanded we
 212          // should follow it, so all the lower-level nodes are available.
 213          if (!$this->running_javascript()) {
 214              if ($parentnodes[0] === $siteadminstr) {
 215                  // We don't know if there if Site admin is already expanded so
 216                  // don't wait, it is non-JS and we already waited for the DOM.
 217                  if ($siteadminlink = $this->getSession()->getPage()->find('named', array('link', "'" . $siteadminstr . "'"))) {
 218                      $siteadminlink->click();
 219                  }
 220              }
 221          }
 222  
 223          // Expand first node, and get it.
 224          $node = $this->get_top_navigation_node($parentnodes[0]);
 225  
 226          // Expand parent, sub-parent nodes in navigation if js enabled.
 227          if ($node->hasClass('collapsed') || ($node->hasAttribute('data-loaded') && $node->getAttribute('data-loaded') == 0)) {
 228              $xpath = "/p[contains(concat(' ', normalize-space(@class), ' '), ' tree_item ')]/span";
 229              $nodetoexpand = $node->find('xpath', $xpath);
 230  
 231              if ($this->running_javascript()) {
 232                  $this->ensure_node_is_visible($nodetoexpand);
 233                  $nodetoexpand->click();
 234  
 235                  // Site administration node needs to be expanded.
 236                  if ($parentnodes[0] === $siteadminstr) {
 237                      $this->getSession()->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
 238                  }
 239              }
 240          }
 241  
 242          // If sub-parent nodes then get to the last one.
 243          if ($countparentnode > 1) {
 244              for ($i = 1; $i < $countparentnode; $i++) {
 245                  $node = $this->get_navigation_node($parentnodes[$i], $node);
 246  
 247                  // Keep expanding all sub-parents if js enabled.
 248                  if ($this->running_javascript()) {
 249                      $xpath = "/p[contains(concat(' ', normalize-space(@class), ' '), ' tree_item ')]";
 250                      if ($node->hasClass('collapsed')) {
 251                          $nodetoexpand = $node->find('xpath', $xpath);
 252                          if ($this->running_javascript()) {
 253                              $this->ensure_node_is_visible($nodetoexpand);
 254                              $nodetoexpand->click();
 255                          }
 256                      }
 257                  }
 258              }
 259          }
 260  
 261          // Finally, click on requested node under navigation.
 262          $nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($nodetext);
 263          $xpath = "/ul/li/p[contains(concat(' ', normalize-space(@class), ' '), ' tree_item ')]" .
 264                  "/a[normalize-space(.)=" . $nodetextliteral . "]";
 265          $node = $node->find('xpath', $xpath);
 266  
 267          // Throw exception if no node found.
 268          if (!$node) {
 269              throw new ExpectationException('Navigation node "' . $nodetext . '" not found under "' .
 270                  implode($parentnodes, ' > ') . '"', $this->getSession());
 271          }
 272  
 273          if ($this->running_javascript()) {
 274              $this->ensure_node_is_visible($node);
 275          }
 276  
 277          $node->click();
 278      }
 279  
 280      /**
 281       * Helper function to get top navigation node in tree.
 282       *
 283       * @throws ExpectationException if note not found.
 284       * @param string $nodetext name of top navigation node in tree.
 285       * @return NodeElement
 286       */
 287      protected function get_top_navigation_node($nodetext) {
 288  
 289          // Avoid problems with quotes.
 290          $nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($nodetext);
 291          $exception = new ExpectationException('Top navigation node "' . $nodetext . ' not found in "', $this->getSession());
 292  
 293          // First find in navigation block.
 294          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]" .
 295              "/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
 296              "/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 297              "/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 298              "[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
 299              "/span[normalize-space(.)=" . $nodetextliteral ."]]" .
 300              "|" .
 301              "//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]/div" .
 302              "/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
 303              "/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 304              "/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 305              "[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
 306              "/span[normalize-space(.)=" . $nodetextliteral ."]]" .
 307              "|" .
 308              "//div[contains(concat(' ', normalize-space(@class), ' '), ' content ')]/div" .
 309              "/ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
 310              "/li[p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
 311              "/span[normalize-space(.)=" . $nodetextliteral ."]]";
 312              $node = $this->find('xpath', $xpath, $exception);
 313  
 314          return $node;
 315      }
 316  
 317      /**
 318       * Helper function to get sub-navigation node.
 319       *
 320       * @throws ExpectationException if note not found.
 321       * @param string $nodetext node to find.
 322       * @param NodeElement $parentnode parent navigation node.
 323       * @return NodeElement.
 324       */
 325      protected function get_navigation_node($nodetext, $parentnode = null) {
 326  
 327          // Avoid problems with quotes.
 328          $nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($nodetext);
 329  
 330          $xpath = "/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 331              "[child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
 332              "/child::span[normalize-space(.)=" . $nodetextliteral ."]]";
 333          $node = $parentnode->find('xpath', $xpath);
 334          if (!$node) {
 335              $xpath = "/ul/li[contains(concat(' ', normalize-space(@class), ' '), ' contains_branch ')]" .
 336                  "[child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
 337                  "/child::a[normalize-space(.)=" . $nodetextliteral ."]]";
 338              $node = $parentnode->find('xpath', $xpath);
 339          }
 340  
 341          if (!$node) {
 342              throw new ExpectationException('Sub-navigation node "' . $nodetext . '" not found under "' .
 343                  $parentnode->getText() . '"', $this->getSession());
 344          }
 345          return $node;
 346      }
 347  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1