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