[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |