[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |