MDL-66147 mod_assign: external get_participant supports relative dates
[moodle.git] / mod / assign / tests / externallib_test.php
CommitLineData
1f8c8f61
PC
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
17defined('MOODLE_INTERNAL') || die();
18
19global $CFG;
20
21require_once($CFG->dirroot . '/webservice/tests/helpers.php');
757d5b7c 22require_once($CFG->dirroot . '/mod/assign/externallib.php');
a6b8fc78 23require_once(__DIR__ . '/fixtures/testable_assign.php');
1f8c8f61
PC
24
25/**
26 * External mod assign functions unit tests
27 *
28 * @package mod_assign
29 * @category external
30 * @copyright 2012 Paul Charsley
31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 */
33class mod_assign_external_testcase extends externallib_advanced_testcase {
34
1f8c8f61
PC
35 /**
36 * Test get_grades
37 */
05a6445a 38 public function test_get_grades() {
1f8c8f61
PC
39 global $DB, $USER;
40
41 $this->resetAfterTest(true);
42 // Create a course and assignment.
43 $coursedata['idnumber'] = 'idnumbercourse';
44 $coursedata['fullname'] = 'Lightwork Course';
45 $coursedata['summary'] = 'Lightwork Course description';
46 $coursedata['summaryformat'] = FORMAT_MOODLE;
47 $course = self::getDataGenerator()->create_course($coursedata);
48
49 $assigndata['course'] = $course->id;
50 $assigndata['name'] = 'lightwork assignment';
51
52 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
53
54 // Create a manual enrolment record.
07df8c38
PC
55 $manualenroldata['enrol'] = 'manual';
56 $manualenroldata['status'] = 0;
57 $manualenroldata['courseid'] = $course->id;
58 $enrolid = $DB->insert_record('enrol', $manualenroldata);
1f8c8f61
PC
59
60 // Create a teacher and give them capabilities.
61 $context = context_course::instance($course->id);
62 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 63 $context = context_module::instance($assign->cmid);
cf0cad92 64 $this->assignUserCapability('mod/assign:viewgrades', $context->id, $roleid);
1f8c8f61
PC
65
66 // Create the teacher's enrolment record.
07df8c38
PC
67 $userenrolmentdata['status'] = 0;
68 $userenrolmentdata['enrolid'] = $enrolid;
69 $userenrolmentdata['userid'] = $USER->id;
70 $DB->insert_record('user_enrolments', $userenrolmentdata);
1f8c8f61 71
a13fbf5f 72 // Create a student and give them 2 grades (for 2 attempts).
1f8c8f61 73 $student = self::getDataGenerator()->create_user();
9e3eee67
DW
74
75 $submission = new stdClass();
76 $submission->assignment = $assign->id;
77 $submission->userid = $student->id;
78 $submission->status = ASSIGN_SUBMISSION_STATUS_NEW;
79 $submission->latest = 0;
80 $submission->attemptnumber = 0;
81 $submission->groupid = 0;
82 $submission->timecreated = time();
83 $submission->timemodified = time();
84 $DB->insert_record('assign_submission', $submission);
85
a13fbf5f
DW
86 $grade = new stdClass();
87 $grade->assignment = $assign->id;
88 $grade->userid = $student->id;
89 $grade->timecreated = time();
90 $grade->timemodified = $grade->timecreated;
91 $grade->grader = $USER->id;
92 $grade->grade = 50;
a13fbf5f
DW
93 $grade->attemptnumber = 0;
94 $DB->insert_record('assign_grades', $grade);
95
9e3eee67
DW
96 $submission = new stdClass();
97 $submission->assignment = $assign->id;
98 $submission->userid = $student->id;
99 $submission->status = ASSIGN_SUBMISSION_STATUS_NEW;
100 $submission->latest = 1;
101 $submission->attemptnumber = 1;
102 $submission->groupid = 0;
103 $submission->timecreated = time();
104 $submission->timemodified = time();
105 $DB->insert_record('assign_submission', $submission);
106
1f8c8f61
PC
107 $grade = new stdClass();
108 $grade->assignment = $assign->id;
109 $grade->userid = $student->id;
110 $grade->timecreated = time();
111 $grade->timemodified = $grade->timecreated;
112 $grade->grader = $USER->id;
113 $grade->grade = 75;
a13fbf5f 114 $grade->attemptnumber = 1;
1f8c8f61
PC
115 $DB->insert_record('assign_grades', $grade);
116
117 $assignmentids[] = $assign->id;
118 $result = mod_assign_external::get_grades($assignmentids);
119
fb695f6e
JM
120 // We need to execute the return values cleaning process to simulate the web service server.
121 $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
122
1f8c8f61
PC
123 // Check that the correct grade information for the student is returned.
124 $this->assertEquals(1, count($result['assignments']));
125 $assignment = $result['assignments'][0];
126 $this->assertEquals($assign->id, $assignment['assignmentid']);
a13fbf5f 127 // Should only get the last grade for this student.
1f8c8f61
PC
128 $this->assertEquals(1, count($assignment['grades']));
129 $grade = $assignment['grades'][0];
130 $this->assertEquals($student->id, $grade['userid']);
13e82f1c 131 // Should be the last grade (not the first).
1f8c8f61
PC
132 $this->assertEquals(75, $grade['grade']);
133 }
134
1378838e
PC
135 /**
136 * Test get_assignments
137 */
05a6445a 138 public function test_get_assignments() {
9e6c63a7 139 global $DB, $USER, $CFG;
1378838e
PC
140
141 $this->resetAfterTest(true);
142
143 $category = self::getDataGenerator()->create_category(array(
144 'name' => 'Test category'
145 ));
146
147 // Create a course.
148 $course1 = self::getDataGenerator()->create_course(array(
149 'idnumber' => 'idnumbercourse1',
d889b587
JL
150 'fullname' => '<b>Lightwork Course 1</b>', // Adding tags here to check that external_format_string works.
151 'shortname' => '<b>Lightwork Course 1</b>', // Adding tags here to check that external_format_string works.
1378838e
PC
152 'summary' => 'Lightwork Course 1 description',
153 'summaryformat' => FORMAT_MOODLE,
154 'category' => $category->id
155 ));
156
157 // Create a second course, just for testing.
158 $course2 = self::getDataGenerator()->create_course(array(
159 'idnumber' => 'idnumbercourse2',
160 'fullname' => 'Lightwork Course 2',
161 'summary' => 'Lightwork Course 2 description',
162 'summaryformat' => FORMAT_MOODLE,
163 'category' => $category->id
164 ));
165
988065c0 166 // Create the assignment module with links to a filerecord.
1378838e
PC
167 $assign1 = self::getDataGenerator()->create_module('assign', array(
168 'course' => $course1->id,
d1ec5c83 169 'name' => 'lightwork assignment',
988065c0
PFO
170 'intro' => 'the assignment intro text here <a href="@@PLUGINFILE@@/intro.txt">link</a>',
171 'introformat' => FORMAT_HTML,
d1ec5c83
PC
172 'markingworkflow' => 1,
173 'markingallocation' => 1
1378838e
PC
174 ));
175
988065c0
PFO
176 // Add a file as assignment attachment.
177 $context = context_module::instance($assign1->cmid);
178 $filerecord = array('component' => 'mod_assign', 'filearea' => 'intro', 'contextid' => $context->id, 'itemid' => 0,
179 'filename' => 'intro.txt', 'filepath' => '/');
180 $fs = get_file_storage();
181 $fs->create_file_from_string($filerecord, 'Test intro file');
182
1378838e
PC
183 // Create manual enrolment record.
184 $enrolid = $DB->insert_record('enrol', (object)array(
185 'enrol' => 'manual',
186 'status' => 0,
187 'courseid' => $course1->id
188 ));
189
190 // Create the user and give them capabilities.
191 $context = context_course::instance($course1->id);
192 $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
74b63eae 193 $context = context_module::instance($assign1->cmid);
1378838e
PC
194 $this->assignUserCapability('mod/assign:view', $context->id, $roleid);
195
196 // Create the user enrolment record.
197 $DB->insert_record('user_enrolments', (object)array(
198 'status' => 0,
199 'enrolid' => $enrolid,
200 'userid' => $USER->id
201 ));
202
0be81772
JL
203 // Add a file as assignment attachment.
204 $filerecord = array('component' => 'mod_assign', 'filearea' => ASSIGN_INTROATTACHMENT_FILEAREA,
205 'contextid' => $context->id, 'itemid' => 0,
206 'filename' => 'introattachment.txt', 'filepath' => '/');
207 $fs = get_file_storage();
208 $fs->create_file_from_string($filerecord, 'Test intro attachment file');
209
1378838e 210 $result = mod_assign_external::get_assignments();
fb695f6e
JM
211
212 // We need to execute the return values cleaning process to simulate the web service server.
213 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
214
1378838e
PC
215 // Check the course and assignment are returned.
216 $this->assertEquals(1, count($result['courses']));
217 $course = $result['courses'][0];
218 $this->assertEquals('Lightwork Course 1', $course['fullname']);
d889b587 219 $this->assertEquals('Lightwork Course 1', $course['shortname']);
1378838e
PC
220 $this->assertEquals(1, count($course['assignments']));
221 $assignment = $course['assignments'][0];
222 $this->assertEquals($assign1->id, $assignment['id']);
223 $this->assertEquals($course1->id, $assignment['course']);
224 $this->assertEquals('lightwork assignment', $assignment['name']);
988065c0 225 $this->assertContains('the assignment intro text here', $assignment['intro']);
30cdddb0 226 $this->assertNotEmpty($assignment['configs']);
988065c0 227 // Check the url of the file attatched.
9e6c63a7 228 $this->assertRegExp('@"' . $CFG->wwwroot . '/webservice/pluginfile.php/\d+/mod_assign/intro/intro\.txt"@', $assignment['intro']);
d1ec5c83
PC
229 $this->assertEquals(1, $assignment['markingworkflow']);
230 $this->assertEquals(1, $assignment['markingallocation']);
79616101 231 $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
1378838e 232
0be81772
JL
233 $this->assertCount(1, $assignment['introattachments']);
234 $this->assertEquals('introattachment.txt', $assignment['introattachments'][0]['filename']);
235
236 // Now, hide the descritption until the submission from date.
237 $DB->set_field('assign', 'alwaysshowdescription', 0, array('id' => $assign1->id));
238 $DB->set_field('assign', 'allowsubmissionsfromdate', time() + DAYSECS, array('id' => $assign1->id));
239
1378838e 240 $result = mod_assign_external::get_assignments(array($course1->id));
fb695f6e
JM
241
242 // We need to execute the return values cleaning process to simulate the web service server.
243 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
244
1378838e
PC
245 $this->assertEquals(1, count($result['courses']));
246 $course = $result['courses'][0];
247 $this->assertEquals('Lightwork Course 1', $course['fullname']);
248 $this->assertEquals(1, count($course['assignments']));
249 $assignment = $course['assignments'][0];
250 $this->assertEquals($assign1->id, $assignment['id']);
251 $this->assertEquals($course1->id, $assignment['course']);
252 $this->assertEquals('lightwork assignment', $assignment['name']);
0be81772
JL
253 $this->assertArrayNotHasKey('intro', $assignment);
254 $this->assertArrayNotHasKey('introattachments', $assignment);
d1ec5c83
PC
255 $this->assertEquals(1, $assignment['markingworkflow']);
256 $this->assertEquals(1, $assignment['markingallocation']);
79616101 257 $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
1378838e
PC
258
259 $result = mod_assign_external::get_assignments(array($course2->id));
fb695f6e
JM
260
261 // We need to execute the return values cleaning process to simulate the web service server.
262 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
263
1378838e
PC
264 $this->assertEquals(0, count($result['courses']));
265 $this->assertEquals(1, count($result['warnings']));
8e76a2fa
JL
266
267 // Test with non-enrolled user, but with view capabilities.
268 $this->setAdminUser();
269 $result = mod_assign_external::get_assignments();
270 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
271 $this->assertEquals(0, count($result['courses']));
272 $this->assertEquals(0, count($result['warnings']));
273
274 // Expect no courses, because we are not using the special flag.
275 $result = mod_assign_external::get_assignments(array($course1->id));
276 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
277 $this->assertCount(0, $result['courses']);
278
279 // Now use the special flag to return courses where you are not enroled in.
280 $result = mod_assign_external::get_assignments(array($course1->id), array(), true);
281 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
282 $this->assertCount(1, $result['courses']);
283
284 $course = $result['courses'][0];
285 $this->assertEquals('Lightwork Course 1', $course['fullname']);
286 $this->assertEquals(1, count($course['assignments']));
287 $assignment = $course['assignments'][0];
288 $this->assertEquals($assign1->id, $assignment['id']);
289 $this->assertEquals($course1->id, $assignment['course']);
290 $this->assertEquals('lightwork assignment', $assignment['name']);
291 $this->assertArrayNotHasKey('intro', $assignment);
292 $this->assertArrayNotHasKey('introattachments', $assignment);
293 $this->assertEquals(1, $assignment['markingworkflow']);
294 $this->assertEquals(1, $assignment['markingallocation']);
79616101 295 $this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
1378838e 296 }
c144959c 297
9ac99220
DP
298 /**
299 * Test get_assignments with submissionstatement.
300 */
301 public function test_get_assignments_with_submissionstatement() {
302 global $DB, $USER, $CFG;
303
304 $this->resetAfterTest(true);
305
306 // Setup test data. Create 2 assigns, one with requiresubmissionstatement and the other without it.
307 $course = $this->getDataGenerator()->create_course();
308 $assign = $this->getDataGenerator()->create_module('assign', array(
309 'course' => $course->id,
310 'requiresubmissionstatement' => 1
311 ));
312 $assign2 = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
313
314 // Create student.
315 $student = self::getDataGenerator()->create_user();
316
317 // Users enrolments.
318 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
319 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
320
321 // Update the submissionstatement.
322 $submissionstatement = 'This is a fake submission statement.';
323 set_config('submissionstatement', $submissionstatement, 'assign');
324
325 $this->setUser($student);
326
327 $result = mod_assign_external::get_assignments();
328 // We need to execute the return values cleaning process to simulate the web service server.
329 $result = external_api::clean_returnvalue(mod_assign_external::get_assignments_returns(), $result);
330
331 // Check that the amount of courses and assignments is right.
332 $this->assertCount(1, $result['courses']);
333 $assignmentsret = $result['courses'][0]['assignments'];
334 $this->assertCount(2, $assignmentsret);
335
336 // Order the returned assignments by ID.
337 usort($assignmentsret, function($a, $b) {
338 return strcmp($a['id'], $b['id']);
339 });
340
341 // Check that the first assign contains the submission statement.
342 $assignmentret = $assignmentsret[0];
343 $this->assertEquals($assign->id, $assignmentret['id']);
344 $this->assertEquals(1, $assignmentret['requiresubmissionstatement']);
345 $this->assertEquals($submissionstatement, $assignmentret['submissionstatement']);
346
347 // Check that the second assign does NOT contain the submission statement.
348 $assignmentret = $assignmentsret[1];
349 $this->assertEquals($assign2->id, $assignmentret['id']);
350 $this->assertEquals(0, $assignmentret['requiresubmissionstatement']);
351 $this->assertArrayNotHasKey('submissionstatement', $assignmentret);
352 }
353
c144959c
PC
354 /**
355 * Test get_submissions
356 */
05a6445a 357 public function test_get_submissions() {
c144959c
PC
358 global $DB, $USER;
359
360 $this->resetAfterTest(true);
361 // Create a course and assignment.
362 $coursedata['idnumber'] = 'idnumbercourse1';
363 $coursedata['fullname'] = 'Lightwork Course 1';
364 $coursedata['summary'] = 'Lightwork Course 1 description';
365 $coursedata['summaryformat'] = FORMAT_MOODLE;
366 $course1 = self::getDataGenerator()->create_course($coursedata);
367
368 $assigndata['course'] = $course1->id;
369 $assigndata['name'] = 'lightwork assignment';
370
371 $assign1 = self::getDataGenerator()->create_module('assign', $assigndata);
372
373 // Create a student with an online text submission.
a13fbf5f 374 // First attempt.
c144959c 375 $student = self::getDataGenerator()->create_user();
df3d8776 376 $teacher = self::getDataGenerator()->create_user();
c144959c
PC
377 $submission = new stdClass();
378 $submission->assignment = $assign1->id;
379 $submission->userid = $student->id;
380 $submission->timecreated = time();
381 $submission->timemodified = $submission->timecreated;
a13fbf5f
DW
382 $submission->status = 'draft';
383 $submission->attemptnumber = 0;
1523f9e0 384 $submission->latest = 0;
a13fbf5f
DW
385 $sid = $DB->insert_record('assign_submission', $submission);
386
387 // Second attempt.
388 $submission = new stdClass();
389 $submission->assignment = $assign1->id;
390 $submission->userid = $student->id;
391 $submission->timecreated = time();
392 $submission->timemodified = $submission->timecreated;
c144959c 393 $submission->status = 'submitted';
a13fbf5f 394 $submission->attemptnumber = 1;
1523f9e0 395 $submission->latest = 1;
c144959c
PC
396 $sid = $DB->insert_record('assign_submission', $submission);
397 $submission->id = $sid;
398
399 $onlinetextsubmission = new stdClass();
9f780282 400 $onlinetextsubmission->onlinetext = "<p>online test text</p>";
c144959c
PC
401 $onlinetextsubmission->onlineformat = 1;
402 $onlinetextsubmission->submission = $submission->id;
403 $onlinetextsubmission->assignment = $assign1->id;
404 $DB->insert_record('assignsubmission_onlinetext', $onlinetextsubmission);
405
df3d8776
JL
406 // Enrol the teacher in the course.
407 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
408 $this->getDataGenerator()->enrol_user($teacher->id, $course1->id, $teacherrole->id);
409 $this->setUser($teacher);
c144959c 410
df3d8776
JL
411 $assignmentids[] = $assign1->id;
412 $result = mod_assign_external::get_submissions($assignmentids);
413 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
c144959c 414
df3d8776
JL
415 // Check the online text submission is NOT returned because the student is not yet enrolled in the course.
416 $this->assertEquals(1, count($result['assignments']));
417 $assignment = $result['assignments'][0];
418 $this->assertEquals($assign1->id, $assignment['assignmentid']);
419 $this->assertEquals(0, count($assignment['submissions']));
420
421 // Enrol the student in the course.
422 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
423 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id);
c144959c 424
c144959c 425 $result = mod_assign_external::get_submissions($assignmentids);
7f45111e 426 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
c144959c 427
c144959c
PC
428 $this->assertEquals(1, count($result['assignments']));
429 $assignment = $result['assignments'][0];
430 $this->assertEquals($assign1->id, $assignment['assignmentid']);
df3d8776 431 // Now, we get the submission because the user is enrolled.
c144959c
PC
432 $this->assertEquals(1, count($assignment['submissions']));
433 $submission = $assignment['submissions'][0];
434 $this->assertEquals($sid, $submission['id']);
bdf1ac27 435 $this->assertCount(1, $submission['plugins']);
8845688c 436 $this->assertEquals('notgraded', $submission['gradingstatus']);
cf0cad92
JL
437
438 // Test locking the context.
439 set_config('contextlocking', 1);
440 $context = context_course::instance($course1->id);
441 $context->set_locked(true);
442
443 $this->setUser($teacher);
444 $assignmentids[] = $assign1->id;
445 $result = mod_assign_external::get_submissions($assignmentids);
446 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
447 $this->assertEquals(1, count($result['assignments']));
c144959c 448 }
07df8c38
PC
449
450 /**
451 * Test get_user_flags
452 */
05a6445a 453 public function test_get_user_flags() {
07df8c38
PC
454 global $DB, $USER;
455
456 $this->resetAfterTest(true);
457 // Create a course and assignment.
458 $coursedata['idnumber'] = 'idnumbercourse';
459 $coursedata['fullname'] = 'Lightwork Course';
460 $coursedata['summary'] = 'Lightwork Course description';
461 $coursedata['summaryformat'] = FORMAT_MOODLE;
462 $course = self::getDataGenerator()->create_course($coursedata);
463
464 $assigndata['course'] = $course->id;
465 $assigndata['name'] = 'lightwork assignment';
466
467 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
468
469 // Create a manual enrolment record.
470 $manualenroldata['enrol'] = 'manual';
471 $manualenroldata['status'] = 0;
472 $manualenroldata['courseid'] = $course->id;
473 $enrolid = $DB->insert_record('enrol', $manualenroldata);
474
475 // Create a teacher and give them capabilities.
476 $context = context_course::instance($course->id);
477 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 478 $context = context_module::instance($assign->cmid);
07df8c38
PC
479 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
480
481 // Create the teacher's enrolment record.
482 $userenrolmentdata['status'] = 0;
483 $userenrolmentdata['enrolid'] = $enrolid;
484 $userenrolmentdata['userid'] = $USER->id;
485 $DB->insert_record('user_enrolments', $userenrolmentdata);
486
487 // Create a student and give them a user flag record.
488 $student = self::getDataGenerator()->create_user();
489 $userflag = new stdClass();
490 $userflag->assignment = $assign->id;
491 $userflag->userid = $student->id;
492 $userflag->locked = 0;
493 $userflag->mailed = 0;
494 $userflag->extensionduedate = 0;
495 $userflag->workflowstate = 'inmarking';
496 $userflag->allocatedmarker = $USER->id;
497
498 $DB->insert_record('assign_user_flags', $userflag);
499
500 $assignmentids[] = $assign->id;
501 $result = mod_assign_external::get_user_flags($assignmentids);
502
503 // We need to execute the return values cleaning process to simulate the web service server.
504 $result = external_api::clean_returnvalue(mod_assign_external::get_user_flags_returns(), $result);
505
506 // Check that the correct user flag information for the student is returned.
507 $this->assertEquals(1, count($result['assignments']));
508 $assignment = $result['assignments'][0];
509 $this->assertEquals($assign->id, $assignment['assignmentid']);
510 // Should be one user flag record.
511 $this->assertEquals(1, count($assignment['userflags']));
512 $userflag = $assignment['userflags'][0];
513 $this->assertEquals($student->id, $userflag['userid']);
514 $this->assertEquals(0, $userflag['locked']);
515 $this->assertEquals(0, $userflag['mailed']);
516 $this->assertEquals(0, $userflag['extensionduedate']);
517 $this->assertEquals('inmarking', $userflag['workflowstate']);
518 $this->assertEquals($USER->id, $userflag['allocatedmarker']);
519 }
520
521 /**
522 * Test get_user_mappings
523 */
05a6445a 524 public function test_get_user_mappings() {
07df8c38
PC
525 global $DB, $USER;
526
527 $this->resetAfterTest(true);
528 // Create a course and assignment.
529 $coursedata['idnumber'] = 'idnumbercourse';
530 $coursedata['fullname'] = 'Lightwork Course';
531 $coursedata['summary'] = 'Lightwork Course description';
532 $coursedata['summaryformat'] = FORMAT_MOODLE;
533 $course = self::getDataGenerator()->create_course($coursedata);
534
535 $assigndata['course'] = $course->id;
536 $assigndata['name'] = 'lightwork assignment';
537
538 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
539
540 // Create a manual enrolment record.
541 $manualenroldata['enrol'] = 'manual';
542 $manualenroldata['status'] = 0;
543 $manualenroldata['courseid'] = $course->id;
544 $enrolid = $DB->insert_record('enrol', $manualenroldata);
545
546 // Create a teacher and give them capabilities.
547 $context = context_course::instance($course->id);
548 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 549 $context = context_module::instance($assign->cmid);
07df8c38
PC
550 $this->assignUserCapability('mod/assign:revealidentities', $context->id, $roleid);
551
552 // Create the teacher's enrolment record.
553 $userenrolmentdata['status'] = 0;
554 $userenrolmentdata['enrolid'] = $enrolid;
555 $userenrolmentdata['userid'] = $USER->id;
556 $DB->insert_record('user_enrolments', $userenrolmentdata);
557
558 // Create a student and give them a user mapping record.
559 $student = self::getDataGenerator()->create_user();
560 $mapping = new stdClass();
561 $mapping->assignment = $assign->id;
562 $mapping->userid = $student->id;
563
564 $DB->insert_record('assign_user_mapping', $mapping);
565
566 $assignmentids[] = $assign->id;
567 $result = mod_assign_external::get_user_mappings($assignmentids);
568
569 // We need to execute the return values cleaning process to simulate the web service server.
570 $result = external_api::clean_returnvalue(mod_assign_external::get_user_mappings_returns(), $result);
571
572 // Check that the correct user mapping information for the student is returned.
573 $this->assertEquals(1, count($result['assignments']));
574 $assignment = $result['assignments'][0];
575 $this->assertEquals($assign->id, $assignment['assignmentid']);
576 // Should be one user mapping record.
577 $this->assertEquals(1, count($assignment['mappings']));
578 $mapping = $assignment['mappings'][0];
579 $this->assertEquals($student->id, $mapping['userid']);
580 }
581
05a6445a
DW
582 /**
583 * Test lock_submissions
52f3e060
RT
584 *
585 * @expectedException moodle_exception
05a6445a
DW
586 */
587 public function test_lock_submissions() {
588 global $DB, $USER;
589
590 $this->resetAfterTest(true);
591 // Create a course and assignment and users.
592 $course = self::getDataGenerator()->create_course();
593
594 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
595 $params['course'] = $course->id;
596 $params['assignsubmission_onlinetext_enabled'] = 1;
597 $instance = $generator->create_instance($params);
598 $cm = get_coursemodule_from_instance('assign', $instance->id);
599 $context = context_module::instance($cm->id);
600
601 $assign = new assign($context, $cm, $course);
602
603 $student1 = self::getDataGenerator()->create_user();
604 $student2 = self::getDataGenerator()->create_user();
605 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
606 $this->getDataGenerator()->enrol_user($student1->id,
607 $course->id,
608 $studentrole->id);
609 $this->getDataGenerator()->enrol_user($student2->id,
610 $course->id,
611 $studentrole->id);
612 $teacher = self::getDataGenerator()->create_user();
613 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
614 $this->getDataGenerator()->enrol_user($teacher->id,
615 $course->id,
616 $teacherrole->id);
617
6d90ef2b 618 // Create a student1 with an online text submission.
05a6445a
DW
619 // Simulate a submission.
620 $this->setUser($student1);
621 $submission = $assign->get_user_submission($student1->id, true);
622 $data = new stdClass();
623 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
624 'text'=>'Submission text',
625 'format'=>FORMAT_MOODLE);
626 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
627 $plugin->save($submission, $data);
628
539af602 629 // Ready to test.
05a6445a
DW
630 $this->setUser($teacher);
631 $students = array($student1->id, $student2->id);
632 $result = mod_assign_external::lock_submissions($instance->id, $students);
7f45111e 633 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
05a6445a
DW
634
635 // Check for 0 warnings.
636 $this->assertEquals(0, count($result));
637
638 $this->setUser($student2);
639 $submission = $assign->get_user_submission($student2->id, true);
640 $data = new stdClass();
641 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
642 'text'=>'Submission text',
643 'format'=>FORMAT_MOODLE);
644 $notices = array();
05a6445a
DW
645 $assign->save_submission($data, $notices);
646 }
647
648 /**
649 * Test unlock_submissions
650 */
651 public function test_unlock_submissions() {
652 global $DB, $USER;
653
654 $this->resetAfterTest(true);
655 // Create a course and assignment and users.
656 $course = self::getDataGenerator()->create_course();
657
658 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
659 $params['course'] = $course->id;
660 $params['assignsubmission_onlinetext_enabled'] = 1;
661 $instance = $generator->create_instance($params);
662 $cm = get_coursemodule_from_instance('assign', $instance->id);
663 $context = context_module::instance($cm->id);
664
665 $assign = new assign($context, $cm, $course);
666
667 $student1 = self::getDataGenerator()->create_user();
668 $student2 = self::getDataGenerator()->create_user();
669 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
670 $this->getDataGenerator()->enrol_user($student1->id,
671 $course->id,
672 $studentrole->id);
673 $this->getDataGenerator()->enrol_user($student2->id,
674 $course->id,
675 $studentrole->id);
676 $teacher = self::getDataGenerator()->create_user();
677 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
678 $this->getDataGenerator()->enrol_user($teacher->id,
679 $course->id,
680 $teacherrole->id);
681
6d90ef2b 682 // Create a student1 with an online text submission.
05a6445a
DW
683 // Simulate a submission.
684 $this->setUser($student1);
685 $submission = $assign->get_user_submission($student1->id, true);
686 $data = new stdClass();
687 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
688 'text'=>'Submission text',
689 'format'=>FORMAT_MOODLE);
690 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
691 $plugin->save($submission, $data);
692
539af602 693 // Ready to test.
05a6445a
DW
694 $this->setUser($teacher);
695 $students = array($student1->id, $student2->id);
696 $result = mod_assign_external::lock_submissions($instance->id, $students);
7f45111e 697 $result = external_api::clean_returnvalue(mod_assign_external::lock_submissions_returns(), $result);
05a6445a
DW
698
699 // Check for 0 warnings.
700 $this->assertEquals(0, count($result));
701
702 $result = mod_assign_external::unlock_submissions($instance->id, $students);
7f45111e 703 $result = external_api::clean_returnvalue(mod_assign_external::unlock_submissions_returns(), $result);
05a6445a
DW
704
705 // Check for 0 warnings.
706 $this->assertEquals(0, count($result));
707
708 $this->setUser($student2);
709 $submission = $assign->get_user_submission($student2->id, true);
710 $data = new stdClass();
711 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
712 'text'=>'Submission text',
713 'format'=>FORMAT_MOODLE);
714 $notices = array();
715 $assign->save_submission($data, $notices);
716 }
717
718 /**
719 * Test submit_for_grading
720 */
721 public function test_submit_for_grading() {
722 global $DB, $USER;
723
724 $this->resetAfterTest(true);
725 // Create a course and assignment and users.
726 $course = self::getDataGenerator()->create_course();
727
728 set_config('submissionreceipts', 0, 'assign');
729 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
730 $params['course'] = $course->id;
731 $params['assignsubmission_onlinetext_enabled'] = 1;
732 $params['submissiondrafts'] = 1;
733 $params['sendnotifications'] = 0;
91327d96 734 $params['requiresubmissionstatement'] = 1;
05a6445a
DW
735 $instance = $generator->create_instance($params);
736 $cm = get_coursemodule_from_instance('assign', $instance->id);
737 $context = context_module::instance($cm->id);
738
739 $assign = new assign($context, $cm, $course);
740
741 $student1 = self::getDataGenerator()->create_user();
742 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
743 $this->getDataGenerator()->enrol_user($student1->id,
744 $course->id,
745 $studentrole->id);
746
747 // Create a student1 with an online text submission.
748 // Simulate a submission.
749 $this->setUser($student1);
750 $submission = $assign->get_user_submission($student1->id, true);
751 $data = new stdClass();
752 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
753 'text'=>'Submission text',
754 'format'=>FORMAT_MOODLE);
755 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
756 $plugin->save($submission, $data);
757
91327d96 758 $result = mod_assign_external::submit_for_grading($instance->id, false);
7f45111e 759 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
91327d96
DW
760
761 // Should be 1 fail because the submission statement was not aceptted.
762 $this->assertEquals(1, count($result));
763
764 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 765 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
766
767 // Check for 0 warnings.
768 $this->assertEquals(0, count($result));
769
770 $submission = $assign->get_user_submission($student1->id, false);
771
772 $this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
773 }
774
775 /**
776 * Test save_user_extensions
777 */
778 public function test_save_user_extensions() {
779 global $DB, $USER;
780
781 $this->resetAfterTest(true);
782 // Create a course and assignment and users.
783 $course = self::getDataGenerator()->create_course();
784
785 $teacher = self::getDataGenerator()->create_user();
786 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
787 $this->getDataGenerator()->enrol_user($teacher->id,
788 $course->id,
789 $teacherrole->id);
790 $this->setUser($teacher);
791
792 $now = time();
793 $yesterday = $now - 24*60*60;
794 $tomorrow = $now + 24*60*60;
795 set_config('submissionreceipts', 0, 'assign');
796 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
797 $params['course'] = $course->id;
798 $params['submissiondrafts'] = 1;
799 $params['sendnotifications'] = 0;
800 $params['duedate'] = $yesterday;
801 $params['cutoffdate'] = $now - 10;
802 $instance = $generator->create_instance($params);
803 $cm = get_coursemodule_from_instance('assign', $instance->id);
804 $context = context_module::instance($cm->id);
805
806 $assign = new assign($context, $cm, $course);
807
808 $student1 = self::getDataGenerator()->create_user();
809 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
810 $this->getDataGenerator()->enrol_user($student1->id,
811 $course->id,
812 $studentrole->id);
813
814 $this->setUser($student1);
91327d96 815 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 816 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
817
818 // Check for 0 warnings.
819 $this->assertEquals(1, count($result));
820
821 $this->setUser($teacher);
822 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
7f45111e 823 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
824 $this->assertEquals(1, count($result));
825
826 $this->setUser($teacher);
827 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
7f45111e 828 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
829 $this->assertEquals(1, count($result));
830
831 $this->setUser($teacher);
832 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
7f45111e 833 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
834 $this->assertEquals(0, count($result));
835
836 $this->setUser($student1);
91327d96 837 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 838 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
839 $this->assertEquals(0, count($result));
840
841 $this->setUser($student1);
842 $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
7f45111e 843 $result = external_api::clean_returnvalue(mod_assign_external::save_user_extensions_returns(), $result);
05a6445a
DW
844
845 }
846
847 /**
848 * Test reveal_identities
52f3e060
RT
849 *
850 * @expectedException required_capability_exception
05a6445a
DW
851 */
852 public function test_reveal_identities() {
853 global $DB, $USER;
854
855 $this->resetAfterTest(true);
856 // Create a course and assignment and users.
857 $course = self::getDataGenerator()->create_course();
858
859 $teacher = self::getDataGenerator()->create_user();
860 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
861 $this->getDataGenerator()->enrol_user($teacher->id,
862 $course->id,
863 $teacherrole->id);
864 $this->setUser($teacher);
865
866 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
867 $params['course'] = $course->id;
868 $params['submissiondrafts'] = 1;
869 $params['sendnotifications'] = 0;
870 $params['blindmarking'] = 1;
871 $instance = $generator->create_instance($params);
872 $cm = get_coursemodule_from_instance('assign', $instance->id);
873 $context = context_module::instance($cm->id);
874
875 $assign = new assign($context, $cm, $course);
876
877 $student1 = self::getDataGenerator()->create_user();
878 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
879 $this->getDataGenerator()->enrol_user($student1->id,
880 $course->id,
881 $studentrole->id);
882
883 $this->setUser($student1);
05a6445a 884 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 885 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
886 $this->assertEquals(1, count($result));
887 $this->assertEquals(true, $assign->is_blind_marking());
888
889 $this->setUser($teacher);
890 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 891 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
892 $this->assertEquals(0, count($result));
893 $this->assertEquals(false, $assign->is_blind_marking());
894
895 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
896 $params['course'] = $course->id;
897 $params['submissiondrafts'] = 1;
898 $params['sendnotifications'] = 0;
899 $params['blindmarking'] = 0;
900 $instance = $generator->create_instance($params);
901 $cm = get_coursemodule_from_instance('assign', $instance->id);
902 $context = context_module::instance($cm->id);
903
904 $assign = new assign($context, $cm, $course);
905 $result = mod_assign_external::reveal_identities($instance->id);
7f45111e 906 $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result);
05a6445a
DW
907 $this->assertEquals(1, count($result));
908 $this->assertEquals(false, $assign->is_blind_marking());
909
910 }
911
912 /**
913 * Test revert_submissions_to_draft
914 */
915 public function test_revert_submissions_to_draft() {
916 global $DB, $USER;
917
918 $this->resetAfterTest(true);
919 set_config('submissionreceipts', 0, 'assign');
920 // Create a course and assignment and users.
921 $course = self::getDataGenerator()->create_course();
922
923 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
924 $params['course'] = $course->id;
925 $params['sendnotifications'] = 0;
926 $params['submissiondrafts'] = 1;
927 $instance = $generator->create_instance($params);
928 $cm = get_coursemodule_from_instance('assign', $instance->id);
929 $context = context_module::instance($cm->id);
930
931 $assign = new assign($context, $cm, $course);
932
933 $student1 = self::getDataGenerator()->create_user();
934 $student2 = self::getDataGenerator()->create_user();
935 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
936 $this->getDataGenerator()->enrol_user($student1->id,
937 $course->id,
938 $studentrole->id);
939 $this->getDataGenerator()->enrol_user($student2->id,
940 $course->id,
941 $studentrole->id);
942 $teacher = self::getDataGenerator()->create_user();
943 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
944 $this->getDataGenerator()->enrol_user($teacher->id,
945 $course->id,
946 $teacherrole->id);
947
948 // Create a student1 with an online text submission.
949 // Simulate a submission.
950 $this->setUser($student1);
91327d96 951 $result = mod_assign_external::submit_for_grading($instance->id, true);
7f45111e 952 $result = external_api::clean_returnvalue(mod_assign_external::submit_for_grading_returns(), $result);
05a6445a
DW
953 $this->assertEquals(0, count($result));
954
539af602 955 // Ready to test.
05a6445a
DW
956 $this->setUser($teacher);
957 $students = array($student1->id, $student2->id);
958 $result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
7f45111e 959 $result = external_api::clean_returnvalue(mod_assign_external::revert_submissions_to_draft_returns(), $result);
05a6445a
DW
960
961 // Check for 0 warnings.
962 $this->assertEquals(0, count($result));
963
964 }
965
966 /**
967 * Test save_submission
968 */
969 public function test_save_submission() {
970 global $DB, $USER;
971
972 $this->resetAfterTest(true);
973 // Create a course and assignment and users.
974 $course = self::getDataGenerator()->create_course();
975
976 $teacher = self::getDataGenerator()->create_user();
977 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
978 $this->getDataGenerator()->enrol_user($teacher->id,
979 $course->id,
980 $teacherrole->id);
981 $this->setUser($teacher);
982
983 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
984 $params['course'] = $course->id;
985 $params['assignsubmission_onlinetext_enabled'] = 1;
986 $params['assignsubmission_file_enabled'] = 1;
987 $params['assignsubmission_file_maxfiles'] = 5;
988 $params['assignsubmission_file_maxsizebytes'] = 1024*1024;
989 $instance = $generator->create_instance($params);
990 $cm = get_coursemodule_from_instance('assign', $instance->id);
991 $context = context_module::instance($cm->id);
992
993 $assign = new assign($context, $cm, $course);
994
995 $student1 = self::getDataGenerator()->create_user();
996 $student2 = self::getDataGenerator()->create_user();
997 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
998 $this->getDataGenerator()->enrol_user($student1->id,
999 $course->id,
1000 $studentrole->id);
1001 $this->getDataGenerator()->enrol_user($student2->id,
1002 $course->id,
1003 $studentrole->id);
1004 // Create a student1 with an online text submission.
1005 // Simulate a submission.
1006 $this->setUser($student1);
1007
1008 // Create a file in a draft area.
1009 $draftidfile = file_get_unused_draft_itemid();
1010
1011 $usercontext = context_user::instance($student1->id);
1012 $filerecord = array(
1013 'contextid' => $usercontext->id,
1014 'component' => 'user',
1015 'filearea' => 'draft',
1016 'itemid' => $draftidfile,
1017 'filepath' => '/',
1018 'filename' => 'testtext.txt',
1019 );
1020
1021 $fs = get_file_storage();
1022 $fs->create_file_from_string($filerecord, 'text contents');
1023
1024 // Create another file in a different draft area.
1025 $draftidonlinetext = file_get_unused_draft_itemid();
1026
1027 $filerecord = array(
1028 'contextid' => $usercontext->id,
1029 'component' => 'user',
1030 'filearea' => 'draft',
1031 'itemid' => $draftidonlinetext,
1032 'filepath' => '/',
1033 'filename' => 'shouldbeanimage.txt',
1034 );
1035
1036 $fs->create_file_from_string($filerecord, 'image contents (not really)');
1037
539af602 1038 // Now try a submission.
05a6445a
DW
1039 $submissionpluginparams = array();
1040 $submissionpluginparams['files_filemanager'] = $draftidfile;
5609da91 1041 $onlinetexteditorparams = array('text' => '<p>Yeeha!</p>',
05a6445a
DW
1042 'format'=>1,
1043 'itemid'=>$draftidonlinetext);
1044 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1045 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
7f45111e 1046 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
05a6445a
DW
1047
1048 $this->assertEquals(0, count($result));
1049
711f9468
JL
1050 // Set up a due and cutoff passed date.
1051 $instance->duedate = time() - WEEKSECS;
1052 $instance->cutoffdate = time() - WEEKSECS;
1053 $DB->update_record('assign', $instance);
1054
1055 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
1056 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
1057
1058 $this->assertCount(1, $result);
1059 $this->assertEquals(get_string('duedatereached', 'assign'), $result[0]['item']);
05a6445a
DW
1060 }
1061
1062 /**
1063 * Test save_grade
1064 */
1065 public function test_save_grade() {
1066 global $DB, $USER;
1067
1068 $this->resetAfterTest(true);
1069 // Create a course and assignment and users.
1070 $course = self::getDataGenerator()->create_course();
1071
1072 $teacher = self::getDataGenerator()->create_user();
1073 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1074 $this->getDataGenerator()->enrol_user($teacher->id,
1075 $course->id,
1076 $teacherrole->id);
1077 $this->setUser($teacher);
1078
1079 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1080 $params['course'] = $course->id;
1081 $params['assignfeedback_file_enabled'] = 1;
1082 $params['assignfeedback_comments_enabled'] = 1;
1083 $instance = $generator->create_instance($params);
1084 $cm = get_coursemodule_from_instance('assign', $instance->id);
1085 $context = context_module::instance($cm->id);
1086
1087 $assign = new assign($context, $cm, $course);
1088
1089 $student1 = self::getDataGenerator()->create_user();
1090 $student2 = self::getDataGenerator()->create_user();
40c3dacf 1091 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
05a6445a
DW
1092 $this->getDataGenerator()->enrol_user($student1->id,
1093 $course->id,
1094 $studentrole->id);
1095 $this->getDataGenerator()->enrol_user($student2->id,
1096 $course->id,
1097 $studentrole->id);
1098 // Simulate a grade.
1099 $this->setUser($teacher);
1100
1101 // Create a file in a draft area.
1102 $draftidfile = file_get_unused_draft_itemid();
1103
1104 $usercontext = context_user::instance($teacher->id);
1105 $filerecord = array(
1106 'contextid' => $usercontext->id,
1107 'component' => 'user',
1108 'filearea' => 'draft',
1109 'itemid' => $draftidfile,
1110 'filepath' => '/',
1111 'filename' => 'testtext.txt',
1112 );
1113
1114 $fs = get_file_storage();
1115 $fs->create_file_from_string($filerecord, 'text contents');
1116
539af602 1117 // Now try a grade.
05a6445a
DW
1118 $feedbackpluginparams = array();
1119 $feedbackpluginparams['files_filemanager'] = $draftidfile;
40c3dacf
PC
1120 $feedbackeditorparams = array('text' => 'Yeeha!',
1121 'format' => 1);
05a6445a 1122 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
539af602
DW
1123 $result = mod_assign_external::save_grade($instance->id,
1124 $student1->id,
1125 50.0,
1126 -1,
1127 true,
1128 'released',
1129 false,
1130 $feedbackpluginparams);
05a6445a 1131 // No warnings.
7f45111e 1132 $this->assertNull($result);
05a6445a
DW
1133
1134 $result = mod_assign_external::get_grades(array($instance->id));
7f45111e 1135 $result = external_api::clean_returnvalue(mod_assign_external::get_grades_returns(), $result);
05a6445a 1136
85f47bae 1137 $this->assertEquals((float)$result['assignments'][0]['grades'][0]['grade'], '50.0');
05a6445a
DW
1138 }
1139
40c3dacf
PC
1140 /**
1141 * Test save grades with advanced grading data
1142 */
1143 public function test_save_grades_with_advanced_grading() {
1144 global $DB, $USER;
1145
1146 $this->resetAfterTest(true);
1147 // Create a course and assignment and users.
1148 $course = self::getDataGenerator()->create_course();
1149
1150 $teacher = self::getDataGenerator()->create_user();
1151 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1152 $this->getDataGenerator()->enrol_user($teacher->id,
1153 $course->id,
1154 $teacherrole->id);
1155
1156 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1157 $params['course'] = $course->id;
1158 $params['assignfeedback_file_enabled'] = 0;
1159 $params['assignfeedback_comments_enabled'] = 0;
1160 $instance = $generator->create_instance($params);
1161 $cm = get_coursemodule_from_instance('assign', $instance->id);
1162 $context = context_module::instance($cm->id);
1163
1164 $assign = new assign($context, $cm, $course);
1165
1166 $student1 = self::getDataGenerator()->create_user();
1167 $student2 = self::getDataGenerator()->create_user();
1168 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1169 $this->getDataGenerator()->enrol_user($student1->id,
1170 $course->id,
1171 $studentrole->id);
1172 $this->getDataGenerator()->enrol_user($student2->id,
1173 $course->id,
1174 $studentrole->id);
1175
1176 $this->setUser($teacher);
1177
1178 $feedbackpluginparams = array();
1179 $feedbackpluginparams['files_filemanager'] = 0;
1180 $feedbackeditorparams = array('text' => '', 'format' => 1);
1181 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1182
1183 // Create advanced grading data.
1184 // Create grading area.
1185 $gradingarea = array(
1186 'contextid' => $context->id,
1187 'component' => 'mod_assign',
1188 'areaname' => 'submissions',
1189 'activemethod' => 'rubric'
1190 );
1191 $areaid = $DB->insert_record('grading_areas', $gradingarea);
1192
1193 // Create a rubric grading definition.
1194 $rubricdefinition = array (
1195 'areaid' => $areaid,
1196 'method' => 'rubric',
1197 'name' => 'test',
1198 'status' => 20,
1199 'copiedfromid' => 1,
1200 'timecreated' => 1,
1201 'usercreated' => $teacher->id,
1202 'timemodified' => 1,
1203 'usermodified' => $teacher->id,
1204 'timecopied' => 0
1205 );
1206 $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
1207
1208 // Create a criterion with a level.
1209 $rubriccriteria = array (
1210 'definitionid' => $definitionid,
1211 'sortorder' => 1,
1212 'description' => 'Demonstrate an understanding of disease control',
1213 'descriptionformat' => 0
1214 );
1215 $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
1216 $rubriclevel1 = array (
1217 'criterionid' => $criterionid,
1218 'score' => 50,
1219 'definition' => 'pass',
1220 'definitionformat' => 0
1221 );
1222 $rubriclevel2 = array (
1223 'criterionid' => $criterionid,
1224 'score' => 100,
1225 'definition' => 'excellent',
1226 'definitionformat' => 0
1227 );
1228 $rubriclevel3 = array (
1229 'criterionid' => $criterionid,
1230 'score' => 0,
1231 'definition' => 'fail',
1232 'definitionformat' => 0
1233 );
1234 $levelid1 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
1235 $levelid2 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
1236 $levelid3 = $DB->insert_record('gradingform_rubric_levels', $rubriclevel3);
1237
1238 // Create the filling.
1239 $student1filling = array (
1240 'criterionid' => $criterionid,
1241 'levelid' => $levelid1,
1242 'remark' => 'well done you passed',
1243 'remarkformat' => 0
1244 );
1245
1246 $student2filling = array (
1247 'criterionid' => $criterionid,
1248 'levelid' => $levelid2,
1249 'remark' => 'Excellent work',
1250 'remarkformat' => 0
1251 );
1252
1253 $student1criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student1filling)));
1254 $student1advancedgradingdata = array('rubric' => array('criteria' => $student1criteria));
1255
1256 $student2criteria = array(array('criterionid' => $criterionid, 'fillings' => array($student2filling)));
1257 $student2advancedgradingdata = array('rubric' => array('criteria' => $student2criteria));
1258
1259 $grades = array();
1260 $student1gradeinfo = array();
1261 $student1gradeinfo['userid'] = $student1->id;
1262 $student1gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1263 $student1gradeinfo['attemptnumber'] = -1;
1264 $student1gradeinfo['addattempt'] = true;
1265 $student1gradeinfo['workflowstate'] = 'released';
1266 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1267 $student1gradeinfo['advancedgradingdata'] = $student1advancedgradingdata;
1268 $grades[] = $student1gradeinfo;
1269
1270 $student2gradeinfo = array();
1271 $student2gradeinfo['userid'] = $student2->id;
1272 $student2gradeinfo['grade'] = 0; // Ignored since advanced grading is being used.
1273 $student2gradeinfo['attemptnumber'] = -1;
1274 $student2gradeinfo['addattempt'] = true;
1275 $student2gradeinfo['workflowstate'] = 'released';
1276 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1277 $student2gradeinfo['advancedgradingdata'] = $student2advancedgradingdata;
1278 $grades[] = $student2gradeinfo;
1279
1280 $result = mod_assign_external::save_grades($instance->id, false, $grades);
7f45111e 1281 $this->assertNull($result);
40c3dacf
PC
1282
1283 $student1grade = $DB->get_record('assign_grades',
1284 array('userid' => $student1->id, 'assignment' => $instance->id),
1285 '*',
1286 MUST_EXIST);
85f47bae 1287 $this->assertEquals((float)$student1grade->grade, '50.0');
40c3dacf
PC
1288
1289 $student2grade = $DB->get_record('assign_grades',
1290 array('userid' => $student2->id, 'assignment' => $instance->id),
1291 '*',
1292 MUST_EXIST);
85f47bae 1293 $this->assertEquals((float)$student2grade->grade, '100.0');
40c3dacf
PC
1294 }
1295
1296 /**
1297 * Test save grades for a team submission
52f3e060
RT
1298 *
1299 * @expectedException invalid_parameter_exception
40c3dacf
PC
1300 */
1301 public function test_save_grades_with_group_submission() {
1302 global $DB, $USER, $CFG;
1303 require_once($CFG->dirroot . '/group/lib.php');
1304
1305 $this->resetAfterTest(true);
1306 // Create a course and assignment and users.
1307 $course = self::getDataGenerator()->create_course();
1308
1309 $teacher = self::getDataGenerator()->create_user();
1310 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1311 $this->getDataGenerator()->enrol_user($teacher->id,
1312 $course->id,
1313 $teacherrole->id);
1314
1315 $groupingdata = array();
1316 $groupingdata['courseid'] = $course->id;
1317 $groupingdata['name'] = 'Group assignment grouping';
1318
1319 $grouping = self::getDataGenerator()->create_grouping($groupingdata);
1320
1321 $group1data = array();
1322 $group1data['courseid'] = $course->id;
1323 $group1data['name'] = 'Team 1';
1324 $group2data = array();
1325 $group2data['courseid'] = $course->id;
1326 $group2data['name'] = 'Team 2';
1327
1328 $group1 = self::getDataGenerator()->create_group($group1data);
1329 $group2 = self::getDataGenerator()->create_group($group2data);
1330
1331 groups_assign_grouping($grouping->id, $group1->id);
1332 groups_assign_grouping($grouping->id, $group2->id);
1333
1334 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1335 $params['course'] = $course->id;
1336 $params['teamsubmission'] = 1;
1337 $params['teamsubmissiongroupingid'] = $grouping->id;
1338 $instance = $generator->create_instance($params);
1339 $cm = get_coursemodule_from_instance('assign', $instance->id);
1340 $context = context_module::instance($cm->id);
1341
1342 $assign = new assign($context, $cm, $course);
1343
1344 $student1 = self::getDataGenerator()->create_user();
1345 $student2 = self::getDataGenerator()->create_user();
1346 $student3 = self::getDataGenerator()->create_user();
1347 $student4 = self::getDataGenerator()->create_user();
1348 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1349 $this->getDataGenerator()->enrol_user($student1->id,
1350 $course->id,
1351 $studentrole->id);
1352 $this->getDataGenerator()->enrol_user($student2->id,
1353 $course->id,
1354 $studentrole->id);
1355 $this->getDataGenerator()->enrol_user($student3->id,
1356 $course->id,
1357 $studentrole->id);
1358 $this->getDataGenerator()->enrol_user($student4->id,
1359 $course->id,
1360 $studentrole->id);
1361
1362 groups_add_member($group1->id, $student1->id);
1363 groups_add_member($group1->id, $student2->id);
1364 groups_add_member($group1->id, $student3->id);
1365 groups_add_member($group2->id, $student4->id);
1366 $this->setUser($teacher);
1367
1368 $feedbackpluginparams = array();
1369 $feedbackpluginparams['files_filemanager'] = 0;
1370 $feedbackeditorparams = array('text' => '', 'format' => 1);
1371 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
1372
1373 $grades1 = array();
1374 $student1gradeinfo = array();
1375 $student1gradeinfo['userid'] = $student1->id;
1376 $student1gradeinfo['grade'] = 50;
1377 $student1gradeinfo['attemptnumber'] = -1;
1378 $student1gradeinfo['addattempt'] = true;
1379 $student1gradeinfo['workflowstate'] = 'released';
1380 $student1gradeinfo['plugindata'] = $feedbackpluginparams;
1381 $grades1[] = $student1gradeinfo;
1382
1383 $student2gradeinfo = array();
1384 $student2gradeinfo['userid'] = $student2->id;
1385 $student2gradeinfo['grade'] = 75;
1386 $student2gradeinfo['attemptnumber'] = -1;
1387 $student2gradeinfo['addattempt'] = true;
1388 $student2gradeinfo['workflowstate'] = 'released';
1389 $student2gradeinfo['plugindata'] = $feedbackpluginparams;
1390 $grades1[] = $student2gradeinfo;
1391
40c3dacf
PC
1392 // Expect an exception since 2 grades have been submitted for the same team.
1393 $result = mod_assign_external::save_grades($instance->id, true, $grades1);
7f45111e 1394 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
40c3dacf
PC
1395
1396 $grades2 = array();
1397 $student3gradeinfo = array();
1398 $student3gradeinfo['userid'] = $student3->id;
1399 $student3gradeinfo['grade'] = 50;
1400 $student3gradeinfo['attemptnumber'] = -1;
1401 $student3gradeinfo['addattempt'] = true;
1402 $student3gradeinfo['workflowstate'] = 'released';
1403 $student3gradeinfo['plugindata'] = $feedbackpluginparams;
1404 $grades2[] = $student3gradeinfo;
1405
1406 $student4gradeinfo = array();
1407 $student4gradeinfo['userid'] = $student4->id;
1408 $student4gradeinfo['grade'] = 75;
1409 $student4gradeinfo['attemptnumber'] = -1;
1410 $student4gradeinfo['addattempt'] = true;
1411 $student4gradeinfo['workflowstate'] = 'released';
1412 $student4gradeinfo['plugindata'] = $feedbackpluginparams;
1413 $grades2[] = $student4gradeinfo;
1414 $result = mod_assign_external::save_grades($instance->id, true, $grades2);
7f45111e 1415 $result = external_api::clean_returnvalue(mod_assign_external::save_grades_returns(), $result);
40c3dacf
PC
1416 // There should be no warnings.
1417 $this->assertEquals(0, count($result));
1418
1419 $student3grade = $DB->get_record('assign_grades',
1420 array('userid' => $student3->id, 'assignment' => $instance->id),
1421 '*',
1422 MUST_EXIST);
1423 $this->assertEquals($student3grade->grade, '50.0');
1424
1425 $student4grade = $DB->get_record('assign_grades',
1426 array('userid' => $student4->id, 'assignment' => $instance->id),
1427 '*',
1428 MUST_EXIST);
1429 $this->assertEquals($student4grade->grade, '75.0');
1430 }
1431
05a6445a
DW
1432 /**
1433 * Test copy_previous_attempt
1434 */
1435 public function test_copy_previous_attempt() {
1436 global $DB, $USER;
1437
1438 $this->resetAfterTest(true);
1439 // Create a course and assignment and users.
1440 $course = self::getDataGenerator()->create_course();
1441
1442 $teacher = self::getDataGenerator()->create_user();
1443 $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
1444 $this->getDataGenerator()->enrol_user($teacher->id,
1445 $course->id,
1446 $teacherrole->id);
1447 $this->setUser($teacher);
1448
1449 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1450 $params['course'] = $course->id;
1451 $params['assignsubmission_onlinetext_enabled'] = 1;
1452 $params['assignsubmission_file_enabled'] = 0;
1453 $params['assignfeedback_file_enabled'] = 0;
1454 $params['attemptreopenmethod'] = 'manual';
1455 $params['maxattempts'] = 5;
1456 $instance = $generator->create_instance($params);
1457 $cm = get_coursemodule_from_instance('assign', $instance->id);
1458 $context = context_module::instance($cm->id);
1459
1460 $assign = new assign($context, $cm, $course);
1461
1462 $student1 = self::getDataGenerator()->create_user();
1463 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
1464 $this->getDataGenerator()->enrol_user($student1->id,
1465 $course->id,
1466 $studentrole->id);
539af602 1467 // Now try a submission.
05a6445a
DW
1468 $this->setUser($student1);
1469 $draftidonlinetext = file_get_unused_draft_itemid();
1470 $submissionpluginparams = array();
1471 $onlinetexteditorparams = array('text'=>'Yeeha!',
1472 'format'=>1,
1473 'itemid'=>$draftidonlinetext);
1474 $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
1475 $submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1476 $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
7f45111e 1477 $result = external_api::clean_returnvalue(mod_assign_external::save_submission_returns(), $result);
05a6445a
DW
1478
1479 $this->setUser($teacher);
1480 // Add a grade and reopen the attempt.
539af602 1481 // Now try a grade.
05a6445a
DW
1482 $feedbackpluginparams = array();
1483 $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
1484 $feedbackeditorparams = array('text'=>'Yeeha!',
1485 'format'=>1);
1486 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
539af602
DW
1487 $result = mod_assign_external::save_grade($instance->id,
1488 $student1->id,
1489 50.0,
1490 -1,
1491 true,
1492 'released',
1493 false,
1494 $feedbackpluginparams);
7f45111e 1495 $this->assertNull($result);
05a6445a
DW
1496
1497 $this->setUser($student1);
1498 // Now copy the previous attempt.
1499 $result = mod_assign_external::copy_previous_attempt($instance->id);
7f45111e 1500 $result = external_api::clean_returnvalue(mod_assign_external::copy_previous_attempt_returns(), $result);
05a6445a
DW
1501 // No warnings.
1502 $this->assertEquals(0, count($result));
1503
1504 $this->setUser($teacher);
1505 $result = mod_assign_external::get_submissions(array($instance->id));
7f45111e 1506 $result = external_api::clean_returnvalue(mod_assign_external::get_submissions_returns(), $result);
05a6445a
DW
1507
1508 // Check we are now on the second attempt.
1509 $this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
1510 // Check the plugins data is not empty.
1511 $this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
1512
1513 }
e8b443df
PC
1514
1515 /**
1516 * Test set_user_flags
1517 */
1518 public function test_set_user_flags() {
1519 global $DB, $USER;
1520
1521 $this->resetAfterTest(true);
1522 // Create a course and assignment.
1523 $coursedata['idnumber'] = 'idnumbercourse';
1524 $coursedata['fullname'] = 'Lightwork Course';
1525 $coursedata['summary'] = 'Lightwork Course description';
1526 $coursedata['summaryformat'] = FORMAT_MOODLE;
1527 $course = self::getDataGenerator()->create_course($coursedata);
1528
1529 $assigndata['course'] = $course->id;
1530 $assigndata['name'] = 'lightwork assignment';
1531
1532 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
1533
1534 // Create a manual enrolment record.
1535 $manualenroldata['enrol'] = 'manual';
1536 $manualenroldata['status'] = 0;
1537 $manualenroldata['courseid'] = $course->id;
1538 $enrolid = $DB->insert_record('enrol', $manualenroldata);
1539
1540 // Create a teacher and give them capabilities.
1541 $context = context_course::instance($course->id);
1542 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
780cf0a7 1543 $context = context_module::instance($assign->cmid);
e8b443df
PC
1544 $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
1545
1546 // Create the teacher's enrolment record.
1547 $userenrolmentdata['status'] = 0;
1548 $userenrolmentdata['enrolid'] = $enrolid;
1549 $userenrolmentdata['userid'] = $USER->id;
1550 $DB->insert_record('user_enrolments', $userenrolmentdata);
1551
1552 // Create a student.
1553 $student = self::getDataGenerator()->create_user();
1554
1555 // Create test user flags record.
1556 $userflags = array();
1557 $userflag['userid'] = $student->id;
1558 $userflag['workflowstate'] = 'inmarking';
1559 $userflag['allocatedmarker'] = $USER->id;
1560 $userflags = array($userflag);
1561
1562 $createduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1563 // We need to execute the return values cleaning process to simulate the web service server.
1564 $createduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $createduserflags);
1565
1566 $this->assertEquals($student->id, $createduserflags[0]['userid']);
1567 $createduserflag = $DB->get_record('assign_user_flags', array('id' => $createduserflags[0]['id']));
1568
1569 // Confirm that all data was inserted correctly.
1570 $this->assertEquals($student->id, $createduserflag->userid);
1571 $this->assertEquals($assign->id, $createduserflag->assignment);
1572 $this->assertEquals(0, $createduserflag->locked);
1573 $this->assertEquals(2, $createduserflag->mailed);
1574 $this->assertEquals(0, $createduserflag->extensionduedate);
1575 $this->assertEquals('inmarking', $createduserflag->workflowstate);
1576 $this->assertEquals($USER->id, $createduserflag->allocatedmarker);
1577
1578 // Create update data.
1579 $userflags = array();
1580 $userflag['userid'] = $createduserflag->userid;
1581 $userflag['workflowstate'] = 'readyforreview';
1582 $userflags = array($userflag);
1583
1584 $updateduserflags = mod_assign_external::set_user_flags($assign->id, $userflags);
1585 // We need to execute the return values cleaning process to simulate the web service server.
1586 $updateduserflags = external_api::clean_returnvalue(mod_assign_external::set_user_flags_returns(), $updateduserflags);
1587
1588 $this->assertEquals($student->id, $updateduserflags[0]['userid']);
1589 $updateduserflag = $DB->get_record('assign_user_flags', array('id' => $updateduserflags[0]['id']));
1590
1591 // Confirm that all data was updated correctly.
1592 $this->assertEquals($student->id, $updateduserflag->userid);
1593 $this->assertEquals($assign->id, $updateduserflag->assignment);
1594 $this->assertEquals(0, $updateduserflag->locked);
1595 $this->assertEquals(2, $updateduserflag->mailed);
1596 $this->assertEquals(0, $updateduserflag->extensionduedate);
1597 $this->assertEquals('readyforreview', $updateduserflag->workflowstate);
1598 $this->assertEquals($USER->id, $updateduserflag->allocatedmarker);
1599 }
1600
91a12bc6
JL
1601 /**
1602 * Test view_grading_table
52f3e060
RT
1603 *
1604 * @expectedException dml_missing_record_exception
91a12bc6 1605 */
64d64656 1606 public function test_view_grading_table_invalid_instance() {
91a12bc6
JL
1607 global $DB;
1608
1609 $this->resetAfterTest(true);
1610
91a12bc6
JL
1611 // Setup test data.
1612 $course = $this->getDataGenerator()->create_course();
1613 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1614 $context = context_module::instance($assign->cmid);
1615 $cm = get_coursemodule_from_instance('assign', $assign->id);
1616
1617 // Test invalid instance id.
64d64656
AN
1618 mod_assign_external::view_grading_table(0);
1619 }
1620
1621 /**
1622 * Test view_grading_table
52f3e060
RT
1623 *
1624 * @expectedException require_login_exception
64d64656
AN
1625 */
1626 public function test_view_grading_table_not_enrolled() {
1627 global $DB;
1628
1629 $this->resetAfterTest(true);
1630
1631 // Setup test data.
1632 $course = $this->getDataGenerator()->create_course();
1633 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1634 $context = context_module::instance($assign->cmid);
1635 $cm = get_coursemodule_from_instance('assign', $assign->id);
91a12bc6
JL
1636
1637 // Test not-enrolled user.
1638 $user = self::getDataGenerator()->create_user();
1639 $this->setUser($user);
64d64656 1640
64d64656
AN
1641 mod_assign_external::view_grading_table($assign->id);
1642 }
1643
1644 /**
1645 * Test view_grading_table
1646 */
1647 public function test_view_grading_table_correct() {
1648 global $DB;
1649
1650 $this->resetAfterTest(true);
1651
1652 // Setup test data.
1653 $course = $this->getDataGenerator()->create_course();
1654 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1655 $context = context_module::instance($assign->cmid);
1656 $cm = get_coursemodule_from_instance('assign', $assign->id);
91a12bc6
JL
1657
1658 // Test user with full capabilities.
64d64656
AN
1659 $user = self::getDataGenerator()->create_user();
1660 $this->setUser($user);
91a12bc6
JL
1661 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1662 $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1663
1664 // Trigger and capture the event.
1665 $sink = $this->redirectEvents();
1666
1667 $result = mod_assign_external::view_grading_table($assign->id);
1668 $result = external_api::clean_returnvalue(mod_assign_external::view_grading_table_returns(), $result);
1669
1670 $events = $sink->get_events();
1671 $this->assertCount(1, $events);
1672 $event = array_shift($events);
1673
1674 // Checking that the event contains the expected values.
1675 $this->assertInstanceOf('\mod_assign\event\grading_table_viewed', $event);
1676 $this->assertEquals($context, $event->get_context());
1677 $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1678 $this->assertEquals($moodleurl, $event->get_url());
1679 $this->assertEventContextNotUsed($event);
1680 $this->assertNotEmpty($event->get_name());
64d64656
AN
1681 }
1682
1683 /**
1684 * Test view_grading_table
52f3e060
RT
1685 *
1686 * @expectedException require_login_exception
1687 * @expectedExceptionMessage Course or activity not accessible. (Activity is hidden)
64d64656
AN
1688 */
1689 public function test_view_grading_table_without_capability() {
1690 global $DB;
1691
1692 $this->resetAfterTest(true);
1693
1694 // Setup test data.
1695 $course = $this->getDataGenerator()->create_course();
1696 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1697 $context = context_module::instance($assign->cmid);
1698 $cm = get_coursemodule_from_instance('assign', $assign->id);
91a12bc6
JL
1699
1700 // Test user with no capabilities.
64d64656
AN
1701 $user = self::getDataGenerator()->create_user();
1702 $this->setUser($user);
1703 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1704 $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
1705
91a12bc6 1706 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
64d64656 1707 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
91a12bc6 1708 assign_capability('mod/assign:view', CAP_PROHIBIT, $teacherrole->id, $context->id);
0bf6c0be 1709 // Empty all the caches that may be affected by this change.
91a12bc6 1710 accesslib_clear_all_caches_for_unit_testing();
0bf6c0be 1711 course_modinfo::clear_instance_cache();
91a12bc6 1712
64d64656 1713 mod_assign_external::view_grading_table($assign->id);
91a12bc6
JL
1714 }
1715
7cc21061
JL
1716 /**
1717 * Test subplugins availability
1718 */
1719 public function test_subplugins_availability() {
1720 global $CFG;
1721
1722 require_once($CFG->dirroot . '/mod/assign/adminlib.php');
1723 $this->resetAfterTest(true);
1724
1725 // Hide assignment file submissiong plugin.
1726 $pluginmanager = new assign_plugin_manager('assignsubmission');
1727 $pluginmanager->hide_plugin('file');
1728 $parameters = mod_assign_external::save_submission_parameters();
1729
1730 $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1731
1732 // Show it again and check that the value is returned as optional.
1733 $pluginmanager->show_plugin('file');
1734 $parameters = mod_assign_external::save_submission_parameters();
1735 $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1736 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1737
1738 // Hide feedback file submissiong plugin.
1739 $pluginmanager = new assign_plugin_manager('assignfeedback');
1740 $pluginmanager->hide_plugin('file');
1741
1742 $parameters = mod_assign_external::save_grade_parameters();
1743
1744 $this->assertTrue(!isset($parameters->keys['plugindata']->keys['files_filemanager']));
1745
1746 // Show it again and check that the value is returned as optional.
1747 $pluginmanager->show_plugin('file');
1748 $parameters = mod_assign_external::save_grade_parameters();
1749
1750 $this->assertTrue(isset($parameters->keys['plugindata']->keys['files_filemanager']));
1751 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['files_filemanager']->required);
1752
1753 // Check a different one.
1754 $pluginmanager->show_plugin('comments');
1755 $this->assertTrue(isset($parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']));
1756 $this->assertEquals(VALUE_OPTIONAL, $parameters->keys['plugindata']->keys['assignfeedbackcomments_editor']->required);
1757 }
1758
e3e036ee
JL
1759 /**
1760 * Test test_view_submission_status
1761 */
1762 public function test_view_submission_status() {
1763 global $DB;
1764
1765 $this->resetAfterTest(true);
1766
1767 $this->setAdminUser();
1768 // Setup test data.
1769 $course = $this->getDataGenerator()->create_course();
1770 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
1771 $context = context_module::instance($assign->cmid);
1772 $cm = get_coursemodule_from_instance('assign', $assign->id);
1773
1774 // Test invalid instance id.
1775 try {
1776 mod_assign_external::view_submission_status(0);
1777 $this->fail('Exception expected due to invalid mod_assign instance id.');
1778 } catch (moodle_exception $e) {
1779 $this->assertEquals('invalidrecord', $e->errorcode);
1780 }
1781
1782 // Test not-enrolled user.
1783 $user = self::getDataGenerator()->create_user();
1784 $this->setUser($user);
1785 try {
1786 mod_assign_external::view_submission_status($assign->id);
1787 $this->fail('Exception expected due to not enrolled user.');
1788 } catch (moodle_exception $e) {
1789 $this->assertEquals('requireloginerror', $e->errorcode);
1790 }
1791
1792 // Test user with full capabilities.
1793 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1794 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
1795
1796 // Trigger and capture the event.
1797 $sink = $this->redirectEvents();
1798
1799 $result = mod_assign_external::view_submission_status($assign->id);
1800 $result = external_api::clean_returnvalue(mod_assign_external::view_submission_status_returns(), $result);
1801
1802 $events = $sink->get_events();
1803 $this->assertCount(1, $events);
1804 $event = array_shift($events);
1805
1806 // Checking that the event contains the expected values.
1807 $this->assertInstanceOf('\mod_assign\event\submission_status_viewed', $event);
1808 $this->assertEquals($context, $event->get_context());
1809 $moodleurl = new \moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1810 $this->assertEquals($moodleurl, $event->get_url());
1811 $this->assertEventContextNotUsed($event);
1812 $this->assertNotEmpty($event->get_name());
1813
1814 // Test user with no capabilities.
1815 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
1816 assign_capability('mod/assign:view', CAP_PROHIBIT, $studentrole->id, $context->id);
1817 accesslib_clear_all_caches_for_unit_testing();
1818 course_modinfo::clear_instance_cache();
1819
1820 try {
1821 mod_assign_external::view_submission_status($assign->id);
1822 $this->fail('Exception expected due to missing capability.');
1823 } catch (moodle_exception $e) {
1824 $this->assertEquals('requireloginerror', $e->errorcode);
1825 }
e3e036ee
JL
1826 }
1827
bdf1ac27
JL
1828 /**
1829 * Create a submission for testing the get_submission_status function.
1830 * @param boolean $submitforgrading whether to submit for grading the submission
1831 * @return array an array containing all the required data for testing
1832 */
1833 private function create_submission_for_testing_status($submitforgrading = false) {
a6b8fc78 1834 global $DB;
bdf1ac27
JL
1835
1836 // Create a course and assignment and users.
ff626f7b
JL
1837 $course = self::getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
1838
1839 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
1840 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
bdf1ac27
JL
1841
1842 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1843 $params = array(
1844 'course' => $course->id,
1845 'assignsubmission_file_maxfiles' => 1,
1846 'assignsubmission_file_maxsizebytes' => 1024 * 1024,
1847 'assignsubmission_onlinetext_enabled' => 1,
1848 'assignsubmission_file_enabled' => 1,
1849 'submissiondrafts' => 1,
1850 'assignfeedback_file_enabled' => 1,
1851 'assignfeedback_comments_enabled' => 1,
1852 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1853 'sendnotifications' => 0
1854 );
1855
1856 set_config('submissionreceipts', 0, 'assign');
1857
1858 $instance = $generator->create_instance($params);
1859 $cm = get_coursemodule_from_instance('assign', $instance->id);
1860 $context = context_module::instance($cm->id);
1861
a6b8fc78 1862 $assign = new mod_assign_testable_assign($context, $cm, $course);
bdf1ac27
JL
1863
1864 $student1 = self::getDataGenerator()->create_user();
1865 $student2 = self::getDataGenerator()->create_user();
1866 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1867 $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
1868 $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
1869 $teacher = self::getDataGenerator()->create_user();
1870 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
1871 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
1872
ff626f7b
JL
1873 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $student1->id));
1874 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $teacher->id));
1875 $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $student2->id));
1876 $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $teacher->id));
1877
bdf1ac27
JL
1878 $this->setUser($student1);
1879
1880 // Create a student1 with an online text submission.
1881 // Simulate a submission.
1882 $submission = $assign->get_user_submission($student1->id, true);
1883
1884 $data = new stdClass();
1885 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
38b1f8fd 1886 'text' => 'Submission text with a <a href="@@PLUGINFILE@@/intro.txt">link</a>',
bdf1ac27
JL
1887 'format' => FORMAT_MOODLE);
1888
1889 $draftidfile = file_get_unused_draft_itemid();
1890 $usercontext = context_user::instance($student1->id);
1891 $filerecord = array(
1892 'contextid' => $usercontext->id,
1893 'component' => 'user',
1894 'filearea' => 'draft',
1895 'itemid' => $draftidfile,
1896 'filepath' => '/',
1897 'filename' => 't.txt',
1898 );
1899 $fs = get_file_storage();
1900 $fs->create_file_from_string($filerecord, 'text contents');
1901
1902 $data->files_filemanager = $draftidfile;
1903
1904 $notices = array();
1905 $assign->save_submission($data, $notices);
1906
1907 if ($submitforgrading) {
1908 // Now, submit the draft for grading.
1909 $notices = array();
1910
1911 $data = new stdClass;
1912 $data->userid = $student1->id;
1913 $assign->submit_for_grading($data, $notices);
1914 }
1915
ff626f7b 1916 return array($assign, $instance, $student1, $student2, $teacher, $group1, $group2);
bdf1ac27
JL
1917 }
1918
1919 /**
1920 * Test get_submission_status for a draft submission.
1921 */
1922 public function test_get_submission_status_in_draft_status() {
1923 $this->resetAfterTest(true);
1924
ff626f7b 1925 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
38b1f8fd 1926 $studentsubmission = $assign->get_user_submission($student1->id, true);
bdf1ac27
JL
1927
1928 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1929 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1930 $this->assertDebuggingCalled();
1931
1932 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1933
1934 // The submission is now in draft mode.
1935 $this->assertCount(0, $result['warnings']);
1936 $this->assertFalse(isset($result['gradingsummary']));
1937 $this->assertFalse(isset($result['feedback']));
1938 $this->assertFalse(isset($result['previousattempts']));
1939
1940 $this->assertTrue($result['lastattempt']['submissionsenabled']);
1941 $this->assertTrue($result['lastattempt']['canedit']);
1942 $this->assertTrue($result['lastattempt']['cansubmit']);
1943 $this->assertFalse($result['lastattempt']['locked']);
1944 $this->assertFalse($result['lastattempt']['graded']);
1945 $this->assertEmpty($result['lastattempt']['extensionduedate']);
1946 $this->assertFalse($result['lastattempt']['blindmarking']);
1947 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
1948 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
1949
1950 $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
1951 $this->assertEquals(0, $result['lastattempt']['submission']['attemptnumber']);
1952 $this->assertEquals('draft', $result['lastattempt']['submission']['status']);
1953 $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
1954 $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
1955 $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
11ee4f71
AO
1956
1957 // Map plugins based on their type - we can't rely on them being in a
1958 // particular order, especially if 3rd party plugins are installed.
1959 $submissionplugins = array();
1960 foreach ($result['lastattempt']['submission']['plugins'] as $plugin) {
1961 $submissionplugins[$plugin['type']] = $plugin;
1962 }
38b1f8fd
DP
1963
1964 // Format expected online text.
1965 $onlinetext = 'Submission text with a <a href="@@PLUGINFILE@@/intro.txt">link</a>';
1966 list($expectedtext, $expectedformat) = external_format_text($onlinetext, FORMAT_HTML, $assign->get_context()->id,
1967 'assignsubmission_onlinetext', ASSIGNSUBMISSION_ONLINETEXT_FILEAREA, $studentsubmission->id);
1968
1969 $this->assertEquals($expectedtext, $submissionplugins['onlinetext']['editorfields'][0]['text']);
1970 $this->assertEquals($expectedformat, $submissionplugins['onlinetext']['editorfields'][0]['format']);
14590070
JL
1971 $this->assertEquals('/', $submissionplugins['file']['fileareas'][0]['files'][0]['filepath']);
1972 $this->assertEquals('t.txt', $submissionplugins['file']['fileareas'][0]['files'][0]['filename']);
bdf1ac27
JL
1973 }
1974
1975 /**
1976 * Test get_submission_status for a submitted submission.
1977 */
1978 public function test_get_submission_status_in_submission_status() {
1979 $this->resetAfterTest(true);
1980
ff626f7b 1981 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(true);
bdf1ac27
JL
1982
1983 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
1984 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
1985 $this->assertDebuggingCalled();
1986 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
1987
1988 $this->assertCount(0, $result['warnings']);
1989 $this->assertFalse(isset($result['gradingsummary']));
1990 $this->assertFalse(isset($result['feedback']));
1991 $this->assertFalse(isset($result['previousattempts']));
1992
1993 $this->assertTrue($result['lastattempt']['submissionsenabled']);
1994 $this->assertFalse($result['lastattempt']['canedit']);
1995 $this->assertFalse($result['lastattempt']['cansubmit']);
1996 $this->assertFalse($result['lastattempt']['locked']);
1997 $this->assertFalse($result['lastattempt']['graded']);
1998 $this->assertEmpty($result['lastattempt']['extensionduedate']);
1999 $this->assertFalse($result['lastattempt']['blindmarking']);
2000 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
2001 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
2002
2003 }
2004
2005 /**
2006 * Test get_submission_status using the teacher role.
2007 */
2008 public function test_get_submission_status_in_submission_status_for_teacher() {
2009 $this->resetAfterTest(true);
2010
ff626f7b 2011 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(true);
bdf1ac27
JL
2012
2013 // Now, as teacher, see the grading summary.
2014 $this->setUser($teacher);
ff626f7b
JL
2015 // First one group.
2016 $result = mod_assign_external::get_submission_status($assign->get_instance()->id, 0, $g1->id);
bdf1ac27
JL
2017 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
2018 $this->assertDebuggingCalled();
2019 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2020
2021 $this->assertCount(0, $result['warnings']);
2022 $this->assertFalse(isset($result['lastattempt']));
2023 $this->assertFalse(isset($result['feedback']));
2024 $this->assertFalse(isset($result['previousattempts']));
2025
ff626f7b 2026 $this->assertEquals(1, $result['gradingsummary']['participantcount']);
bdf1ac27
JL
2027 $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
2028 $this->assertEquals(1, $result['gradingsummary']['submissionsenabled']);
ddeabbc5
JL
2029 $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
2030 $this->assertEquals(1, $result['gradingsummary']['submissionssubmittedcount']); // One student from G1 submitted.
2031 $this->assertEquals(1, $result['gradingsummary']['submissionsneedgradingcount']); // One student from G1 submitted.
8773296b 2032 $this->assertEmpty($result['gradingsummary']['warnofungroupedusers']);
ff626f7b
JL
2033
2034 // Second group.
2035 $result = mod_assign_external::get_submission_status($assign->get_instance()->id, 0, $g2->id);
2036 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2037 $this->assertCount(0, $result['warnings']);
2038 $this->assertEquals(1, $result['gradingsummary']['participantcount']);
ddeabbc5
JL
2039 $this->assertEquals(0, $result['gradingsummary']['submissionssubmittedcount']); // G2 students didn't submit yet.
2040 $this->assertEquals(0, $result['gradingsummary']['submissionsneedgradingcount']); // G2 students didn't submit yet.
ff626f7b
JL
2041
2042 // Should return also 1 participant if we allow the function to auto-select the group.
2043 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
2044 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2045 $this->assertCount(0, $result['warnings']);
2046 $this->assertEquals(1, $result['gradingsummary']['participantcount']);
ddeabbc5
JL
2047 $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
2048 $this->assertEquals(1, $result['gradingsummary']['submissionssubmittedcount']); // One student from G1 submitted.
2049 $this->assertEquals(1, $result['gradingsummary']['submissionsneedgradingcount']); // One student from G1 submitted.
2050
2051 // Now check draft submissions.
2052 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(false);
2053 $this->setUser($teacher);
2054 $result = mod_assign_external::get_submission_status($assign->get_instance()->id, 0, $g1->id);
2055 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2056 $this->assertCount(0, $result['warnings']);
2057 $this->assertEquals(1, $result['gradingsummary']['participantcount']);
2058 $this->assertEquals(1, $result['gradingsummary']['submissiondraftscount']); // We have a draft submission.
2059 $this->assertEquals(0, $result['gradingsummary']['submissionssubmittedcount']); // We have only draft submissions.
2060 $this->assertEquals(0, $result['gradingsummary']['submissionsneedgradingcount']); // We have only draft submissions.
bdf1ac27
JL
2061 }
2062
2063 /**
2064 * Test get_submission_status for a reopened submission.
2065 */
2066 public function test_get_submission_status_in_reopened_status() {
2067 global $USER;
2068
2069 $this->resetAfterTest(true);
2070
ff626f7b 2071 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(true);
38b1f8fd 2072 $studentsubmission = $assign->get_user_submission($student1->id, true);
bdf1ac27
JL
2073
2074 $this->setUser($teacher);
2075 // Grade and reopen.
2076 $feedbackpluginparams = array();
2077 $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
2078 $feedbackeditorparams = array('text' => 'Yeeha!',
2079 'format' => 1);
2080 $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
2081 $result = mod_assign_external::save_grade($instance->id,
2082 $student1->id,
2083 50.0,
2084 -1,
2085 false,
2086 'released',
2087 false,
2088 $feedbackpluginparams);
2089 $USER->ignoresesskey = true;
2090 $assign->testable_process_add_attempt($student1->id);
2091
2092 $this->setUser($student1);
2093
2094 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
2095 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
2096 $this->assertDebuggingCalled();
2097 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2098
2099 $this->assertCount(0, $result['warnings']);
2100 $this->assertFalse(isset($result['gradingsummary']));
2101
2102 $this->assertTrue($result['lastattempt']['submissionsenabled']);
2103 $this->assertTrue($result['lastattempt']['canedit']);
2104 $this->assertFalse($result['lastattempt']['cansubmit']);
2105 $this->assertFalse($result['lastattempt']['locked']);
2106 $this->assertFalse($result['lastattempt']['graded']);
2107 $this->assertEmpty($result['lastattempt']['extensionduedate']);
2108 $this->assertFalse($result['lastattempt']['blindmarking']);
2109 $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
2110 $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
2111
2112 // Check new attempt reopened.
2113 $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
2114 $this->assertEquals(1, $result['lastattempt']['submission']['attemptnumber']);
2115 $this->assertEquals('reopened', $result['lastattempt']['submission']['status']);
2116 $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
2117 $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
2118 $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
2119 $this->assertCount(3, $result['lastattempt']['submission']['plugins']);
2120
2121 // Now see feedback and the attempts history (remember, is a submission reopened).
2122 // Only 2 fields (no grade, no plugins data).
2123 $this->assertCount(2, $result['feedback']);
2124
2125 // One previous attempt.
2126 $this->assertCount(1, $result['previousattempts']);
2127 $this->assertEquals(0, $result['previousattempts'][0]['attemptnumber']);
2128 $this->assertEquals(50, $result['previousattempts'][0]['grade']['grade']);
2129 $this->assertEquals($teacher->id, $result['previousattempts'][0]['grade']['grader']);
2130 $this->assertEquals($student1->id, $result['previousattempts'][0]['grade']['userid']);
11ee4f71
AO
2131
2132 // Map plugins based on their type - we can't rely on them being in a
2133 // particular order, especially if 3rd party plugins are installed.
2134 $feedbackplugins = array();
2135 foreach ($result['previousattempts'][0]['feedbackplugins'] as $plugin) {
2136 $feedbackplugins[$plugin['type']] = $plugin;
2137 }
2138 $this->assertEquals('Yeeha!', $feedbackplugins['comments']['editorfields'][0]['text']);
2139
2140 $submissionplugins = array();
2141 foreach ($result['previousattempts'][0]['submission']['plugins'] as $plugin) {
2142 $submissionplugins[$plugin['type']] = $plugin;
2143 }
38b1f8fd
DP
2144 // Format expected online text.
2145 $onlinetext = 'Submission text with a <a href="@@PLUGINFILE@@/intro.txt">link</a>';
2146 list($expectedtext, $expectedformat) = external_format_text($onlinetext, FORMAT_HTML, $assign->get_context()->id,
2147 'assignsubmission_onlinetext', ASSIGNSUBMISSION_ONLINETEXT_FILEAREA, $studentsubmission->id);
2148
2149 $this->assertEquals($expectedtext, $submissionplugins['onlinetext']['editorfields'][0]['text']);
2150 $this->assertEquals($expectedformat, $submissionplugins['onlinetext']['editorfields'][0]['format']);
14590070
JL
2151 $this->assertEquals('/', $submissionplugins['file']['fileareas'][0]['files'][0]['filepath']);
2152 $this->assertEquals('t.txt', $submissionplugins['file']['fileareas'][0]['files'][0]['filename']);
372dd371 2153
bdf1ac27
JL
2154 }
2155
2156 /**
2157 * Test access control for get_submission_status.
52f3e060
RT
2158 *
2159 * @expectedException required_capability_exception
bdf1ac27
JL
2160 */
2161 public function test_get_submission_status_access_control() {
2162 $this->resetAfterTest(true);
2163
ff626f7b 2164 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
bdf1ac27
JL
2165
2166 $this->setUser($student2);
2167
2168 // Access control test.
bdf1ac27
JL
2169 mod_assign_external::get_submission_status($assign->get_instance()->id, $student1->id);
2170
2171 }
1b2f9dc6 2172
468ee73b
DP
2173 /**
2174 * Test hidden grader for get_submission_status.
2175 */
2176 public function test_get_submission_status_hidden_grader() {
2177 $this->resetAfterTest(true);
2178
2179 list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(true);
2180
2181 // Grade the assign for the student1.
2182 $this->setUser($teacher);
2183
2184 $data = new stdClass();
2185 $data->grade = '50.0';
2186 $data->assignfeedbackcomments_editor = ['text' => ''];
2187 $assign->testable_apply_grade_to_user($data, $student1->id, 0);
2188
2189 $this->setUser($student1);
2190
2191 // Check that the student can see the grader by default.
2192 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
2193 // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
2194 $this->assertDebuggingCalled();
2195
2196 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2197
2198 $this->assertTrue(isset($result['feedback']));
2199 $this->assertTrue(isset($result['feedback']['grade']));
2200 $this->assertEquals($teacher->id, $result['feedback']['grade']['grader']);
2201
2202 // Now change the setting so the grader is hidden.
2203 $this->setAdminUser();
2204
2205 $instance = $assign->get_instance();
2206 $instance->instance = $instance->id;
2207 $instance->hidegrader = true;
2208 $assign->update_instance($instance);
2209
2210 $this->setUser($student1);
2211
2212 // Check that the student cannot see the grader anymore.
2213 $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
2214 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2215
2216 $this->assertTrue(isset($result['feedback']));
2217 $this->assertTrue(isset($result['feedback']['grade']));
2218 $this->assertEquals(-1, $result['feedback']['grade']['grader']);
2219
2220 // Check that the teacher can see the grader.
2221 $this->setUser($teacher);
2222
2223 $result = mod_assign_external::get_submission_status($assign->get_instance()->id, $student1->id);
2224 $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
2225
2226 $this->assertTrue(isset($result['feedback']));
2227 $this->assertTrue(isset($result['feedback']['grade']));
2228 $this->assertEquals($teacher->id, $result['feedback']['grade']['grader']);
2229 }
2230
1b2f9dc6
RW
2231 /**
2232 * get_participant should throw an excaption if the requested assignment doesn't exist.
52f3e060
RT
2233 *
2234 * @expectedException moodle_exception
1b2f9dc6
RW
2235 */
2236 public function test_get_participant_no_assignment() {
2237 $this->resetAfterTest(true);
1b2f9dc6
RW
2238 mod_assign_external::get_participant('-1', '-1', false);
2239 }
2240
2241 /**
2242 * get_participant should throw a require_login_exception if the user doesn't have access
2243 * to view assignments.
52f3e060
RT
2244 *
2245 * @expectedException require_login_exception
1b2f9dc6
RW
2246 */
2247 public function test_get_participant_no_view_capability() {
2248 global $DB;
2249 $this->resetAfterTest(true);
2250
2251 $result = $this->create_assign_with_student_and_teacher();
2252 $assign = $result['assign'];
2253 $student = $result['student'];
2254 $course = $result['course'];
2255 $context = context_course::instance($course->id);
2256 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
2257
2258 $this->setUser($student);
2259 assign_capability('mod/assign:view', CAP_PROHIBIT, $studentrole->id, $context->id, true);
2260
1b2f9dc6
RW
2261 mod_assign_external::get_participant($assign->id, $student->id, false);
2262 }
2263
2264 /**
2265 * get_participant should throw a required_capability_exception if the user doesn't have access
2266 * to view assignment grades.
52f3e060
RT
2267 *
2268 * @expectedException required_capability_exception
1b2f9dc6
RW
2269 */
2270 public function test_get_participant_no_grade_capability() {
2271 global $DB;
2272 $this->resetAfterTest(true);
2273
2274 $result = $this->create_assign_with_student_and_teacher();
2275 $assign = $result['assign'];
2276 $student = $result['student'];
2277 $teacher = $result['teacher'];
2278 $course = $result['course'];
2279 $context = context_course::instance($course->id);
2280 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2281
2282 $this->setUser($teacher);
2283 assign_capability('mod/assign:viewgrades', CAP_PROHIBIT, $teacherrole->id, $context->id, true);
2284 assign_capability('mod/assign:grade', CAP_PROHIBIT, $teacherrole->id, $context->id, true);
2285 accesslib_clear_all_caches_for_unit_testing();
2286
1b2f9dc6
RW
2287 mod_assign_external::get_participant($assign->id, $student->id, false);
2288 }
2289
2290 /**
2291 * get_participant should throw an exception if the user isn't enrolled in the course.
52f3e060
RT
2292 *
2293 * @expectedException moodle_exception
1b2f9dc6
RW
2294 */
2295 public function test_get_participant_no_participant() {
2296 global $DB;
2297 $this->resetAfterTest(true);
2298
2299 $result = $this->create_assign_with_student_and_teacher(array('blindmarking' => true));
2300 $student = $this->getDataGenerator()->create_user();
2301 $assign = $result['assign'];
2302 $teacher = $result['teacher'];
2303
2304 $this->setUser($teacher);
2305
1b2f9dc6 2306 $result = mod_assign_external::get_participant($assign->id, $student->id, false);
396395b8 2307 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
1b2f9dc6
RW
2308 }
2309
2310 /**
2311 * get_participant should return a summarised list of details with a different fullname if blind
2312 * marking is on for the requested assignment.
2313 */
2314 public function test_get_participant_blind_marking() {
2315 global $DB;
2316 $this->resetAfterTest(true);
2317
2318 $result = $this->create_assign_with_student_and_teacher(array('blindmarking' => true));
2319 $assign = $result['assign'];
2320 $student = $result['student'];
2321 $teacher = $result['teacher'];
2322 $course = $result['course'];
2323 $context = context_course::instance($course->id);
2324 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2325
2326 $this->setUser($teacher);
2327
2328 $result = mod_assign_external::get_participant($assign->id, $student->id, true);
396395b8 2329 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
1b2f9dc6
RW
2330 $this->assertEquals($student->id, $result['id']);
2331 $this->assertFalse(fullname($student) == $result['fullname']);
2332 $this->assertFalse($result['submitted']);
2333 $this->assertFalse($result['requiregrading']);
eb43ef6c 2334 $this->assertFalse($result['grantedextension']);
1b2f9dc6
RW
2335 $this->assertTrue($result['blindmarking']);
2336 // Make sure we don't get any additional info.
396395b8 2337 $this->assertArrayNotHasKey('user', $result);
1b2f9dc6
RW
2338 }
2339
2340 /**
2341 * get_participant should return a summarised list of details if requested.
2342 */
2343 public function test_get_participant_no_user() {
2344 global $DB;
2345 $this->resetAfterTest(true);
2346
2347 $result = $this->create_assign_with_student_and_teacher();
2348 $assignmodule = $result['assign'];
2349 $student = $result['student'];
2350 $teacher = $result['teacher'];
2351 $course = $result['course'];
2352 $context = context_course::instance($course->id);
2353 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2354
2355 // Create an assign instance to save a submission.
2356 set_config('submissionreceipts', 0, 'assign');
2357
2358 $cm = get_coursemodule_from_instance('assign', $assignmodule->id);
2359 $context = context_module::instance($cm->id);
2360
2361 $assign = new assign($context, $cm, $course);
2362
2363 $this->setUser($student);
2364
2365 // Simulate a submission.
2366 $data = new stdClass();
2367 $data->onlinetext_editor = array(
2368 'itemid' => file_get_unused_draft_itemid(),
2369 'text' => 'Student submission text',
2370 'format' => FORMAT_MOODLE
2371 );
2372
2373 $notices = array();
2374 $assign->save_submission($data, $notices);
2375
2376 $data = new stdClass;
2377 $data->userid = $student->id;
2378 $assign->submit_for_grading($data, array());
2379
2380 $this->setUser($teacher);
2381
2382 $result = mod_assign_external::get_participant($assignmodule->id, $student->id, false);
396395b8 2383 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
1b2f9dc6
RW
2384 $this->assertEquals($student->id, $result['id']);
2385 $this->assertEquals(fullname($student), $result['fullname']);
2386 $this->assertTrue($result['submitted']);
2387 $this->assertTrue($result['requiregrading']);
eb43ef6c 2388 $this->assertFalse($result['grantedextension']);
1b2f9dc6
RW
2389 $this->assertFalse($result['blindmarking']);
2390 // Make sure we don't get any additional info.
396395b8 2391 $this->assertArrayNotHasKey('user', $result);
1b2f9dc6
RW
2392 }
2393
2394 /**
2395 * get_participant should return user details if requested.
2396 */
2397 public function test_get_participant_full_details() {
2398 global $DB;
2399 $this->resetAfterTest(true);
2400
2401 $result = $this->create_assign_with_student_and_teacher();
2402 $assign = $result['assign'];
2403 $student = $result['student'];
2404 $teacher = $result['teacher'];
2405 $course = $result['course'];
2406 $context = context_course::instance($course->id);
2407 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2408
2409 $this->setUser($teacher);
2410
2411 $result = mod_assign_external::get_participant($assign->id, $student->id, true);
396395b8 2412 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
1b2f9dc6
RW
2413 // Check some of the extended properties we get when requesting the user.
2414 $this->assertEquals($student->id, $result['id']);
2415 // We should get user infomation back.
2416 $user = $result['user'];
2417 $this->assertFalse(empty($user));
2418 $this->assertEquals($student->firstname, $user['firstname']);
2419 $this->assertEquals($student->lastname, $user['lastname']);
2420 $this->assertEquals($student->email, $user['email']);
2421 }
2422
2423 /**
2424 * get_participant should return group details if a group submission was
2425 * submitted.
2426 */
2427 public function test_get_participant_group_submission() {
a6b8fc78 2428 global $DB;
1b2f9dc6
RW
2429
2430 $this->resetAfterTest(true);
2431
2432 $result = $this->create_assign_with_student_and_teacher(array(
2433 'assignsubmission_onlinetext_enabled' => 1,
2434 'teamsubmission' => 1
2435 ));
2436 $assignmodule = $result['assign'];
2437 $student = $result['student'];
2438 $teacher = $result['teacher'];
2439 $course = $result['course'];
2440 $context = context_course::instance($course->id);
2441 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2442 $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
2443 $cm = get_coursemodule_from_instance('assign', $assignmodule->id);
2444 $context = context_module::instance($cm->id);
a6b8fc78 2445 $assign = new mod_assign_testable_assign($context, $cm, $course);
1b2f9dc6
RW
2446
2447 groups_add_member($group, $student);
2448
2449 $this->setUser($student);
2450 $submission = $assign->get_group_submission($student->id, $group->id, true);
2451 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2452 $assign->testable_update_submission($submission, $student->id, true, false);
2453 $data = new stdClass();
2454 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
2455 'text' => 'Submission text',
2456 'format' => FORMAT_MOODLE);
2457 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2458 $plugin->save($submission, $data);
2459
2460 $this->setUser($teacher);
2461
2462 $result = mod_assign_external::get_participant($assignmodule->id, $student->id, false);
396395b8 2463 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
1b2f9dc6
RW
2464 // Check some of the extended properties we get when not requesting a summary.
2465 $this->assertEquals($student->id, $result['id']);
2466 $this->assertEquals($group->id, $result['groupid']);
2467 $this->assertEquals($group->name, $result['groupname']);
2468 }
2469
d0cff236
JD
2470 /**
2471 * Test get_participant() when relative dates mode is enabled on the course.
2472 *
2473 * @dataProvider get_participant_relative_dates_provider
2474 * @param array $courseconfig the config to use when creating the course.
2475 * @param array $assignconfig the config to use when creating the assignment.
2476 * @param array $enrolconfig the enrolement to create.
2477 * @param array $expectedproperties array of expected assign properties.
2478 */
2479 public function test_get_participant_relative_dates(array $courseconfig, array $assignconfig, array $enrolconfig,
2480 array $expectedproperties) {
2481 $this->resetAfterTest();
2482
2483 set_config('enablecourserelativedates', true); // Enable relative dates at site level.
2484
2485 $course = $this->getDataGenerator()->create_course($courseconfig);
2486 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
2487 $assignconfig['course'] = $course->id;
2488 $instance = $generator->create_instance($assignconfig);
2489 $cm = get_coursemodule_from_instance('assign', $instance->id);
2490 $context = context_module::instance($cm->id);
2491 $assign = new assign($context, $cm, $course);
2492
2493 $user = $this->getDataGenerator()->create_and_enrol($course, ...array_values($enrolconfig));
2494
2495 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher', null, 'manual', time() - 50 * DAYSECS);
2496
2497 $this->setUser($teacher);
2498 $result = mod_assign_external::get_participant($assign->get_instance()->id, $user->id, false);
2499 $result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
2500
2501 foreach ($expectedproperties as $propertyname => $propertyval) {
2502 $this->assertEquals($propertyval, $result[$propertyname]);
2503 }
2504 }
2505
2506 /**
2507 * The test_get_participant_relative_dates data provider.
2508 */
2509 public function get_participant_relative_dates_provider() {
2510 $timenow = time();
2511
2512 return [
2513 'Student whose enrolment starts after the course start date, relative dates mode enabled' => [
2514 'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
2515 'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
2516 'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
2517 'startdate' => $timenow - 8 * DAYSECS],
2518 'expectedproperties' => ['duedate' => $timenow + 6 * DAYSECS]
2519 ],
2520 'Student whose enrolment starts before the course start date, relative dates mode enabled' => [
2521 'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
2522 'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
2523 'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
2524 'startdate' => $timenow - 12 * DAYSECS],
2525 'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
2526 ],
2527 ];
2528 }
2529
7150323e
JP
2530 /**
2531 * Test for mod_assign_external::list_participants().
2532 *
2533 * @throws coding_exception
2534 */
2535 public function test_list_participants_user_info_with_special_characters() {
2536 global $CFG, $DB;
2537 $this->resetAfterTest(true);
2538 $CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
2539
2540 $data = $this->create_assign_with_student_and_teacher();
2541 $assignment = $data['assign'];
2542 $teacher = $data['teacher'];
2543
2544 // Set data for student info that contain special characters.
2545 $student = $data['student'];
2546 $student->idnumber = '<\'"1am@wesome&c00l"\'>';
2547 $student->phone1 = '+63 (999) 888-7777';
2548 $student->phone2 = '(011) [15]4-123-4567';
2549 $student->department = 'Arts & Sciences & \' " ¢ £ © € ¥ ® < >';
2550 $student->institution = 'University of Awesome People & \' " ¢ £ © € ¥ ® < >';
2551 // Assert that we have valid user data.
2552 $this->assertTrue(core_user::validate($student));
2553 // Update the user record.
2554 $DB->update_record('user', $student);
2555
2556 $this->setUser($teacher);
064f1503 2557 $participants = mod_assign_external::list_participants($assignment->id, 0, '', 0, 0, false, true, true);
396395b8 2558 $participants = external_api::clean_returnvalue(mod_assign_external::list_participants_returns(), $participants);
7150323e
JP
2559 $this->assertCount(1, $participants);
2560
2561 // Asser that we have a valid response data.
2562 $response = external_api::clean_returnvalue(mod_assign_external::list_participants_returns(), $participants);
2563 $this->assertEquals($response, $participants);
2564
2565 // Check participant data.
2566 $participant = $participants[0];
2567 $this->assertEquals($student->idnumber, $participant['idnumber']);
2568 $this->assertEquals($student->email, $participant['email']);
2569 $this->assertEquals($student->phone1, $participant['phone1']);
2570 $this->assertEquals($student->phone2, $participant['phone2']);
2571 $this->assertEquals($student->department, $participant['department']);
2572 $this->assertEquals($student->institution, $participant['institution']);
6399ecd7
JPG
2573 $this->assertArrayHasKey('enrolledcourses', $participant);
2574
064f1503 2575 $participants = mod_assign_external::list_participants($assignment->id, 0, '', 0, 0, false, false, true);
396395b8 2576 $participants = external_api::clean_returnvalue(mod_assign_external::list_participants_returns(), $participants);
6399ecd7
JPG
2577 // Check that the list of courses the participant is enrolled is not returned.
2578 $participant = $participants[0];
2579 $this->assertArrayNotHasKey('enrolledcourses', $participant);
7150323e
JP
2580 }
2581
2582 /**
2583 * Test for the type of the user-related properties in mod_assign_external::list_participants_returns().
7150323e
JP
2584 */
2585 public function test_list_participants_returns_user_property_types() {
920d3a95
JP
2586 // Get user properties.
2587 $userdesc = core_user_external::user_description();
2588 $this->assertTrue(isset($userdesc->keys));
2589 $userproperties = array_keys($userdesc->keys);
2590
2591 // Get returns description for mod_assign_external::list_participants_returns().
2592 $listreturns = mod_assign_external::list_participants_returns();
2593 $this->assertTrue(isset($listreturns->content));
2594 $listreturnsdesc = $listreturns->content->keys;
2595
2596 // Iterate over list returns description's keys.
2597 foreach ($listreturnsdesc as $key => $desc) {
2598 // Check if key exists in user properties and the description has a type attribute.
2599 if (in_array($key, $userproperties) && isset($desc->type)) {
2600 try {
2601 // The core_user::get_property_type() method might throw a coding_exception since
2602 // core_user_external::user_description() might contain properties that are not yet included in
2603 // core_user's $propertiescache.
2604 $propertytype = core_user::get_property_type($key);
2605
2606 // Assert that user-related property types match those of the defined in core_user.
2607 $this->assertEquals($propertytype, $desc->type);
2608 } catch (coding_exception $e) {
2609 // All good.
2610 }
2611 }
7150323e
JP
2612 }
2613 }
2614
1b2f9dc6
RW
2615 /**
2616 * Create a a course, assignment module instance, student and teacher and enrol them in
2617 * the course.
2618 *
2619 * @param array $params parameters to be provided to the assignment module creation
2620 * @return array containing the course, assignment module, student and teacher
2621 */
2622 private function create_assign_with_student_and_teacher($params = array()) {
2623 global $DB;
2624
2625 $course = $this->getDataGenerator()->create_course();
2626 $params = array_merge(array(
2627 'course' => $course->id,
2628 'name' => 'assignment',
2629 'intro' => 'assignment intro text',
2630 ), $params);
2631
2632 // Create a course and assignment and users.
2633 $assign = $this->getDataGenerator()->create_module('assign', $params);
2634
2635 $cm = get_coursemodule_from_instance('assign', $assign->id);
2636 $context = context_module::instance($cm->id);
2637
2638 $student = $this->getDataGenerator()->create_user();
2639 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
2640 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
2641 $teacher = $this->getDataGenerator()->create_user();
2642 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2643 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
2644
2645 assign_capability('mod/assign:view', CAP_ALLOW, $teacherrole->id, $context->id, true);
2646 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $teacherrole->id, $context->id, true);
2647 assign_capability('mod/assign:grade', CAP_ALLOW, $teacherrole->id, $context->id, true);
2648 accesslib_clear_all_caches_for_unit_testing();
2649
2650 return array(
2651 'course' => $course,
2652 'assign' => $assign,
2653 'student' => $student,
2654 'teacher' => $teacher
2655 );
2656 }
7336b66f
JL
2657
2658 /**
2659 * Test test_view_assign
2660 */
2661 public function test_view_assign() {
2662 global $CFG;
2663
2664 $CFG->enablecompletion = 1;
2665 $this->resetAfterTest();
2666
2667 $this->setAdminUser();
2668 // Setup test data.
2669 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
2670 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id),
2671 array('completion' => 2, 'completionview' => 1));
2672 $context = context_module::instance($assign->cmid);
2673 $cm = get_coursemodule_from_instance('assign', $assign->id);
2674
2675 $result = mod_assign_external::view_assign($assign->id);
2676 $result = external_api::clean_returnvalue(mod_assign_external::view_assign_returns(), $result);
2677 $this->assertTrue($result['status']);
2678 $this->assertEmpty($result['warnings']);
2679
2680 // Check completion status.
2681 $completion = new completion_info($course);
2682 $completiondata = $completion->get_data($cm);
2683 $this->assertEquals(1, $completiondata->completionstate);
2684 }
1f8c8f61 2685}