[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/backup/util/ui/tests/behat/ -> behat_backup.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   * Backup and restore actions to help behat feature files writting.
  19   *
  20   * @package    core_backup
  21   * @category   test
  22   * @copyright  2013 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  require_once (__DIR__ . '/../../../../../lib/tests/behat/behat_navigation.php');
  31  
  32  use Behat\Gherkin\Node\TableNode as TableNode,
  33      Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
  34      Behat\Mink\Exception\ExpectationException as ExpectationException;
  35  
  36  /**
  37   * Backup-related steps definitions.
  38   *
  39   * @package    core_backup
  40   * @category   test
  41   * @copyright  2013 David Monllaó
  42   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  43   */
  44  class behat_backup extends behat_base {
  45  
  46      /**
  47       * Follow a link like 'Backup' or 'Import', where the link name comes from
  48       * a language string, in the settings nav block of a course.
  49       * @param string $langstring the lang string to look for. E.g. 'backup' or 'import'.
  50       * @param string $component (optional) second argument to {@link get_string}.
  51       */
  52      protected function navigate_to_course_settings_link($langstring, $component = '') {
  53          $behatnavigation = new behat_navigation();
  54          $behatnavigation->setMink($this->getMink());
  55          $behatnavigation->i_navigate_to_node_in(get_string($langstring, $component),
  56                  get_string('courseadministration'));
  57      }
  58  
  59      /**
  60       * Backups the specified course using the provided options. If you are interested in restoring this backup would be useful to provide a 'Filename' option.
  61       *
  62       * @Given /^I backup "(?P<course_fullname_string>(?:[^"]|\\")*)" course using this options:$/
  63       * @param string $backupcourse
  64       * @param TableNode $options Backup options or false if no options provided
  65       */
  66      public function i_backup_course_using_this_options($backupcourse, $options = false) {
  67          // We can not use other steps here as we don't know where the provided data
  68          // table elements are used, and we need to catch exceptions contantly.
  69  
  70          // Go to homepage.
  71          $this->getSession()->visit($this->locate_path('/'));
  72  
  73          // Click the course link.
  74          $this->find_link($backupcourse)->click();
  75  
  76          // Click the backup link.
  77          $this->navigate_to_course_settings_link('backup');
  78          $this->wait();
  79  
  80          // Initial settings.
  81          $this->fill_backup_restore_form($this->get_step_options($options, "Initial"));
  82          $this->find_button(get_string('backupstage1action', 'backup'))->press();
  83          $this->wait();
  84  
  85          // Schema settings.
  86          $this->fill_backup_restore_form($this->get_step_options($options, "Schema"));
  87          $this->find_button(get_string('backupstage2action', 'backup'))->press();
  88          $this->wait();
  89  
  90          // Confirmation and review, backup filename can also be specified.
  91          $this->fill_backup_restore_form($this->get_step_options($options, "Confirmation"));
  92          $this->find_button(get_string('backupstage4action', 'backup'))->press();
  93  
  94          // Waiting for it to finish.
  95          $this->wait(self::EXTENDED_TIMEOUT);
  96  
  97          // Last backup continue button.
  98          $this->find_button(get_string('backupstage16action', 'backup'))->press();
  99      }
 100  
 101      /**
 102       * Performs a quick (one click) backup of a course.
 103       *
 104       * Please note that because you can't set settings with this there is no way to know what the filename
 105       * that was produced was. It contains a timestamp making it hard to find.
 106       *
 107       * @Given /^I perform a quick backup of course "(?P<course_fullname_string>(?:[^"]|\\")*)"$/
 108       * @param string $backupcourse
 109       */
 110      public function i_perform_a_quick_backup_of_course($backupcourse) {
 111          // We can not use other steps here as we don't know where the provided data
 112          // table elements are used, and we need to catch exceptions contantly.
 113  
 114          // Go to homepage.
 115          $this->getSession()->visit($this->locate_path('/'));
 116  
 117          // Click the course link.
 118          $this->find_link($backupcourse)->click();
 119  
 120          // Click the backup link.
 121          $this->find_link(get_string('backup'))->click();
 122          $this->wait();
 123  
 124          // Initial settings.
 125          $this->find_button(get_string('jumptofinalstep', 'backup'))->press();
 126          $this->wait();
 127  
 128          // Waiting for it to finish.
 129          $this->wait(self::EXTENDED_TIMEOUT);
 130  
 131          // Last backup continue button.
 132          $this->find_button(get_string('backupstage16action', 'backup'))->press();
 133      }
 134  
 135      /**
 136       * Imports the specified origin course into the other course using the provided options.
 137       *
 138       * Keeping it separatelly from backup & restore, it the number of
 139       * steps and duplicate code becomes bigger a common method should
 140       * be generalized.
 141       *
 142       * @Given /^I import "(?P<from_course_fullname_string>(?:[^"]|\\")*)" course into "(?P<to_course_fullname_string>(?:[^"]|\\")*)" course using this options:$/
 143       * @param string $fromcourse
 144       * @param string $tocourse
 145       * @param TableNode $options
 146       */
 147      public function i_import_course_into_course($fromcourse, $tocourse, $options = false) {
 148  
 149          // We can not use other steps here as we don't know where the provided data
 150          // table elements are used, and we need to catch exceptions contantly.
 151  
 152          // Go to homepage.
 153          $this->getSession()->visit($this->locate_path('/'));
 154          $this->wait();
 155  
 156          // Click the course link.
 157          $this->find_link($tocourse)->click();
 158          $this->wait();
 159  
 160          // Click the import link.
 161          $this->navigate_to_course_settings_link('import');
 162          $this->wait();
 163  
 164          // Select the course.
 165          $exception = new ExpectationException('"' . $fromcourse . '" course not found in the list of courses to import from', $this->getSession());
 166  
 167          // The argument should be converted to an xpath literal.
 168          $fromcourse = $this->getSession()->getSelectorsHandler()->xpathLiteral($fromcourse);
 169          $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' ics-results ')]" .
 170              "/descendant::tr[contains(., $fromcourse)]" .
 171              "/descendant::input[@type='radio']";
 172          $radionode = $this->find('xpath', $xpath, $exception);
 173          $radionode->check();
 174          $radionode->click();
 175  
 176          $this->find_button(get_string('continue'))->press();
 177          $this->wait();
 178  
 179          // Initial settings.
 180          $this->fill_backup_restore_form($this->get_step_options($options, "Initial"));
 181          $this->find_button(get_string('importbackupstage1action', 'backup'))->press();
 182          $this->wait();
 183  
 184          // Schema settings.
 185          $this->fill_backup_restore_form($this->get_step_options($options, "Schema"));
 186          $this->find_button(get_string('importbackupstage2action', 'backup'))->press();
 187          $this->wait();
 188  
 189          // Run it.
 190          $this->find_button(get_string('importbackupstage4action', 'backup'))->press();
 191          $this->wait(self::EXTENDED_TIMEOUT);
 192  
 193          // Continue and redirect to 'to' course.
 194          $this->find_button(get_string('continue'))->press();
 195      }
 196  
 197      /**
 198       * Restores the backup into the specified course and the provided options. You should be in the 'Restore' page where the backup is.
 199       *
 200       * @Given /^I restore "(?P<backup_filename_string>(?:[^"]|\\")*)" backup into "(?P<existing_course_fullname_string>(?:[^"]|\\")*)" course using this options:$/
 201       * @param string $backupfilename
 202       * @param string $existingcourse
 203       * @param TableNode $options Restore forms options or false if no options provided
 204       */
 205      public function i_restore_backup_into_course_using_this_options($backupfilename, $existingcourse, $options = false) {
 206  
 207          // Confirm restore.
 208          $this->select_backup($backupfilename);
 209  
 210          // The argument should be converted to an xpath literal.
 211          $existingcourse = $this->getSession()->getSelectorsHandler()->xpathLiteral($existingcourse);
 212  
 213          // Selecting the specified course (we can not call behat_forms::select_radio here as is in another behat subcontext).
 214          $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-existing-course ')]" .
 215              "/descendant::div[@class='restore-course-search']" .
 216              "/descendant::tr[contains(., $existingcourse)]" .
 217              "/descendant::input[@type='radio']");
 218          $radionode->check();
 219          $radionode->click();
 220  
 221          // Pressing the continue button of the restore into an existing course section.
 222          $continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-existing-course ')]" .
 223              "/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
 224          $continuenode->click();
 225          $this->wait();
 226  
 227          // Common restore process using provided key/value options.
 228          $this->process_restore($options);
 229      }
 230  
 231      /**
 232       * Restores the specified backup into a new course using the provided options. You should be in the 'Restore' page where the backup is.
 233       *
 234       * @Given /^I restore "(?P<backup_filename_string>(?:[^"]|\\")*)" backup into a new course using this options:$/
 235       * @param string $backupfilename
 236       * @param TableNode $options Restore forms options or false if no options provided
 237       */
 238      public function i_restore_backup_into_a_new_course_using_this_options($backupfilename, $options = false) {
 239  
 240          // Confirm restore.
 241          $this->select_backup($backupfilename);
 242  
 243          // The first category in the list.
 244          $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-new-course ')]" .
 245              "/descendant::div[@class='restore-course-search']" .
 246              "/descendant::input[@type='radio']");
 247          $radionode->check();
 248          $radionode->click();
 249  
 250          // Pressing the continue button of the restore into an existing course section.
 251          $continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-new-course ')]" .
 252              "/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
 253          $continuenode->click();
 254          $this->wait();
 255  
 256          // Common restore process using provided key/value options.
 257          $this->process_restore($options);
 258      }
 259  
 260      /**
 261       * Merges the backup into the current course using the provided restore options. You should be in the 'Restore' page where the backup is.
 262       *
 263       * @Given /^I merge "(?P<backup_filename_string>(?:[^"]|\\")*)" backup into the current course using this options:$/
 264       * @param string $backupfilename
 265       * @param TableNode $options Restore forms options or false if no options provided
 266       */
 267      public function i_merge_backup_into_the_current_course($backupfilename, $options = false) {
 268  
 269          // Confirm restore.
 270          $this->select_backup($backupfilename);
 271  
 272          // Merge without deleting radio option.
 273          $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
 274              "/descendant::input[@type='radio'][@name='target'][@value='1']");
 275          $radionode->check();
 276          $radionode->click();
 277  
 278          // Pressing the continue button of the restore merging section.
 279          $continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
 280              "/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
 281          $continuenode->click();
 282          $this->wait();
 283  
 284          // Common restore process using provided key/value options.
 285          $this->process_restore($options);
 286      }
 287  
 288      /**
 289       * Merges the backup into the current course after deleting this contents, using the provided restore options. You should be in the 'Restore' page where the backup is.
 290       *
 291       * @Given /^I merge "(?P<backup_filename_string>(?:[^"]|\\")*)" backup into the current course after deleting it's contents using this options:$/
 292       * @param string $backupfilename
 293       * @param TableNode $options Restore forms options or false if no options provided
 294       */
 295      public function i_merge_backup_into_current_course_deleting_its_contents($backupfilename, $options = false) {
 296  
 297          // Confirm restore.
 298          $this->select_backup($backupfilename);
 299  
 300          // Delete contents radio option.
 301          $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
 302              "/descendant::input[@type='radio'][@name='target'][@value='0']");
 303          $radionode->check();
 304          $radionode->click();
 305  
 306          // Pressing the continue button of the restore merging section.
 307          $continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
 308              "/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
 309          $continuenode->click();
 310          $this->wait();
 311  
 312          // Common restore process using provided key/value options.
 313          $this->process_restore($options);
 314      }
 315  
 316      /**
 317       * Selects the backup to restore.
 318       *
 319       * @throws ExpectationException
 320       * @param string $backupfilename
 321       * @return void
 322       */
 323      protected function select_backup($backupfilename) {
 324  
 325          // Using xpath as there are other restore links before this one.
 326          $exception = new ExpectationException('The "' . $backupfilename . '" backup file can not be found in this page', $this->getSession());
 327  
 328          // The argument should be converted to an xpath literal.
 329          $backupfilename = $this->getSession()->getSelectorsHandler()->xpathLiteral($backupfilename);
 330  
 331          $xpath = "//tr[contains(., $backupfilename)]/descendant::a[contains(., '" . get_string('restore') . "')]";
 332          $restorelink = $this->find('xpath', $xpath, $exception);
 333          $restorelink->click();
 334  
 335          // Confirm the backup contents.
 336          $restore = $this->find_button(get_string('continue'))->press();
 337      }
 338  
 339      /**
 340       * Executes the common steps of all restore processes.
 341       *
 342       * @param TableNode $options The backup and restore options or false if no options provided
 343       * @return void
 344       */
 345      protected function process_restore($options) {
 346  
 347          // We can not use other steps here as we don't know where the provided data
 348          // table elements are used, and we need to catch exceptions contantly.
 349  
 350          // Settings.
 351          $this->fill_backup_restore_form($this->get_step_options($options, "Settings"));
 352          $this->find_button(get_string('restorestage4action', 'backup'))->press();
 353          $this->wait();
 354  
 355          // Schema.
 356          $this->fill_backup_restore_form($this->get_step_options($options, "Schema"));
 357          $this->find_button(get_string('restorestage8action', 'backup'))->press();
 358          $this->wait();
 359  
 360          // Review, no options here.
 361          $this->find_button(get_string('restorestage16action', 'backup'))->press();
 362          $this->wait();
 363  
 364          // Last restore continue button, redirected to restore course after this.
 365          $this->find_button(get_string('restorestage32action', 'backup'))->press();
 366  
 367          // Long wait when waiting for the restore to finish.
 368          $this->wait(self::EXTENDED_TIMEOUT);
 369      }
 370  
 371      /**
 372       * Tries to fill the current page form elements with the provided options.
 373       *
 374       * This step is slow as it spins over each provided option, we are
 375       * not expected to have lots of provided options, anyways, is better
 376       * to be conservative and wait for the elements to appear rather than
 377       * to have false failures.
 378       *
 379       * @param TableNode $options The backup and restore options or false if no options provided
 380       * @return void
 381       */
 382      protected function fill_backup_restore_form($options) {
 383  
 384          // Nothing to fill if no options are provided.
 385          if (!$options) {
 386              return;
 387          }
 388  
 389          // If we find any of the provided options in the current form we should set the value.
 390          $datahash = $options->getRowsHash();
 391          foreach ($datahash as $locator => $value) {
 392              $field = behat_field_manager::get_form_field_from_label($locator, $this);
 393              $field->set_value($value);
 394          }
 395      }
 396  
 397      /**
 398       * Get the options specific to this step of the backup/restore process.
 399       *
 400       * @param TableNode $options The options table to filter
 401       * @param string $step The name of the step
 402       * @return TableNode The filtered options table
 403       * @throws ExpectationException
 404       */
 405      protected function get_step_options($options, $step) {
 406          // Nothing to fill if no options are provided.
 407          if (!$options) {
 408              return;
 409          }
 410  
 411          $pageoptions = clone $options;
 412  
 413          $rows = $options->getRows();
 414          $newrows = array();
 415          foreach ($rows as $k => $data) {
 416              if (count($data) !== 3) {
 417                  // Not enough information to guess the page.
 418                  throw new ExpectationException("The backup/restore step must be specified for all backup options");
 419              } else if ($data[0] == $step) {
 420                  unset($data[0]);
 421                  $newrows[] = $data;
 422              }
 423          }
 424          $pageoptions->setRows($newrows);
 425          return $pageoptions;
 426      }
 427  
 428  
 429      /**
 430       * Waits until the DOM and the page Javascript code is ready.
 431       *
 432       * @param int $timeout The number of seconds that we wait.
 433       * @return void
 434       */
 435      protected function wait($timeout = false) {
 436  
 437          if (!$this->running_javascript()) {
 438              return;
 439          }
 440  
 441          if (!$timeout) {
 442              $timeout = self::TIMEOUT;
 443          }
 444  
 445          $this->getSession()->wait($timeout * 1000, self::PAGE_READY_JS);
 446      }
 447  
 448  }


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