Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}