MDL-50132 mod_choice: New WS mod_choice_get_choices_by_courses
[moodle.git] / mod / choice / tests / externallib_test.php
CommitLineData
dffb87ed
JL
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 * External choice functions unit tests
19 *
20 * @package mod_choice
21 * @category external
22 * @copyright 2015 Costantino Cito <ccito@cvaconsulting.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29
30require_once($CFG->dirroot . '/webservice/tests/helpers.php');
31require_once($CFG->dirroot . '/mod/choice/lib.php');
32
33/**
34 * External choice functions unit tests
35 *
36 * @package mod_choice
37 * @category external
38 * @copyright 2015 Costantino Cito <ccito@cvaconsulting.com>
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 */
41class mod_choice_externallib_testcase extends externallib_advanced_testcase {
42
43 /**
44 * Test get_choice_results
45 */
46 public function test_get_choice_results() {
47 global $DB;
48
49 $this->resetAfterTest(true);
50
51 $course = self::getDataGenerator()->create_course();
52 $params = new stdClass();
53 $params->course = $course->id;
54 $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
55 $params->name = 'First Choice Activity';
56 $params->showresults = CHOICE_SHOWRESULTS_AFTER_ANSWER;
57 $params->publish = 1;
58 $params->allowmultiple = 1;
59 $params->showunanswered = 1;
60 $choice = self::getDataGenerator()->create_module('choice', $params);
61
62 $cm = get_coursemodule_from_id('choice', $choice->cmid);
63 $choiceinstance = choice_get_choice($cm->instance);
64 $options = array_keys($choiceinstance->option);
65 $student1 = $this->getDataGenerator()->create_user();
66 $student2 = $this->getDataGenerator()->create_user();
67 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
68
69 // Enroll Students in Course1.
70 self::getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
71 self::getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
72
73 $this->setUser($student1);
74 $myanswer = $options[2];
75 choice_user_submit_response($myanswer, $choice, $student1->id, $course, $cm);
76 $results = mod_choice_external::get_choice_results($choice->id);
77 // We need to execute the return values cleaning process to simulate the web service server.
78 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
79
80 // Create an array with optionID as Key.
81 $resultsarr = array();
82 foreach ($results['options'] as $option) {
83 $resultsarr[$option['id']] = $option['userresponses'];
84 }
85 // The stundent1 is the userid who choosed the myanswer(option 3).
86 $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
87 // The stundent2 is the userid who didn't answered yet.
88 $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
89
90 // As Stundent2 we cannot see results (until we answered).
91 $this->setUser($student2);
92 $results = mod_choice_external::get_choice_results($choice->id);
93 // We need to execute the return values cleaning process to simulate the web service server.
94 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
95 // We do not retrieve any response!
96 foreach ($results['options'] as $option) {
97 $this->assertCount(0, $option['userresponses']);
98 }
99
100 $timenow = time();
101 // We can see results only after activity close (even if we didn't answered).
102 $choice->showresults = CHOICE_SHOWRESULTS_AFTER_CLOSE;
103 // Set timeopen and timeclose in the past.
104 $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
105 $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
106 $DB->update_record('choice', $choice);
107
108 $results = mod_choice_external::get_choice_results($choice->id);
109 // We need to execute the return values cleaning process to simulate the web service server.
110 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
111 // We do not retrieve any response (activity is still open).
112 foreach ($results['options'] as $option) {
113 $this->assertCount(0, $option['userresponses']);
114 }
115
116 // We close the activity (setting timeclose in the past).
117 $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
118 $DB->update_record('choice', $choice);
119 // Now as Stundent2 we will see results!
120 $results = mod_choice_external::get_choice_results($choice->id);
121 // We need to execute the return values cleaning process to simulate the web service server.
122 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
123 // Create an array with optionID as Key.
124 $resultsarr = array();
125 foreach ($results['options'] as $option) {
126 $resultsarr[$option['id']] = $option['userresponses'];
127 }
128 // The stundent1 is the userid who choosed the myanswer(option 3).
129 $this->assertEquals($resultsarr[$myanswer][0]['userid'], $student1->id);
130 // The stundent2 is the userid who didn't answered yet.
131 $this->assertEquals($resultsarr[0][0]['userid'], $student2->id);
132
133 // Do not publish user names!
134 $choice->publish = 0;
135 $DB->update_record('choice', $choice);
136 $results = mod_choice_external::get_choice_results($choice->id);
137 // We need to execute the return values cleaning process to simulate the web service server.
138 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
139 // Create an array with optionID as Key.
140 $resultsarr = array();
141 // Does not show any user response!
142 foreach ($results['options'] as $option) {
143 $this->assertCount(0, $option['userresponses']);
144 $resultsarr[$option['id']] = $option;
145 }
146 // But we can see totals and percentages.
147 $this->assertEquals(1, $resultsarr[$myanswer]['numberofuser']);
148 }
149
150 /**
151 * Test get_choice_options
152 */
153 public function test_get_choice_options() {
154 global $DB;
155
156 // Warningcodes.
157 $notopenyet = 1;
158 $previewonly = 2;
159 $expired = 3;
160
161 $this->resetAfterTest(true);
162 $timenow = time();
163 $timeopen = $timenow + (60 * 60 * 24 * 2);
164 $timeclose = $timenow + (60 * 60 * 24 * 7);
165 $course = self::getDataGenerator()->create_course();
166 $possibleoptions = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
167 $params = array();
168 $params['course'] = $course->id;
169 $params['option'] = $possibleoptions;
170 $params['name'] = 'First Choice Activity';
171 $params['showpreview'] = 0;
172
173 $generator = $this->getDataGenerator()->get_plugin_generator('mod_choice');
174 $choice = $generator->create_instance($params);
175
176 $student1 = $this->getDataGenerator()->create_user();
177 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
178 // Enroll Students in Course.
179 self::getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
180 $this->setUser($student1);
181
182 $results = mod_choice_external::get_choice_options($choice->id);
183 // We need to execute the return values cleaning process to simulate the web service server.
184 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
185 // We should retrieve all options.
186 $this->assertCount(count($possibleoptions), $results['options']);
187
188 // Here we force timeopen/close in the future.
189 $choice->timeopen = $timeopen;
190 $choice->timeclose = $timeclose;
191 $DB->update_record('choice', $choice);
192
193 $results = mod_choice_external::get_choice_options($choice->id);
194 // We need to execute the return values cleaning process to simulate the web service server.
195 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
196 // We should retrieve no options.
197 $this->assertCount(0, $results['options']);
198 $this->assertEquals($notopenyet, $results['warnings'][0]['warningcode']);
199
200 // Here we see the options because of preview!
201 $choice->showpreview = 1;
202 $DB->update_record('choice', $choice);
203 $results = mod_choice_external::get_choice_options($choice->id);
204 // We need to execute the return values cleaning process to simulate the web service server.
205 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
206 // We should retrieve all options.
207 $this->assertCount(count($possibleoptions), $results['options']);
208
209 foreach ($results['options'] as $option) {
210 // Each option is disabled as this is only the preview!
211 $this->assertEquals(1, $option['disabled']);
212 }
213 $warnings = array();
214 foreach ($results['warnings'] as $warning) {
215 $warnings[$warning['warningcode']] = $warning['message'];
216 }
217 $this->assertTrue(isset($warnings[$previewonly]));
218 $this->assertTrue(isset($warnings[$notopenyet]));
219
220 // Simulate activity as opened!
221 $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
222 $choice->timeclose = $timenow + (60 * 60 * 24 * 2);
223 $DB->update_record('choice', $choice);
224 $cm = get_coursemodule_from_id('choice', $choice->cmid);
225 $choiceinstance = choice_get_choice($cm->instance);
226 $optionsids = array_keys($choiceinstance->option);
227 $myanswerid = $optionsids[2];
228 choice_user_submit_response($myanswerid, $choice, $student1->id, $course, $cm);
229
230 $results = mod_choice_external::get_choice_options($choice->id);
231 // We need to execute the return values cleaning process to simulate the web service server.
232 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
233 // We should retrieve all options.
234 $this->assertCount(count($possibleoptions), $results['options']);
235 foreach ($results['options'] as $option) {
236 // When we answered and we cannot update our choice.
237 if ($option['id'] == $myanswerid and !$choice->allowupdate) {
238 $this->assertEquals(1, $option['disabled']);
239 $this->assertEquals(1, $option['checked']);
240 } else {
241 $this->assertEquals(0, $option['disabled']);
242 }
243 }
244
245 // Set timeopen and timeclose as older than today!
246 // We simulate what happens when the activity is closed.
247 $choice->timeopen = $timenow - (60 * 60 * 24 * 3);
248 $choice->timeclose = $timenow - (60 * 60 * 24 * 2);
249 $DB->update_record('choice', $choice);
250 $results = mod_choice_external::get_choice_options($choice->id);
251 // We need to execute the return values cleaning process to simulate the web service server.
252 $results = external_api::clean_returnvalue(mod_choice_external::get_choice_options_returns(), $results);
253 // We should retrieve no options.
254 $this->assertCount(0, $results['options']);
255 $this->assertEquals($expired, $results['warnings'][0]['warningcode']);
256
257 }
258
259 /**
260 * Test submit_choice_response
261 */
262 public function test_submit_choice_response() {
263 global $DB;
264
265 $this->resetAfterTest(true);
266
267 $course = self::getDataGenerator()->create_course();
268 $params = new stdClass();
269 $params->course = $course->id;
270 $params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
271 $params->name = 'First Choice Activity';
272 $params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
273 $params->allowmultiple = 1;
274 $params->showunanswered = 1;
275 $choice = self::getDataGenerator()->create_module('choice', $params);
276 $cm = get_coursemodule_from_id('choice', $choice->cmid);
277 $choiceinstance = choice_get_choice($cm->instance);
278 $options = array_keys($choiceinstance->option);
279 $student1 = $this->getDataGenerator()->create_user();
280 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
281
282 // Enroll Students in Course1.
283 self::getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
284
285 $this->setUser($student1);
286 $myresponse = $options[2];
287 $results = mod_choice_external::submit_choice_response($choice->id, array($myresponse));
288 // We need to execute the return values cleaning process to simulate the web service server.
289 $results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
290 $myanswers = $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $student1->id));
291 $myanswer = reset($myanswers);
292 $this->assertEquals($results['answers'][0]['id'], $myanswer->id);
293 $this->assertEquals($results['answers'][0]['choiceid'], $myanswer->choiceid);
294 $this->assertEquals($results['answers'][0]['userid'], $myanswer->userid);
295 $this->assertEquals($results['answers'][0]['timemodified'], $myanswer->timemodified);
296 }
297
298 /**
299 * Test view_choice
300 */
301 public function test_view_choice() {
302 global $DB;
303
304 $this->resetAfterTest(true);
305
306 // Setup test data.
307 $course = $this->getDataGenerator()->create_course();
308 $choice = $this->getDataGenerator()->create_module('choice', array('course' => $course->id));
309 $context = context_module::instance($choice->cmid);
310 $cm = get_coursemodule_from_instance('choice', $choice->id);
311
312 // Test invalid instance id.
313 try {
314 mod_choice_external::view_choice(0);
315 $this->fail('Exception expected due to invalid mod_choice instance id.');
316 } catch (moodle_exception $e) {
317 $this->assertEquals('invalidcoursemodule', $e->errorcode);
318 }
319
320 // Test not-enrolled user.
321 $user = self::getDataGenerator()->create_user();
322 $this->setUser($user);
323 try {
324 mod_choice_external::view_choice($choice->id);
325 $this->fail('Exception expected due to not enrolled user.');
326 } catch (moodle_exception $e) {
327 $this->assertEquals('requireloginerror', $e->errorcode);
328 }
329
330 // Test user with full capabilities.
331 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
332 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
333
334 // Trigger and capture the event.
335 $sink = $this->redirectEvents();
336
337 $result = mod_choice_external::view_choice($choice->id);
338 $result = external_api::clean_returnvalue(mod_choice_external::view_choice_returns(), $result);
339
340 $events = $sink->get_events();
341 $this->assertCount(1, $events);
342 $event = array_shift($events);
343
344 // Checking that the event contains the expected values.
345 $this->assertInstanceOf('\mod_choice\event\course_module_viewed', $event);
346 $this->assertEquals($context, $event->get_context());
347 $moodlechoice = new \moodle_url('/mod/choice/view.php', array('id' => $cm->id));
348 $this->assertEquals($moodlechoice, $event->get_url());
349 $this->assertEventContextNotUsed($event);
350 $this->assertNotEmpty($event->get_name());
351
352 }
f07a2bb0
JL
353
354 /**
355 * Test get_choices_by_courses
356 */
357 public function test_get_choices_by_courses() {
358 global $DB;
359 $this->resetAfterTest(true);
360 // As admin.
361 $this->setAdminUser();
362 $course1 = self::getDataGenerator()->create_course();
363 $choiceoptions1 = array(
364 'course' => $course1->id,
365 'name' => 'First IMSCP'
366 );
367 $choice1 = self::getDataGenerator()->create_module('choice', $choiceoptions1);
368 $course2 = self::getDataGenerator()->create_course();
369
370 $choiceoptions2 = array(
371 'course' => $course2->id,
372 'name' => 'Second IMSCP'
373 );
374 $choice2 = self::getDataGenerator()->create_module('choice', $choiceoptions2);
375 $student1 = $this->getDataGenerator()->create_user();
376
377 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
378
379 // Enroll Student1 in Course1.
380 self::getDataGenerator()->enrol_user($student1->id, $course1->id, $studentrole->id);
381
382 $this->setUser($student1);
383 $choices = mod_choice_external::get_choices_by_courses(array());
384 $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
385 $this->assertCount(1, $choices['choices']);
386 $this->assertEquals('First IMSCP', $choices['choices'][0]['name']);
387 // As Student you cannot see some IMSCP properties like 'section'.
388 $this->assertFalse(isset($choices['choices'][0]['section']));
389
390 // Student1 is not enrolled in this Course.
391 // The webservice will give a warning!
392 $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
393 $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
394 $this->assertCount(0, $choices['choices']);
395 $this->assertEquals(1, $choices['warnings'][0]['warningcode']);
396
397 // Now as admin.
398 $this->setAdminUser();
399 // As Admin we can see this IMSCP.
400 $choices = mod_choice_external::get_choices_by_courses(array($course2->id));
401 $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
402 $this->assertCount(1, $choices['choices']);
403 $this->assertEquals('Second IMSCP', $choices['choices'][0]['name']);
404 // As an Admin you can see some IMSCP properties like 'section'.
405 $this->assertEquals(0, $choices['choices'][0]['section']);
406
407 // Now, prohibit capabilities.
408 $this->setUser($student1);
409 $contextcourse1 = context_course::instance($course1->id);
410 // Prohibit capability = mod:choice:choose on Course1 for students.
411 assign_capability('mod/choice:choose', CAP_PROHIBIT, $studentrole->id, $contextcourse1->id);
412 accesslib_clear_all_caches_for_unit_testing();
413
414 $choices = mod_choice_external::get_choices_by_courses(array($course1->id));
415 $choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
416 $this->assertFalse(isset($choices['choices'][0]['timeopen']));
417 }
dffb87ed 418}