Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
namespace mod_survey;
18
 
19
use core_external\external_api;
20
use externallib_advanced_testcase;
21
use mod_survey_external;
22
 
23
defined('MOODLE_INTERNAL') || die();
24
 
25
global $CFG;
26
 
27
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
28
require_once($CFG->dirroot . '/mod/survey/lib.php');
29
 
30
/**
31
 * Survey module external functions tests
32
 *
33
 * @package    mod_survey
34
 * @category   external
35
 * @copyright  2015 Juan Leyva <juan@moodle.com>
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 * @since      Moodle 3.0
38
 */
39
class externallib_test extends externallib_advanced_testcase {
40
 
41
    /** @var \stdClass course record. */
42
    protected $course;
43
 
44
    /** @var \stdClass activity record. */
45
    protected $survey;
46
 
47
    /** @var \context_module context instance. */
48
    protected $context;
49
 
50
    /** @var \StdClass course module. */
51
    protected $cm;
52
 
53
    /** @var \StdClass student record. */
54
    protected $student;
55
 
56
    /** @var \StdClass teacher record. */
57
    protected $teacher;
58
 
59
    /** @var \StdClass student role. */
60
    protected $studentrole;
61
 
62
    /** @var \StdClass teacher role. */
63
    protected $teacherrole;
64
 
65
    /**
66
     * Set up for every test
67
     */
68
    public function setUp(): void {
69
        global $DB;
70
        $this->resetAfterTest();
71
        $this->setAdminUser();
72
 
73
        // Survey module is disabled by default, enable it for testing.
74
        $manager = \core_plugin_manager::resolve_plugininfo_class('mod');
75
        $manager::enable_plugin('survey', 1);
76
 
77
        // Setup test data.
78
        $this->course = $this->getDataGenerator()->create_course();
79
        $this->survey = $this->getDataGenerator()->create_module('survey', array('course' => $this->course->id));
80
        $this->context = \context_module::instance($this->survey->cmid);
81
        $this->cm = get_coursemodule_from_instance('survey', $this->survey->id);
82
 
83
        // Create users.
84
        $this->student = self::getDataGenerator()->create_user();
85
        $this->teacher = self::getDataGenerator()->create_user();
86
 
87
        // Users enrolments.
88
        $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
89
        $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
90
        $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
91
        $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
92
    }
93
 
94
 
95
    /*
96
     * Test get surveys by courses
97
     */
11 efrain 98
    public function test_mod_survey_get_surveys_by_courses(): void {
1 efrain 99
        global $DB;
100
 
101
        // Create additional course.
102
        $course2 = self::getDataGenerator()->create_course();
103
 
104
        // Second survey.
105
        $record = new \stdClass();
106
        $record->course = $course2->id;
107
        $survey2 = self::getDataGenerator()->create_module('survey', $record);
108
        // Force empty intro.
109
        $DB->set_field('survey', 'intro', '', array('id' => $survey2->id));
110
 
111
        // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
112
        $enrol = enrol_get_plugin('manual');
113
        $enrolinstances = enrol_get_instances($course2->id, true);
114
        foreach ($enrolinstances as $courseenrolinstance) {
115
            if ($courseenrolinstance->enrol == "manual") {
116
                $instance2 = $courseenrolinstance;
117
                break;
118
            }
119
        }
120
        $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id);
121
 
122
        self::setUser($this->student);
123
 
124
        $returndescription = mod_survey_external::get_surveys_by_courses_returns();
125
 
126
        // Create what we expect to be returned when querying the two courses.
127
        // First for the student user.
128
        $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'lang',
129
                'template', 'days', 'questions', 'surveydone');
130
 
131
        // Add expected coursemodule and data.
132
        $survey1 = $this->survey;
133
        $survey1->coursemodule = $survey1->cmid;
134
        $survey1->introformat = 1;
135
        $survey1->surveydone = 0;
136
        $survey1->section = 0;
137
        $survey1->visible = true;
138
        $survey1->groupmode = 0;
139
        $survey1->groupingid = 0;
140
        $survey1->introfiles = [];
141
        $survey1->lang = '';
142
 
143
        $survey2->coursemodule = $survey2->cmid;
144
        $survey2->introformat = 1;
145
        $survey2->surveydone = 0;
146
        $survey2->section = 0;
147
        $survey2->visible = true;
148
        $survey2->groupmode = 0;
149
        $survey2->groupingid = 0;
150
        $tempo = $DB->get_field("survey", "intro", array("id" => $survey2->template));
151
        $survey2->intro = nl2br(get_string($tempo, "survey"));
152
        $survey2->introfiles = [];
153
        $survey2->lang = '';
154
 
155
        foreach ($expectedfields as $field) {
156
            $expected1[$field] = $survey1->{$field};
157
            $expected2[$field] = $survey2->{$field};
158
        }
159
 
160
        $expectedsurveys = array($expected2, $expected1);
161
 
162
        // Call the external function passing course ids.
163
        $result = mod_survey_external::get_surveys_by_courses(array($course2->id, $this->course->id));
164
        $result = external_api::clean_returnvalue($returndescription, $result);
165
 
166
        $this->assertEquals($expectedsurveys, $result['surveys']);
167
        $this->assertCount(0, $result['warnings']);
168
 
169
        // Call the external function without passing course id.
170
        $result = mod_survey_external::get_surveys_by_courses();
171
        $result = external_api::clean_returnvalue($returndescription, $result);
172
        $this->assertEquals($expectedsurveys, $result['surveys']);
173
        $this->assertCount(0, $result['warnings']);
174
 
175
        // Unenrol user from second course and alter expected surveys.
176
        $enrol->unenrol_user($instance2, $this->student->id);
177
        array_shift($expectedsurveys);
178
 
179
        // Call the external function without passing course id.
180
        $result = mod_survey_external::get_surveys_by_courses();
181
        $result = external_api::clean_returnvalue($returndescription, $result);
182
        $this->assertEquals($expectedsurveys, $result['surveys']);
183
 
184
        // Call for the second course we unenrolled the user from, expected warning.
185
        $result = mod_survey_external::get_surveys_by_courses(array($course2->id));
186
        $this->assertCount(1, $result['warnings']);
187
        $this->assertEquals('1', $result['warnings'][0]['warningcode']);
188
        $this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
189
 
190
        // Now, try as a teacher for getting all the additional fields.
191
        self::setUser($this->teacher);
192
 
193
        $additionalfields = array('timecreated', 'timemodified', 'section', 'visible', 'groupmode', 'groupingid');
194
 
195
        foreach ($additionalfields as $field) {
196
            $expectedsurveys[0][$field] = $survey1->{$field};
197
        }
198
 
199
        $result = mod_survey_external::get_surveys_by_courses();
200
        $result = external_api::clean_returnvalue($returndescription, $result);
201
        $this->assertEquals($expectedsurveys, $result['surveys']);
202
 
203
        // Admin also should get all the information.
204
        self::setAdminUser();
205
 
206
        $result = mod_survey_external::get_surveys_by_courses(array($this->course->id));
207
        $result = external_api::clean_returnvalue($returndescription, $result);
208
        $this->assertEquals($expectedsurveys, $result['surveys']);
209
 
210
        // Now, prohibit capabilities.
211
        $this->setUser($this->student);
212
        $contextcourse1 = \context_course::instance($this->course->id);
213
        // Prohibit capability = mod/survey:participate on Course1 for students.
214
        assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $contextcourse1->id);
215
        accesslib_clear_all_caches_for_unit_testing();
216
 
217
        $surveys = mod_survey_external::get_surveys_by_courses(array($this->course->id));
218
        $surveys = external_api::clean_returnvalue(mod_survey_external::get_surveys_by_courses_returns(), $surveys);
219
        $this->assertFalse(isset($surveys['surveys'][0]['intro']));
220
    }
221
 
222
    /**
223
     * Test view_survey
224
     */
11 efrain 225
    public function test_view_survey(): void {
1 efrain 226
        global $DB;
227
 
228
        // Test invalid instance id.
229
        try {
230
            mod_survey_external::view_survey(0);
231
            $this->fail('Exception expected due to invalid mod_survey instance id.');
232
        } catch (\moodle_exception $e) {
233
            $this->assertEquals('invalidrecord', $e->errorcode);
234
        }
235
 
236
        // Test not-enrolled user.
237
        $usernotenrolled = self::getDataGenerator()->create_user();
238
        $this->setUser($usernotenrolled);
239
        try {
240
            mod_survey_external::view_survey($this->survey->id);
241
            $this->fail('Exception expected due to not enrolled user.');
242
        } catch (\moodle_exception $e) {
243
            $this->assertEquals('requireloginerror', $e->errorcode);
244
        }
245
 
246
        // Test user with full capabilities.
247
        $this->setUser($this->student);
248
 
249
        // Trigger and capture the event.
250
        $sink = $this->redirectEvents();
251
 
252
        $result = mod_survey_external::view_survey($this->survey->id);
253
        $result = external_api::clean_returnvalue(mod_survey_external::view_survey_returns(), $result);
254
        $this->assertTrue($result['status']);
255
 
256
        $events = $sink->get_events();
257
        $this->assertCount(1, $events);
258
        $event = array_shift($events);
259
 
260
        // Checking that the event contains the expected values.
261
        $this->assertInstanceOf('\mod_survey\event\course_module_viewed', $event);
262
        $this->assertEquals($this->context, $event->get_context());
263
        $moodlesurvey = new \moodle_url('/mod/survey/view.php', array('id' => $this->cm->id));
264
        $this->assertEquals($moodlesurvey, $event->get_url());
265
        $this->assertEventContextNotUsed($event);
266
        $this->assertNotEmpty($event->get_name());
267
 
268
        // Test user with no capabilities.
269
        // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
270
        assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
271
        accesslib_clear_all_caches_for_unit_testing();
272
 
273
        try {
274
            mod_survey_external::view_survey($this->survey->id);
275
            $this->fail('Exception expected due to missing capability.');
276
        } catch (\moodle_exception $e) {
277
            $this->assertEquals('nopermissions', $e->errorcode);
278
        }
279
 
280
    }
281
 
282
    /**
283
     * Test get_questions
284
     */
11 efrain 285
    public function test_get_questions(): void {
1 efrain 286
        global $DB;
287
 
288
        // Test user with full capabilities.
289
        $this->setUser($this->student);
290
 
291
        // Build our expectation array.
292
        $expectedquestions = array();
293
        $questions = survey_get_questions($this->survey);
294
        foreach ($questions as $q) {
295
            if ($q->type >= 0) {
296
                $expectedquestions[$q->id] = $q;
297
                if ($q->multi) {
298
                    $subquestions = survey_get_subquestions($q);
299
                    foreach ($subquestions as $sq) {
300
                        $expectedquestions[$sq->id] = $sq;
301
                    }
302
                }
303
            }
304
        }
305
 
306
        $result = mod_survey_external::get_questions($this->survey->id);
307
        $result = external_api::clean_returnvalue(mod_survey_external::get_questions_returns(), $result);
308
 
309
        // Check we receive the same questions.
310
        $this->assertCount(0, $result['warnings']);
311
        foreach ($result['questions'] as $q) {
312
            $this->assertEquals(get_string($expectedquestions[$q['id']]->text, 'survey'), $q['text']);
313
            $this->assertEquals(get_string($expectedquestions[$q['id']]->shorttext, 'survey'), $q['shorttext']);
314
            $this->assertEquals($expectedquestions[$q['id']]->multi, $q['multi']);
315
            $this->assertEquals($expectedquestions[$q['id']]->type, $q['type']);
316
            // Parent questions must have parent eq to 0.
317
            if ($q['multi']) {
318
                $this->assertEquals(0, $q['parent']);
319
                $this->assertEquals(get_string($expectedquestions[$q['id']]->options, 'survey'), $q['options']);
320
            }
321
        }
322
 
323
        // Test user with no capabilities.
324
        // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
325
        assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
326
        accesslib_clear_all_caches_for_unit_testing();
327
 
328
        try {
329
            mod_survey_external::get_questions($this->survey->id);
330
            $this->fail('Exception expected due to missing capability.');
331
        } catch (\moodle_exception $e) {
332
            $this->assertEquals('nopermissions', $e->errorcode);
333
        }
334
    }
335
 
336
    /**
337
     * Test submit_answers
338
     */
11 efrain 339
    public function test_submit_answers(): void {
1 efrain 340
        global $DB;
341
 
342
        // Test user with full capabilities.
343
        $this->setUser($this->student);
344
 
345
        // Build our questions and responses array.
346
        $realquestions = array();
347
        $questions = survey_get_questions($this->survey);
348
        $i = 5;
349
        foreach ($questions as $q) {
350
            if ($q->type >= 0) {
351
                if ($q->multi) {
352
                    $subquestions = survey_get_subquestions($q);
353
                    foreach ($subquestions as $sq) {
354
                        $realquestions[] = array(
355
                            'key' => 'q' . $sq->id,
356
                            'value' => $i % 5 + 1   // Values between 1 and 5.
357
                        );
358
                        $i++;
359
                    }
360
                } else {
361
                    $realquestions[] = array(
362
                        'key' => 'q' . $q->id,
363
                        'value' => $i % 5 + 1
364
                    );
365
                    $i++;
366
                }
367
            }
368
        }
369
 
370
        $result = mod_survey_external::submit_answers($this->survey->id, $realquestions);
371
        $result = external_api::clean_returnvalue(mod_survey_external::submit_answers_returns(), $result);
372
 
373
        $this->assertTrue($result['status']);
374
        $this->assertCount(0, $result['warnings']);
375
 
376
        $dbanswers = $DB->get_records_menu('survey_answers', array('survey' => $this->survey->id), '', 'question, answer1');
377
        foreach ($realquestions as $q) {
378
            $id = str_replace('q', '', $q['key']);
379
            $this->assertEquals($q['value'], $dbanswers[$id]);
380
        }
381
 
382
        // Submit again, we expect an error here.
383
        try {
384
            mod_survey_external::submit_answers($this->survey->id, $realquestions);
385
            $this->fail('Exception expected due to answers already submitted.');
386
        } catch (\moodle_exception $e) {
387
            $this->assertEquals('alreadysubmitted', $e->errorcode);
388
        }
389
 
390
        // Test user with no capabilities.
391
        // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
392
        assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
393
        accesslib_clear_all_caches_for_unit_testing();
394
 
395
        try {
396
            mod_survey_external::submit_answers($this->survey->id, $realquestions);
397
            $this->fail('Exception expected due to missing capability.');
398
        } catch (\moodle_exception $e) {
399
            $this->assertEquals('nopermissions', $e->errorcode);
400
        }
401
 
402
        // Test not-enrolled user.
403
        $usernotenrolled = self::getDataGenerator()->create_user();
404
        $this->setUser($usernotenrolled);
405
        try {
406
            mod_survey_external::submit_answers($this->survey->id, $realquestions);
407
            $this->fail('Exception expected due to not enrolled user.');
408
        } catch (\moodle_exception $e) {
409
            $this->assertEquals('requireloginerror', $e->errorcode);
410
        }
411
    }
412
 
413
}