[ Index ]

PHP Cross Reference of Unnamed Project

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


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