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
 * Steps definitions related with the questionnaire activity.
19
 *
20
 * @package    mod_questionnaire
21
 * @category   test
22
 * @copyright  2016 Mike Churchward - Poet Open Source
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
 
30
use Behat\Behat\Context\Step\Given as Given,
31
    Behat\Behat\Context\Step\When as When,
32
    Behat\Gherkin\Node\TableNode as TableNode,
33
    Behat\Gherkin\Node\PyStringNode as PyStringNode,
34
    Behat\Mink\Exception\ExpectationException as ExpectationException;
35
;
36
/**
37
 * Questionnaire-related steps definitions.
38
 *
39
 * @package    mod_questionnaire
40
 * @category   test
41
 * @copyright  2016 Mike Churchward - Poet Open Source
42
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43
 */
44
class behat_mod_questionnaire extends behat_base {
45
 
46
    /**
47
     * Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
48
     *
49
     * Recognised page names are:
50
     * | None so far!      |                                                              |
51
     *
52
     * @param string $page name of the page, with the component name removed e.g. 'Admin notification'.
53
     * @return moodle_url the corresponding URL.
54
     * @throws Exception with a meaningful error message if the specified page cannot be found.
55
     */
56
    protected function resolve_page_url(string $page): moodle_url {
57
        switch (strtolower($page)) {
58
            default:
59
                throw new Exception('Unrecognised quiz page type "' . $page . '."');
60
        }
61
    }
62
 
63
    /**
64
     * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
65
     *
66
     * Recognised page names are:
67
     * | pagetype          | name meaning                                | description                                           |
68
     * | view              | Questionnaire name                          | The questionnaire info page (view.php)                |
69
     * | preview           | Questionnaire name                          | The questionnaire preview page (preview.php)          |
70
     * | questions         | Questionnaire name                          | The questionnaire questions page (questions.php)      |
71
     * | advsettings       | Questionnaire name                          | The advanced settings page (questions.php)            |
72
     *
73
     * @param string $type identifies which type of page this is, e.g. 'preview'.
74
     * @param string $identifier identifies the particular page, e.g. 'Test questionnaire > preview > Attempt 1'.
75
     * @return moodle_url the corresponding URL.
76
     * @throws Exception with a meaningful error message if the specified page cannot be found.
77
     */
78
    protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
79
        switch (strtolower($type)) {
80
            case 'view':
81
                return new moodle_url('/mod/questionnaire/view.php',
82
                    ['id' => $this->get_cm_by_questionnaire_name($identifier)->id]);
83
 
84
            case 'preview':
85
                return new moodle_url('/mod/questionnaire/preview.php',
86
                    ['id' => $this->get_cm_by_questionnaire_name($identifier)->id]);
87
 
88
            case 'questions':
89
                return new moodle_url('/mod/questionnaire/questions.php',
90
                    ['id' => $this->get_cm_by_questionnaire_name($identifier)->id]);
91
 
92
            case 'advsettings':
93
                return new moodle_url('/mod/questionnaire/qsettings.php',
94
                    ['id' => $this->get_cm_by_questionnaire_name($identifier)->id]);
95
 
96
            default:
97
                throw new Exception('Unrecognised questionnaire page type "' . $type . '."');
98
        }
99
    }
100
 
101
    /**
102
     * Adds a question to the questionnaire with the provided data.
103
     *
104
     * @Given /^I add a "([^"]*)" question and I fill the form with:$/
105
     *
106
     * @param string $questiontype The question type by text name to enter.
107
     * @param TableNode $fielddata
108
     */
109
    public function i_add_a_question_and_i_fill_the_form_with($questiontype, TableNode $fielddata) {
110
        $validtypes = array(
111
            '----- Page Break -----',
112
            'Check Boxes',
113
            'Date',
114
            'Dropdown Box',
115
            'Essay Box',
116
            'Label',
117
            'Numeric',
118
            'Radio Buttons',
119
            'Rate (scale 1..5)',
120
            'Text Box',
121
            'Yes/No',
122
            'Slider');
123
 
124
        if (!in_array($questiontype, $validtypes)) {
125
            throw new ExpectationException('Invalid question type specified.', $this->getSession());
126
        }
127
 
128
        // We get option choices as CSV strings. If we have this, modify it for use in
129
        // multiline data.
130
        $rows = $fielddata->getRows();
131
        $hashrows = $fielddata->getRowsHash();
132
        if (isset($hashrows['Possible answers'])) {
133
            // Find the row that contained multiline data and add line breaks. Rows are two item arrays where the
134
            // first is an identifier and the second is the value.
135
            foreach ($rows as $key => $row) {
136
                if ($row[0] == 'Possible answers') {
137
                    $row[1] = str_replace(',', "\n", $row[1]);
138
                    $rows[$key] = $row;
139
                    break;
140
                }
141
            }
142
            $fielddata = new TableNode($rows);
143
        }
144
        if (isset($hashrows['Named degrees'])) {
145
            // Find the row that contained multiline data and add line breaks. Rows are two item arrays where the
146
            // first is an identifier and the second is the value.
147
            foreach ($rows as $key => $row) {
148
                if ($row[0] == 'Named degrees') {
149
                    $row[1] = str_replace(',', "\n", $row[1]);
150
                    $rows[$key] = $row;
151
                    break;
152
                }
153
            }
154
            $fielddata = new TableNode($rows);
155
        }
156
 
157
        $this->execute('behat_forms::i_set_the_field_to', array('id_type_id', $questiontype));
158
        $this->execute('behat_forms::press_button', 'Add selected question type');
159
        if (isset($hashrows['id_dependquestions_and_1'])) {
160
            $this->execute('behat_forms::press_button', 'id_adddependencies_and');
161
        }
162
        if (isset($hashrows['id_dependquestions_or_1'])) {
163
            $this->execute('behat_forms::press_button', 'id_adddependencies_or');
164
        }
165
        $this->execute('behat_forms::i_set_the_following_fields_to_these_values', $fielddata);
166
        $this->execute('behat_forms::press_button', 'Save changes');
167
    }
168
 
169
    /**
170
     * Selects a radio button option in the named radio button group.
171
     *
172
     * @Given /^I click the "([^"]*)" radio button$/
173
     *
174
     * @param int $radioid
175
     */
176
    public function i_click_the_radio_button($radioid) {
177
        $session = $this->getSession();
178
        $page = $session->getPage();
179
        $radios = $page->findAll('xpath', '//input[@type="radio" and @id="'.$radioid.'"]');
180
        $radios[0]->click();
181
    }
182
 
183
    /**
184
     * Adds a questions and responses to the questionnaire with the provided name.
185
     *
186
     * @Given /^"([^"]*)" has questions and responses$/
187
     *
188
     * @param string $questionnairename The name of an existing questionnaire.
189
     */
190
    public function has_questions_and_responses($questionnairename) {
191
        global $DB;
192
 
193
        if (!$questionnaire = $DB->get_record('questionnaire', array('name' => $questionnairename), 'id,sid')) {
194
            throw new ExpectationException('Invalid questionnaire name specified.', $this->getSession());
195
        }
196
 
197
        if (!$DB->record_exists('questionnaire_survey', array('id' => $questionnaire->sid))) {
198
            throw new ExpectationException('Questionnaire survey does not exist.', $this->getSession());
199
        }
200
 
201
        $this->add_question_data($questionnaire->sid);
202
        $this->add_response_data($questionnaire->id, $questionnaire->sid);
203
    }
204
 
205
    /**
206
     * Adds a question data to the given survey id.
207
     *
208
     * @param int $sid The id field of an existing questionnaire_survey record.
209
     * @return null
210
     */
211
    private function add_question_data($sid) {
212
        $questiondata = array(
213
            array("id", "surveyid", "name", "type_id", "result_id", "length", "precise", "position", "content", "required",
214
                  "deleted", "dependquestion", "dependchoice"),
215
            array("1", $sid, "own car", "1", null, "0", "0", "1", "<p>Do you own a car?</p>", "y", "n", "0", "0"),
216
            array("2", $sid, "optional", "2", null, "20", "25", "3", "<p>What is the colour of your car?</p>", "y", "n", "121",
217
                  "0"),
218
            array("3", $sid, null, "99", null, "0", "0", "2", "break", "n", "n", "0", "0"),
219
            array("4", $sid, "optional2", "1", null, "0", "0", "5", "<p>Do you sometimes use public transport to go to work?</p>",
220
                  "y", "n", "0", "0"),
221
            array("5", $sid, null, "99", null, "0", "0", "4", "break", "n", "n", "0", "0"),
222
            array("6", $sid, "entertext", "2", null, "20", "10", "6", "<p>Enter no more than 10 characters.<br></p>", "n", "n", "0",
223
                  "0"),
224
            array("7", $sid, "q7", "5", null, "0", "0", "7", "<p>Check all that apply<br></p>", "n", "n", "0", "0"),
225
            array("8", $sid, "q8", "9", null, "0", "0", "8", "<p>Enter today's date<br></p>", "n", "n", "0", "0"),
226
            array("9", $sid, "q9", "6", null, "0", "0", "9", "<p>Choose One<br></p>", "n", "n", "0", "0"),
227
            array("10", $sid, "q10", "3", null, "5", "0", "10", "<p>Write an essay<br></p>", "n", "n", "0", "0"),
228
            array("11", $sid, "q11", "10", null, "10", "0", "11", "<p>Enter a number<br></p>", "n", "n", "0", "0"),
229
            array("12", $sid, "q12", "4", null, "1", "0", "13", "<p>Choose a colour<br></p>", "n", "n", "0", "0"),
230
            array("13", $sid, "q13", "8", null, "5", "1", "14", "<p>Rate this.<br></p>", "n", "n", "0", "0"),
231
            array("14", $sid, null, "99", null, "0", "0", "12", "break", "n", "y", "0", "0"),
232
            array("15", $sid, null, "99", null, "0", "0", "12", "break", "n", "n", "0", "0"),
233
            array("16", $sid, "Q1", "10", null, "3", "2", "15", "Enter a number<br><p><br></p>", "y", "n", "0", "0")
234
        );
235
 
236
        $choicedata = array(
237
            array("id", "question_id", "content", "value"),
238
            array("1", "7", "1", null),
239
            array("2", "7", "2", null),
240
            array("3", "7", "3", null),
241
            array("4", "7", "4", null),
242
            array("5", "7", "5", null),
243
            array("6", "9", "1", null),
244
            array("7", "9", "One", null),
245
            array("8", "9", "2", null),
246
            array("9", "9", "Two", null),
247
            array("10", "9", "3", null),
248
            array("11", "9", "Three", null),
249
            array("12", "12", "Red", null),
250
            array("13", "12", "Toyota", null),
251
            array("14", "12", "Bird", null),
252
            array("15", "12", "Blew", null),
253
            array("16", "13", "Good", null),
254
            array("17", "13", "Great", null),
255
            array("18", "13", "So-so", null),
256
            array("19", "13", "Lamp", null),
257
            array("20", "13", "Huh?", null),
258
            array("21", "7", "!other=Another number", null),
259
            array("22", "12", "!other=Something else", null)
260
        );
261
 
262
        $this->add_data($questiondata, 'questionnaire_question', 'questionmap');
263
        $this->add_data($choicedata, 'questionnaire_quest_choice', 'choicemap', array('questionmap' => 'question_id'));
264
    }
265
 
266
    /**
267
     * Adds response data to the given questionnaire and survey id.
268
     *
269
     * @param int $qid The id field of an existing questionnaire record.
270
     * @param int $sid The id field of an existing questionnaire_survey record.
271
     * @return null
272
     */
273
    private function add_response_data($qid, $sid) {
274
        global $DB;
275
 
276
        $responses = array(
277
            array("id", "questionnaireid", "submitted", "complete", "grade", "userid"),
278
            array("1", $qid, "1419011935", "y", "0", "2"),
279
            array("2", $qid, "1449064371", "y", "0", "2"),
280
            array("3", $qid, "1449258520", "y", "0", "2"),
281
            array("4", $qid, "1452020444", "y", "0", "2"),
282
            array("5", $qid, "1452804783", "y", "0", "2"),
283
            array("6", $qid, "1452806547", "y", "0", "2"),
284
            array("7", $qid, "1465415731", "n", "0", "2")
285
        );
286
        $this->add_data($responses, 'questionnaire_response', 'responsemap');
287
 
288
        $responsebool = array(
289
            array("id", "response_id", "question_id", "choice_id"),
290
            array("", "1", "1", "y"),
291
            array("", "1", "4", "n"),
292
            array("", "2", "1", "y"),
293
            array("", "2", "4", "n"),
294
            array("", "3", "1", "n"),
295
            array("", "3", "4", "y"),
296
            array("", "4", "1", "y"),
297
            array("", "4", "4", "n"),
298
            array("", "5", "1", "n"),
299
            array("", "5", "4", "n"),
300
            array("", "6", "1", "n"),
301
            array("", "6", "4", "n"),
302
            array("", "7", "1", "y"),
303
            array("", "7", "4", "y")
304
        );
305
        $this->add_data($responsebool, 'questionnaire_response_bool', '',
306
            array('responsemap' => 'response_id', 'questionmap' => 'question_id'));
307
 
308
        $responsedate = array(
309
            array("id", "response_id", "question_id", "response"),
310
            array("", "1", "8", "2014-12-19"),
311
            array("", "2", "8", "2015-12-02"),
312
            array("", "3", "8", "2015-12-04"),
313
            array("", "4", "8", "2016-01-06"),
314
            array("", "5", "8", "2016-01-13"),
315
            array("", "6", "8", "2016-01-13")
316
        );
317
        $this->add_data($responsedate, 'questionnaire_response_date', '',
318
            array('responsemap' => 'response_id', 'questionmap' => 'question_id'));
319
 
320
        $responseother = array(
321
            array("id", "response_id", "question_id", "choice_id", "response"),
322
            array("", "5", "7", "21", "Forty-four"),
323
            array("", "6", "12", "22", "Green"),
324
            array("", "7", "7", "21", "5")
325
        );
326
        $this->add_data($responseother, 'questionnaire_response_other', '',
327
            array('responsemap' => 'response_id', 'questionmap' => 'question_id', 'choicemap' => 'choice_id'));
328
 
329
        $responserank = array(
330
            array("id", "response_id", "question_id", "choice_id", "rankvalue"),
331
            array("", "1", "13", "16", "0"),
332
            array("", "1", "13", "17", "1"),
333
            array("", "1", "13", "18", "2"),
334
            array("", "1", "13", "19", "3"),
335
            array("", "1", "13", "20", "4"),
336
            array("", "2", "13", "16", "0"),
337
            array("", "2", "13", "17", "1"),
338
            array("", "2", "13", "18", "2"),
339
            array("", "2", "13", "19", "3"),
340
            array("", "2", "13", "20", "4"),
341
            array("", "3", "13", "16", "4"),
342
            array("", "3", "13", "17", "0"),
343
            array("", "3", "13", "18", "3"),
344
            array("", "3", "13", "19", "1"),
345
            array("", "3", "13", "20", "2"),
346
            array("", "4", "13", "16", "2"),
347
            array("", "4", "13", "17", "2"),
348
            array("", "4", "13", "18", "2"),
349
            array("", "4", "13", "19", "2"),
350
            array("", "4", "13", "20", "2"),
351
            array("", "5", "13", "16", "1"),
352
            array("", "5", "13", "17", "1"),
353
            array("", "5", "13", "18", "1"),
354
            array("", "5", "13", "19", "1"),
355
            array("", "5", "13", "20", "-1"),
356
            array("", "6", "13", "16", "2"),
357
            array("", "6", "13", "17", "3"),
358
            array("", "6", "13", "18", "-1"),
359
            array("", "6", "13", "19", "1"),
360
            array("", "6", "13", "20", "-1"),
361
            array("", "7", "13", "16", "-999"),
362
            array("", "7", "13", "17", "-999"),
363
            array("", "7", "13", "18", "-999"),
364
            array("", "7", "13", "19", "-999"),
365
            array("", "7", "13", "20", "-999")
366
        );
367
        $this->add_data($responserank, 'questionnaire_response_rank', '',
368
            array('responsemap' => 'response_id', 'questionmap' => 'question_id', 'choicemap' => 'choice_id'));
369
 
370
        $respmultiple = array(
371
            array("id", "response_id", "question_id", "choice_id"),
372
            array("", "1", "7", "1"),
373
            array("", "1", "7", "3"),
374
            array("", "1", "7", "5"),
375
            array("", "2", "7", "4"),
376
            array("", "3", "7", "2"),
377
            array("", "3", "7", "4"),
378
            array("", "4", "7", "2"),
379
            array("", "4", "7", "4"),
380
            array("", "4", "7", "5"),
381
            array("", "5", "7", "2"),
382
            array("", "5", "7", "3"),
383
            array("", "5", "7", "21"),
384
            array("", "6", "7", "2"),
385
            array("", "6", "7", "5"),
386
            array("", "7", "7", "21")
387
        );
388
        $this->add_data($respmultiple, 'questionnaire_resp_multiple', '',
389
            array('responsemap' => 'response_id', 'questionmap' => 'question_id', 'choicemap' => 'choice_id'));
390
 
391
        $respsingle = array(
392
            array("id", "response_id", "question_id", "choice_id"),
393
            array("", "1", "9", "7"),
394
            array("", "1", "12", "15"),
395
            array("", "2", "9", "7"),
396
            array("", "2", "12", "14"),
397
            array("", "3", "9", "11"),
398
            array("", "3", "12", "15"),
399
            array("", "4", "9", "6"),
400
            array("", "4", "12", "12"),
401
            array("", "5", "9", "6"),
402
            array("", "5", "12", "13"),
403
            array("", "6", "9", "7"),
404
            array("", "6", "12", "22")
405
        );
406
        $this->add_data($respsingle, 'questionnaire_resp_single', '',
407
            array('responsemap' => 'response_id', 'questionmap' => 'question_id', 'choicemap' => 'choice_id'));
408
    }
409
 
410
    /**
411
     * Helper function to insert record data, save mapping data and remap data where necessary.
412
     *
413
     * @param array $data Array of data record row arrays. The first row contains the field names.
414
     * @param string $datatable The name of the data table to insert records into.
415
     * @param string $mapvar The name of the object variable to store oldid / newid mappings (optional).
416
     * @param array|null $replvars Array of key/value pairs where key is the mapvar and value is the record field
417
     *                         to replace with mapped values.
418
     * @return null
419
     */
420
    private function add_data(array $data, $datatable, $mapvar = '', array $replvars = null) {
421
        global $DB;
422
 
423
        if ($replvars === null) {
424
            $replvars = array();
425
        }
426
        $fields = array_shift($data);
427
        foreach ($data as $row) {
428
            $record = new stdClass();
429
            foreach ($row as $key => $fieldvalue) {
430
                if ($fields[$key] == 'id') {
431
                    if (!empty($mapvar)) {
432
                        $oldid = $fieldvalue;
433
                    }
434
                } else if (($replvar = array_search($fields[$key], $replvars)) !== false) {
435
                    $record->{$fields[$key]} = $this->{$replvar}[$fieldvalue];
436
                } else {
437
                    $record->{$fields[$key]} = $fieldvalue;
438
                }
439
            }
440
            $newid = $DB->insert_record($datatable, $record);
441
            if (!empty($mapvar)) {
442
                $this->{$mapvar}[$oldid] = $newid;
443
            }
444
        }
445
    }
446
    /**
447
     * Get a questionnaire by name.
448
     *
449
     * @param string $name questionnaire name.
450
     * @return stdClass the corresponding DB row.
451
     */
452
    protected function get_questionnaire_by_name(string $name): stdClass {
453
        global $DB;
454
        return $DB->get_record('questionnaire', ['name' => $name], '*', MUST_EXIST);
455
    }
456
 
457
    /**
458
     * Get a questionnaire cmid from the quiz name.
459
     *
460
     * @param string $name questionnaire name.
461
     * @return stdClass cm from get_coursemodule_from_instance.
462
     */
463
    protected function get_cm_by_questionnaire_name(string $name): stdClass {
464
        $questionnaire = $this->get_questionnaire_by_name($name);
465
        return get_coursemodule_from_instance('questionnaire', $questionnaire->id, $questionnaire->course);
466
    }
467
}