Proyectos de Subversion Moodle

Rev

Rev 11 | | 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_choice;
18
 
19
use core_external\external_api;
20
use externallib_advanced_testcase;
21
use mod_choice_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/choice/lib.php');
29
 
30
/**
31
 * External choice functions unit tests
32
 *
33
 * @package    mod_choice
34
 * @category   external
35
 * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1441 ariadna 37
 * @covers     \mod_choice_external
1 efrain 38
 */
1441 ariadna 39
final class externallib_test extends externallib_advanced_testcase {
1 efrain 40
 
41
    /**
42
     * Test get_choice_results
43
     */
11 efrain 44
    public function test_get_choice_results(): void {
1 efrain 45
        global $DB;
46
 
47
        $this->resetAfterTest(true);
48
 
49
        $course = self::getDataGenerator()->create_course();
50
        $params = new \stdClass();
51
        $params->course = $course->id;
52
        $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
53
        $params->name = 'First Choice Activity';
54
        $params->showresults = CHOICE_SHOWRESULTS_AFTER_ANSWER;
55
        $params->publish = 1;
56
        $params->allowmultiple = 1;
57
        $params->showunanswered = 1;
58
        $choice = self::getDataGenerator()->create_module('choice', $params);
59
 
60
        $cm = get_coursemodule_from_id('choice', $choice->cmid);
61
        $choiceinstance = choice_get_choice($cm->instance);
62
        $options = array_keys($choiceinstance->option);
63
        $student1 = $this->getDataGenerator()->create_user();
64
        $student2 = $this->getDataGenerator()->create_user();
65
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
66
 
67
        // Enroll Students in Course1.
68
        self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
69
        self::getDataGenerator()->enrol_user($student2->id,  $course->id, $studentrole->id);
70
 
71
        $this->setUser($student1);
72
        $myanswer = $options[2];
73
        choice_user_submit_response($myanswer, $choice, $student1->id, $course, $cm);
74
        $results = mod_choice_external::get_choice_results($choice->id);
75
        // We need to execute the return values cleaning process to simulate the web service server.
76
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
77
 
78
        // Create an array with optionID as Key.
79
        $resultsarr = array();
80
        foreach ($results['options'] as $option) {
81
            $resultsarr[$option['id']] = $option['userresponses'];
82
        }
83
        // The stundent1 is the userid who choosed the myanswer(option 3).
84
        $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
85
        // The stundent2 is the userid who didn't answered yet.
86
        $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
87
 
88
        // As Stundent2 we cannot see results (until we answered).
89
        $this->setUser($student2);
90
        $results = mod_choice_external::get_choice_results($choice->id);
91
        // We need to execute the return values cleaning process to simulate the web service server.
92
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
93
        // We do not retrieve any response!
94
        foreach ($results['options'] as $option) {
95
            $this->assertCount(0, $option['userresponses']);
96
        }
97
 
98
        $timenow = time();
99
        // We can see results only after activity close (even if we didn't answered).
100
        $choice->showresults = CHOICE_SHOWRESULTS_AFTER_CLOSE;
101
        // Set timeopen and timeclose in the past.
102
        $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
103
        $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
104
        $DB->update_record('choice', $choice);
105
 
106
        $results = mod_choice_external::get_choice_results($choice->id);
107
        // We need to execute the return values cleaning process to simulate the web service server.
108
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
109
        // We do not retrieve any response (activity is still open).
110
        foreach ($results['options'] as $option) {
111
            $this->assertCount(0, $option['userresponses']);
112
        }
113
 
114
        // We close the activity (setting timeclose in the past).
115
        $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
116
        $DB->update_record('choice', $choice);
117
        // Now as Stundent2 we will see results!
118
        $results = mod_choice_external::get_choice_results($choice->id);
119
        // We need to execute the return values cleaning process to simulate the web service server.
120
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
121
        // Create an array with optionID as Key.
122
        $resultsarr = array();
123
        foreach ($results['options'] as $option) {
124
            $resultsarr[$option['id']] = $option['userresponses'];
125
        }
126
        // The stundent1 is the userid who choosed the myanswer(option 3).
127
        $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
128
        // The stundent2 is the userid who didn't answered yet.
129
        $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
130
 
131
        // Do not publish user names!
132
        $choice->publish = 0;
133
        $DB->update_record('choice', $choice);
134
        $results = mod_choice_external::get_choice_results($choice->id);
135
        // We need to execute the return values cleaning process to simulate the web service server.
136
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
137
        // Create an array with optionID as Key.
138
        $resultsarr = array();
139
        // Does not show any user response!
140
        foreach ($results['options'] as $option) {
141
            $this->assertCount(0, $option['userresponses']);
142
            $resultsarr[$option['id']] = $option;
143
        }
144
        // But we can see totals and percentages.
145
        $this->assertEquals(1, $resultsarr[$myanswer]['numberofuser']);
146
    }
147
 
148
    /**
1441 ariadna 149
     * Test get_choice_results using groups.
150
     */
151
    public function test_get_choice_results_with_groups(): void {
152
        $this->resetAfterTest(true);
153
 
154
        $course = $this->getDataGenerator()->create_course();
155
        $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
156
        $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
157
        $choicegenerator = $this->getDataGenerator()->get_plugin_generator('mod_choice');
158
 
159
        // Create 3 choices: one with separate groups, one with visible groups and one with no groups.
160
        $commonparams = [
161
            'course' => $course->id,
162
            'option' => ['fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza'],
163
            'name' => 'Separate groups choice',
164
            'showresults' => CHOICE_SHOWRESULTS_ALWAYS,
165
            'publish' => 1,
166
        ];
167
 
168
        $nogroupschoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => NOGROUPS]));
169
        $separatechoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => SEPARATEGROUPS]));
170
        $visiblechoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => VISIBLEGROUPS]));
171
        $nogroupsoptions = array_keys(choice_get_choice($nogroupschoice->id)->option);
172
        $separateoptions = array_keys(choice_get_choice($separatechoice->id)->option);
173
        $visibleoptions = array_keys(choice_get_choice($visiblechoice->id)->option);
174
        $nogroupscm = get_coursemodule_from_id('choice', $nogroupschoice->cmid);
175
        $separatecm = get_coursemodule_from_id('choice', $separatechoice->cmid);
176
        $visiblecm = get_coursemodule_from_id('choice', $visiblechoice->cmid);
177
 
178
        // Enrol 3 students in the course. One student will have no group, the others will belong one to each group.
179
        $student1 = $this->getDataGenerator()->create_user();
180
        $student2 = $this->getDataGenerator()->create_user();
181
        $studentnogroup = $this->getDataGenerator()->create_user();
182
 
183
        self::getDataGenerator()->enrol_user($student1->id,  $course->id, 'student');
184
        self::getDataGenerator()->enrol_user($student2->id,  $course->id, 'student');
185
        self::getDataGenerator()->enrol_user($studentnogroup->id,  $course->id, 'student');
186
 
187
        groups_add_member($group1, $student1);
188
        groups_add_member($group2, $student2);
189
 
190
        // Add answers for both users in all choices.
191
        $this->setUser($student1);
192
        choice_user_submit_response($nogroupsoptions[0], $nogroupschoice, $student1->id, $course, $nogroupscm);
193
        choice_user_submit_response($separateoptions[0], $separatechoice, $student1->id, $course, $separatecm);
194
        choice_user_submit_response($visibleoptions[0], $visiblechoice, $student1->id, $course, $visiblecm);
195
 
196
        $this->setUser($student2);
197
        choice_user_submit_response($nogroupsoptions[1], $nogroupschoice, $student2->id, $course, $nogroupscm);
198
        choice_user_submit_response($separateoptions[1], $separatechoice, $student2->id, $course, $separatecm);
199
        choice_user_submit_response($visibleoptions[1], $visiblechoice, $student2->id, $course, $visiblecm);
200
 
201
        // No groups: check that the groupid parameter is ignored.
202
        $results = mod_choice_external::get_choice_results($nogroupschoice->id, $group1->id);
203
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
204
 
205
        $resultsarr = [];
206
        foreach ($results['options'] as $option) {
207
            $resultsarr[$option['id']] = $option['userresponses'];
208
        }
209
        $this->assertEquals($resultsarr[$nogroupsoptions[0]][0]['userid'], $student1->id);
210
        $this->assertEquals($resultsarr[$nogroupsoptions[1]][0]['userid'], $student2->id);
211
 
212
        $results = mod_choice_external::get_choice_results($nogroupschoice->id, $group2->id);
213
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
214
 
215
        $resultsarr = [];
216
        foreach ($results['options'] as $option) {
217
            $resultsarr[$option['id']] = $option['userresponses'];
218
        }
219
        $this->assertEquals($resultsarr[$nogroupsoptions[0]][0]['userid'], $student1->id);
220
        $this->assertEquals($resultsarr[$nogroupsoptions[1]][0]['userid'], $student2->id);
221
 
222
        // Separate groups: check that students can only see results of the group they belong.
223
        $this->setUser($student1);
224
        $results = mod_choice_external::get_choice_results($separatechoice->id, $group1->id);
225
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
226
 
227
        $resultsarr = [];
228
        foreach ($results['options'] as $option) {
229
            $resultsarr[$option['id']] = $option['userresponses'];
230
        }
231
        $this->assertEquals($resultsarr[$separateoptions[0]][0]['userid'], $student1->id);
232
        $this->assertCount(0, $resultsarr[$separateoptions[1]]); // The answer for the group 2 is not returned.
233
 
234
        try {
235
            mod_choice_external::get_choice_results($separatechoice->id, $group2->id);
236
            $this->fail('Exception expected due to not visible group.');
237
        } catch (\moodle_exception $e) {
238
            $this->assertEquals('notingroup', $e->errorcode);
239
        }
240
 
241
        try {
242
            mod_choice_external::get_choice_results($separatechoice->id, 0); // All participants also throws error.
243
            $this->fail('Exception expected due to not visible group.');
244
        } catch (\moodle_exception $e) {
245
            $this->assertEquals('notingroup', $e->errorcode);
246
        }
247
 
248
        $this->setUser($student2);
249
        $results = mod_choice_external::get_choice_results($separatechoice->id, $group2->id);
250
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
251
 
252
        $resultsarr = [];
253
        foreach ($results['options'] as $option) {
254
            $resultsarr[$option['id']] = $option['userresponses'];
255
        }
256
        $this->assertEquals($resultsarr[$separateoptions[1]][0]['userid'], $student2->id);
257
        $this->assertCount(0, $resultsarr[$separateoptions[0]]); // The answer for the group 1 is not returned.
258
 
259
        try {
260
            mod_choice_external::get_choice_results($separatechoice->id, $group1->id);
261
            $this->fail('Exception expected due to not visible group.');
262
        } catch (\moodle_exception $e) {
263
            $this->assertEquals('notingroup', $e->errorcode);
264
        }
265
 
266
        // Visible groups: check that students can see results of all groups, including 'All participants'.
267
        $this->setUser($student1);
268
        $results = mod_choice_external::get_choice_results($visiblechoice->id, $group1->id);
269
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
270
 
271
        $resultsarr = [];
272
        foreach ($results['options'] as $option) {
273
            $resultsarr[$option['id']] = $option['userresponses'];
274
        }
275
        $this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
276
        $this->assertCount(0, $resultsarr[$visibleoptions[1]]); // The answer for the other group is not returned.
277
 
278
        $results = mod_choice_external::get_choice_results($visiblechoice->id, $group2->id);
279
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
280
 
281
        $resultsarr = [];
282
        foreach ($results['options'] as $option) {
283
            $resultsarr[$option['id']] = $option['userresponses'];
284
        }
285
        $this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
286
        $this->assertCount(0, $resultsarr[$visibleoptions[0]]); // The answer for the other group is not returned.
287
 
288
        $results = mod_choice_external::get_choice_results($visiblechoice->id, 0);
289
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
290
 
291
        $resultsarr = [];
292
        foreach ($results['options'] as $option) {
293
            $resultsarr[$option['id']] = $option['userresponses'];
294
        }
295
        $this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
296
        $this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
297
 
298
        // User with no groups can view results for the visible groups choice, but not for separate groups.
299
        $this->setUser($studentnogroup);
300
        $results = mod_choice_external::get_choice_results($visiblechoice->id, 0);
301
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
302
 
303
        $resultsarr = [];
304
        foreach ($results['options'] as $option) {
305
            $resultsarr[$option['id']] = $option['userresponses'];
306
        }
307
        $this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
308
        $this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
309
 
310
        try {
311
            mod_choice_external::get_choice_results($separatechoice->id, 0);
312
            $this->fail('Exception expected due to not visible group.');
313
        } catch (\moodle_exception $e) {
314
            $this->assertEquals('notingroup', $e->errorcode);
315
        }
316
    }
317
 
318
    /**
1 efrain 319
     * Test get_choice_options
320
     */
11 efrain 321
    public function test_get_choice_options(): void {
1 efrain 322
        global $DB;
323
 
324
        // Warningcodes.
325
        $notopenyet = 1;
326
        $previewonly = 2;
327
        $expired = 3;
328
 
329
        $this->resetAfterTest(true);
330
        $timenow = time();
331
        $timeopen = $timenow + (60 * 60 * 24 * 2);
332
        $timeclose = $timenow + (60 * 60 * 24 * 7);
333
        $course = self::getDataGenerator()->create_course();
334
        $possibleoptions = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
335
        $params = array();
336
        $params['course'] = $course->id;
337
        $params['option'] = $possibleoptions;
338
        $params['name'] = 'First Choice Activity';
339
        $params['showpreview'] = 0;
340
 
341
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_choice');
342
        $choice = $generator->create_instance($params);
343
 
344
        $student1 = $this->getDataGenerator()->create_user();
345
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
346
        // Enroll Students in Course.
347
        self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
348
        $this->setUser($student1);
349
 
350
        $results = mod_choice_external::get_choice_options($choice->id);
351
        // We need to execute the return values cleaning process to simulate the web service server.
352
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
353
        // We should retrieve all options.
354
        $this->assertCount(count($possibleoptions), $results['options']);
355
 
356
        // Here we force timeopen/close in the future.
357
        $choice->timeopen = $timeopen;
358
        $choice->timeclose = $timeclose;
359
        $DB->update_record('choice', $choice);
360
 
361
        $results = mod_choice_external::get_choice_options($choice->id);
362
        // We need to execute the return values cleaning process to simulate the web service server.
363
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
364
        // We should retrieve no options.
365
        $this->assertCount(0, $results['options']);
366
        $this->assertEquals($notopenyet, $results['warnings'][0]['warningcode']);
367
 
368
        // Here we see the options because of preview!
369
        $choice->showpreview = 1;
370
        $DB->update_record('choice', $choice);
371
        $results = mod_choice_external::get_choice_options($choice->id);
372
        // We need to execute the return values cleaning process to simulate the web service server.
373
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
374
        // We should retrieve all options.
375
        $this->assertCount(count($possibleoptions), $results['options']);
376
 
377
        foreach ($results['options'] as $option) {
378
            // Each option is disabled as this is only the preview!
379
            $this->assertEquals(1, $option['disabled']);
380
        }
381
        $warnings = array();
382
        foreach ($results['warnings'] as $warning) {
383
            $warnings[$warning['warningcode']] = $warning['message'];
384
        }
385
        $this->assertTrue(isset($warnings[$previewonly]));
386
        $this->assertTrue(isset($warnings[$notopenyet]));
387
 
388
        // Simulate activity as opened!
389
        $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
390
        $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
391
        $DB->update_record('choice', $choice);
392
        $cm = get_coursemodule_from_id('choice', $choice->cmid);
393
        $choiceinstance = choice_get_choice($cm->instance);
394
        $optionsids = array_keys($choiceinstance->option);
395
        $myanswerid = $optionsids[2];
396
        choice_user_submit_response($myanswerid, $choice, $student1->id, $course, $cm);
397
 
398
        $results = mod_choice_external::get_choice_options($choice->id);
399
        // We need to execute the return values cleaning process to simulate the web service server.
400
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
401
        // We should retrieve all options.
402
        $this->assertCount(count($possibleoptions), $results['options']);
403
        foreach ($results['options'] as $option) {
404
            // When we answered and we cannot update our choice.
405
            if ($option['id'] == $myanswerid and !$choice->allowupdate) {
406
                $this->assertEquals(1, $option['disabled']);
407
                $this->assertEquals(1, $option['checked']);
408
            } else {
409
                $this->assertEquals(0, $option['disabled']);
410
            }
411
        }
412
 
413
        // Set timeopen and timeclose as older than today!
414
        // We simulate what happens when the activity is closed.
415
        $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
416
        $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
417
        $DB->update_record('choice', $choice);
418
        $results = mod_choice_external::get_choice_options($choice->id);
419
        // We need to execute the return values cleaning process to simulate the web service server.
420
        $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
421
        // We should retrieve no options.
422
        $this->assertCount(0, $results['options']);
423
        $this->assertEquals($expired, $results['warnings'][0]['warningcode']);
424
 
425
    }
426
 
427
    /**
428
     * Test submit_choice_response
429
     */
11 efrain 430
    public function test_submit_choice_response(): void {
1 efrain 431
        global $DB;
432
 
433
        $this->resetAfterTest(true);
434
 
435
        $course = self::getDataGenerator()->create_course();
436
        $params = new \stdClass();
437
        $params->course = $course->id;
438
        $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
439
        $params->name = 'First Choice Activity';
440
        $params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
441
        $params->allowmultiple = 1;
442
        $params->showunanswered = 1;
443
        $choice = self::getDataGenerator()->create_module('choice', $params);
444
        $cm = get_coursemodule_from_id('choice', $choice->cmid);
445
        $choiceinstance = choice_get_choice($cm->instance);
446
        $options = array_keys($choiceinstance->option);
447
        $student1 = $this->getDataGenerator()->create_user();
448
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
449
 
450
        // Enroll Students in Course1.
451
        self::getDataGenerator()->enrol_user($student1->id,  $course->id, $studentrole->id);
452
 
453
        $this->setUser($student1);
454
        $myresponse = $options[2];
455
        $results = mod_choice_external::submit_choice_response($choice->id, array($myresponse));
456
        // We need to execute the return values cleaning process to simulate the web service server.
457
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
458
        $myanswers = $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $student1->id));
459
        $myanswer = reset($myanswers);
460
        $this->assertEquals($results['answers'][0]['id'], $myanswer->id);
461
        $this->assertEquals($results['answers'][0]['choiceid'], $myanswer->choiceid);
462
        $this->assertEquals($results['answers'][0]['userid'], $myanswer->userid);
463
        $this->assertEquals($results['answers'][0]['timemodified'], $myanswer->timemodified);
464
    }
465
 
466
    /**
467
     * Test view_choice
468
     */
11 efrain 469
    public function test_view_choice(): void {
1 efrain 470
        global $DB;
471
 
472
        $this->resetAfterTest(true);
473
 
474
        // Setup test data.
475
        $course = $this->getDataGenerator()->create_course();
476
        $choice = $this->getDataGenerator()->create_module('choice', array('course' => $course->id));
477
        $context = \context_module::instance($choice->cmid);
478
        $cm = get_coursemodule_from_instance('choice', $choice->id);
479
 
480
        // Test invalid instance id.
481
        try {
482
            mod_choice_external::view_choice(0);
483
            $this->fail('Exception expected due to invalid mod_choice instance id.');
484
        } catch (\moodle_exception $e) {
485
            $this->assertEquals('invalidcoursemodule', $e->errorcode);
486
        }
487
 
488
        // Test not-enrolled user.
489
        $user = self::getDataGenerator()->create_user();
490
        $this->setUser($user);
491
        try {
492
            mod_choice_external::view_choice($choice->id);
493
            $this->fail('Exception expected due to not enrolled user.');
494
        } catch (\moodle_exception $e) {
495
            $this->assertEquals('requireloginerror', $e->errorcode);
496
        }
497
 
498
        // Test user with full capabilities.
499
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
500
        $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
501
 
502
        // Trigger and capture the event.
503
        $sink = $this->redirectEvents();
504
 
505
        $result = mod_choice_external::view_choice($choice->id);
506
        $result = external_api::clean_returnvalue(mod_choice_external::view_choice_returns(), $result);
507
 
508
        $events = $sink->get_events();
509
        $this->assertCount(1, $events);
510
        $event = array_shift($events);
511
 
512
        // Checking that the event contains the expected values.
513
        $this->assertInstanceOf('\mod_choice\event\course_module_viewed', $event);
514
        $this->assertEquals($context, $event->get_context());
515
        $moodlechoice = new \moodle_url('/mod/choice/view.php', array('id' => $cm->id));
516
        $this->assertEquals($moodlechoice, $event->get_url());
517
        $this->assertEventContextNotUsed($event);
518
        $this->assertNotEmpty($event->get_name());
519
 
520
    }
521
 
522
    /**
523
     * Test get_choices_by_courses
524
     */
11 efrain 525
    public function test_get_choices_by_courses(): void {
1 efrain 526
        global $DB;
527
        $this->resetAfterTest(true);
528
        // As admin.
529
        $this->setAdminUser();
530
        $course1 = self::getDataGenerator()->create_course();
531
        $choiceoptions1 = array(
532
          'course' => $course1->id,
533
          'name' => 'First IMSCP'
534
        );
535
        $choice1 = self::getDataGenerator()->create_module('choice', $choiceoptions1);
536
        $course2 = self::getDataGenerator()->create_course();
537
 
538
        $choiceoptions2 = array(
539
          'course' => $course2->id,
540
          'name' => 'Second IMSCP'
541
        );
542
        $choice2 = self::getDataGenerator()->create_module('choice', $choiceoptions2);
543
        $student1 = $this->getDataGenerator()->create_user();
544
 
545
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
546
 
547
        // Enroll Student1 in Course1.
548
        self::getDataGenerator()->enrol_user($student1->id,  $course1->id, $studentrole->id);
549
 
550
        $this->setUser($student1);
551
        $choices = mod_choice_external::get_choices_by_courses(array());
552
        $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
553
        $this->assertCount(1, $choices['choices']);
554
        $this->assertEquals('First IMSCP', $choices['choices'][0]['name']);
555
        // As Student you cannot see some IMSCP properties like 'section'.
556
        $this->assertFalse(isset($choices['choices'][0]['section']));
557
 
558
        // Student1 is not enrolled in this Course.
559
        // The webservice will give a warning!
560
        $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
561
        $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
562
        $this->assertCount(0, $choices['choices']);
563
        $this->assertEquals(1, $choices['warnings'][0]['warningcode']);
564
 
565
        // Now as admin.
566
        $this->setAdminUser();
567
        // As Admin we can see this IMSCP.
568
        $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
569
        $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
570
        $this->assertCount(1, $choices['choices']);
571
        $this->assertEquals('Second IMSCP', $choices['choices'][0]['name']);
572
        // As an Admin you can see some IMSCP properties like 'section'.
573
        $this->assertEquals(0, $choices['choices'][0]['section']);
574
 
575
        // Now, prohibit capabilities.
576
        $this->setUser($student1);
577
        $contextcourse1 = \context_course::instance($course1->id);
578
        // Prohibit capability = mod:choice:choose on Course1 for students.
579
        assign_capability('mod/choice:choose', CAP_PROHIBIT, $studentrole->id, $contextcourse1->id);
580
        accesslib_clear_all_caches_for_unit_testing();
581
 
582
        $choices = mod_choice_external::get_choices_by_courses(array($course1->id));
583
        $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
584
        $this->assertFalse(isset($choices['choices'][0]['timeopen']));
585
    }
586
 
587
    /**
588
     * Test delete_choice_responses
589
     */
11 efrain 590
    public function test_delete_choice_responses(): void {
1 efrain 591
        global $DB;
592
 
593
        $this->resetAfterTest(true);
594
 
595
        $course = self::getDataGenerator()->create_course();
596
        $params = new \stdClass();
597
        $params->course = $course->id;
598
        $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
599
        $params->name = 'First Choice Activity';
600
        $params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
601
        $params->allowmultiple = 1;
602
        $params->showunanswered = 1;
603
        $choice = self::getDataGenerator()->create_module('choice', $params);
604
        $cm = get_coursemodule_from_id('choice', $choice->cmid);
605
 
606
        $choiceinstance = choice_get_choice($cm->instance);
607
        $options = array_keys($choiceinstance->option);
608
 
609
        $student = $this->getDataGenerator()->create_user();
610
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
611
 
612
        // Enroll student in Course1.
613
        self::getDataGenerator()->enrol_user($student->id,  $course->id, $studentrole->id);
614
 
615
        $this->setUser($student);
616
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
617
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
618
 
619
        $myresponses = array_keys(choice_get_my_response($choice));
620
 
621
        // Try to delete responses when allow update is false.
622
        try {
623
            mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[0]));
624
            $this->fail('Exception expected due to missing permissions.');
625
        } catch (\required_capability_exception $e) {
626
            $this->assertEquals('nopermissions', $e->errorcode);
627
        }
628
 
629
        // Set allow update to true, and a passed time close.
630
        $DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
631
        $DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
632
        try {
633
            mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
634
            $this->fail('Exception expected due to expired choice.');
635
        } catch (\moodle_exception $e) {
636
            $this->assertEquals('expired', $e->errorcode);
637
        }
638
 
639
        // Reset time close. We should be able now to delete all the responses.
640
        $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
641
        $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
642
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
643
 
644
        $this->assertTrue($results['status']);
645
        $this->assertCount(0, $results['warnings']);
646
        // Now, in the DB 0 responses.
647
        $this->assertCount(0, choice_get_my_response($choice));
648
 
649
        // Submit again the responses.
650
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
651
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
652
 
653
        $myresponses = array_keys(choice_get_my_response($choice));
654
        // Delete only one response.
655
        $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0]));
656
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
657
        $this->assertTrue($results['status']);
658
        $this->assertCount(0, $results['warnings']);
659
        // Now, in the DB 1 response still.
660
        $this->assertCount(1, choice_get_my_response($choice));
661
 
662
        // Delete the remaining response, passing 2 invalid responses ids.
663
        $results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[1], $myresponses[0] + 2,
664
                                                                $myresponses[0] + 3));
665
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
666
        $this->assertTrue($results['status']);
667
        // 2 warnings, 2 invalid responses.
668
        $this->assertCount(2, $results['warnings']);
669
        // Now, in the DB 0 responses.
670
        $this->assertCount(0, choice_get_my_response($choice));
671
 
672
        // Now, as an admin we must be able to delete all the responses under any condition.
673
        $this->setUser($student);
674
        // Submit again the responses.
675
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
676
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
677
        $studentresponses = array_keys(choice_get_my_response($choice));
678
 
679
        $this->setAdminUser();
680
        $DB->set_field('choice', 'allowupdate', 0, array('id' => $choice->id));
681
        $DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
682
 
683
        $results = mod_choice_external::delete_choice_responses($choice->id, array($studentresponses[0], $studentresponses[1]));
684
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
685
 
686
        $this->assertTrue($results['status']);
687
        $this->assertCount(0, $results['warnings']);
688
 
689
        // Submit again the responses.
690
        $this->setUser($student);
691
        $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
692
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
693
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
694
 
695
        // Test admin try to delete his own responses (he didn't respond so nothing should be deleted).
696
        $this->setAdminUser();
697
        $results = mod_choice_external::delete_choice_responses($choice->id);
698
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
699
        $this->assertFalse($results['status']);
700
        $this->assertCount(0, $results['warnings']);
701
        $allresponses = choice_get_all_responses($choice);
702
        $this->assertCount(2, $allresponses);   // No responses deleted (admin didn't submit any).
703
 
704
        // Now admin submit a couple of responses more.
705
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
706
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
707
        $allresponses = choice_get_all_responses($choice);
708
        $this->assertCount(4, $allresponses);
709
        // Admin responses are deleted when passing an empty array.
710
        $results = mod_choice_external::delete_choice_responses($choice->id);
711
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
712
        $this->assertTrue($results['status']);
713
        $this->assertCount(0, $results['warnings']);
714
        $allresponses = choice_get_all_responses($choice);
715
        $this->assertCount(2, $allresponses);
716
 
717
        // Now admin will delete all the other users responses.
718
        $results = mod_choice_external::delete_choice_responses($choice->id, array_keys($allresponses));
719
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
720
 
721
        $this->assertTrue($results['status']);
722
        $this->assertCount(0, $results['warnings']);
723
        $allresponses = choice_get_all_responses($choice);
724
        $this->assertCount(0, $allresponses);   // Now all the responses were deleted.
725
 
726
        // Admin try do delete an invalid response.
727
        $results = mod_choice_external::delete_choice_responses($choice->id, array(-1));
728
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
729
 
730
        $this->assertFalse($results['status']);
731
        $this->assertCount(1, $results['warnings']);
732
 
733
        // Now, in the DB 0 responses.
734
        $this->setUser($student);
735
 
736
        // Submit again respones.
737
        $DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
738
        $DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
739
        $results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
740
        $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
741
 
742
        // Delete all responses.
743
        $results = mod_choice_external::delete_choice_responses($choice->id);
744
        $results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
745
 
746
        $this->assertTrue($results['status']);
747
        $this->assertCount(0, $results['warnings']);
748
        $this->assertCount(0, choice_get_my_response($choice));
749
 
750
    }
751
}