MDL-59252 mod_workshop: Move assessment evaluation code to API
[moodle.git] / mod / workshop / tests / external_test.php
CommitLineData
9f1ab2db
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 * Workshop module external functions tests
19 *
20 * @package mod_workshop
21 * @category external
22 * @copyright 2017 Juan Leyva <juan@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 * @since Moodle 3.4
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30
31require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32require_once($CFG->dirroot . '/mod/workshop/lib.php');
33
34use mod_workshop\external\workshop_summary_exporter;
3f08cfc5 35use mod_workshop\external\submission_exporter;
9f1ab2db
JL
36
37/**
38 * Workshop module external functions tests
39 *
40 * @package mod_workshop
41 * @category external
42 * @copyright 2017 Juan Leyva <juan@moodle.com>
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44 * @since Moodle 3.4
45 */
46class mod_workshop_external_testcase extends externallib_advanced_testcase {
47
48 /** @var stdClass course object */
49 private $course;
50 /** @var stdClass workshop object */
51 private $workshop;
52 /** @var stdClass context object */
53 private $context;
54 /** @var stdClass cm object */
55 private $cm;
56 /** @var stdClass student object */
57 private $student;
58 /** @var stdClass teacher object */
59 private $teacher;
60 /** @var stdClass student role object */
61 private $studentrole;
62 /** @var stdClass teacher role object */
63 private $teacherrole;
64
65 /**
66 * Set up for every test
67 */
68 public function setUp() {
69 global $DB;
70 $this->resetAfterTest();
71 $this->setAdminUser();
72
73 // Setup test data.
3f08cfc5
JL
74 $course = new stdClass();
75 $course->groupmode = SEPARATEGROUPS;
76 $course->groupmodeforce = true;
77 $this->course = $this->getDataGenerator()->create_course($course);
fe966a27
JL
78 $this->workshop = $this->getDataGenerator()->create_module('workshop',
79 array(
80 'course' => $this->course->id,
81 'overallfeedbackfiles' => 1,
82 )
83 );
9f1ab2db
JL
84 $this->context = context_module::instance($this->workshop->cmid);
85 $this->cm = get_coursemodule_from_instance('workshop', $this->workshop->id);
86
46f5e9a0
JL
87 // Add grading strategy data (accumulative is the default).
88 $workshop = new workshop($this->workshop, $this->cm, $this->course);
89 $strategy = $workshop->grading_strategy_instance();
90 $data = array();
91 for ($i = 0; $i < 4; $i++) {
92 $data['dimensionid__idx_'.$i] = 0;
93 $data['description__idx_'.$i.'_editor'] = array('text' => "Content $i", 'format' => FORMAT_MOODLE);
94 $data['grade__idx_'.$i] = 25;
95 $data['weight__idx_'.$i] = 25;
96 }
97 $data['workshopid'] = $workshop->id;
98 $data['norepeats'] = 4;
99 $strategy->save_edit_strategy_form((object) $data);
100
9f1ab2db
JL
101 // Create users.
102 $this->student = self::getDataGenerator()->create_user();
3f08cfc5
JL
103 $this->anotherstudentg1 = self::getDataGenerator()->create_user();
104 $this->anotherstudentg2 = self::getDataGenerator()->create_user();
9f1ab2db
JL
105 $this->teacher = self::getDataGenerator()->create_user();
106
107 // Users enrolments.
108 $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
109 $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
110 $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
3f08cfc5
JL
111 $this->getDataGenerator()->enrol_user($this->anotherstudentg1->id, $this->course->id, $this->studentrole->id, 'manual');
112 $this->getDataGenerator()->enrol_user($this->anotherstudentg2->id, $this->course->id, $this->studentrole->id, 'manual');
9f1ab2db 113 $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
3f08cfc5
JL
114
115 $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
116 $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
117 groups_add_member($this->group1, $this->student);
118 groups_add_member($this->group1, $this->anotherstudentg1);
119 groups_add_member($this->group2, $this->anotherstudentg2);
9f1ab2db
JL
120 }
121
122 /**
123 * Test test_mod_workshop_get_workshops_by_courses
124 */
125 public function test_mod_workshop_get_workshops_by_courses() {
126 global $DB;
127
128 // Create additional course.
129 $course2 = self::getDataGenerator()->create_course();
130
131 // Second workshop.
132 $record = new stdClass();
133 $record->course = $course2->id;
134 $workshop2 = self::getDataGenerator()->create_module('workshop', $record);
135
136 // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
137 $enrol = enrol_get_plugin('manual');
138 $enrolinstances = enrol_get_instances($course2->id, true);
139 foreach ($enrolinstances as $courseenrolinstance) {
140 if ($courseenrolinstance->enrol == "manual") {
141 $instance2 = $courseenrolinstance;
142 break;
143 }
144 }
145 $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id);
146
147 self::setUser($this->student);
148
149 $returndescription = mod_workshop_external::get_workshops_by_courses_returns();
150
151 // Create what we expect to be returned when querying the two courses.
152 $properties = workshop_summary_exporter::read_properties_definition();
153 $expectedfields = array_keys($properties);
154
155 // Add expected coursemodule and data.
156 $workshop1 = $this->workshop;
157 $workshop1->coursemodule = $workshop1->cmid;
158 $workshop1->introformat = 1;
159 $workshop1->introfiles = [];
160 $workshop1->instructauthorsfiles = [];
161 $workshop1->instructauthorsformat = 1;
162 $workshop1->instructreviewersfiles = [];
163 $workshop1->instructreviewersformat = 1;
164 $workshop1->conclusionfiles = [];
165 $workshop1->conclusionformat = 1;
166
167 $workshop2->coursemodule = $workshop2->cmid;
168 $workshop2->introformat = 1;
169 $workshop2->introfiles = [];
170 $workshop2->instructauthorsfiles = [];
171 $workshop2->instructauthorsformat = 1;
172 $workshop2->instructreviewersfiles = [];
173 $workshop2->instructreviewersformat = 1;
174 $workshop2->conclusionfiles = [];
175 $workshop2->conclusionformat = 1;
176
177 foreach ($expectedfields as $field) {
178 if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) {
179 $workshop1->{$field} = (bool) $workshop1->{$field};
180 $workshop2->{$field} = (bool) $workshop2->{$field};
181 }
182 $expected1[$field] = $workshop1->{$field};
183 $expected2[$field] = $workshop2->{$field};
184 }
185
186 $expectedworkshops = array($expected2, $expected1);
187
188 // Call the external function passing course ids.
189 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id, $this->course->id));
190 $result = external_api::clean_returnvalue($returndescription, $result);
191
192 $this->assertEquals($expectedworkshops, $result['workshops']);
193 $this->assertCount(0, $result['warnings']);
194
195 // Call the external function without passing course id.
196 $result = mod_workshop_external::get_workshops_by_courses();
197 $result = external_api::clean_returnvalue($returndescription, $result);
198 $this->assertEquals($expectedworkshops, $result['workshops']);
199 $this->assertCount(0, $result['warnings']);
200
201 // Unenrol user from second course and alter expected workshops.
202 $enrol->unenrol_user($instance2, $this->student->id);
203 array_shift($expectedworkshops);
204
205 // Call the external function without passing course id.
206 $result = mod_workshop_external::get_workshops_by_courses();
207 $result = external_api::clean_returnvalue($returndescription, $result);
208 $this->assertEquals($expectedworkshops, $result['workshops']);
209
210 // Call for the second course we unenrolled the user from, expected warning.
211 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id));
212 $this->assertCount(1, $result['warnings']);
213 $this->assertEquals('1', $result['warnings'][0]['warningcode']);
214 $this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
215 }
977fdfa3
JL
216
217 /**
218 * Test mod_workshop_get_workshop_access_information for students.
219 */
220 public function test_mod_workshop_get_workshop_access_information_student() {
221
222 self::setUser($this->student);
223 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
224 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
225 // Check default values for capabilities.
226 $enabledcaps = array('canpeerassess', 'cansubmit', 'canview', 'canviewauthornames', 'canviewauthorpublished',
227 'canviewpublishedsubmissions', 'canexportsubmissions');
228
229 foreach ($result as $capname => $capvalue) {
230 if (strpos($capname, 'can') !== 0) {
231 continue;
232 }
233 if (in_array($capname, $enabledcaps)) {
234 $this->assertTrue($capvalue);
235 } else {
236 $this->assertFalse($capvalue);
237 }
238 }
239 // Now, unassign some capabilities.
240 unassign_capability('mod/workshop:peerassess', $this->studentrole->id);
241 unassign_capability('mod/workshop:submit', $this->studentrole->id);
242 unset($enabledcaps[0]);
243 unset($enabledcaps[1]);
244 accesslib_clear_all_caches_for_unit_testing();
245
246 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
247 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
248 foreach ($result as $capname => $capvalue) {
249 if (strpos($capname, 'can') !== 0) {
250 continue;
251 }
252 if (in_array($capname, $enabledcaps)) {
253 $this->assertTrue($capvalue);
254 } else {
255 $this->assertFalse($capvalue);
256 }
257 }
258
259 // Now, specific functionalities.
260 $this->assertFalse($result['creatingsubmissionallowed']);
261 $this->assertFalse($result['modifyingsubmissionallowed']);
262 $this->assertFalse($result['assessingallowed']);
263 $this->assertFalse($result['assessingexamplesallowed']);
86928d2a
JL
264 $this->assertTrue($result['examplesassessedbeforesubmission']);
265 $this->assertTrue($result['examplesassessedbeforeassessment']);
977fdfa3
JL
266
267 // Switch phase.
268 $workshop = new workshop($this->workshop, $this->cm, $this->course);
269 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
270 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
271 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
272
273 $this->assertTrue($result['creatingsubmissionallowed']);
274 $this->assertTrue($result['modifyingsubmissionallowed']);
275 $this->assertFalse($result['assessingallowed']);
276 $this->assertFalse($result['assessingexamplesallowed']);
86928d2a
JL
277 $this->assertTrue($result['examplesassessedbeforesubmission']);
278 $this->assertTrue($result['examplesassessedbeforeassessment']);
977fdfa3
JL
279
280 // Switch to next (to assessment).
281 $workshop = new workshop($this->workshop, $this->cm, $this->course);
282 $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
283 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
284 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
285
286 $this->assertFalse($result['creatingsubmissionallowed']);
287 $this->assertFalse($result['modifyingsubmissionallowed']);
288 $this->assertTrue($result['assessingallowed']);
289 $this->assertFalse($result['assessingexamplesallowed']);
86928d2a
JL
290 $this->assertTrue($result['examplesassessedbeforesubmission']);
291 $this->assertTrue($result['examplesassessedbeforeassessment']);
977fdfa3
JL
292 }
293
294 /**
295 * Test mod_workshop_get_workshop_access_information for teachers.
296 */
297 public function test_mod_workshop_get_workshop_access_information_teacher() {
298
299 self::setUser($this->teacher);
300 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
301 $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
302 // Check default values.
303 $disabledcaps = array('canpeerassess', 'cansubmit');
304
305 foreach ($result as $capname => $capvalue) {
306 if (strpos($capname, 'can') !== 0) {
307 continue;
308 }
309 if (in_array($capname, $disabledcaps)) {
310 $this->assertFalse($capvalue);
311 } else {
312 $this->assertTrue($capvalue);
313 }
314 }
315
316 // Now, specific functionalities.
317 $this->assertFalse($result['creatingsubmissionallowed']);
318 $this->assertFalse($result['modifyingsubmissionallowed']);
319 $this->assertFalse($result['assessingallowed']);
320 $this->assertFalse($result['assessingexamplesallowed']);
321 }
cd495029
JL
322
323 /**
324 * Test mod_workshop_get_user_plan for students.
325 */
326 public function test_mod_workshop_get_user_plan_student() {
327
328 self::setUser($this->student);
329 $result = mod_workshop_external::get_user_plan($this->workshop->id);
330 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
331
332 $this->assertCount(0, $result['userplan']['examples']); // No examples given.
333 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases.
334 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup.
335 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
336
337 // Switch phase.
338 $workshop = new workshop($this->workshop, $this->cm, $this->course);
339 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
340
341 $result = mod_workshop_external::get_user_plan($this->workshop->id);
342 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
343
344 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
345 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
346 }
347
348 /**
349 * Test mod_workshop_get_user_plan for teachers.
350 */
351 public function test_mod_workshop_get_user_plan_teacher() {
352 global $DB;
353
354 self::setUser($this->teacher);
355 $result = mod_workshop_external::get_user_plan($this->workshop->id);
356 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
357
358 $this->assertCount(0, $result['userplan']['examples']); // No examples given.
359 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases.
360 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup.
361 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
362 $this->assertCount(4, $result['userplan']['phases'][0]['tasks']); // For new empty workshops, always 4 tasks.
363
364 foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
46f5e9a0 365 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform') {
cd495029
JL
366 $this->assertEquals(1, $task['completed']);
367 } else {
368 $this->assertEmpty($task['completed']);
369 }
370 }
371
372 // Do some of the tasks asked - switch phase.
373 $workshop = new workshop($this->workshop, $this->cm, $this->course);
374 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
375
376 $result = mod_workshop_external::get_user_plan($this->workshop->id);
377 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
378 foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
46f5e9a0
JL
379 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform' ||
380 $task['code'] == 'switchtonextphase') {
cd495029
JL
381 $this->assertEquals(1, $task['completed']);
382 } else {
383 $this->assertEmpty($task['completed']);
384 }
385 }
386
387 $result = mod_workshop_external::get_user_plan($this->workshop->id);
388 $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
389
390 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
391 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
392 }
291645f7
JL
393
394 /**
395 * Test test_view_workshop invalid id.
396 */
397 public function test_view_workshop_invalid_id() {
398 $this->expectException('moodle_exception');
399 mod_workshop_external::view_workshop(0);
400 }
401
402 /**
403 * Test test_view_workshop user not enrolled.
404 */
405 public function test_view_workshop_user_not_enrolled() {
406 // Test not-enrolled user.
407 $usernotenrolled = self::getDataGenerator()->create_user();
408 $this->setUser($usernotenrolled);
409 $this->expectException('moodle_exception');
410 mod_workshop_external::view_workshop($this->workshop->id);
411 }
412
413 /**
414 * Test test_view_workshop user student.
415 */
416 public function test_view_workshop_user_student() {
417 // Test user with full capabilities.
418 $this->setUser($this->student);
419
420 // Trigger and capture the event.
421 $sink = $this->redirectEvents();
422
423 $result = mod_workshop_external::view_workshop($this->workshop->id);
424 $result = external_api::clean_returnvalue(mod_workshop_external::view_workshop_returns(), $result);
425 $this->assertTrue($result['status']);
426
427 $events = $sink->get_events();
428 $this->assertCount(1, $events);
429 $event = array_shift($events);
430
431 // Checking that the event contains the expected values.
432 $this->assertInstanceOf('\mod_workshop\event\course_module_viewed', $event);
433 $this->assertEquals($this->context, $event->get_context());
434 $moodleworkshop = new \moodle_url('/mod/workshop/view.php', array('id' => $this->cm->id));
435 $this->assertEquals($moodleworkshop, $event->get_url());
436 $this->assertEventContextNotUsed($event);
437 $this->assertNotEmpty($event->get_name());
438 }
439
440 /**
441 * Test test_view_workshop user missing capabilities.
442 */
443 public function test_view_workshop_user_missing_capabilities() {
444 // Test user with no capabilities.
445 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
446 assign_capability('mod/workshop:view', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
447 // Empty all the caches that may be affected by this change.
448 accesslib_clear_all_caches_for_unit_testing();
449 course_modinfo::clear_instance_cache();
450
451 $this->setUser($this->student);
452 $this->expectException('moodle_exception');
453 mod_workshop_external::view_workshop($this->workshop->id);
454 }
c2cf2450
JL
455
456 /**
457 * Test test_add_submission.
458 */
459 public function test_add_submission() {
460 $fs = get_file_storage();
461
462 // Test user with full capabilities.
463 $this->setUser($this->student);
464
465 $title = 'Submission title';
466 $content = 'Submission contents';
467
468 // Create a file in a draft area for inline attachments.
469 $draftidinlineattach = file_get_unused_draft_itemid();
470 $usercontext = context_user::instance($this->student->id);
471 $filenameimg = 'shouldbeanimage.txt';
472 $filerecordinline = array(
473 'contextid' => $usercontext->id,
474 'component' => 'user',
475 'filearea' => 'draft',
476 'itemid' => $draftidinlineattach,
477 'filepath' => '/',
478 'filename' => $filenameimg,
479 );
480 $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
481
482 // Create a file in a draft area for regular attachments.
483 $draftidattach = file_get_unused_draft_itemid();
484 $filerecordattach = $filerecordinline;
485 $attachfilename = 'attachment.txt';
486 $filerecordattach['filename'] = $attachfilename;
487 $filerecordattach['itemid'] = $draftidattach;
488 $fs->create_file_from_string($filerecordattach, 'simple text attachment');
489
490 // Switch to submission phase.
491 $workshop = new workshop($this->workshop, $this->cm, $this->course);
492 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
493
494 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
495 $draftidattach);
496 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
497 $this->assertEmpty($result['warnings']);
498
499 // Check submission created.
500 $submission = $workshop->get_submission_by_author($this->student->id);
4834e127 501 $this->assertTrue($result['status']);
c2cf2450
JL
502 $this->assertEquals($result['submissionid'], $submission->id);
503 $this->assertEquals($title, $submission->title);
504 $this->assertEquals($content, $submission->content);
505
506 // Check files.
507 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);
508 $this->assertCount(2, $contentfiles);
509 foreach ($contentfiles as $file) {
510 if ($file->is_directory()) {
511 continue;
512 } else {
513 $this->assertEquals($filenameimg, $file->get_filename());
514 }
515 }
516 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);
517 $this->assertCount(2, $contentfiles);
518 foreach ($contentfiles as $file) {
519 if ($file->is_directory()) {
520 continue;
521 } else {
522 $this->assertEquals($attachfilename, $file->get_filename());
523 }
524 }
525 }
526
527 /**
528 * Test test_add_submission invalid phase.
529 */
530 public function test_add_submission_invalid_phase() {
531 $this->setUser($this->student);
532
533 $this->expectException('moodle_exception');
534 mod_workshop_external::add_submission($this->workshop->id, 'Test');
535 }
536
537 /**
538 * Test test_add_submission empty title.
539 */
540 public function test_add_submission_empty_title() {
541 $this->setUser($this->student);
542
543 // Switch to submission phase.
544 $workshop = new workshop($this->workshop, $this->cm, $this->course);
545 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
546
547 $this->expectException('moodle_exception');
548 mod_workshop_external::add_submission($this->workshop->id, '');
549 }
550
551 /**
552 * Test test_add_submission already added.
553 */
554 public function test_add_submission_already_added() {
555 $this->setUser($this->student);
556
557 // Switch to submission phase.
558 $workshop = new workshop($this->workshop, $this->cm, $this->course);
559 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
560
561 // Create the submission.
562 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission');
563 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
564
565 // Try to create it again.
566 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission');
567 $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
4834e127
JL
568 $this->assertFalse($result['status']);
569 $this->assertArrayNotHasKey('submissionid', $result);
c2cf2450
JL
570 $this->assertCount(2, $result['warnings']);
571 $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']);
572 $this->assertEquals('content_editor', $result['warnings'][0]['item']);
573 $this->assertEquals('fielderror', $result['warnings'][1]['warningcode']);
574 $this->assertEquals('attachment_filemanager', $result['warnings'][1]['item']);
575 }
c1698a37
JL
576
577 /**
578 * Helper method to create a submission for testing for the given user.
579 *
580 * @param int $user the submission will be created by this student.
581 * @return int the submission id
582 */
583 protected function create_test_submission($user) {
584 // Test user with full capabilities.
585 $this->setUser($user);
586
587 $title = 'Submission title';
588 $content = 'Submission contents';
589
590 // Create a file in a draft area for inline attachments.
591 $fs = get_file_storage();
592 $draftidinlineattach = file_get_unused_draft_itemid();
593 $usercontext = context_user::instance($this->student->id);
594 $filenameimg = 'shouldbeanimage.txt';
595 $filerecordinline = array(
596 'contextid' => $usercontext->id,
597 'component' => 'user',
598 'filearea' => 'draft',
599 'itemid' => $draftidinlineattach,
600 'filepath' => '/',
601 'filename' => $filenameimg,
602 );
603 $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
604
605 // Create a file in a draft area for regular attachments.
606 $draftidattach = file_get_unused_draft_itemid();
607 $filerecordattach = $filerecordinline;
608 $attachfilename = 'attachment.txt';
609 $filerecordattach['filename'] = $attachfilename;
610 $filerecordattach['itemid'] = $draftidattach;
611 $fs->create_file_from_string($filerecordattach, 'simple text attachment');
612
613 // Switch to submission phase.
614 $workshop = new workshop($this->workshop, $this->cm, $this->course);
615 $workshop->switch_phase(workshop::PHASE_SUBMISSION);
616
617 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
618 $draftidattach);
619 return $result['submissionid'];
620 }
621
622 /**
623 * Test test_update_submission.
624 */
625 public function test_update_submission() {
626
627 // Create the submission that will be updated.
628 $submissionid = $this->create_test_submission($this->student);
629
630 // Test user with full capabilities.
631 $this->setUser($this->student);
632
633 $title = 'Submission new title';
634 $content = 'Submission new contents';
635
636 // Create a different file in a draft area for inline attachments.
637 $fs = get_file_storage();
638 $draftidinlineattach = file_get_unused_draft_itemid();
639 $usercontext = context_user::instance($this->student->id);
640 $filenameimg = 'shouldbeanimage_new.txt';
641 $filerecordinline = array(
642 'contextid' => $usercontext->id,
643 'component' => 'user',
644 'filearea' => 'draft',
645 'itemid' => $draftidinlineattach,
646 'filepath' => '/',
647 'filename' => $filenameimg,
648 );
649 $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
650
651 // Create a different file in a draft area for regular attachments.
652 $draftidattach = file_get_unused_draft_itemid();
653 $filerecordattach = $filerecordinline;
654 $attachfilename = 'attachment_new.txt';
655 $filerecordattach['filename'] = $attachfilename;
656 $filerecordattach['itemid'] = $draftidattach;
657 $fs->create_file_from_string($filerecordattach, 'simple text attachment');
658
659 $result = mod_workshop_external::update_submission($submissionid, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
660 $draftidattach);
661 $result = external_api::clean_returnvalue(mod_workshop_external::update_submission_returns(), $result);
662 $this->assertEmpty($result['warnings']);
663
664 // Check submission updated.
665 $workshop = new workshop($this->workshop, $this->cm, $this->course);
666 $submission = $workshop->get_submission_by_id($submissionid);
667 $this->assertTrue($result['status']);
668 $this->assertEquals($title, $submission->title);
669 $this->assertEquals($content, $submission->content);
670
671 // Check files.
672 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);
673 $this->assertCount(2, $contentfiles);
674 foreach ($contentfiles as $file) {
675 if ($file->is_directory()) {
676 continue;
677 } else {
678 $this->assertEquals($filenameimg, $file->get_filename());
679 }
680 }
681 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);
682 $this->assertCount(2, $contentfiles);
683 foreach ($contentfiles as $file) {
684 if ($file->is_directory()) {
685 continue;
686 } else {
687 $this->assertEquals($attachfilename, $file->get_filename());
688 }
689 }
690 }
691
692 /**
693 * Test test_update_submission belonging to other user.
694 */
695 public function test_update_submission_of_other_user() {
696 // Create the submission that will be updated.
697 $submissionid = $this->create_test_submission($this->student);
698
699 $this->setUser($this->teacher);
700
701 $this->expectException('moodle_exception');
702 mod_workshop_external::update_submission($submissionid, 'Test');
703 }
704
705 /**
706 * Test test_update_submission invalid phase.
707 */
708 public function test_update_submission_invalid_phase() {
709 // Create the submission that will be updated.
710 $submissionid = $this->create_test_submission($this->student);
711
712 $this->setUser($this->student);
713
714 // Switch to assessment phase.
715 $workshop = new workshop($this->workshop, $this->cm, $this->course);
716 $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
717
718 $this->expectException('moodle_exception');
719 mod_workshop_external::update_submission($submissionid, 'Test');
720 }
721
722 /**
723 * Test test_update_submission empty title.
724 */
725 public function test_update_submission_empty_title() {
726 // Create the submission that will be updated.
727 $submissionid = $this->create_test_submission($this->student);
728
729 $this->setUser($this->student);
730
731 $this->expectException('moodle_exception');
732 mod_workshop_external::update_submission($submissionid, '');
733 }
bde5631d
JL
734
735 /**
736 * Test test_delete_submission.
737 */
738 public function test_delete_submission() {
739
740 // Create the submission that will be deleted.
741 $submissionid = $this->create_test_submission($this->student);
742
743 $this->setUser($this->student);
744
745 // Trigger and capture the event.
746 $sink = $this->redirectEvents();
747
748 $result = mod_workshop_external::delete_submission($submissionid);
749 $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);
750 $this->assertEmpty($result['warnings']);
751 $this->assertTrue($result['status']);
752 $workshop = new workshop($this->workshop, $this->cm, $this->course);
753 $submission = $workshop->get_submission_by_author($this->student->id);
754 $this->assertFalse($submission);
755
756 $events = $sink->get_events();
757 $this->assertCount(1, $events);
758 $event = array_shift($events);
759
760 // Checking event.
761 $this->assertInstanceOf('\mod_workshop\event\submission_deleted', $event);
762 $this->assertEquals($this->context, $event->get_context());
763 }
764
765 /**
766 * Test test_delete_submission_with_assessments.
767 */
768 public function test_delete_submission_with_assessments() {
769
770 // Create the submission that will be deleted.
771 $submissionid = $this->create_test_submission($this->student);
772
773 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
774 $workshopgenerator->create_assessment($submissionid, $this->teacher->id, array(
775 'weight' => 3,
776 'grade' => 95.00000,
777 ));
778
779 $this->setUser($this->student);
780 $this->expectException('moodle_exception');
781 mod_workshop_external::delete_submission($submissionid);
782 }
783
784 /**
785 * Test test_delete_submission_invalid_phase.
786 */
787 public function test_delete_submission_invalid_phase() {
788
789 // Create the submission that will be deleted.
790 $submissionid = $this->create_test_submission($this->student);
791
792 // Switch to assessment phase.
793 $workshop = new workshop($this->workshop, $this->cm, $this->course);
794 $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
795
796 $this->setUser($this->student);
797 $this->expectException('moodle_exception');
798 mod_workshop_external::delete_submission($submissionid);
799 }
800
801 /**
802 * Test test_delete_submission_as_teacher.
803 */
804 public function test_delete_submission_as_teacher() {
805
806 // Create the submission that will be deleted.
807 $submissionid = $this->create_test_submission($this->student);
808
809 $this->setUser($this->teacher);
810 $result = mod_workshop_external::delete_submission($submissionid);
811 $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);
812 $this->assertEmpty($result['warnings']);
813 $this->assertTrue($result['status']);
814 }
815
816 /**
817 * Test test_delete_submission_other_user.
818 */
819 public function test_delete_submission_other_user() {
820
821 $anotheruser = self::getDataGenerator()->create_user();
822 $this->getDataGenerator()->enrol_user($anotheruser->id, $this->course->id, $this->studentrole->id, 'manual');
823 // Create the submission that will be deleted.
824 $submissionid = $this->create_test_submission($this->student);
825
826 $this->setUser($anotheruser);
827 $this->expectException('moodle_exception');
828 mod_workshop_external::delete_submission($submissionid);
829 }
3f08cfc5
JL
830
831 /**
832 * Test test_get_submissions_student.
833 */
834 public function test_get_submissions_student() {
835
836 // Create a couple of submissions with files.
837 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.
838 $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1->id);
839
840 $this->setUser($this->student);
841 $result = mod_workshop_external::get_submissions($this->workshop->id);
842 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
843 // We should get just our submission.
844 $this->assertCount(1, $result['submissions']);
845 $this->assertEquals(1, $result['totalcount']);
846 $this->assertEquals($firstsubmissionid, $result['submissions'][0]['id']);
847 $this->assertCount(1, $result['submissions'][0]['contentfiles']); // Check we retrieve submission text files.
848 $this->assertCount(1, $result['submissions'][0]['attachmentfiles']); // Check we retrieve attachment files.
849 // We shoul not see the grade or feedback information.
850 $properties = submission_exporter::properties_definition();
851 foreach ($properties as $attribute => $settings) {
852 if (!empty($settings['optional'])) {
853 if (isset($result['submissions'][0][$attribute])) {
854 echo "error $attribute";
855 }
856 $this->assertFalse(isset($result['submissions'][0][$attribute]));
857 }
858 }
859 }
860
861 /**
862 * Test test_get_submissions_published_student.
863 */
864 public function test_get_submissions_published_student() {
865 global $DB;
866
867 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
868 // Create a couple of submissions with files.
869 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
870 $submission = array('published' => 1);
871 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);
872
873 $this->setUser($this->student);
874 $result = mod_workshop_external::get_submissions($this->workshop->id);
875 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
876 // We should get just our submission.
877 $this->assertCount(1, $result['submissions']);
878 $this->assertEquals(1, $result['totalcount']);
879 $this->assertEquals($submissionid, $result['submissions'][0]['id']);
880
881 // Check with group restrictions.
882 $this->setUser($this->anotherstudentg2);
883 $result = mod_workshop_external::get_submissions($this->workshop->id);
884 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
885 $this->assertCount(0, $result['submissions']); // I can't see other users in separated groups.
886 $this->assertEquals(0, $result['totalcount']);
887 }
888
889 /**
890 * Test test_get_submissions_from_student_with_feedback_from_teacher.
891 */
892 public function test_get_submissions_from_student_with_feedback_from_teacher() {
893 global $DB;
894
895 // Create a couple of submissions with files.
896 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
897 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
898 // Create teacher feedback for submission.
899 $record = new stdclass();
900 $record->id = $submissionid;
901 $record->gradeover = 9;
902 $record->gradeoverby = $this->teacher->id;
903 $record->feedbackauthor = 'Hey';
904 $record->feedbackauthorformat = FORMAT_MOODLE;
905 $record->published = 1;
906 $DB->update_record('workshop_submissions', $record);
907
908 // Remove teacher caps.
909 assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id);
910 // Empty all the caches that may be affected by this change.
911 accesslib_clear_all_caches_for_unit_testing();
912 course_modinfo::clear_instance_cache();
913
914 $this->setUser($this->teacher);
915 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->student->id);
916 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
917 // We should get just our submission.
918 $this->assertEquals(1, $result['totalcount']);
919 $this->assertEquals($submissionid, $result['submissions'][0]['id']);
920 }
921
922 /**
923 * Test test_get_submissions_from_students_as_teacher.
924 */
925 public function test_get_submissions_from_students_as_teacher() {
926 global $DB;
927
928 // Create a couple of submissions with files.
929 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
930 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
931 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);
932 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);
933
934 $this->setUser($this->teacher);
935 $result = mod_workshop_external::get_submissions($this->workshop->id); // Get all.
936 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
937 $this->assertEquals(3, $result['totalcount']);
938 $this->assertCount(3, $result['submissions']);
939
940 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, 0, 0, 2); // Check pagination.
941 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
942 $this->assertEquals(3, $result['totalcount']);
943 $this->assertCount(2, $result['submissions']);
944
945 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, $this->group2->id); // Get group 2.
946 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
947 $this->assertEquals(1, $result['totalcount']);
948 $this->assertCount(1, $result['submissions']);
949 $this->assertEquals($submissionid3, $result['submissions'][0]['id']);
950
951 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->anotherstudentg1->id); // Get one.
952 $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
953 $this->assertEquals(1, $result['totalcount']);
954 $this->assertEquals($submissionid2, $result['submissions'][0]['id']);
955 }
6e2f4866
JL
956
957 /**
958 * Test test_get_submission_student.
959 */
960 public function test_get_submission_student() {
961
962 // Create a couple of submissions with files.
963 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.
964
965 $this->setUser($this->student);
966 $result = mod_workshop_external::get_submission($firstsubmissionid);
967 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
968 $this->assertEquals($firstsubmissionid, $result['submission']['id']);
969 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.
970 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.
971 }
972
973 /**
974 * Test test_get_submission_i_reviewed.
975 */
976 public function test_get_submission_i_reviewed() {
977
978 // Create a couple of submissions with files.
979 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.
980 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
981 $workshopgenerator->create_assessment($firstsubmissionid, $this->anotherstudentg1->id, array(
982 'weight' => 3,
983 'grade' => 95,
984 ));
985 // Now try to get the submission I just reviewed.
986 $this->setUser($this->anotherstudentg1);
987 $result = mod_workshop_external::get_submission($firstsubmissionid);
988 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
989 $this->assertEquals($firstsubmissionid, $result['submission']['id']);
990 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.
991 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.
992 }
993
994 /**
995 * Test test_get_submission_other_student.
996 */
997 public function test_get_submission_other_student() {
998
999 // Create a couple of submissions with files.
1000 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.
1001 // Expect failure.
1002 $this->setUser($this->anotherstudentg1);
1003 $this->expectException('moodle_exception');
1004 $result = mod_workshop_external::get_submission($firstsubmissionid);
1005 }
1006
1007 /**
1008 * Test test_get_submission_published_student.
1009 */
1010 public function test_get_submission_published_student() {
1011 global $DB;
1012
1013 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1014 // Create a couple of submissions with files.
1015 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1016 $submission = array('published' => 1);
1017 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);
1018
1019 $this->setUser($this->student);
1020 $result = mod_workshop_external::get_submission($submissionid);
1021 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1022 $this->assertEquals($submissionid, $result['submission']['id']);
1023 // Check that the student don't see the other student grade/feedback data even if is published.
1024 // We shoul not see the grade or feedback information.
1025 $properties = submission_exporter::properties_definition();
1026 foreach ($properties as $attribute => $settings) {
1027 if (!empty($settings['optional'])) {
1028 if (isset($result['submission'][$attribute])) {
1029 echo "error $attribute";
1030 }
1031 $this->assertFalse(isset($result['submission'][$attribute]));
1032 }
1033 }
1034
1035 // Check with group restrictions.
1036 $this->setUser($this->anotherstudentg2);
1037 $this->expectException('moodle_exception');
1038 mod_workshop_external::get_submission($submissionid);
1039 }
1040
1041 /**
1042 * Test test_get_submission_from_student_with_feedback_from_teacher.
1043 */
1044 public function test_get_submission_from_student_with_feedback_from_teacher() {
1045 global $DB;
1046
1047 // Create a couple of submissions with files.
1048 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1049 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
1050 // Create teacher feedback for submission.
1051 $record = new stdclass();
1052 $record->id = $submissionid;
1053 $record->gradeover = 9;
1054 $record->gradeoverby = $this->teacher->id;
1055 $record->feedbackauthor = 'Hey';
1056 $record->feedbackauthorformat = FORMAT_MOODLE;
1057 $record->published = 1;
1058 $DB->update_record('workshop_submissions', $record);
1059
1060 // Remove teacher caps.
1061 assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id);
1062 // Empty all the caches that may be affected by this change.
1063 accesslib_clear_all_caches_for_unit_testing();
1064 course_modinfo::clear_instance_cache();
1065
1066 $this->setUser($this->teacher);
1067 $result = mod_workshop_external::get_submission($submissionid);
1068 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1069 $this->assertEquals($submissionid, $result['submission']['id']);
1070 }
1071
1072 /**
1073 * Test test_get_submission_from_students_as_teacher.
1074 */
1075 public function test_get_submission_from_students_as_teacher() {
1076 // Create a couple of submissions with files.
1077 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1078 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
1079 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);
1080 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);
1081
1082 $this->setUser($this->teacher);
1083 $result = mod_workshop_external::get_submission($submissionid1); // Get all.
1084 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1085 $this->assertEquals($submissionid1, $result['submission']['id']);
1086
1087 $result = mod_workshop_external::get_submission($submissionid3); // Get group 2.
1088 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1089 $this->assertEquals($submissionid3, $result['submission']['id']);
1090 }
30b54b82
JL
1091
1092
1093 /**
1094 * Test get_submission_assessments_student.
1095 */
1096 public function test_get_submission_assessments_student() {
1097 global $DB;
1098
1099 // Create the submission that will be deleted.
1100 $submissionid = $this->create_test_submission($this->student);
1101
1102 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1103 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1104 'weight' => 3,
1105 'grade' => 95,
1106 ));
1107 $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1108 'weight' => 2,
1109 'grade' => 90,
1110 ));
1111
1112 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1113 $this->setUser($this->student);
1114 $result = mod_workshop_external::get_submission_assessments($submissionid);
1115 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);
1116 $this->assertCount(2, $result['assessments']); // I received my two assessments.
1117 foreach ($result['assessments'] as $assessment) {
1118 if ($assessment['grade'] == 90) {
1119 // My own assessment, I can see me.
1120 $this->assertEquals($this->student->id, $assessment['reviewerid']);
1121 } else {
1122 // Student's can't see who did the review.
1123 $this->assertEquals(0, $assessment['reviewerid']);
1124 }
1125 }
1126 }
1127
1128 /**
1129 * Test get_submission_assessments_invalid_phase.
1130 */
1131 public function test_get_submission_assessments_invalid_phase() {
1132 global $DB;
1133
1134 // Create the submission that will be deleted.
1135 $submissionid = $this->create_test_submission($this->student);
1136
1137 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1138 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1139 'weight' => 3,
1140 'grade' => 95,
1141 ));
1142
1143 $this->expectException('moodle_exception');
1144 mod_workshop_external::get_submission_assessments($submissionid);
1145 }
1146
1147 /**
1148 * Test get_submission_assessments_teacher.
1149 */
1150 public function test_get_submission_assessments_teacher() {
1151
1152 // Create the submission that will be deleted.
1153 $submissionid = $this->create_test_submission($this->student);
1154
1155 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1156 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1157 'weight' => 1,
1158 'grade' => 50,
1159 ));
1160
1161 $this->setUser($this->teacher);
1162 $result = mod_workshop_external::get_submission_assessments($submissionid);
1163 $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);
1164 $this->assertCount(1, $result['assessments']);
1165 $this->assertEquals(50, $result['assessments'][0]['grade']);
1166 $this->assertEquals($assessmentid, $result['assessments'][0]['id']);
1167 }
b1e896cf
JL
1168
1169 /**
1170 * Test get_assessment_author.
1171 */
1172 public function test_get_assessment_author() {
1173 global $DB;
1174
1175 // Create the submission.
1176 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1177
1178 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1179 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1180 'weight' => 2,
1181 'grade' => 90,
1182 ));
1183
1184 // Switch to closed phase.
1185 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1186 $this->setUser($this->anotherstudentg1);
1187 $result = mod_workshop_external::get_assessment($assessmentid);
1188 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1189 $this->assertEquals($assessmentid, $result['assessment']['id']);
1190 $this->assertEquals(90, $result['assessment']['grade']);
1191 // I can't see the reviewer review.
1192 $this->assertFalse(isset($result['assessment']['feedbackreviewer']));
1193 }
1194
1195 /**
1196 * Test get_assessment_reviewer.
1197 */
1198 public function test_get_assessment_reviewer() {
1199 global $DB;
1200
1201 // Create the submission.
1202 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1203
1204 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1205 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1206 'weight' => 2,
1207 'grade' => 90,
1208 ));
1209
1210 // Switch to closed phase.
1211 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1212 $this->setUser($this->student);
1213 $result = mod_workshop_external::get_assessment($assessmentid);
1214 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1215 $this->assertEquals($assessmentid, $result['assessment']['id']);
1216 $this->assertEquals(90, $result['assessment']['grade']);
1217 // I can see the reviewer review.
1218 $this->assertTrue(isset($result['assessment']['feedbackreviewer']));
1219 }
1220
1221 /**
1222 * Test get_assessment_teacher.
1223 */
1224 public function test_get_assessment_teacher() {
1225 global $DB;
1226
1227 // Create the submission.
1228 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1229
1230 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1231 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1232 'weight' => 2,
1233 'grade' => 90,
1234 ));
1235
1236 // Switch to closed phase.
1237 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1238 $this->setUser($this->teacher);
1239 $result = mod_workshop_external::get_assessment($assessmentid);
1240 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1241 $this->assertEquals($assessmentid, $result['assessment']['id']);
1242 $this->assertEquals(90, $result['assessment']['grade']);
1243 }
1244
1245 /**
1246 * Test get_assessment_student_invalid_phase.
1247 */
1248 public function test_get_assessment_student_invalid_phase() {
1249 global $DB;
1250
1251 // Create the submission.
1252 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1253
1254 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1255 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1256 'weight' => 2,
1257 'grade' => 90,
1258 ));
1259
1260 // Switch to closed phase.
1261 $this->setUser($this->anotherstudentg1);
1262
1263 $this->setExpectedException('moodle_exception');
1264 mod_workshop_external::get_assessment($assessmentid);
1265 }
1266
1267 /**
1268 * Test get_assessment_student_invalid_user.
1269 */
1270 public function test_get_assessment_student_invalid_user() {
1271 global $DB;
1272
1273 // Create the submission.
1274 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1275
1276 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1277 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1278 'weight' => 2,
1279 'grade' => 90,
1280 ));
1281
1282 // Switch to closed phase.
1283 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1284 $this->setUser($this->anotherstudentg2);
1285
1286 $this->setExpectedException('moodle_exception');
1287 mod_workshop_external::get_assessment($assessmentid);
1288 }
46f5e9a0
JL
1289
1290 /**
1291 * Test get_assessment_form_definition_reviewer_new_assessment.
1292 */
1293 public function test_get_assessment_form_definition_reviewer_new_assessment() {
1294 global $DB;
1295
1296 // Create the submission.
1297 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1298
1299 $workshop = new workshop($this->workshop, $this->cm, $this->course);
1300 $submission = $workshop->get_submission_by_id($submissionid);
1301 $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1302
1303 // Switch to assessment phase.
1304 $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1305 $this->setUser($this->student);
1306 $result = mod_workshop_external::get_assessment_form_definition($assessmentid);
1307 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);
1308 $this->assertEquals(4, $result['dimenssionscount']); // We receive the expected 4 dimensions.
1309 $this->assertEmpty($result['current']); // Assessment not yet done.
1310 foreach ($result['fields'] as $field) {
1311 if (strpos($field['name'], 'grade__idx_') === 0) {
1312 $this->assertEquals(25, $field['value']); // Check one of the dimension fields attributes.
1313 }
1314 }
1315 }
1316
1317 /**
1318 * Test get_assessment_form_definition_teacher_new_assessment.
1319 */
1320 public function test_get_assessment_form_definition_teacher_new_assessment() {
1321 global $DB;
1322
1323 // Create the submission.
1324 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1325
1326 $workshop = new workshop($this->workshop, $this->cm, $this->course);
1327 $submission = $workshop->get_submission_by_id($submissionid);
1328 $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1329
1330 // Switch to assessment phase.
1331 $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1332 $this->setUser($this->teacher);
1333 $this->setExpectedException('moodle_exception');
1334 mod_workshop_external::get_assessment_form_definition($assessmentid); // Teachers can't add/edit assessments.
1335 }
1336
1337 /**
1338 * Test get_assessment_form_definition_invalid_phase.
1339 */
1340 public function test_get_assessment_form_definition_invalid_phase() {
1341 global $DB;
1342
1343 // Create the submission.
1344 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1345
1346 $workshop = new workshop($this->workshop, $this->cm, $this->course);
1347 $submission = $workshop->get_submission_by_id($submissionid);
1348 $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1349
1350 $this->setUser($this->student);
1351 $this->setExpectedException('moodle_exception');
1352 mod_workshop_external::get_assessment_form_definition($assessmentid);
1353 }
aac70425
JL
1354
1355 /**
1356 * Test get_reviewer_assessments.
1357 */
1358 public function test_get_reviewer_assessments() {
1359 global $DB;
1360
1361 // Create the submission.
1362 $submissionid1 = $this->create_test_submission($this->student);
1363 $submissionid2 = $this->create_test_submission($this->anotherstudentg1);
1364
1365 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1366 $assessmentid1 = $workshopgenerator->create_assessment($submissionid1, $this->student->id, array(
1367 'weight' => 2,
1368 'grade' => 90,
1369 ));
1370 $assessmentid2 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array(
1371 'weight' => 3,
1372 'grade' => 80,
1373 ));
1374
1375 // Switch to assessment phase.
1376 $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1377 $this->setUser($this->student);
1378 // Get my assessments.
1379 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id);
1380 $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);
1381 $this->assertCount(2, $result['assessments']);
1382 foreach ($result['assessments'] as $assessment) {
1383 if ($assessment['id'] == $assessmentid1) {
1384 $this->assertEquals(90, $assessment['grade']);
1385 } else {
1386 $this->assertEquals($assessmentid2, $assessment['id']);
1387 $this->assertEquals(80, $assessment['grade']);
1388 }
1389 }
1390
1391 // Now, as teacher try to get the same student assessments.
1392 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->student->id);
1393 $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);
1394 $this->assertCount(2, $result['assessments']);
1395 }
1396
1397 /**
1398 * Test get_reviewer_assessments_other_student.
1399 */
1400 public function test_get_reviewer_assessments_other_student() {
1401 global $DB;
1402
1403 $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1404 // Try to get other user assessments.
1405 $this->setUser($this->student);
1406 $this->setExpectedException('moodle_exception');
1407 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);
1408 }
1409
1410 /**
1411 * Test get_reviewer_assessments_invalid_phase.
1412 */
1413 public function test_get_reviewer_assessments_invalid_phase() {
1414 global $DB;
1415
1416 $DB->set_field('workshop', 'phase', workshop::PHASE_SUBMISSION, array('id' => $this->workshop->id));
1417 // Try to get other user assessments.
1418 $this->setUser($this->student);
1419 $this->setExpectedException('moodle_exception');
1420 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);
1421 }
fe966a27
JL
1422
1423 /**
1424 * Test update_assessment.
1425 */
1426 public function test_update_assessment() {
1427 global $DB;
1428
1429 // Create the submission.
1430 $submissionid = $this->create_test_submission($this->anotherstudentg1);
1431
1432 $workshop = new workshop($this->workshop, $this->cm, $this->course);
1433 $submission = $workshop->get_submission_by_id($submissionid);
1434 $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1435
1436 // Switch to assessment phase.
1437 $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1438 $this->setUser($this->student);
1439 // Get the form definition.
1440 $result = mod_workshop_external::get_assessment_form_definition($assessmentid);
1441 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);
1442
1443 // Prepare the data to be sent.
1444 $data = $result['fields'];
1445 foreach ($data as $key => $param) {
1446 if (strpos($param['name'], 'peercomment__idx_') === 0) {
1447 $data[$key]['value'] = 'Some content';
1448 } else if (strpos($param['name'], 'grade__idx_') === 0) {
1449 $data[$key]['value'] = 25; // Set all to 25.
1450 }
1451 }
1452
1453 // Required data.
1454 $data[] = array(
1455 'name' => 'nodims',
1456 'value' => $result['dimenssionscount'],
1457 );
1458
1459 // General feedback.
1460 $data[] = array(
1461 'name' => 'feedbackauthor',
1462 'value' => 'Feedback for the author',
1463 );
1464 $data[] = array(
1465 'name' => 'feedbackauthorformat',
1466 'value' => FORMAT_MOODLE,
1467 );
1468
1469 // Create a file in a draft area for inline attachments.
1470 $fs = get_file_storage();
1471 $draftidinlineattach = file_get_unused_draft_itemid();
1472 $usercontext = context_user::instance($this->student->id);
1473 $filenameimg = 'shouldbeanimage.txt';
1474 $filerecordinline = array(
1475 'contextid' => $usercontext->id,
1476 'component' => 'user',
1477 'filearea' => 'draft',
1478 'itemid' => $draftidinlineattach,
1479 'filepath' => '/',
1480 'filename' => $filenameimg,
1481 );
1482 $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
1483
1484 // Create a file in a draft area for regular attachments.
1485 $draftidattach = file_get_unused_draft_itemid();
1486 $filerecordattach = $filerecordinline;
1487 $attachfilename = 'attachment.txt';
1488 $filerecordattach['filename'] = $attachfilename;
1489 $filerecordattach['itemid'] = $draftidattach;
1490 $fs->create_file_from_string($filerecordattach, 'simple text attachment');
1491
1492 $data[] = array(
1493 'name' => 'feedbackauthorinlineattachmentsid',
1494 'value' => $draftidinlineattach,
1495 );
1496 $data[] = array(
1497 'name' => 'feedbackauthorattachmentsid',
1498 'value' => $draftidattach,
1499 );
1500
1501 // Update the assessment.
1502 $result = mod_workshop_external::update_assessment($assessmentid, $data);
1503 $result = external_api::clean_returnvalue(mod_workshop_external::update_assessment_returns(), $result);
1504 $this->assertEquals(100, $result['rawgrade']);
1505 $this->assertTrue($result['status']);
1506
1507 // Get the assessment and check it was updated properly.
1508 $result = mod_workshop_external::get_assessment($assessmentid);
1509 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1510 $this->assertEquals(100, $result['assessment']['grade']);
1511 $this->assertEquals($this->student->id, $result['assessment']['reviewerid']);
1512 $this->assertEquals('Feedback for the author', $result['assessment']['feedbackauthor']);
1513 $this->assertCount(1, $result['assessment']['feedbackcontentfiles']);
1514 $this->assertCount(1, $result['assessment']['feedbackattachmentfiles']);
1515
1516 // Now, get again the form and check we received the data we already sent.
1517 $result = mod_workshop_external::get_assessment_form_definition($assessmentid);
1518 $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);
1519 foreach ($result['current'] as $currentdata) {
1520 if (strpos($currentdata['name'], 'peercomment__idx_') === 0) {
1521 $this->assertEquals('Some content', $currentdata['value']);
1522 } else if (strpos($currentdata['name'], 'grade__idx_') === 0) {
1523 $this->assertEquals(25, (int) $currentdata['value']);
1524 }
1525 }
1526 }
d769f871
JL
1527
1528 /**
1529 * Test get_grades.
1530 */
1531 public function test_get_grades() {
1532 global $DB;
1533
1534 $timenow = time();
1535 $submissiongrade = array(
1536 'userid' => $this->student->id,
1537 'rawgrade' => 40,
1538 'feedback' => '',
1539 'feedbackformat' => 1,
1540 'datesubmitted' => $timenow,
1541 'dategraded' => $timenow,
1542 );
1543 $assessmentgrade = array(
1544 'userid' => $this->student->id,
1545 'rawgrade' => 10,
1546 'feedback' => '',
1547 'feedbackformat' => 1,
1548 'datesubmitted' => $timenow,
1549 'dategraded' => $timenow,
1550 );
1551
1552 workshop_grade_item_update($this->workshop, (object) $submissiongrade, (object) $assessmentgrade);
1553
1554 // First retrieve my grades.
1555 $this->setUser($this->student);
1556 $result = mod_workshop_external::get_grades($this->workshop->id);
1557 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result);
1558 $this->assertCount(0, $result['warnings']);
1559 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']);
1560 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']);
1561 $this->assertFalse($result['assessmentgradehidden']);
1562 $this->assertFalse($result['submissiongradehidden']);
1563 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']);
1564 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']);
1565
1566 // Second, teacher retrieve user grades.
1567 $this->setUser($this->teacher);
1568 $result = mod_workshop_external::get_grades($this->workshop->id, $this->student->id);
1569 $result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result);
1570 $this->assertCount(0, $result['warnings']);
1571 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']);
1572 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']);
1573 $this->assertFalse($result['assessmentgradehidden']);
1574 $this->assertFalse($result['submissiongradehidden']);
1575 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']);
1576 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']);
1577 }
1578
1579 /**
1580 * Test get_grades_other_student.
1581 */
1582 public function test_get_grades_other_student() {
1583 global $DB;
1584
1585 // Create the submission that will be deleted.
1586 $submissionid = $this->create_test_submission($this->student);
1587
1588 $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1589 $this->setUser($this->anotherstudentg1);
1590 $this->expectException('moodle_exception');
1591 mod_workshop_external::get_grades($this->workshop->id, $this->student->id);
1592 }
9f1ab2db 1593}