Merge branch 'MDL-59401-master' of git://github.com/jleyva/moodle
[moodle.git] / mod / workshop / tests / external_test.php
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/>.
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  */
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
31 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32 require_once($CFG->dirroot . '/mod/workshop/lib.php');
34 use mod_workshop\external\workshop_summary_exporter;
35 use mod_workshop\external\submission_exporter;
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  */
46 class mod_workshop_external_testcase extends externallib_advanced_testcase {
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;
65     /**
66      * Set up for every test
67      */
68     public function setUp() {
69         global $DB;
70         $this->resetAfterTest();
71         $this->setAdminUser();
73         // Setup test data.
74         $course = new stdClass();
75         $course->groupmode = SEPARATEGROUPS;
76         $course->groupmodeforce = true;
77         $this->course = $this->getDataGenerator()->create_course($course);
78         $this->workshop = $this->getDataGenerator()->create_module('workshop', array('course' => $this->course->id));
79         $this->context = context_module::instance($this->workshop->cmid);
80         $this->cm = get_coursemodule_from_instance('workshop', $this->workshop->id);
82         // Add grading strategy data (accumulative is the default).
83         $workshop = new workshop($this->workshop, $this->cm, $this->course);
84         $strategy = $workshop->grading_strategy_instance();
85         $data = array();
86         for ($i = 0; $i < 4; $i++) {
87             $data['dimensionid__idx_'.$i] = 0;
88             $data['description__idx_'.$i.'_editor'] = array('text' => "Content $i", 'format' => FORMAT_MOODLE);
89             $data['grade__idx_'.$i] = 25;
90             $data['weight__idx_'.$i] = 25;
91         }
92         $data['workshopid'] = $workshop->id;
93         $data['norepeats'] = 4;
94         $strategy->save_edit_strategy_form((object) $data);
96         // Create users.
97         $this->student = self::getDataGenerator()->create_user();
98         $this->anotherstudentg1 = self::getDataGenerator()->create_user();
99         $this->anotherstudentg2 = self::getDataGenerator()->create_user();
100         $this->teacher = self::getDataGenerator()->create_user();
102         // Users enrolments.
103         $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
104         $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
105         $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
106         $this->getDataGenerator()->enrol_user($this->anotherstudentg1->id, $this->course->id, $this->studentrole->id, 'manual');
107         $this->getDataGenerator()->enrol_user($this->anotherstudentg2->id, $this->course->id, $this->studentrole->id, 'manual');
108         $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
110         $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
111         $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
112         groups_add_member($this->group1, $this->student);
113         groups_add_member($this->group1, $this->anotherstudentg1);
114         groups_add_member($this->group2, $this->anotherstudentg2);
115     }
117     /**
118      * Test test_mod_workshop_get_workshops_by_courses
119      */
120     public function test_mod_workshop_get_workshops_by_courses() {
121         global $DB;
123         // Create additional course.
124         $course2 = self::getDataGenerator()->create_course();
126         // Second workshop.
127         $record = new stdClass();
128         $record->course = $course2->id;
129         $workshop2 = self::getDataGenerator()->create_module('workshop', $record);
131         // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
132         $enrol = enrol_get_plugin('manual');
133         $enrolinstances = enrol_get_instances($course2->id, true);
134         foreach ($enrolinstances as $courseenrolinstance) {
135             if ($courseenrolinstance->enrol == "manual") {
136                 $instance2 = $courseenrolinstance;
137                 break;
138             }
139         }
140         $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id);
142         self::setUser($this->student);
144         $returndescription = mod_workshop_external::get_workshops_by_courses_returns();
146         // Create what we expect to be returned when querying the two courses.
147         $properties = workshop_summary_exporter::read_properties_definition();
148         $expectedfields = array_keys($properties);
150         // Add expected coursemodule and data.
151         $workshop1 = $this->workshop;
152         $workshop1->coursemodule = $workshop1->cmid;
153         $workshop1->introformat = 1;
154         $workshop1->introfiles = [];
155         $workshop1->instructauthorsfiles = [];
156         $workshop1->instructauthorsformat = 1;
157         $workshop1->instructreviewersfiles = [];
158         $workshop1->instructreviewersformat = 1;
159         $workshop1->conclusionfiles = [];
160         $workshop1->conclusionformat = 1;
162         $workshop2->coursemodule = $workshop2->cmid;
163         $workshop2->introformat = 1;
164         $workshop2->introfiles = [];
165         $workshop2->instructauthorsfiles = [];
166         $workshop2->instructauthorsformat = 1;
167         $workshop2->instructreviewersfiles = [];
168         $workshop2->instructreviewersformat = 1;
169         $workshop2->conclusionfiles = [];
170         $workshop2->conclusionformat = 1;
172         foreach ($expectedfields as $field) {
173             if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) {
174                 $workshop1->{$field} = (bool) $workshop1->{$field};
175                 $workshop2->{$field} = (bool) $workshop2->{$field};
176             }
177             $expected1[$field] = $workshop1->{$field};
178             $expected2[$field] = $workshop2->{$field};
179         }
181         $expectedworkshops = array($expected2, $expected1);
183         // Call the external function passing course ids.
184         $result = mod_workshop_external::get_workshops_by_courses(array($course2->id, $this->course->id));
185         $result = external_api::clean_returnvalue($returndescription, $result);
187         $this->assertEquals($expectedworkshops, $result['workshops']);
188         $this->assertCount(0, $result['warnings']);
190         // Call the external function without passing course id.
191         $result = mod_workshop_external::get_workshops_by_courses();
192         $result = external_api::clean_returnvalue($returndescription, $result);
193         $this->assertEquals($expectedworkshops, $result['workshops']);
194         $this->assertCount(0, $result['warnings']);
196         // Unenrol user from second course and alter expected workshops.
197         $enrol->unenrol_user($instance2, $this->student->id);
198         array_shift($expectedworkshops);
200         // Call the external function without passing course id.
201         $result = mod_workshop_external::get_workshops_by_courses();
202         $result = external_api::clean_returnvalue($returndescription, $result);
203         $this->assertEquals($expectedworkshops, $result['workshops']);
205         // Call for the second course we unenrolled the user from, expected warning.
206         $result = mod_workshop_external::get_workshops_by_courses(array($course2->id));
207         $this->assertCount(1, $result['warnings']);
208         $this->assertEquals('1', $result['warnings'][0]['warningcode']);
209         $this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
210     }
212     /**
213      * Test mod_workshop_get_workshop_access_information for students.
214      */
215     public function test_mod_workshop_get_workshop_access_information_student() {
217         self::setUser($this->student);
218         $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
219         $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
220         // Check default values for capabilities.
221         $enabledcaps = array('canpeerassess', 'cansubmit', 'canview', 'canviewauthornames', 'canviewauthorpublished',
222             'canviewpublishedsubmissions', 'canexportsubmissions');
224         foreach ($result as $capname => $capvalue) {
225             if (strpos($capname, 'can') !== 0) {
226                 continue;
227             }
228             if (in_array($capname, $enabledcaps)) {
229                 $this->assertTrue($capvalue);
230             } else {
231                 $this->assertFalse($capvalue);
232             }
233         }
234         // Now, unassign some capabilities.
235         unassign_capability('mod/workshop:peerassess', $this->studentrole->id);
236         unassign_capability('mod/workshop:submit', $this->studentrole->id);
237         unset($enabledcaps[0]);
238         unset($enabledcaps[1]);
239         accesslib_clear_all_caches_for_unit_testing();
241         $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
242         $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
243         foreach ($result as $capname => $capvalue) {
244             if (strpos($capname, 'can') !== 0) {
245                 continue;
246             }
247             if (in_array($capname, $enabledcaps)) {
248                 $this->assertTrue($capvalue);
249             } else {
250                 $this->assertFalse($capvalue);
251             }
252         }
254         // Now, specific functionalities.
255         $this->assertFalse($result['creatingsubmissionallowed']);
256         $this->assertFalse($result['modifyingsubmissionallowed']);
257         $this->assertFalse($result['assessingallowed']);
258         $this->assertFalse($result['assessingexamplesallowed']);
259         $this->assertTrue($result['examplesassessedbeforesubmission']);
260         $this->assertTrue($result['examplesassessedbeforeassessment']);
262         // Switch phase.
263         $workshop = new workshop($this->workshop, $this->cm, $this->course);
264         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
265         $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
266         $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
268         $this->assertTrue($result['creatingsubmissionallowed']);
269         $this->assertTrue($result['modifyingsubmissionallowed']);
270         $this->assertFalse($result['assessingallowed']);
271         $this->assertFalse($result['assessingexamplesallowed']);
272         $this->assertTrue($result['examplesassessedbeforesubmission']);
273         $this->assertTrue($result['examplesassessedbeforeassessment']);
275         // Switch to next (to assessment).
276         $workshop = new workshop($this->workshop, $this->cm, $this->course);
277         $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
278         $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
279         $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
281         $this->assertFalse($result['creatingsubmissionallowed']);
282         $this->assertFalse($result['modifyingsubmissionallowed']);
283         $this->assertTrue($result['assessingallowed']);
284         $this->assertFalse($result['assessingexamplesallowed']);
285         $this->assertTrue($result['examplesassessedbeforesubmission']);
286         $this->assertTrue($result['examplesassessedbeforeassessment']);
287     }
289     /**
290      * Test mod_workshop_get_workshop_access_information for teachers.
291      */
292     public function test_mod_workshop_get_workshop_access_information_teacher() {
294         self::setUser($this->teacher);
295         $result = mod_workshop_external::get_workshop_access_information($this->workshop->id);
296         $result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);
297         // Check default values.
298         $disabledcaps = array('canpeerassess', 'cansubmit');
300         foreach ($result as $capname => $capvalue) {
301             if (strpos($capname, 'can') !== 0) {
302                 continue;
303             }
304             if (in_array($capname, $disabledcaps)) {
305                 $this->assertFalse($capvalue);
306             } else {
307                 $this->assertTrue($capvalue);
308             }
309         }
311         // Now, specific functionalities.
312         $this->assertFalse($result['creatingsubmissionallowed']);
313         $this->assertFalse($result['modifyingsubmissionallowed']);
314         $this->assertFalse($result['assessingallowed']);
315         $this->assertFalse($result['assessingexamplesallowed']);
316     }
318     /**
319      * Test mod_workshop_get_user_plan for students.
320      */
321     public function test_mod_workshop_get_user_plan_student() {
323         self::setUser($this->student);
324         $result = mod_workshop_external::get_user_plan($this->workshop->id);
325         $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
327         $this->assertCount(0, $result['userplan']['examples']);  // No examples given.
328         $this->assertCount(5, $result['userplan']['phases']);  // Always 5 phases.
329         $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']);  // First phase always setup.
330         $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
332         // Switch phase.
333         $workshop = new workshop($this->workshop, $this->cm, $this->course);
334         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
336         $result = mod_workshop_external::get_user_plan($this->workshop->id);
337         $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
339         $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
340         $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
341     }
343     /**
344      * Test mod_workshop_get_user_plan for teachers.
345      */
346     public function test_mod_workshop_get_user_plan_teacher() {
347         global $DB;
349         self::setUser($this->teacher);
350         $result = mod_workshop_external::get_user_plan($this->workshop->id);
351         $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
353         $this->assertCount(0, $result['userplan']['examples']);  // No examples given.
354         $this->assertCount(5, $result['userplan']['phases']);  // Always 5 phases.
355         $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']);  // First phase always setup.
356         $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
357         $this->assertCount(4, $result['userplan']['phases'][0]['tasks']);  // For new empty workshops, always 4 tasks.
359         foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
360             if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform') {
361                 $this->assertEquals(1, $task['completed']);
362             } else {
363                 $this->assertEmpty($task['completed']);
364             }
365         }
367         // Do some of the tasks asked - switch phase.
368         $workshop = new workshop($this->workshop, $this->cm, $this->course);
369         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
371         $result = mod_workshop_external::get_user_plan($this->workshop->id);
372         $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
373         foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
374             if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform' ||
375                     $task['code'] == 'switchtonextphase') {
376                 $this->assertEquals(1, $task['completed']);
377             } else {
378                 $this->assertEmpty($task['completed']);
379             }
380         }
382         $result = mod_workshop_external::get_user_plan($this->workshop->id);
383         $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
385         $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
386         $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
387     }
389     /**
390      * Test test_view_workshop invalid id.
391      */
392     public function test_view_workshop_invalid_id() {
393         $this->expectException('moodle_exception');
394         mod_workshop_external::view_workshop(0);
395     }
397     /**
398      * Test test_view_workshop user not enrolled.
399      */
400     public function test_view_workshop_user_not_enrolled() {
401         // Test not-enrolled user.
402         $usernotenrolled = self::getDataGenerator()->create_user();
403         $this->setUser($usernotenrolled);
404         $this->expectException('moodle_exception');
405         mod_workshop_external::view_workshop($this->workshop->id);
406     }
408     /**
409      * Test test_view_workshop user student.
410      */
411     public function test_view_workshop_user_student() {
412         // Test user with full capabilities.
413         $this->setUser($this->student);
415         // Trigger and capture the event.
416         $sink = $this->redirectEvents();
418         $result = mod_workshop_external::view_workshop($this->workshop->id);
419         $result = external_api::clean_returnvalue(mod_workshop_external::view_workshop_returns(), $result);
420         $this->assertTrue($result['status']);
422         $events = $sink->get_events();
423         $this->assertCount(1, $events);
424         $event = array_shift($events);
426         // Checking that the event contains the expected values.
427         $this->assertInstanceOf('\mod_workshop\event\course_module_viewed', $event);
428         $this->assertEquals($this->context, $event->get_context());
429         $moodleworkshop = new \moodle_url('/mod/workshop/view.php', array('id' => $this->cm->id));
430         $this->assertEquals($moodleworkshop, $event->get_url());
431         $this->assertEventContextNotUsed($event);
432         $this->assertNotEmpty($event->get_name());
433     }
435     /**
436      * Test test_view_workshop user missing capabilities.
437      */
438     public function test_view_workshop_user_missing_capabilities() {
439         // Test user with no capabilities.
440         // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
441         assign_capability('mod/workshop:view', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
442         // Empty all the caches that may be affected  by this change.
443         accesslib_clear_all_caches_for_unit_testing();
444         course_modinfo::clear_instance_cache();
446         $this->setUser($this->student);
447         $this->expectException('moodle_exception');
448         mod_workshop_external::view_workshop($this->workshop->id);
449     }
451     /**
452      * Test test_add_submission.
453      */
454     public function test_add_submission() {
455         $fs = get_file_storage();
457         // Test user with full capabilities.
458         $this->setUser($this->student);
460         $title = 'Submission title';
461         $content = 'Submission contents';
463         // Create a file in a draft area for inline attachments.
464         $draftidinlineattach = file_get_unused_draft_itemid();
465         $usercontext = context_user::instance($this->student->id);
466         $filenameimg = 'shouldbeanimage.txt';
467         $filerecordinline = array(
468             'contextid' => $usercontext->id,
469             'component' => 'user',
470             'filearea'  => 'draft',
471             'itemid'    => $draftidinlineattach,
472             'filepath'  => '/',
473             'filename'  => $filenameimg,
474         );
475         $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
477         // Create a file in a draft area for regular attachments.
478         $draftidattach = file_get_unused_draft_itemid();
479         $filerecordattach = $filerecordinline;
480         $attachfilename = 'attachment.txt';
481         $filerecordattach['filename'] = $attachfilename;
482         $filerecordattach['itemid'] = $draftidattach;
483         $fs->create_file_from_string($filerecordattach, 'simple text attachment');
485         // Switch to submission phase.
486         $workshop = new workshop($this->workshop, $this->cm, $this->course);
487         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
489         $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
490             $draftidattach);
491         $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
492         $this->assertEmpty($result['warnings']);
494         // Check submission created.
495         $submission = $workshop->get_submission_by_author($this->student->id);
496         $this->assertTrue($result['status']);
497         $this->assertEquals($result['submissionid'], $submission->id);
498         $this->assertEquals($title, $submission->title);
499         $this->assertEquals($content, $submission->content);
501         // Check files.
502         $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);
503         $this->assertCount(2, $contentfiles);
504         foreach ($contentfiles as $file) {
505             if ($file->is_directory()) {
506                 continue;
507             } else {
508                 $this->assertEquals($filenameimg, $file->get_filename());
509             }
510         }
511         $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);
512         $this->assertCount(2, $contentfiles);
513         foreach ($contentfiles as $file) {
514             if ($file->is_directory()) {
515                 continue;
516             } else {
517                 $this->assertEquals($attachfilename, $file->get_filename());
518             }
519         }
520     }
522     /**
523      * Test test_add_submission invalid phase.
524      */
525     public function test_add_submission_invalid_phase() {
526         $this->setUser($this->student);
528         $this->expectException('moodle_exception');
529         mod_workshop_external::add_submission($this->workshop->id, 'Test');
530     }
532     /**
533      * Test test_add_submission empty title.
534      */
535     public function test_add_submission_empty_title() {
536         $this->setUser($this->student);
538         // Switch to submission phase.
539         $workshop = new workshop($this->workshop, $this->cm, $this->course);
540         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
542         $this->expectException('moodle_exception');
543         mod_workshop_external::add_submission($this->workshop->id, '');
544     }
546     /**
547      * Test test_add_submission already added.
548      */
549     public function test_add_submission_already_added() {
550         $this->setUser($this->student);
552         // Switch to submission phase.
553         $workshop = new workshop($this->workshop, $this->cm, $this->course);
554         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
556         // Create the submission.
557         $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission');
558         $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
560         // Try to create it again.
561         $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission');
562         $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);
563         $this->assertFalse($result['status']);
564         $this->assertArrayNotHasKey('submissionid', $result);
565         $this->assertCount(2, $result['warnings']);
566         $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']);
567         $this->assertEquals('content_editor', $result['warnings'][0]['item']);
568         $this->assertEquals('fielderror', $result['warnings'][1]['warningcode']);
569         $this->assertEquals('attachment_filemanager', $result['warnings'][1]['item']);
570     }
572     /**
573      * Helper method to create a submission for testing for the given user.
574      *
575      * @param int $user the submission will be created by this student.
576      * @return int the submission id
577      */
578     protected function create_test_submission($user) {
579         // Test user with full capabilities.
580         $this->setUser($user);
582         $title = 'Submission title';
583         $content = 'Submission contents';
585         // Create a file in a draft area for inline attachments.
586         $fs = get_file_storage();
587         $draftidinlineattach = file_get_unused_draft_itemid();
588         $usercontext = context_user::instance($this->student->id);
589         $filenameimg = 'shouldbeanimage.txt';
590         $filerecordinline = array(
591             'contextid' => $usercontext->id,
592             'component' => 'user',
593             'filearea'  => 'draft',
594             'itemid'    => $draftidinlineattach,
595             'filepath'  => '/',
596             'filename'  => $filenameimg,
597         );
598         $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
600         // Create a file in a draft area for regular attachments.
601         $draftidattach = file_get_unused_draft_itemid();
602         $filerecordattach = $filerecordinline;
603         $attachfilename = 'attachment.txt';
604         $filerecordattach['filename'] = $attachfilename;
605         $filerecordattach['itemid'] = $draftidattach;
606         $fs->create_file_from_string($filerecordattach, 'simple text attachment');
608         // Switch to submission phase.
609         $workshop = new workshop($this->workshop, $this->cm, $this->course);
610         $workshop->switch_phase(workshop::PHASE_SUBMISSION);
612         $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
613             $draftidattach);
614         return $result['submissionid'];
615     }
617     /**
618      * Test test_update_submission.
619      */
620     public function test_update_submission() {
622         // Create the submission that will be updated.
623         $submissionid = $this->create_test_submission($this->student);
625         // Test user with full capabilities.
626         $this->setUser($this->student);
628         $title = 'Submission new title';
629         $content = 'Submission new contents';
631         // Create a different file in a draft area for inline attachments.
632         $fs = get_file_storage();
633         $draftidinlineattach = file_get_unused_draft_itemid();
634         $usercontext = context_user::instance($this->student->id);
635         $filenameimg = 'shouldbeanimage_new.txt';
636         $filerecordinline = array(
637             'contextid' => $usercontext->id,
638             'component' => 'user',
639             'filearea'  => 'draft',
640             'itemid'    => $draftidinlineattach,
641             'filepath'  => '/',
642             'filename'  => $filenameimg,
643         );
644         $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
646         // Create a different file in a draft area for regular attachments.
647         $draftidattach = file_get_unused_draft_itemid();
648         $filerecordattach = $filerecordinline;
649         $attachfilename = 'attachment_new.txt';
650         $filerecordattach['filename'] = $attachfilename;
651         $filerecordattach['itemid'] = $draftidattach;
652         $fs->create_file_from_string($filerecordattach, 'simple text attachment');
654         $result = mod_workshop_external::update_submission($submissionid, $title, $content, FORMAT_MOODLE, $draftidinlineattach,
655             $draftidattach);
656         $result = external_api::clean_returnvalue(mod_workshop_external::update_submission_returns(), $result);
657         $this->assertEmpty($result['warnings']);
659         // Check submission updated.
660         $workshop = new workshop($this->workshop, $this->cm, $this->course);
661         $submission = $workshop->get_submission_by_id($submissionid);
662         $this->assertTrue($result['status']);
663         $this->assertEquals($title, $submission->title);
664         $this->assertEquals($content, $submission->content);
666         // Check files.
667         $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);
668         $this->assertCount(2, $contentfiles);
669         foreach ($contentfiles as $file) {
670             if ($file->is_directory()) {
671                 continue;
672             } else {
673                 $this->assertEquals($filenameimg, $file->get_filename());
674             }
675         }
676         $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);
677         $this->assertCount(2, $contentfiles);
678         foreach ($contentfiles as $file) {
679             if ($file->is_directory()) {
680                 continue;
681             } else {
682                 $this->assertEquals($attachfilename, $file->get_filename());
683             }
684         }
685     }
687     /**
688      * Test test_update_submission belonging to other user.
689      */
690     public function test_update_submission_of_other_user() {
691         // Create the submission that will be updated.
692         $submissionid = $this->create_test_submission($this->student);
694         $this->setUser($this->teacher);
696         $this->expectException('moodle_exception');
697         mod_workshop_external::update_submission($submissionid, 'Test');
698     }
700     /**
701      * Test test_update_submission invalid phase.
702      */
703     public function test_update_submission_invalid_phase() {
704         // Create the submission that will be updated.
705         $submissionid = $this->create_test_submission($this->student);
707         $this->setUser($this->student);
709         // Switch to assessment phase.
710         $workshop = new workshop($this->workshop, $this->cm, $this->course);
711         $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
713         $this->expectException('moodle_exception');
714         mod_workshop_external::update_submission($submissionid, 'Test');
715     }
717     /**
718      * Test test_update_submission empty title.
719      */
720     public function test_update_submission_empty_title() {
721         // Create the submission that will be updated.
722         $submissionid = $this->create_test_submission($this->student);
724         $this->setUser($this->student);
726         $this->expectException('moodle_exception');
727         mod_workshop_external::update_submission($submissionid, '');
728     }
730     /**
731      * Test test_delete_submission.
732      */
733     public function test_delete_submission() {
735         // Create the submission that will be deleted.
736         $submissionid = $this->create_test_submission($this->student);
738         $this->setUser($this->student);
740         // Trigger and capture the event.
741         $sink = $this->redirectEvents();
743         $result = mod_workshop_external::delete_submission($submissionid);
744         $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);
745         $this->assertEmpty($result['warnings']);
746         $this->assertTrue($result['status']);
747         $workshop = new workshop($this->workshop, $this->cm, $this->course);
748         $submission = $workshop->get_submission_by_author($this->student->id);
749         $this->assertFalse($submission);
751         $events = $sink->get_events();
752         $this->assertCount(1, $events);
753         $event = array_shift($events);
755         // Checking event.
756         $this->assertInstanceOf('\mod_workshop\event\submission_deleted', $event);
757         $this->assertEquals($this->context, $event->get_context());
758     }
760     /**
761      * Test test_delete_submission_with_assessments.
762      */
763     public function test_delete_submission_with_assessments() {
765         // Create the submission that will be deleted.
766         $submissionid = $this->create_test_submission($this->student);
768         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
769         $workshopgenerator->create_assessment($submissionid, $this->teacher->id, array(
770             'weight' => 3,
771             'grade' => 95.00000,
772         ));
774         $this->setUser($this->student);
775         $this->expectException('moodle_exception');
776         mod_workshop_external::delete_submission($submissionid);
777     }
779     /**
780      * Test test_delete_submission_invalid_phase.
781      */
782     public function test_delete_submission_invalid_phase() {
784         // Create the submission that will be deleted.
785         $submissionid = $this->create_test_submission($this->student);
787         // Switch to assessment phase.
788         $workshop = new workshop($this->workshop, $this->cm, $this->course);
789         $workshop->switch_phase(workshop::PHASE_ASSESSMENT);
791         $this->setUser($this->student);
792         $this->expectException('moodle_exception');
793         mod_workshop_external::delete_submission($submissionid);
794     }
796     /**
797      * Test test_delete_submission_as_teacher.
798      */
799     public function test_delete_submission_as_teacher() {
801         // Create the submission that will be deleted.
802         $submissionid = $this->create_test_submission($this->student);
804         $this->setUser($this->teacher);
805         $result = mod_workshop_external::delete_submission($submissionid);
806         $result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);
807         $this->assertEmpty($result['warnings']);
808         $this->assertTrue($result['status']);
809     }
811     /**
812      * Test test_delete_submission_other_user.
813      */
814     public function test_delete_submission_other_user() {
816         $anotheruser = self::getDataGenerator()->create_user();
817         $this->getDataGenerator()->enrol_user($anotheruser->id, $this->course->id, $this->studentrole->id, 'manual');
818         // Create the submission that will be deleted.
819         $submissionid = $this->create_test_submission($this->student);
821         $this->setUser($anotheruser);
822         $this->expectException('moodle_exception');
823         mod_workshop_external::delete_submission($submissionid);
824     }
826     /**
827      * Test test_get_submissions_student.
828      */
829     public function test_get_submissions_student() {
831         // Create a couple of submissions with files.
832         $firstsubmissionid = $this->create_test_submission($this->student);  // Create submission with files.
833         $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1->id);
835         $this->setUser($this->student);
836         $result = mod_workshop_external::get_submissions($this->workshop->id);
837         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
838         // We should get just our submission.
839         $this->assertCount(1, $result['submissions']);
840         $this->assertEquals(1, $result['totalcount']);
841         $this->assertEquals($firstsubmissionid, $result['submissions'][0]['id']);
842         $this->assertCount(1, $result['submissions'][0]['contentfiles']); // Check we retrieve submission text files.
843         $this->assertCount(1, $result['submissions'][0]['attachmentfiles']); // Check we retrieve attachment files.
844         // We shoul not see the grade or feedback information.
845         $properties = submission_exporter::properties_definition();
846         foreach ($properties as $attribute => $settings) {
847             if (!empty($settings['optional'])) {
848                 if (isset($result['submissions'][0][$attribute])) {
849                     echo "error $attribute";
850                 }
851                 $this->assertFalse(isset($result['submissions'][0][$attribute]));
852             }
853         }
854     }
856     /**
857      * Test test_get_submissions_published_student.
858      */
859     public function test_get_submissions_published_student() {
860         global $DB;
862         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
863         // Create a couple of submissions with files.
864         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
865         $submission = array('published' => 1);
866         $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);
868         $this->setUser($this->student);
869         $result = mod_workshop_external::get_submissions($this->workshop->id);
870         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
871         // We should get just our submission.
872         $this->assertCount(1, $result['submissions']);
873         $this->assertEquals(1, $result['totalcount']);
874         $this->assertEquals($submissionid, $result['submissions'][0]['id']);
876         // Check with group restrictions.
877         $this->setUser($this->anotherstudentg2);
878         $result = mod_workshop_external::get_submissions($this->workshop->id);
879         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
880         $this->assertCount(0, $result['submissions']);  // I can't see other users in separated groups.
881         $this->assertEquals(0, $result['totalcount']);
882     }
884     /**
885      * Test test_get_submissions_from_student_with_feedback_from_teacher.
886      */
887     public function test_get_submissions_from_student_with_feedback_from_teacher() {
888         global $DB;
890         // Create a couple of submissions with files.
891         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
892         $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
893         // Create teacher feedback for submission.
894         $record = new stdclass();
895         $record->id = $submissionid;
896         $record->gradeover = 9;
897         $record->gradeoverby = $this->teacher->id;
898         $record->feedbackauthor = 'Hey';
899         $record->feedbackauthorformat = FORMAT_MOODLE;
900         $record->published = 1;
901         $DB->update_record('workshop_submissions', $record);
903         // Remove teacher caps.
904         assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id);
905         // Empty all the caches that may be affected  by this change.
906         accesslib_clear_all_caches_for_unit_testing();
907         course_modinfo::clear_instance_cache();
909         $this->setUser($this->teacher);
910         $result = mod_workshop_external::get_submissions($this->workshop->id, $this->student->id);
911         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
912         // We should get just our submission.
913         $this->assertEquals(1, $result['totalcount']);
914         $this->assertEquals($submissionid, $result['submissions'][0]['id']);
915     }
917     /**
918      * Test test_get_submissions_from_students_as_teacher.
919      */
920     public function test_get_submissions_from_students_as_teacher() {
921         global $DB;
923         // Create a couple of submissions with files.
924         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
925         $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
926         $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);
927         $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);
929         $this->setUser($this->teacher);
930         $result = mod_workshop_external::get_submissions($this->workshop->id); // Get all.
931         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
932         $this->assertEquals(3, $result['totalcount']);
933         $this->assertCount(3, $result['submissions']);
935         $result = mod_workshop_external::get_submissions($this->workshop->id, 0, 0, 0, 2); // Check pagination.
936         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
937         $this->assertEquals(3, $result['totalcount']);
938         $this->assertCount(2, $result['submissions']);
940         $result = mod_workshop_external::get_submissions($this->workshop->id, 0, $this->group2->id); // Get group 2.
941         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
942         $this->assertEquals(1, $result['totalcount']);
943         $this->assertCount(1, $result['submissions']);
944         $this->assertEquals($submissionid3, $result['submissions'][0]['id']);
946         $result = mod_workshop_external::get_submissions($this->workshop->id, $this->anotherstudentg1->id); // Get one.
947         $result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);
948         $this->assertEquals(1, $result['totalcount']);
949         $this->assertEquals($submissionid2, $result['submissions'][0]['id']);
950     }
952     /**
953      * Test test_get_submission_student.
954      */
955     public function test_get_submission_student() {
957         // Create a couple of submissions with files.
958         $firstsubmissionid = $this->create_test_submission($this->student);  // Create submission with files.
960         $this->setUser($this->student);
961         $result = mod_workshop_external::get_submission($firstsubmissionid);
962         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
963         $this->assertEquals($firstsubmissionid, $result['submission']['id']);
964         $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.
965         $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.
966     }
968     /**
969      * Test test_get_submission_i_reviewed.
970      */
971     public function test_get_submission_i_reviewed() {
973         // Create a couple of submissions with files.
974         $firstsubmissionid = $this->create_test_submission($this->student);  // Create submission with files.
975         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
976         $workshopgenerator->create_assessment($firstsubmissionid, $this->anotherstudentg1->id, array(
977             'weight' => 3,
978             'grade' => 95,
979         ));
980         // Now try to get the submission I just reviewed.
981         $this->setUser($this->anotherstudentg1);
982         $result = mod_workshop_external::get_submission($firstsubmissionid);
983         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
984         $this->assertEquals($firstsubmissionid, $result['submission']['id']);
985         $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.
986         $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.
987     }
989     /**
990      * Test test_get_submission_other_student.
991      */
992     public function test_get_submission_other_student() {
994         // Create a couple of submissions with files.
995         $firstsubmissionid = $this->create_test_submission($this->student);  // Create submission with files.
996         // Expect failure.
997         $this->setUser($this->anotherstudentg1);
998         $this->expectException('moodle_exception');
999         $result = mod_workshop_external::get_submission($firstsubmissionid);
1000     }
1002     /**
1003      * Test test_get_submission_published_student.
1004      */
1005     public function test_get_submission_published_student() {
1006         global $DB;
1008         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1009         // Create a couple of submissions with files.
1010         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1011         $submission = array('published' => 1);
1012         $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);
1014         $this->setUser($this->student);
1015         $result = mod_workshop_external::get_submission($submissionid);
1016         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1017         $this->assertEquals($submissionid, $result['submission']['id']);
1018         // Check that the student don't see the other student grade/feedback data even if is published.
1019         // We shoul not see the grade or feedback information.
1020         $properties = submission_exporter::properties_definition();
1021         foreach ($properties as $attribute => $settings) {
1022             if (!empty($settings['optional'])) {
1023                 if (isset($result['submission'][$attribute])) {
1024                     echo "error $attribute";
1025                 }
1026                 $this->assertFalse(isset($result['submission'][$attribute]));
1027             }
1028         }
1030         // Check with group restrictions.
1031         $this->setUser($this->anotherstudentg2);
1032         $this->expectException('moodle_exception');
1033         mod_workshop_external::get_submission($submissionid);
1034     }
1036     /**
1037      * Test test_get_submission_from_student_with_feedback_from_teacher.
1038      */
1039     public function test_get_submission_from_student_with_feedback_from_teacher() {
1040         global $DB;
1042         // Create a couple of submissions with files.
1043         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1044         $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
1045         // Create teacher feedback for submission.
1046         $record = new stdclass();
1047         $record->id = $submissionid;
1048         $record->gradeover = 9;
1049         $record->gradeoverby = $this->teacher->id;
1050         $record->feedbackauthor = 'Hey';
1051         $record->feedbackauthorformat = FORMAT_MOODLE;
1052         $record->published = 1;
1053         $DB->update_record('workshop_submissions', $record);
1055         // Remove teacher caps.
1056         assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id);
1057         // Empty all the caches that may be affected  by this change.
1058         accesslib_clear_all_caches_for_unit_testing();
1059         course_modinfo::clear_instance_cache();
1061         $this->setUser($this->teacher);
1062         $result = mod_workshop_external::get_submission($submissionid);
1063         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1064         $this->assertEquals($submissionid, $result['submission']['id']);
1065     }
1067     /**
1068      * Test test_get_submission_from_students_as_teacher.
1069      */
1070     public function test_get_submission_from_students_as_teacher() {
1071         // Create a couple of submissions with files.
1072         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1073         $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);
1074         $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);
1075         $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);
1077         $this->setUser($this->teacher);
1078         $result = mod_workshop_external::get_submission($submissionid1); // Get all.
1079         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1080         $this->assertEquals($submissionid1, $result['submission']['id']);
1082         $result = mod_workshop_external::get_submission($submissionid3); // Get group 2.
1083         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);
1084         $this->assertEquals($submissionid3, $result['submission']['id']);
1085     }
1088     /**
1089      * Test get_submission_assessments_student.
1090      */
1091     public function test_get_submission_assessments_student() {
1092         global $DB;
1094         // Create the submission that will be deleted.
1095         $submissionid = $this->create_test_submission($this->student);
1097         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1098         $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1099             'weight' => 3,
1100             'grade' => 95,
1101         ));
1102         $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1103             'weight' => 2,
1104             'grade' => 90,
1105         ));
1107         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1108         $this->setUser($this->student);
1109         $result = mod_workshop_external::get_submission_assessments($submissionid);
1110         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);
1111         $this->assertCount(2, $result['assessments']);  // I received my two assessments.
1112         foreach ($result['assessments'] as $assessment) {
1113             if ($assessment['grade'] == 90) {
1114                 // My own assessment, I can see me.
1115                 $this->assertEquals($this->student->id, $assessment['reviewerid']);
1116             } else {
1117                 // Student's can't see who did the review.
1118                 $this->assertEquals(0, $assessment['reviewerid']);
1119             }
1120         }
1121     }
1123     /**
1124      * Test get_submission_assessments_invalid_phase.
1125      */
1126     public function test_get_submission_assessments_invalid_phase() {
1127         global $DB;
1129         // Create the submission that will be deleted.
1130         $submissionid = $this->create_test_submission($this->student);
1132         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1133         $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1134             'weight' => 3,
1135             'grade' => 95,
1136         ));
1138         $this->expectException('moodle_exception');
1139         mod_workshop_external::get_submission_assessments($submissionid);
1140     }
1142     /**
1143      * Test get_submission_assessments_teacher.
1144      */
1145     public function test_get_submission_assessments_teacher() {
1147         // Create the submission that will be deleted.
1148         $submissionid = $this->create_test_submission($this->student);
1150         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1151         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array(
1152             'weight' => 1,
1153             'grade' => 50,
1154         ));
1156         $this->setUser($this->teacher);
1157         $result = mod_workshop_external::get_submission_assessments($submissionid);
1158         $result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);
1159         $this->assertCount(1, $result['assessments']);
1160         $this->assertEquals(50, $result['assessments'][0]['grade']);
1161         $this->assertEquals($assessmentid, $result['assessments'][0]['id']);
1162     }
1164     /**
1165      * Test get_assessment_author.
1166      */
1167     public function test_get_assessment_author() {
1168         global $DB;
1170         // Create the submission.
1171         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1173         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1174         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1175             'weight' => 2,
1176             'grade' => 90,
1177         ));
1179         // Switch to closed phase.
1180         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1181         $this->setUser($this->anotherstudentg1);
1182         $result = mod_workshop_external::get_assessment($assessmentid);
1183         $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1184         $this->assertEquals($assessmentid, $result['assessment']['id']);
1185         $this->assertEquals(90, $result['assessment']['grade']);
1186         // I can't see the reviewer review.
1187         $this->assertFalse(isset($result['assessment']['feedbackreviewer']));
1188     }
1190     /**
1191      * Test get_assessment_reviewer.
1192      */
1193     public function test_get_assessment_reviewer() {
1194         global $DB;
1196         // Create the submission.
1197         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1199         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1200         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1201             'weight' => 2,
1202             'grade' => 90,
1203         ));
1205         // Switch to closed phase.
1206         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1207         $this->setUser($this->student);
1208         $result = mod_workshop_external::get_assessment($assessmentid);
1209         $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1210         $this->assertEquals($assessmentid, $result['assessment']['id']);
1211         $this->assertEquals(90, $result['assessment']['grade']);
1212         // I can see the reviewer review.
1213         $this->assertTrue(isset($result['assessment']['feedbackreviewer']));
1214     }
1216     /**
1217      * Test get_assessment_teacher.
1218      */
1219     public function test_get_assessment_teacher() {
1220         global $DB;
1222         // Create the submission.
1223         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1225         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1226         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1227             'weight' => 2,
1228             'grade' => 90,
1229         ));
1231         // Switch to closed phase.
1232         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1233         $this->setUser($this->teacher);
1234         $result = mod_workshop_external::get_assessment($assessmentid);
1235         $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);
1236         $this->assertEquals($assessmentid, $result['assessment']['id']);
1237         $this->assertEquals(90, $result['assessment']['grade']);
1238     }
1240     /**
1241      * Test get_assessment_student_invalid_phase.
1242      */
1243     public function test_get_assessment_student_invalid_phase() {
1244         global $DB;
1246         // Create the submission.
1247         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1249         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1250         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1251             'weight' => 2,
1252             'grade' => 90,
1253         ));
1255         // Switch to closed phase.
1256         $this->setUser($this->anotherstudentg1);
1258         $this->setExpectedException('moodle_exception');
1259         mod_workshop_external::get_assessment($assessmentid);
1260     }
1262     /**
1263      * Test get_assessment_student_invalid_user.
1264      */
1265     public function test_get_assessment_student_invalid_user() {
1266         global $DB;
1268         // Create the submission.
1269         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1271         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1272         $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array(
1273             'weight' => 2,
1274             'grade' => 90,
1275         ));
1277         // Switch to closed phase.
1278         $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
1279         $this->setUser($this->anotherstudentg2);
1281         $this->setExpectedException('moodle_exception');
1282         mod_workshop_external::get_assessment($assessmentid);
1283     }
1285     /**
1286      * Test get_assessment_form_definition_reviewer_new_assessment.
1287      */
1288     public function test_get_assessment_form_definition_reviewer_new_assessment() {
1289         global $DB;
1291         // Create the submission.
1292         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1294         $workshop = new workshop($this->workshop, $this->cm, $this->course);
1295         $submission = $workshop->get_submission_by_id($submissionid);
1296         $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1298         // Switch to assessment phase.
1299         $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1300         $this->setUser($this->student);
1301         $result = mod_workshop_external::get_assessment_form_definition($assessmentid);
1302         $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);
1303         $this->assertEquals(4, $result['dimenssionscount']);    // We receive the expected 4 dimensions.
1304         $this->assertEmpty($result['current']); // Assessment not yet done.
1305         foreach ($result['fields'] as $field) {
1306             if (strpos($field['name'], 'grade__idx_') === 0) {
1307                 $this->assertEquals(25, $field['value']); // Check one of the dimension fields attributes.
1308             }
1309         }
1310     }
1312     /**
1313      * Test get_assessment_form_definition_teacher_new_assessment.
1314      */
1315     public function test_get_assessment_form_definition_teacher_new_assessment() {
1316         global $DB;
1318         // Create the submission.
1319         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1321         $workshop = new workshop($this->workshop, $this->cm, $this->course);
1322         $submission = $workshop->get_submission_by_id($submissionid);
1323         $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1325         // Switch to assessment phase.
1326         $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1327         $this->setUser($this->teacher);
1328         $this->setExpectedException('moodle_exception');
1329         mod_workshop_external::get_assessment_form_definition($assessmentid);   // Teachers can't add/edit assessments.
1330     }
1332     /**
1333      * Test get_assessment_form_definition_invalid_phase.
1334      */
1335     public function test_get_assessment_form_definition_invalid_phase() {
1336         global $DB;
1338         // Create the submission.
1339         $submissionid = $this->create_test_submission($this->anotherstudentg1);
1341         $workshop = new workshop($this->workshop, $this->cm, $this->course);
1342         $submission = $workshop->get_submission_by_id($submissionid);
1343         $assessmentid = $workshop->add_allocation($submission, $this->student->id);
1345         $this->setUser($this->student);
1346         $this->setExpectedException('moodle_exception');
1347         mod_workshop_external::get_assessment_form_definition($assessmentid);
1348     }
1350     /**
1351      * Test get_reviewer_assessments.
1352      */
1353     public function test_get_reviewer_assessments() {
1354         global $DB;
1356         // Create the submission.
1357         $submissionid1 = $this->create_test_submission($this->student);
1358         $submissionid2 = $this->create_test_submission($this->anotherstudentg1);
1360         $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');
1361         $assessmentid1 = $workshopgenerator->create_assessment($submissionid1, $this->student->id, array(
1362             'weight' => 2,
1363             'grade' => 90,
1364         ));
1365         $assessmentid2 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array(
1366             'weight' => 3,
1367             'grade' => 80,
1368         ));
1370         // Switch to assessment phase.
1371         $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1372         $this->setUser($this->student);
1373         // Get my assessments.
1374         $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id);
1375         $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);
1376         $this->assertCount(2, $result['assessments']);
1377         foreach ($result['assessments'] as $assessment) {
1378             if ($assessment['id'] == $assessmentid1) {
1379                 $this->assertEquals(90, $assessment['grade']);
1380             } else {
1381                 $this->assertEquals($assessmentid2, $assessment['id']);
1382                 $this->assertEquals(80, $assessment['grade']);
1383             }
1384         }
1386         // Now, as teacher try to get the same student assessments.
1387         $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->student->id);
1388         $result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);
1389         $this->assertCount(2, $result['assessments']);
1390     }
1392     /**
1393      * Test get_reviewer_assessments_other_student.
1394      */
1395     public function test_get_reviewer_assessments_other_student() {
1396         global $DB;
1398         $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id));
1399         // Try to get other user assessments.
1400         $this->setUser($this->student);
1401         $this->setExpectedException('moodle_exception');
1402         mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);
1403     }
1405     /**
1406      * Test get_reviewer_assessments_invalid_phase.
1407      */
1408     public function test_get_reviewer_assessments_invalid_phase() {
1409         global $DB;
1411         $DB->set_field('workshop', 'phase', workshop::PHASE_SUBMISSION, array('id' => $this->workshop->id));
1412         // Try to get other user assessments.
1413         $this->setUser($this->student);
1414         $this->setExpectedException('moodle_exception');
1415         mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);
1416     }