on-demand release 3.1beta+
[moodle.git] / mod / assign / tests / locallib_test.php
CommitLineData
47f48152
DW
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for (some of) mod/assign/locallib.php.
19 *
20 * @package mod_assign
21 * @category phpunit
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30require_once($CFG->dirroot . '/mod/assign/locallib.php');
31require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
9c986ee0 32require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
47f48152
DW
33
34/**
35 * Unit tests for (some of) mod/assign/locallib.php.
36 *
37 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
9c986ee0 40class mod_assign_locallib_testcase extends mod_assign_base_testcase {
47f48152
DW
41
42 public function test_return_links() {
c2114099 43 global $PAGE;
47f48152
DW
44 $this->setUser($this->editingteachers[0]);
45 $returnaction = 'RETURNACTION';
c2114099 46 $returnparams = array('param'=>'1');
47f48152 47 $assign = $this->create_instance();
c2114099 48 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
47f48152
DW
49 $assign->register_return_link($returnaction, $returnparams);
50 $this->assertEquals($returnaction, $assign->get_return_action());
51 $this->assertEquals($returnparams, $assign->get_return_params());
52 }
53
54 public function test_get_feedback_plugins() {
55 $this->setUser($this->editingteachers[0]);
56 $assign = $this->create_instance();
bd3b3bba 57 $installedplugins = array_keys(core_component::get_plugin_list('assignfeedback'));
11527706
DW
58
59 foreach ($assign->get_feedback_plugins() as $plugin) {
60 $this->assertContains($plugin->get_type(), $installedplugins, 'Feedback plugin not in list of installed plugins');
61 }
47f48152
DW
62 }
63
64 public function test_get_submission_plugins() {
65 $this->setUser($this->editingteachers[0]);
66 $assign = $this->create_instance();
bd3b3bba 67 $installedplugins = array_keys(core_component::get_plugin_list('assignsubmission'));
11527706
DW
68
69 foreach ($assign->get_submission_plugins() as $plugin) {
70 $this->assertContains($plugin->get_type(), $installedplugins, 'Submission plugin not in list of installed plugins');
71 }
47f48152
DW
72 }
73
74 public function test_is_blind_marking() {
75 $this->setUser($this->editingteachers[0]);
76 $assign = $this->create_instance(array('blindmarking'=>1));
77 $this->assertEquals(true, $assign->is_blind_marking());
78
79 // Test cannot see student names.
80 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
81 $output = $assign->get_renderer()->render($gradingtable);
82 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign')));
83
84 // Test students cannot reveal identities.
85 $nopermission = false;
05a6445a 86 $this->students[0]->ignoresesskey = true;
47f48152
DW
87 $this->setUser($this->students[0]);
88 $this->setExpectedException('required_capability_exception');
05a6445a
DW
89 $assign->reveal_identities();
90 $this->students[0]->ignoresesskey = false;
47f48152
DW
91
92 // Test teachers cannot reveal identities.
93 $nopermission = false;
05a6445a 94 $this->teachers[0]->ignoresesskey = true;
47f48152
DW
95 $this->setUser($this->teachers[0]);
96 $this->setExpectedException('required_capability_exception');
05a6445a
DW
97 $assign->reveal_identities();
98 $this->teachers[0]->ignoresesskey = false;
47f48152
DW
99
100 // Test sesskey is required.
47f48152
DW
101 $this->setUser($this->editingteachers[0]);
102 $this->setExpectedException('moodle_exception');
05a6445a 103 $assign->reveal_identities();
47f48152
DW
104
105 // Test editingteacher can reveal identities if sesskey is ignored.
106 $this->editingteachers[0]->ignoresesskey = true;
107 $this->setUser($this->editingteachers[0]);
05a6445a 108 $assign->reveal_identities();
47f48152 109 $this->assertEquals(false, $assign->is_blind_marking());
05a6445a 110 $this->editingteachers[0]->ignoresesskey = false;
47f48152
DW
111
112 // Test student names are visible.
113 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
114 $output = $assign->get_renderer()->render($gradingtable);
115 $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
116
117 // Set this back to default.
118 $this->editingteachers[0]->ignoresesskey = false;
119 }
120
80989850
BH
121 /**
122 * Data provider for test_get_assign_perpage
123 *
124 * @return array Provider data
125 */
126 public function get_assign_perpage_provider() {
127 return array(
128 array(
129 'maxperpage' => -1,
130 'userprefs' => array(
131 -1 => -1,
132 10 => 10,
133 20 => 20,
134 50 => 50,
135 ),
136 ),
137 array(
138 'maxperpage' => 15,
139 'userprefs' => array(
140 -1 => 15,
141 10 => 10,
142 20 => 15,
143 50 => 15,
144 ),
145 ),
146 );
147 }
148
149 /**
150 * Test maxperpage
151 *
152 * @dataProvider get_assign_perpage_provider
153 * @param integer $maxperpage site config value
154 * @param array $userprefs Array of user preferences and expected page sizes
155 */
156 public function test_get_assign_perpage($maxperpage, $userprefs) {
157
158 $this->setUser($this->editingteachers[0]);
159 $assign = $this->create_instance();
160 set_config('maxperpage', $maxperpage, 'assign');
161 set_user_preference('assign_perpage', null);
162 $this->assertEquals(10, $assign->get_assign_perpage());
163 foreach ($userprefs as $pref => $perpage) {
164 set_user_preference('assign_perpage', $pref);
165 $this->assertEquals($perpage, $assign->get_assign_perpage());
166 }
167 }
168
79397b56
DB
169 /**
170 * Test submissions with extension date.
171 */
172 public function test_gradingtable_extension_due_date() {
173 global $PAGE;
174
175 // Setup the assignment.
176 $this->create_extra_users();
177 $this->setUser($this->editingteachers[0]);
178 $assign = $this->create_instance(array(
179 'assignsubmission_onlinetext_enabled'=>1,
180 'duedate' => time() - 4 * 24 * 60 * 60,
181 ));
182 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
183 'id' => $assign->get_course_module()->id,
184 'action' => 'grading',
185 )));
186
187 // Check that the assignment is late.
188 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
189 $output = $assign->get_renderer()->render($gradingtable);
190 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
191 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output);
192
193 // Grant an extension.
5b460d65
MG
194 $extendedtime = time() + 2 * 24 * 60 * 60;
195 $assign->testable_save_user_extension($this->students[0]->id, $extendedtime);
79397b56
DB
196 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
197 $output = $assign->get_renderer()->render($gradingtable);
198 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
5b460d65 199 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
79397b56
DB
200
201 // Simulate a submission.
202 $this->setUser($this->students[0]);
203 $submission = $assign->get_user_submission($this->students[0]->id, true);
204 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
205 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
206 $data = new stdClass();
207 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
208 'text'=>'Submission text',
209 'format'=>FORMAT_MOODLE);
210 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
211 $plugin->save($submission, $data);
212
213 // Verify output.
214 $this->setUser($this->editingteachers[0]);
215 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
216 $output = $assign->get_renderer()->render($gradingtable);
217 $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
5b460d65 218 $this->assertContains(get_string('userextensiondate', 'assign', userdate($extendedtime)), $output);
79397b56
DB
219 }
220
221 /**
222 * Test that late submissions with extension date calculate correctly.
223 */
224 public function test_gradingtable_extension_date_calculation_for_lateness() {
225 global $PAGE;
226
227 // Setup the assignment.
228 $this->create_extra_users();
229 $this->setUser($this->editingteachers[0]);
a0f8db77 230 $time = time();
79397b56
DB
231 $assign = $this->create_instance(array(
232 'assignsubmission_onlinetext_enabled'=>1,
a0f8db77 233 'duedate' => $time - 4 * 24 * 60 * 60,
79397b56
DB
234 ));
235 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
236 'id' => $assign->get_course_module()->id,
237 'action' => 'grading',
238 )));
239
240 // Check that the assignment is late.
241 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
242 $output = $assign->get_renderer()->render($gradingtable);
243 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
a0f8db77
DW
244 $difftime = time() - $time;
245 $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60 + $difftime)), $output);
79397b56
DB
246
247 // Grant an extension that is in the past.
a0f8db77 248 $assign->testable_save_user_extension($this->students[0]->id, $time - 2 * 24 * 60 * 60);
79397b56
DB
249 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
250 $output = $assign->get_renderer()->render($gradingtable);
251 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
a0f8db77
DW
252 $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output);
253 $difftime = time() - $time;
254 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
255
256 // Simulate a submission.
257 $this->setUser($this->students[0]);
258 $submission = $assign->get_user_submission($this->students[0]->id, true);
259 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
260 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
261 $data = new stdClass();
262 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
263 'text'=>'Submission text',
264 'format'=>FORMAT_MOODLE);
265 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
266 $plugin->save($submission, $data);
a0f8db77 267 $submittedtime = time();
79397b56
DB
268
269 // Verify output.
270 $this->setUser($this->editingteachers[0]);
271 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
272 $output = $assign->get_renderer()->render($gradingtable);
273 $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
a0f8db77
DW
274 $this->assertContains(get_string('userextensiondate', 'assign', userdate($time - 2*24*60*60)), $output);
275
276 $difftime = $submittedtime - $time;
277 $this->assertContains(get_string('submittedlateshort', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
278 }
279
232b26f0
CS
280 public function test_gradingtable_status_rendering() {
281 global $PAGE;
282
283 // Setup the assignment.
284 $this->create_extra_users();
285 $this->setUser($this->editingteachers[0]);
286 $time = time();
287 $assign = $this->create_instance(array(
288 'assignsubmission_onlinetext_enabled' => 1,
289 'duedate' => $time - 4 * 24 * 60 * 60,
290 ));
291 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
292 'id' => $assign->get_course_module()->id,
293 'action' => 'grading',
294 )));
295
296 // Check that the assignment is late.
297 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
298 $output = $assign->get_renderer()->render($gradingtable);
299 $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
300 $difftime = time() - $time;
301 $this->assertContains(get_string('overdue', 'assign', format_time(4 * 24 * 60 * 60 + $difftime)), $output);
302
303 // Simulate a student viewing the assignment without submitting.
304 $this->setUser($this->students[0]);
305 $submission = $assign->get_user_submission($this->students[0]->id, true);
306 $submission->status = ASSIGN_SUBMISSION_STATUS_NEW;
307 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
308 $submittedtime = time();
309
310 // Verify output.
311 $this->setUser($this->editingteachers[0]);
312 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
313 $output = $assign->get_renderer()->render($gradingtable);
314 $difftime = $submittedtime - $time;
315 $this->assertContains(get_string('overdue', 'assign', format_time(4 * 24 * 60 * 60 + $difftime)), $output);
316
317 $document = new DOMDocument();
318 $document->loadHTML($output);
319 $xpath = new DOMXPath($document);
320 $this->assertEquals('', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])'));
321 }
322
79397b56
DB
323 /**
324 * Check that group submission information is rendered correctly in the
325 * grading table.
326 */
327 public function test_gradingtable_group_submissions_rendering() {
328 global $PAGE;
329
330 $this->create_extra_users();
331 // Now verify group assignments.
332 $this->setUser($this->teachers[0]);
333 $assign = $this->create_instance(array(
334 'teamsubmission' => 1,
335 'assignsubmission_onlinetext_enabled' => 1,
336 'submissiondrafts' => 1,
337 'requireallteammemberssubmit' => 0,
338 ));
339 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
340 'id' => $assign->get_course_module()->id,
341 'action' => 'grading',
342 )));
343
344 // Add a submission.
345 $this->setUser($this->extrastudents[0]);
346 $data = new stdClass();
347 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
348 'text'=>'Submission text',
349 'format'=>FORMAT_MOODLE);
350 $notices = array();
351 $assign->save_submission($data, $notices);
352
353 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
354 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
355 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
356
357 // Check output.
358 $this->setUser($this->teachers[0]);
359 $gradingtable = new assign_grading_table($assign, 4, '', 0, true);
360 $output = $assign->get_renderer()->render($gradingtable);
361 $document = new DOMDocument();
362 $document->loadHTML($output);
363 $xpath = new DOMXPath($document);
364
365 // Check status.
366 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c4"]/div[@class="submissionstatussubmitted"])'));
367 $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])'));
368
369 // Check submission last modified date
370 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')));
371 $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])')));
372
373 // Check group.
374 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])'));
375 $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])'));
376
377 // Check submission text.
378 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)'));
379 $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)'));
380
381 // Check comments can be made.
382 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)'));
383 $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)'));
384 }
385
47f48152
DW
386 public function test_show_intro() {
387 // Test whether we are showing the intro at the correct times.
388 $this->setUser($this->editingteachers[0]);
389 $assign = $this->create_instance(array('alwaysshowdescription'=>1));
390
391 $this->assertEquals(true, $assign->testable_show_intro());
392
393 $tomorrow = time() + (24*60*60);
394
395 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
396 'allowsubmissionsfromdate'=>$tomorrow));
397 $this->assertEquals(false, $assign->testable_show_intro());
398 $yesterday = time() - (24*60*60);
399 $assign = $this->create_instance(array('alwaysshowdescription'=>0,
400 'allowsubmissionsfromdate'=>$yesterday));
401 $this->assertEquals(true, $assign->testable_show_intro());
402 }
403
404 public function test_has_submissions_or_grades() {
405 $this->setUser($this->editingteachers[0]);
406 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
407
408 $instance = $assign->get_instance();
409
410 // Should start empty.
411 $this->assertEquals(false, $assign->has_submissions_or_grades());
412
413 // Simulate a submission.
414 $this->setUser($this->students[0]);
415 $submission = $assign->get_user_submission($this->students[0]->id, true);
ab14ab74
FM
416
417 // The submission is still new.
418 $this->assertEquals(false, $assign->has_submissions_or_grades());
419
420 // Submit the submission.
421 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
422 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
47f48152
DW
423 $data = new stdClass();
424 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
425 'text'=>'Submission text',
426 'format'=>FORMAT_MOODLE);
427 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
428 $plugin->save($submission, $data);
429
430 // Now test again.
431 $this->assertEquals(true, $assign->has_submissions_or_grades());
432 // Set this back to default.
433 $this->students[0]->ignoresesskey = false;
434 }
435
436 public function test_delete_grades() {
437 $this->setUser($this->editingteachers[0]);
438 $assign = $this->create_instance();
439
440 // Simulate adding a grade.
441 $this->setUser($this->teachers[0]);
442 $data = new stdClass();
443 $data->grade = '50.0';
df211804 444 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
445
446 // Now see if the data is in the gradebook.
447 $gradinginfo = grade_get_grades($this->course->id,
448 'mod',
449 'assign',
450 $assign->get_instance()->id);
451
452 $this->assertNotEquals(0, count($gradinginfo->items));
453
454 $assign->testable_delete_grades();
455 $gradinginfo = grade_get_grades($this->course->id,
456 'mod',
457 'assign',
458 $assign->get_instance()->id);
459
460 $this->assertEquals(0, count($gradinginfo->items));
461 }
462
463 public function test_delete_instance() {
464 $this->setUser($this->editingteachers[0]);
465 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
466
467 // Simulate adding a grade.
468 $this->setUser($this->teachers[0]);
469 $data = new stdClass();
470 $data->grade = '50.0';
df211804 471 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
472
473 // Simulate a submission.
474 $this->setUser($this->students[0]);
475 $submission = $assign->get_user_submission($this->students[0]->id, true);
476 $data = new stdClass();
477 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
478 'text'=>'Submission text',
479 'format'=>FORMAT_MOODLE);
480 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
481 $plugin->save($submission, $data);
482
483 // Now try and delete.
484 $this->assertEquals(true, $assign->delete_instance());
485 }
486
487 public function test_reset_userdata() {
488 global $DB;
489
490 $now = time();
491 $this->setUser($this->editingteachers[0]);
492 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
493 'duedate'=>$now));
494
495 // Simulate adding a grade.
496 $this->setUser($this->teachers[0]);
497 $data = new stdClass();
498 $data->grade = '50.0';
df211804 499 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
500
501 // Simulate a submission.
502 $this->setUser($this->students[0]);
503 $submission = $assign->get_user_submission($this->students[0]->id, true);
504 $data = new stdClass();
505 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
506 'text'=>'Submission text',
507 'format'=>FORMAT_MOODLE);
508 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
509 $plugin->save($submission, $data);
510
511 $this->assertEquals(true, $assign->has_submissions_or_grades());
512 // Now try and reset.
513 $data = new stdClass();
514 $data->reset_assign_submissions = 1;
515 $data->reset_gradebook_grades = 1;
516 $data->courseid = $this->course->id;
517 $data->timeshift = 24*60*60;
518 $this->setUser($this->editingteachers[0]);
519 $assign->reset_userdata($data);
520 $this->assertEquals(false, $assign->has_submissions_or_grades());
521
522 // Reload the instance data.
523 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
524 $this->assertEquals($now + 24*60*60, $instance->duedate);
e63515ba
RT
525
526 // Test reset using assign_reset_userdata().
527 $assignduedate = $instance->duedate; // Keep old updated value for comparison.
528 $data->timeshift = 2*24*60*60;
529 assign_reset_userdata($data);
530 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
531 $this->assertEquals($assignduedate + 2*24*60*60, $instance->duedate);
532
533 // Create one more assignment and reset, make sure time shifted for previous assignment is not changed.
534 $assign2 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1,
535 'duedate' => $now));
536 $assignduedate = $instance->duedate;
537 $data->timeshift = 3*24*60*60;
538 $assign2->reset_userdata($data);
539 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
540 $this->assertEquals($assignduedate, $instance->duedate);
541 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
542 $this->assertEquals($now + 3*24*60*60, $instance2->duedate);
543
544 // Reset both assignments using assign_reset_userdata() and make sure both assignments have same date.
545 $assignduedate = $instance->duedate;
546 $assign2duedate = $instance2->duedate;
547 $data->timeshift = 4*24*60*60;
548 assign_reset_userdata($data);
549 $instance = $DB->get_record('assign', array('id' => $assign->get_instance()->id));
550 $this->assertEquals($assignduedate + 4*24*60*60, $instance->duedate);
551 $instance2 = $DB->get_record('assign', array('id' => $assign2->get_instance()->id));
552 $this->assertEquals($assign2duedate + 4*24*60*60, $instance2->duedate);
47f48152
DW
553 }
554
555 public function test_plugin_settings() {
556 global $DB;
557
558 $now = time();
559 $this->setUser($this->editingteachers[0]);
560 $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
561 'assignsubmission_file_maxfiles'=>12,
562 'assignsubmission_file_maxsizebytes'=>10));
563
564 $plugin = $assign->get_submission_plugin_by_type('file');
565 $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
566 }
567
568 public function test_update_calendar() {
569 global $DB;
570
47f48152 571 $this->setUser($this->editingteachers[0]);
f588ea50
FM
572 $userctx = context_user::instance($this->editingteachers[0]->id)->id;
573
574 // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey.
575 $draftid = file_get_unused_draft_itemid();
576 $_REQUEST['introeditor'] = $draftid;
577 $_POST['introeditor'] = $draftid;
578 $_POST['sesskey'] = sesskey();
579
580 // Write links to a draft area.
581 $fakearealink1 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">link</a>', 'draftfile.php', $userctx,
582 'user', 'draft', $draftid);
583 $fakearealink2 = file_rewrite_pluginfile_urls('<a href="@@PLUGINFILE@@/pic.gif">new</a>', 'draftfile.php', $userctx,
584 'user', 'draft', $draftid);
585
586 // Create a new assignment with links to a draft area.
587 $now = time();
588 $assign = $this->create_instance(array(
589 'duedate' => $now,
590 'intro' => $fakearealink1,
591 'introformat' => FORMAT_HTML
592 ));
47f48152
DW
593
594 // See if there is an event in the calendar.
595 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
f588ea50
FM
596 $event = $DB->get_record('event', $params);
597 $this->assertNotEmpty($event);
598 $this->assertSame('link', $event->description); // The pluginfile links are removed.
47f48152 599
f588ea50
FM
600 // Make sure the same works when updating the assignment.
601 $instance = $assign->get_instance();
602 $instance->instance = $instance->id;
603 $instance->intro = $fakearealink2;
604 $instance->introformat = FORMAT_HTML;
605 $assign->update_instance($instance);
606 $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id);
607 $event = $DB->get_record('event', $params);
608 $this->assertNotEmpty($event);
609 $this->assertSame('new', $event->description); // The pluginfile links are removed.
ae7638f7
DW
610
611 // Create an assignment with a description that should be hidden.
612 $assign = $this->create_instance(array('duedate'=>$now + 160,
613 'alwaysshowdescription'=>false,
8112670d 614 'allowsubmissionsfromdate'=>$now + 60,
ae7638f7
DW
615 'intro'=>'Some text'));
616
617 // Get the event from the calendar.
618 $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
619 $event = $DB->get_record('event', $params);
620
621 $this->assertEmpty($event->description);
8112670d
DW
622
623 // Change the allowsubmissionfromdate to the past - do this directly in the DB
624 // because if we call the assignment update method - it will update the calendar
625 // and we want to test that this works from cron.
626 $DB->set_field('assign', 'allowsubmissionsfromdate', $now - 60, array('id'=>$assign->get_instance()->id));
ae7638f7
DW
627 // Run cron to update the event in the calendar.
628 assign::cron();
629 $event = $DB->get_record('event', $params);
630
631 $this->assertContains('Some text', $event->description);
632
47f48152
DW
633 }
634
635 public function test_update_instance() {
636 global $DB;
637
638 $this->setUser($this->editingteachers[0]);
639 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
640
641 $now = time();
642 $instance = $assign->get_instance();
643 $instance->duedate = $now;
644 $instance->instance = $instance->id;
645 $instance->assignsubmission_onlinetext_enabled = 1;
47f48152
DW
646
647 $assign->update_instance($instance);
648
649 $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
650 $this->assertEquals($now, $instance->duedate);
651 }
652
8fd00a24
DW
653 public function test_cannot_submit_empty() {
654 global $PAGE;
655
656 $this->setUser($this->editingteachers[0]);
657 $assign = $this->create_instance(array('submissiondrafts'=>1));
658
659 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
660
661 // Test you cannot see the submit button for an offline assignment regardless.
662 $this->setUser($this->students[0]);
663 $output = $assign->view_student_summary($this->students[0], true);
664 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Can submit empty offline assignment');
665
666 // Test you cannot see the submit button for an online text assignment with no submission.
667 $this->setUser($this->editingteachers[0]);
668 $instance = $assign->get_instance();
669 $instance->instance = $instance->id;
670 $instance->assignsubmission_onlinetext_enabled = 1;
671
672 $assign->update_instance($instance);
673 $this->setUser($this->students[0]);
674 $output = $assign->view_student_summary($this->students[0], true);
675 $this->assertNotContains(get_string('submitassignment', 'assign'), $output, 'Cannot submit empty onlinetext assignment');
676
677 // Simulate a submission.
678 $submission = $assign->get_user_submission($this->students[0]->id, true);
679 $data = new stdClass();
680 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
681 'text'=>'Submission text',
682 'format'=>FORMAT_MOODLE);
683 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
684 $plugin->save($submission, $data);
685 // Test you can see the submit button for an online text assignment with a submission.
686 $output = $assign->view_student_summary($this->students[0], true);
687 $this->assertContains(get_string('submitassignment', 'assign'), $output, 'Can submit non empty onlinetext assignment');
688 }
689
47f48152 690 public function test_list_participants() {
c13ac85d 691 global $CFG, $DB;
692
df211804 693 $this->create_extra_users();
47f48152
DW
694 $this->setUser($this->editingteachers[0]);
695 $assign = $this->create_instance(array('grade'=>100));
696
a5c793c3 697 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
e6cc5347
RT
698
699 // Teacher with user preference set should see suspended users as well.
700 set_user_preference('grade_report_showonlyactiveenrol', false);
701 $assign = $this->create_instance(array('grade'=>100));
702 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT,
703 count($assign->list_participants(null, true)));
704
1ecb8044 705 // Non-editing teacher should not see suspended users, even if user preference is set.
e6cc5347
RT
706 $this->setUser($this->teachers[0]);
707 set_user_preference('grade_report_showonlyactiveenrol', false);
708 $assign = $this->create_instance(array('grade'=>100));
709 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($assign->list_participants(null, true)));
c13ac85d 710
711 // Turn on availability and a group restriction, and check that it doesn't
712 // show users who aren't in the group.
713 $CFG->enableavailability = true;
714 $specialgroup = $this->getDataGenerator()->create_group(
715 array('courseid' => $this->course->id));
716 $assign = $this->create_instance(array('grade' => 100,
717 'availability' => json_encode(\core_availability\tree::get_root_json(
718 array(\availability_group\condition::get_json($specialgroup->id))))));
719 groups_add_member($specialgroup, $this->students[0]);
720 groups_add_member($specialgroup, $this->students[1]);
721 $this->assertEquals(2, count($assign->list_participants(null, true)));
47f48152
DW
722 }
723
724 public function test_count_teams() {
df211804 725 $this->create_extra_users();
47f48152 726 $this->setUser($this->editingteachers[0]);
2dda9417
DM
727 $assign1 = $this->create_instance(array('teamsubmission' => 1));
728 $this->assertEquals(self::GROUP_COUNT + 1, $assign1->count_teams());
47f48152 729
2dda9417
DM
730 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
731 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[0]->id, 'groupingid' => $grouping->id));
732 $this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[1]->id, 'groupingid' => $grouping->id));
733
e528997a
AH
734 // No active group and non group submissions allowed => 2 groups + the default one.
735 $params = array(
736 'teamsubmission' => 1,
737 'teamsubmissiongroupingid' => $grouping->id,
738 'preventsubmissionnotingroup' => false
739 );
740 $assign2 = $this->create_instance($params);
2dda9417
DM
741 $this->assertEquals(3, $assign2->count_teams());
742
743 // An active group => Just the selected one.
744 $this->assertEquals(1, $assign2->count_teams($this->groups[0]->id));
e528997a
AH
745
746 // No active group and non group submissions allowed => 2 groups + no default one.
747 $params = array('teamsubmission' => 1, 'teamsubmissiongroupingid' => $grouping->id, 'preventsubmissionnotingroup' => true);
748 $assign3 = $this->create_instance($params);
749 $this->assertEquals(2, $assign3->count_teams());
750
751 $assign4 = $this->create_instance(array('teamsubmission' => 1, 'preventsubmissionnotingroup' => true));
752 $this->assertEquals(self::GROUP_COUNT, $assign4->count_teams());
47f48152
DW
753 }
754
e2d2d8a1 755 public function test_submit_to_default_group() {
2dda9417 756 global $DB, $SESSION;
e2d2d8a1
DW
757
758 $this->preventResetByRollback();
759 $sink = $this->redirectMessages();
760
761 $this->setUser($this->editingteachers[0]);
762 $params = array('teamsubmission' => 1,
763 'assignsubmission_onlinetext_enabled' => 1,
2dda9417
DM
764 'submissiondrafts' => 0,
765 'groupmode' => VISIBLEGROUPS);
e2d2d8a1
DW
766 $assign = $this->create_instance($params);
767
768 $newstudent = $this->getDataGenerator()->create_user();
769 $studentrole = $DB->get_record('role', array('shortname'=>'student'));
770 $this->getDataGenerator()->enrol_user($newstudent->id,
771 $this->course->id,
772 $studentrole->id);
773 $this->setUser($newstudent);
774 $data = new stdClass();
775 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
776 'text'=>'Submission text',
777 'format'=>FORMAT_MOODLE);
778 $notices = array();
779
780 $group = $assign->get_submission_group($newstudent->id);
781 $this->assertFalse($group, 'New student is in default group');
782 $assign->save_submission($data, $notices);
783 $this->assertEmpty($notices, 'No errors on save submission');
784
2dda9417
DM
785 // Set active groups to all groups.
786 $this->setUser($this->teachers[0]);
787 $SESSION->activegroup[$this->course->id]['aag'][0] = 0;
788 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
789
790 // Set an active group.
791 $anothergroup = $this->groups[0];
792 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id;
793 $this->assertEquals(0, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
794
e2d2d8a1
DW
795 $sink->close();
796 }
797
47f48152 798 public function test_count_submissions() {
2dda9417
DM
799 global $SESSION;
800
df211804 801 $this->create_extra_users();
47f48152 802 $this->setUser($this->editingteachers[0]);
2dda9417 803 $assign1 = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1));
47f48152
DW
804
805 // Simulate a submission.
a5c793c3 806 $this->setUser($this->extrastudents[0]);
2dda9417 807 $submission = $assign1->get_user_submission($this->extrastudents[0]->id, true);
9e3eee67 808 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
2dda9417 809 $assign1->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
810 // Leave this one as DRAFT.
811 $data = new stdClass();
812 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
813 'text'=>'Submission text',
814 'format'=>FORMAT_MOODLE);
2dda9417 815 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
816 $plugin->save($submission, $data);
817
818 // Simulate adding a grade.
819 $this->setUser($this->teachers[0]);
820 $data = new stdClass();
821 $data->grade = '50.0';
2dda9417 822 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
47f48152
DW
823
824 // Simulate a submission.
a5c793c3 825 $this->setUser($this->extrastudents[1]);
2dda9417 826 $submission = $assign1->get_user_submission($this->extrastudents[1]->id, true);
47f48152 827 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 828 $assign1->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
47f48152
DW
829 $data = new stdClass();
830 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
831 'text'=>'Submission text',
832 'format'=>FORMAT_MOODLE);
2dda9417 833 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
834 $plugin->save($submission, $data);
835
836 // Simulate a submission.
a5c793c3 837 $this->setUser($this->extrastudents[2]);
2dda9417 838 $submission = $assign1->get_user_submission($this->extrastudents[2]->id, true);
47f48152 839 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 840 $assign1->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
47f48152
DW
841 $data = new stdClass();
842 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
843 'text'=>'Submission text',
844 'format'=>FORMAT_MOODLE);
2dda9417 845 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
846 $plugin->save($submission, $data);
847
848 // Simulate a submission.
a5c793c3 849 $this->setUser($this->extrastudents[3]);
2dda9417 850 $submission = $assign1->get_user_submission($this->extrastudents[3]->id, true);
47f48152 851 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 852 $assign1->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
47f48152
DW
853 $data = new stdClass();
854 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
855 'text'=>'Submission text',
856 'format'=>FORMAT_MOODLE);
2dda9417 857 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
47f48152
DW
858 $plugin->save($submission, $data);
859
e6cc5347
RT
860 // Simulate a submission for suspended user, this will never be counted.
861 $this->setUser($this->extrastudents[3]);
2dda9417 862 $submission = $assign1->get_user_submission($this->extrasuspendedstudents[0]->id, true);
e6cc5347 863 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
2dda9417 864 $assign1->testable_update_submission($submission, $this->extrasuspendedstudents[0]->id, true, false);
e6cc5347
RT
865 $data = new stdClass();
866 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
867 'text'=>'Submission text',
868 'format'=>FORMAT_MOODLE);
2dda9417 869 $plugin = $assign1->get_submission_plugin_by_type('onlinetext');
e6cc5347
RT
870 $plugin->save($submission, $data);
871
fb6bae3e
DW
872 // Wait 1 second so the submission and grade do not have the same timemodified.
873 sleep(1);
47f48152 874 // Simulate adding a grade.
50c734e8 875 $this->setUser($this->editingteachers[0]);
47f48152
DW
876 $data = new stdClass();
877 $data->grade = '50.0';
2dda9417
DM
878 $assign1->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
879 $assign1->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
47f48152 880
ab14ab74
FM
881 // Create a new submission with status NEW.
882 $this->setUser($this->extrastudents[4]);
2dda9417
DM
883 $submission = $assign1->get_user_submission($this->extrastudents[4]->id, true);
884
885 $this->assertEquals(2, $assign1->count_grades());
886 $this->assertEquals(4, $assign1->count_submissions());
887 $this->assertEquals(5, $assign1->count_submissions(true));
888 $this->assertEquals(2, $assign1->count_submissions_need_grading());
889 $this->assertEquals(3, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
890 $this->assertEquals(1, $assign1->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
891
892 // Groups.
893 $assign2 = $this->create_instance(array(
894 'assignsubmission_onlinetext_enabled' => 1,
895 'groupmode' => VISIBLEGROUPS
896 ));
897
898 $this->setUser($this->extrastudents[1]);
899 $submission = $assign2->get_user_submission($this->extrastudents[1]->id, true);
900 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
901 $assign2->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
902 $data = new stdClass();
903 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
904 'text' => 'Submission text',
905 'format' => FORMAT_MOODLE);
906 $plugin = $assign2->get_submission_plugin_by_type('onlinetext');
907 $plugin->save($submission, $data);
908
909 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
910
911 // Set active groups to all groups.
912 $this->setUser($this->teachers[0]);
913 $SESSION->activegroup[$this->course->id]['aag'][0] = 0;
914 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
915
916 // Set the user group.
917 $studentgroups = groups_get_user_groups($this->course->id, $this->extrastudents[1]->id);
918 $this->assertEquals(1, count($studentgroups));
919 $studentgroup = array_pop($studentgroups);
920 $SESSION->activegroup[$this->course->id]['aag'][0] = $studentgroup[0];
921 $this->assertEquals(1, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
922
923 // Set another group.
924 $anothergroup = $this->groups[0];
925 $this->assertNotEquals($anothergroup->id, $studentgroup[0]);
926 $SESSION->activegroup[$this->course->id]['aag'][0] = (int)$anothergroup->id;
927 $this->assertEquals(0, $assign2->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
47f48152
DW
928 }
929
ab14ab74
FM
930 public function test_count_submissions_for_groups() {
931 $this->create_extra_users();
932 $groupid = null;
933 $this->setUser($this->editingteachers[0]);
934 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1, 'teamsubmission' => 1));
935
936 // Simulate a submission.
937 $this->setUser($this->extrastudents[0]);
938 $submission = $assign->get_group_submission($this->extrastudents[0]->id, $groupid, true);
939 $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
940 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
941 // Leave this one as DRAFT.
942 $data = new stdClass();
943 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
944 'text' => 'Submission text',
945 'format' => FORMAT_MOODLE);
946 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
947 $plugin->save($submission, $data);
948
949 // Simulate adding a grade.
950 $this->setUser($this->teachers[0]);
951 $data = new stdClass();
952 $data->grade = '50.0';
953 $assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
954
955 // Simulate a submission.
956 $this->setUser($this->extrastudents[1]);
957 $submission = $assign->get_group_submission($this->extrastudents[1]->id, $groupid, true);
958 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
959 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, false);
960 $data = new stdClass();
961 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
962 'text' => 'Submission text',
963 'format' => FORMAT_MOODLE);
964 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
965 $plugin->save($submission, $data);
966
967 // Simulate a submission.
968 $this->setUser($this->extrastudents[2]);
969 $submission = $assign->get_group_submission($this->extrastudents[2]->id, $groupid, true);
970 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
971 $assign->testable_update_submission($submission, $this->extrastudents[2]->id, true, false);
972 $data = new stdClass();
973 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
974 'text' => 'Submission text',
975 'format' => FORMAT_MOODLE);
976 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
977 $plugin->save($submission, $data);
978
979 // Simulate a submission.
980 $this->setUser($this->extrastudents[3]);
981 $submission = $assign->get_group_submission($this->extrastudents[3]->id, $groupid, true);
982 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
983 $assign->testable_update_submission($submission, $this->extrastudents[3]->id, true, false);
984 $data = new stdClass();
985 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
986 'text' => 'Submission text',
987 'format' => FORMAT_MOODLE);
988 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
989 $plugin->save($submission, $data);
990
991 // Simulate adding a grade.
50c734e8 992 $this->setUser($this->editingteachers[0]);
ab14ab74
FM
993 $data = new stdClass();
994 $data->grade = '50.0';
995 $assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
996 $assign->testable_apply_grade_to_user($data, $this->extrasuspendedstudents[0]->id, 0);
997
998 // Create a new submission with status NEW.
999 $this->setUser($this->extrastudents[4]);
1000 $submission = $assign->get_group_submission($this->extrastudents[4]->id, $groupid, true);
1001
1002 $this->assertEquals(2, $assign->count_grades());
1003 $this->assertEquals(4, $assign->count_submissions());
1004 $this->assertEquals(5, $assign->count_submissions(true));
1005 $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
1006 $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
1007 }
1008
47f48152 1009 public function test_get_grading_userid_list() {
df211804 1010 $this->create_extra_users();
47f48152
DW
1011 $this->setUser($this->editingteachers[0]);
1012 $assign = $this->create_instance();
1013
1014 $users = $assign->testable_get_grading_userid_list();
a5c793c3 1015 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT, count($users));
e6cc5347
RT
1016
1017 $this->setUser($this->editingteachers[0]);
1018 set_user_preference('grade_report_showonlyactiveenrol', false);
1019 $assign = $this->create_instance();
1020
1021 $users = $assign->testable_get_grading_userid_list();
1022 $this->assertEquals(self::DEFAULT_STUDENT_COUNT + self::EXTRA_STUDENT_COUNT + self::EXTRA_SUSPENDED_COUNT, count($users));
47f48152
DW
1023 }
1024
1025 public function test_cron() {
1026 // First run cron so there are no messages waiting to be sent (from other tests).
1027 cron_setup_user();
1028 assign::cron();
1029
1030 // Now create an assignment and add some feedback.
1031 $this->setUser($this->editingteachers[0]);
8e1266bf 1032 $assign = $this->create_instance(array('sendstudentnotifications'=>1));
47f48152
DW
1033
1034 // Simulate adding a grade.
1035 $this->setUser($this->teachers[0]);
1036 $data = new stdClass();
1037 $data->grade = '50.0';
df211804 1038 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
4d2bd673 1039 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
47f48152 1040
f7dc9871
DW
1041 $data->sendstudentnotifications = false;
1042 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
1043
47f48152
DW
1044 // Now run cron and see that one message was sent.
1045 $this->preventResetByRollback();
1046 $sink = $this->redirectMessages();
1047 cron_setup_user();
4d2bd673 1048 $this->expectOutputRegex('/Done processing 2 assignment submissions/');
47f48152
DW
1049 assign::cron();
1050
1051 $messages = $sink->get_messages();
f7dc9871 1052 // The sent count should be 2, because the 3rd one was marked as do not send notifications.
4d2bd673 1053 $this->assertEquals(2, count($messages));
47f48152
DW
1054 $this->assertEquals(1, $messages[0]->notification);
1055 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
a4b10a52
ZD
1056
1057 // Regrading a grade causes a notification to the user.
1058 $data->sendstudentnotifications = true;
1059 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1060 assign::cron();
1061 $messages = $sink->get_messages();
1062 $this->assertEquals(3, count($messages));
47f48152
DW
1063 }
1064
70cfc878
JF
1065 /**
1066 * Test delivery of grade notifications as controlled by marking workflow.
1067 */
1068 public function test_markingworkflow_cron() {
1069 // First run cron so there are no messages waiting to be sent (from other tests).
1070 cron_setup_user();
1071 assign::cron();
1072
1073 // Now create an assignment with marking workflow enabled.
1074 $this->setUser($this->editingteachers[0]);
1075 $assign = $this->create_instance(array('sendstudentnotifications' => 1, 'markingworkflow' => 1));
1076
1077 // Simulate adding a grade.
1078 $this->setUser($this->teachers[0]);
1079 $data = new stdClass();
1080 $data->grade = '50.0';
1081
1082 // This student will not receive notification.
1083 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
1084 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1085
1086 // This student will receive notification.
1087 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
1088 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
1089
1090 // Now run cron and see that one message was sent.
1091 $this->preventResetByRollback();
1092 $sink = $this->redirectMessages();
1093 cron_setup_user();
1094 $this->expectOutputRegex('/Done processing 1 assignment submissions/');
1095 assign::cron();
1096
1097 $messages = $sink->get_messages();
1098 $this->assertEquals(1, count($messages));
1099 $this->assertEquals($messages[0]->useridto, $this->students[1]->id);
1100 $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
1101 }
1102
47f48152
DW
1103 public function test_is_graded() {
1104 $this->setUser($this->editingteachers[0]);
1105 $assign = $this->create_instance();
1106
1107 // Simulate adding a grade.
1108 $this->setUser($this->teachers[0]);
1109 $data = new stdClass();
1110 $data->grade = '50.0';
df211804 1111 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
47f48152
DW
1112
1113 $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
1114 $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
1115 }
1116
4a47008c
DW
1117 public function test_can_grade() {
1118 global $DB;
1119
1120 $this->setUser($this->editingteachers[0]);
1121 $assign = $this->create_instance();
1122
1123 $this->setUser($this->students[0]);
1124 $this->assertEquals(false, $assign->can_grade());
1125 $this->setUser($this->editingteachers[0]);
1126 $this->assertEquals(true, $assign->can_grade());
1127 $this->setUser($this->teachers[0]);
1128 $this->assertEquals(true, $assign->can_grade());
1129
1130 // Test the viewgrades capability - without mod/assign:grade.
1131 $this->setUser($this->students[0]);
1132 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1133 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
1134 $this->assertEquals(false, $assign->can_grade());
1135 }
1136
47f48152 1137 public function test_can_view_submission() {
4a47008c
DW
1138 global $DB;
1139
e6cc5347 1140 $this->create_extra_users();
47f48152
DW
1141 $this->setUser($this->editingteachers[0]);
1142 $assign = $this->create_instance();
1143
1144 $this->setUser($this->students[0]);
1145 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1146 $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
1147 $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
1148 $this->setUser($this->teachers[0]);
1149 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1150 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1151 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 1152 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
1153 $this->setUser($this->editingteachers[0]);
1154 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1155 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1156 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
e6cc5347 1157 $this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
4a47008c
DW
1158
1159 // Test the viewgrades capability - without mod/assign:grade.
1160 $this->setUser($this->students[0]);
1161 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1162 assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
1163 $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
1164 $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
1165 $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
1166 $this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
47f48152
DW
1167 }
1168
1169
1170 public function test_update_submission() {
df211804 1171 $this->create_extra_users();
47f48152
DW
1172 $this->setUser($this->editingteachers[0]);
1173 $assign = $this->create_instance();
1174
a5c793c3 1175 $this->setUser($this->extrastudents[0]);
47f48152 1176 $now = time();
a5c793c3
DW
1177 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
1178 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
1179
1180 $this->setUser($this->teachers[0]);
1181 // Verify the gradebook update.
1182 $gradinginfo = grade_get_grades($this->course->id,
1183 'mod',
1184 'assign',
1185 $assign->get_instance()->id,
a5c793c3 1186 $this->extrastudents[0]->id);
47f48152 1187
a5c793c3
DW
1188 $this->assertEquals($this->extrastudents[0]->id,
1189 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
1190
1191 // Now verify group assignments.
1192 $this->setUser($this->editingteachers[0]);
1193 $assign = $this->create_instance(array('teamsubmission'=>1));
1194
a5c793c3 1195 $this->setUser($this->extrastudents[0]);
47f48152 1196 $now = time();
a5c793c3
DW
1197 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1198 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
47f48152 1199
e6cc5347 1200 // Check that at least 2 active members and 1 suspended member of the submission group had their submission updated.
47f48152
DW
1201
1202 $this->setUser($this->editingteachers[0]);
1203 $gradinginfo = grade_get_grades($this->course->id,
1204 'mod',
1205 'assign',
1206 $assign->get_instance()->id,
a5c793c3 1207 $this->extrastudents[0]->id);
47f48152 1208
a5c793c3
DW
1209 $this->assertEquals($this->extrastudents[0]->id,
1210 $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->usermodified);
47f48152
DW
1211
1212 $gradinginfo = grade_get_grades($this->course->id,
1213 'mod',
1214 'assign',
1215 $assign->get_instance()->id,
a5c793c3 1216 $this->extrastudents[self::GROUP_COUNT]->id);
47f48152 1217
a5c793c3
DW
1218 $this->assertEquals($this->extrastudents[self::GROUP_COUNT]->id,
1219 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT]->id]->usermodified);
47f48152 1220
e6cc5347
RT
1221 $gradinginfo = grade_get_grades($this->course->id,
1222 'mod',
1223 'assign',
1224 $assign->get_instance()->id,
1225 $this->extrasuspendedstudents[0]->id);
1226 $this->assertEquals($this->extrasuspendedstudents[0]->id,
1227 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[0]->id]->usermodified);
1228
1229 // Check the same with non-editing teacher and make sure submission is not updated for suspended user.
1230 $this->setUser($this->editingteachers[0]);
1231 $assign = $this->create_instance(array('teamsubmission'=>1));
1232
1233 $this->setUser($this->extrastudents[1]);
1234 $now = time();
1235 $submission = $assign->get_group_submission($this->extrastudents[1]->id, 0, true);
1236 $assign->testable_update_submission($submission, $this->extrastudents[1]->id, true, true);
1237
1238 $this->setUser($this->teachers[0]);
1239 $gradinginfo = grade_get_grades($this->course->id,
1240 'mod',
1241 'assign',
1242 $assign->get_instance()->id,
1243 $this->extrastudents[1]->id);
1244
1245 $this->assertEquals($this->extrastudents[1]->id,
1246 $gradinginfo->items[0]->grades[$this->extrastudents[1]->id]->usermodified);
1247
1248 $gradinginfo = grade_get_grades($this->course->id,
1249 'mod',
1250 'assign',
1251 $assign->get_instance()->id,
1252 $this->extrastudents[self::GROUP_COUNT+1]->id);
1253
1254 $this->assertEquals($this->extrastudents[self::GROUP_COUNT+1]->id,
1255 $gradinginfo->items[0]->grades[$this->extrastudents[self::GROUP_COUNT+1]->id]->usermodified);
1256
1257 $gradinginfo = grade_get_grades($this->course->id,
1258 'mod',
1259 'assign',
1260 $assign->get_instance()->id,
1261 $this->extrasuspendedstudents[1]->id);
1262 $this->assertEquals($this->extrasuspendedstudents[1]->id,
1263 $gradinginfo->items[0]->grades[$this->extrasuspendedstudents[1]->id]->usermodified);
1264
47f48152
DW
1265 // Now verify blind marking.
1266 $this->setUser($this->editingteachers[0]);
1267 $assign = $this->create_instance(array('blindmarking'=>1));
1268
a5c793c3 1269 $this->setUser($this->extrastudents[0]);
47f48152 1270 $now = time();
a5c793c3
DW
1271 $submission = $assign->get_user_submission($this->extrastudents[0]->id, true);
1272 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, false);
47f48152
DW
1273
1274 $this->setUser($this->editingteachers[0]);
1275 $gradinginfo = grade_get_grades($this->course->id,
1276 'mod',
1277 'assign',
1278 $assign->get_instance()->id,
a5c793c3 1279 $this->extrastudents[0]->id);
47f48152 1280
a5c793c3 1281 $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
47f48152
DW
1282 }
1283
79397b56 1284 public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() {
2bd27878
DW
1285 global $PAGE;
1286
1287 $this->create_extra_users();
1288 // Now verify group assignments.
1289 $this->setUser($this->editingteachers[0]);
1290 $assign = $this->create_instance(array('teamsubmission'=>1,
1291 'assignsubmission_onlinetext_enabled'=>1,
1292 'submissiondrafts'=>1,
1293 'requireallteammemberssubmit'=>1));
1294 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1295
2bd27878 1296 // Add a submission.
79397b56 1297 $this->setUser($this->extrastudents[0]);
2bd27878
DW
1298 $data = new stdClass();
1299 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1300 'text'=>'Submission text',
1301 'format'=>FORMAT_MOODLE);
1302
1303 $notices = array();
1304 $assign->save_submission($data, $notices);
1305
1306 // Check we can see the submit button.
1307 $output = $assign->view_student_summary($this->extrastudents[0], true);
1308 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1309
1310 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1311 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1312 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1313
1314 // Check that the student does not see "Submit" button.
1315 $output = $assign->view_student_summary($this->extrastudents[0], true);
1316 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1317
1318 // Change to another user in the same group.
1319 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1320 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1321 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1322
1323 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1324 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1325 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1326 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1327 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1328 }
1329
79397b56
DB
1330 public function test_group_submissions_submit_for_marking() {
1331 global $PAGE;
1332
1333 $this->create_extra_users();
1334 // Now verify group assignments.
1335 $this->setUser($this->editingteachers[0]);
a0f8db77 1336 $time = time();
79397b56
DB
1337 $assign = $this->create_instance(array('teamsubmission'=>1,
1338 'assignsubmission_onlinetext_enabled'=>1,
1339 'submissiondrafts'=>1,
1340 'requireallteammemberssubmit'=>0,
a0f8db77 1341 'duedate' => $time - 2*24*60*60));
79397b56
DB
1342 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1343
1344 $this->setUser($this->extrastudents[0]);
1345 // Add a submission.
1346 $data = new stdClass();
1347 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1348 'text'=>'Submission text',
1349 'format'=>FORMAT_MOODLE);
1350
1351 $notices = array();
1352 $assign->save_submission($data, $notices);
1353
1354 // Check we can see the submit button.
1355 $output = $assign->view_student_summary($this->extrastudents[0], true);
1356 $this->assertContains(get_string('submitassignment', 'assign'), $output);
1357 $this->assertContains(get_string('timeremaining', 'assign'), $output);
a0f8db77
DW
1358 $difftime = time() - $time;
1359 $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
1360
1361 $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
1362 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1363 $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
1364
1365 // Check that the student does not see "Submit" button.
1366 $output = $assign->view_student_summary($this->extrastudents[0], true);
1367 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1368
1369 // Change to another user in the same group.
1370 $this->setUser($this->extrastudents[self::GROUP_COUNT]);
1371 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1372 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1373
1374 // Check that time remaining is not overdue.
1375 $this->assertContains(get_string('timeremaining', 'assign'), $output);
a0f8db77
DW
1376 $difftime = time() - $time;
1377 $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60 + $difftime)), $output);
79397b56
DB
1378
1379 $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
1380 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1381 $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
1382 $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
1383 $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
1384 }
1385
47f48152
DW
1386 public function test_submissions_open() {
1387 $this->setUser($this->editingteachers[0]);
1388
1389 $now = time();
1390 $tomorrow = $now + 24*60*60;
1391 $oneweek = $now + 7*24*60*60;
1392 $yesterday = $now - 24*60*60;
1393
1394 $assign = $this->create_instance();
1395 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1396
1397 $assign = $this->create_instance(array('duedate'=>$tomorrow));
1398 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1399
1400 $assign = $this->create_instance(array('duedate'=>$yesterday));
1401 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1402
1403 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
1404 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1405
1406 $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
1407 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1408
1409 $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
1410 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1411
1412 $assign = $this->create_instance(array('submissiondrafts'=>1));
1413 $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
1414
1415 $this->setUser($this->students[0]);
1416 $now = time();
1417 $submission = $assign->get_user_submission($this->students[0]->id, true);
1418 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1419 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1420 $this->setUser($this->editingteachers[0]);
1421 $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
1422 }
1423
1424 public function test_get_graders() {
df211804 1425 $this->create_extra_users();
47f48152 1426 $this->setUser($this->editingteachers[0]);
47f48152 1427
f268fb5d
DW
1428 // Create an assignment with no groups.
1429 $assign = $this->create_instance();
a5c793c3
DW
1430 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1431 self::DEFAULT_EDITING_TEACHER_COUNT +
1432 self::EXTRA_TEACHER_COUNT +
1433 self::EXTRA_EDITING_TEACHER_COUNT,
1434 $assign->testable_get_graders($this->students[0]->id));
47f48152 1435
47f48152 1436 // Force create an assignment with SEPARATEGROUPS.
f268fb5d
DW
1437 $data = new stdClass();
1438 $data->courseid = $this->course->id;
1439 $data->name = 'Grouping';
1440 $groupingid = groups_create_grouping($data);
1441 groups_assign_grouping($groupingid, $this->groups[0]->id);
1442 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
47f48152
DW
1443
1444 $this->setUser($this->students[1]);
a5c793c3 1445 $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
f268fb5d
DW
1446 // Note the second student is in a group that is not in the grouping.
1447 // This means that we get all graders that are not in a group in the grouping.
1448 $this->assertCount(10, $assign->testable_get_graders($this->students[1]->id));
47f48152
DW
1449 }
1450
83360c8d
S
1451 public function test_get_notified_users() {
1452 global $CFG, $DB;
1453
1454 $capability = 'mod/assign:receivegradernotifications';
1455 $coursecontext = context_course::instance($this->course->id);
1456 $role = $DB->get_record('role', array('shortname' => 'teacher'));
1457
1458 $this->create_extra_users();
1459 $this->setUser($this->editingteachers[0]);
1460
1461 // Create an assignment with no groups.
1462 $assign = $this->create_instance();
1463
1464 $this->assertCount(self::DEFAULT_TEACHER_COUNT +
1465 self::DEFAULT_EDITING_TEACHER_COUNT +
1466 self::EXTRA_TEACHER_COUNT +
1467 self::EXTRA_EDITING_TEACHER_COUNT,
1468 $assign->testable_get_notifiable_users($this->students[0]->id));
1469
1470 // Change nonediting teachers role to not receive grader notifications.
1471 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1472
1473 $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT +
1474 self::EXTRA_EDITING_TEACHER_COUNT,
1475 $assign->testable_get_notifiable_users($this->students[0]->id));
1476
1477 // Reset nonediting teachers role to default.
1478 unassign_capability($capability, $role->id, $coursecontext);
1479
1480 // Force create an assignment with SEPARATEGROUPS.
1481 $data = new stdClass();
1482 $data->courseid = $this->course->id;
1483 $data->name = 'Grouping';
1484 $groupingid = groups_create_grouping($data);
1485 groups_assign_grouping($groupingid, $this->groups[0]->id);
1486 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
1487
1488 $this->setUser($this->students[1]);
1489 $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id));
1490 // Note the second student is in a group that is not in the grouping.
1491 // This means that we get all graders that are not in a group in the grouping.
1492 $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id));
1493
1494 // Change nonediting teachers role to not receive grader notifications.
1495 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
1496
1497 $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id));
1498 // Note the second student is in a group that is not in the grouping.
1499 // This means that we get all graders that are not in a group in the grouping.
1500 $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id));
1501 }
1502
20b7dcfc
DW
1503 public function test_group_members_only() {
1504 global $CFG;
1505
1506 $this->setAdminUser();
1507 $this->create_extra_users();
c13ac85d 1508 $CFG->enableavailability = true;
20b7dcfc
DW
1509 $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
1510 groups_assign_grouping($grouping->id, $this->groups[0]->id);
1511
1512 // Force create an assignment with SEPARATEGROUPS.
1513 $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id),
c13ac85d 1514 array('availability' => json_encode(\core_availability\tree::get_root_json(array(
1515 \availability_grouping\condition::get_json()))),
1516 'groupingid' => $grouping->id));
20b7dcfc
DW
1517
1518 $cm = get_coursemodule_from_instance('assign', $instance->id);
1519 $context = context_module::instance($cm->id);
1520 $assign = new testable_assign($context, $cm, $this->course);
1521
1522 $this->setUser($this->teachers[0]);
8270f0d0 1523 get_fast_modinfo($this->course, 0, true);
20b7dcfc
DW
1524 $this->assertCount(5, $assign->list_participants(0, true));
1525
1526 }
1527
47f48152
DW
1528 public function test_get_uniqueid_for_user() {
1529 $this->setUser($this->editingteachers[0]);
1530 $assign = $this->create_instance();
1531
1532 foreach ($this->students as $student) {
1533 $uniqueid = $assign->get_uniqueid_for_user($student->id);
1534 $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
1535 }
1536 }
1537
46692c3a 1538 public function test_show_student_summary() {
c2114099 1539 global $CFG, $PAGE;
46692c3a
DW
1540
1541 $this->setUser($this->editingteachers[0]);
1542 $assign = $this->create_instance();
c2114099 1543 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
46692c3a
DW
1544
1545 // No feedback should be available because this student has not been graded.
1546 $this->setUser($this->students[0]);
1547 $output = $assign->view_student_summary($this->students[0], true);
1548 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
1549 // Simulate adding a grade.
1550 $this->setUser($this->teachers[0]);
1551 $data = new stdClass();
1552 $data->grade = '50.0';
df211804 1553 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
46692c3a 1554
b0da618b 1555 // Now we should see the feedback.
46692c3a
DW
1556 $this->setUser($this->students[0]);
1557 $output = $assign->view_student_summary($this->students[0], true);
1558 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
1559
1560 // Now hide the grade in gradebook.
1561 $this->setUser($this->teachers[0]);
1562 require_once($CFG->libdir.'/gradelib.php');
1563 $gradeitem = new grade_item(array(
1564 'itemtype' => 'mod',
1565 'itemmodule' => 'assign',
1566 'iteminstance' => $assign->get_instance()->id,
1567 'courseid' => $this->course->id));
1568
1569 $gradeitem->set_hidden(1, false);
1570
1571 // No feedback should be available because the grade is hidden.
1572 $this->setUser($this->students[0]);
1573 $output = $assign->view_student_summary($this->students[0], true);
1574 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
1575
b0da618b 1576 // Do the same but add feedback.
46692c3a
DW
1577 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
1578
1579 $this->setUser($this->teachers[0]);
1580 $grade = $assign->get_user_grade($this->students[0]->id, true);
1581 $data = new stdClass();
1582 $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
1583 'format'=>FORMAT_MOODLE);
1584 $plugin = $assign->get_feedback_plugin_by_type('comments');
1585 $plugin->save($grade, $data);
1586
b0da618b 1587 // Should have feedback but no grade.
46692c3a
DW
1588 $this->setUser($this->students[0]);
1589 $output = $assign->view_student_summary($this->students[0], true);
ea698284 1590 $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback even if there is no grade');
46692c3a
DW
1591 $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
1592 $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
45aac51a 1593
ea698284
AD
1594 // Now hide the grade in gradebook.
1595 $this->setUser($this->teachers[0]);
1596 $gradeitem = new grade_item(array(
1597 'itemtype' => 'mod',
1598 'itemmodule' => 'assign',
1599 'iteminstance' => $assign->get_instance()->id,
1600 'courseid' => $this->course->id));
1601
1602 $gradeitem->set_hidden(1, false);
1603
1604 // No feedback should be available because the grade is hidden.
1605 $this->setUser($this->students[0]);
1606 $output = $assign->view_student_summary($this->students[0], true);
1607 $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
46692c3a
DW
1608 }
1609
df211804
DW
1610 public function test_attempt_reopen_method_manual() {
1611 global $PAGE;
1612
1613 $this->setUser($this->editingteachers[0]);
1614 $assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
1615 'maxattempts'=>3,
1616 'submissiondrafts'=>1,
1617 'assignsubmission_onlinetext_enabled'=>1));
1618 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1619
1620 // Student should be able to see an add submission button.
1621 $this->setUser($this->students[0]);
1622 $output = $assign->view_student_summary($this->students[0], true);
1623 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1624
1625 // Add a submission.
1626 $now = time();
1627 $submission = $assign->get_user_submission($this->students[0]->id, true);
1628 $data = new stdClass();
1629 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
1630 'text'=>'Submission text',
1631 'format'=>FORMAT_MOODLE);
1632 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1633 $plugin->save($submission, $data);
1634
1635 // And now submit it for marking.
1636 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1637 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1638
1639 // Verify the student cannot make changes to the submission.
1640 $output = $assign->view_student_summary($this->students[0], true);
1641 $this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1642
1643 // Mark the submission.
1644 $this->setUser($this->teachers[0]);
1645 $data = new stdClass();
1646 $data->grade = '50.0';
1647 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1648
1649 // Check the student can see the grade.
1650 $this->setUser($this->students[0]);
1651 $output = $assign->view_student_summary($this->students[0], true);
1652 $this->assertNotEquals(false, strpos($output, '50.0'));
1653
1654 // Allow the student another attempt.
1655 $this->teachers[0]->ignoresesskey = true;
1656 $this->setUser($this->teachers[0]);
1657 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1658 $this->assertEquals(true, $result);
1659
1660 // Check that the previous attempt is now in the submission history table.
1661 $this->setUser($this->students[0]);
1662 $output = $assign->view_student_summary($this->students[0], true);
1663 // Need a better check.
1664 $this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
1665
1666 // Check that the student now has a button for Add a new attempt".
1667 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1668 // Check that the student now does not have a button for Submit.
1669 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1670
1671 // Check that the student now has a submission history.
1672 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1673
1674 $this->setUser($this->teachers[0]);
1675 // Check that the grading table loads correctly and contains this user.
1676 // This is also testing that we do not get duplicate rows in the grading table.
1677 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1678 $output = $assign->get_renderer()->render($gradingtable);
1679 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1680
1681 // Should be 1 not 2.
1682 $this->assertEquals(1, $assign->count_submissions());
1683 $this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
1684 $this->assertEquals(0, $assign->count_submissions_need_grading());
1685 $this->assertEquals(1, $assign->count_grades());
1686
1687 // Change max attempts to unlimited.
1688 $formdata = clone($assign->get_instance());
1689 $formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
1690 $formdata->instance = $formdata->id;
1691 $assign->update_instance($formdata);
1692
9e3eee67
DW
1693 // Mark the submission again.
1694 $data = new stdClass();
1695 $data->grade = '60.0';
1696 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1697
1698 // Check the grade exists.
1699 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1700 $this->assertEquals(60, (int)$grades[$this->students[0]->id]->rawgrade);
1701
1702 // Check we can reopen still.
df211804
DW
1703 $result = $assign->testable_process_add_attempt($this->students[0]->id);
1704 $this->assertEquals(true, $result);
1705
9e3eee67 1706 // Should no longer have a grade because there is no grade for the latest attempt.
df211804 1707 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
9e3eee67 1708 $this->assertEmpty($grades);
df211804 1709
df211804 1710 }
46692c3a 1711
e77bacab
MP
1712 /**
1713 * Test reopen behavior when in "Reopen until pass" mode.
1714 */
1715 public function test_attempt_reopen_method_untilpass() {
1716 global $PAGE;
1717
1718 $this->setUser($this->editingteachers[0]);
1719 $assign = $this->create_instance(array('attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS,
1720 'maxattempts' => 3,
1721 'submissiondrafts' => 1,
1722 'assignsubmission_onlinetext_enabled' => 1));
1723 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1724
1725 // Set grade to pass to 80.
1726 $gradeitem = $assign->get_grade_item();
1727 $gradeitem->gradepass = '80.0';
1728 $gradeitem->update();
1729
1730 // Student should be able to see an add submission button.
1731 $this->setUser($this->students[0]);
1732 $output = $assign->view_student_summary($this->students[0], true);
1733 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
1734
1735 // Add a submission.
1736 $now = time();
1737 $submission = $assign->get_user_submission($this->students[0]->id, true);
1738 $data = new stdClass();
1739 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1740 'text' => 'Submission text',
1741 'format' => FORMAT_MOODLE);
1742 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1743 $plugin->save($submission, $data);
1744
1745 // And now submit it for marking.
1746 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1747 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1748
1749 // Verify the student cannot make a new attempt.
1750 $output = $assign->view_student_summary($this->students[0], true);
1751 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1752
1753 // Mark the submission as non-passing.
1754 $this->setUser($this->teachers[0]);
1755 $data = new stdClass();
1756 $data->grade = '50.0';
1757 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1758
1759 // Check the student can see the grade.
1760 $this->setUser($this->students[0]);
1761 $output = $assign->view_student_summary($this->students[0], true);
1762 $this->assertNotEquals(false, strpos($output, '50.0'));
1763
1764 // Check that the student now has a button for Add a new attempt.
1765 $output = $assign->view_student_summary($this->students[0], true);
1766 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1767
1768 // Check that the student now does not have a button for Submit.
1769 $this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
1770
1771 // Check that the student now has a submission history.
1772 $this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
1773
1774 // Add a second submission.
1775 $now = time();
1776 $submission = $assign->get_user_submission($this->students[0]->id, true, 1);
1777 $data = new stdClass();
1778 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1779 'text' => 'Submission text',
1780 'format' => FORMAT_MOODLE);
1781 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1782 $plugin->save($submission, $data);
1783
1784 // And now submit it for marking.
1785 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1786 $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
1787
1788 // Mark the submission as passing.
1789 $this->setUser($this->teachers[0]);
1790 $data = new stdClass();
1791 $data->grade = '80.0';
1792 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1793
1794 // Check that the student does not have a button for Add a new attempt.
1795 $this->setUser($this->students[0]);
1796 $output = $assign->view_student_summary($this->students[0], true);
1797 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1798
1799 // Re-mark the submission as not passing.
1800 $this->setUser($this->teachers[0]);
1801 $data = new stdClass();
1802 $data->grade = '50.0';
1803 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 1);
1804
1805 // Check that the student now has a button for Add a new attempt.
1806 $this->setUser($this->students[0]);
1807 $output = $assign->view_student_summary($this->students[0], true);
1808 $this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1809
1810 // Add a submission as a second student.
1811 $this->setUser($this->students[1]);
1812 $now = time();
1813 $submission = $assign->get_user_submission($this->students[1]->id, true);
1814 $data = new stdClass();
1815 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1816 'text' => 'Submission text',
1817 'format' => FORMAT_MOODLE);
1818 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1819 $plugin->save($submission, $data);
1820
1821 // And now submit it for marking.
1822 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1823 $assign->testable_update_submission($submission, $this->students[1]->id, true, false);
1824
1825 // Mark the submission as passing.
1826 $this->setUser($this->teachers[0]);
1827 $data = new stdClass();
1828 $data->grade = '100.0';
1829 $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
1830
1831 // Check the student can see the grade.
1832 $this->setUser($this->students[1]);
1833 $output = $assign->view_student_summary($this->students[1], true);
1834 $this->assertNotEquals(false, strpos($output, '100.0'));
1835
1836 // Check that the student does not have a button for Add a new attempt.
1837 $output = $assign->view_student_summary($this->students[1], true);
1838 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1839
1840 // Set grade to pass to 0, so that no attempts should reopen.
1841 $gradeitem = $assign->get_grade_item();
1842 $gradeitem->gradepass = '0';
1843 $gradeitem->update();
1844
1845 // Add another submission.
1846 $this->setUser($this->students[2]);
1847 $now = time();
1848 $submission = $assign->get_user_submission($this->students[2]->id, true);
1849 $data = new stdClass();
1850 $data->onlinetext_editor = array('itemid' => file_get_unused_draft_itemid(),
1851 'text' => 'Submission text',
1852 'format' => FORMAT_MOODLE);
1853 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
1854 $plugin->save($submission, $data);
1855
1856 // And now submit it for marking.
1857 $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1858 $assign->testable_update_submission($submission, $this->students[2]->id, true, false);
1859
1860 // Mark the submission as graded.
1861 $this->setUser($this->teachers[0]);
1862 $data = new stdClass();
1863 $data->grade = '0.0';
1864 $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
1865
1866 // Check the student can see the grade.
1867 $this->setUser($this->students[2]);
1868 $output = $assign->view_student_summary($this->students[2], true);
1869 $this->assertNotEquals(false, strpos($output, '0.0'));
1870
1871 // Check that the student does not have a button for Add a new attempt.
1872 $output = $assign->view_student_summary($this->students[2], true);
1873 $this->assertEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
1874 }
1875
1876
f8d107b3
DM
1877 public function test_markingworkflow() {
1878 global $PAGE;
1879
1880 $this->setUser($this->editingteachers[0]);
1881 $assign = $this->create_instance(array('markingworkflow'=>1));
1882 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1883
13e82f1c 1884 // Mark the submission and set to notmarked.
f8d107b3
DM
1885 $this->setUser($this->teachers[0]);
1886 $data = new stdClass();
1887 $data->grade = '50.0';
1888 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
1889 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1890
1891 // Check the student can't see the grade.
1892 $this->setUser($this->students[0]);
1893 $output = $assign->view_student_summary($this->students[0], true);
1894 $this->assertEquals(false, strpos($output, '50.0'));
1895
5047b0ea
TB
1896 // Make sure the grade isn't pushed to the gradebook.
1897 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1898 $this->assertEmpty($grades);
1899
13e82f1c 1900 // Mark the submission and set to inmarking.
f8d107b3
DM
1901 $this->setUser($this->teachers[0]);
1902 $data = new stdClass();
1903 $data->grade = '50.0';
1904 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
1905 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1906
1907 // Check the student can't see the grade.
1908 $this->setUser($this->students[0]);
1909 $output = $assign->view_student_summary($this->students[0], true);
1910 $this->assertEquals(false, strpos($output, '50.0'));
1911
5047b0ea
TB
1912 // Make sure the grade isn't pushed to the gradebook.
1913 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1914 $this->assertEmpty($grades);
1915
13e82f1c 1916 // Mark the submission and set to readyforreview.
f8d107b3
DM
1917 $this->setUser($this->teachers[0]);
1918 $data = new stdClass();
1919 $data->grade = '50.0';
1920 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
1921 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1922
1923 // Check the student can't see the grade.
1924 $this->setUser($this->students[0]);
1925 $output = $assign->view_student_summary($this->students[0], true);
1926 $this->assertEquals(false, strpos($output, '50.0'));
1927
5047b0ea
TB
1928 // Make sure the grade isn't pushed to the gradebook.
1929 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1930 $this->assertEmpty($grades);
1931
13e82f1c 1932 // Mark the submission and set to inreview.
f8d107b3
DM
1933 $this->setUser($this->teachers[0]);
1934 $data = new stdClass();
1935 $data->grade = '50.0';
1936 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
1937 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1938
1939 // Check the student can't see the grade.
1940 $this->setUser($this->students[0]);
1941 $output = $assign->view_student_summary($this->students[0], true);
1942 $this->assertEquals(false, strpos($output, '50.0'));
1943
5047b0ea
TB
1944 // Make sure the grade isn't pushed to the gradebook.
1945 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1946 $this->assertEmpty($grades);
1947
13e82f1c 1948 // Mark the submission and set to readyforrelease.
f8d107b3
DM
1949 $this->setUser($this->teachers[0]);
1950 $data = new stdClass();
1951 $data->grade = '50.0';
1952 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
1953 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1954
1955 // Check the student can't see the grade.
1956 $this->setUser($this->students[0]);
1957 $output = $assign->view_student_summary($this->students[0], true);
1958 $this->assertEquals(false, strpos($output, '50.0'));
1959
5047b0ea
TB
1960 // Make sure the grade isn't pushed to the gradebook.
1961 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1962 $this->assertEmpty($grades);
1963
13e82f1c 1964 // Mark the submission and set to released.
f8d107b3
DM
1965 $this->setUser($this->teachers[0]);
1966 $data = new stdClass();
1967 $data->grade = '50.0';
1968 $data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
1969 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1970
1971 // Check the student can see the grade.
1972 $this->setUser($this->students[0]);
1973 $output = $assign->view_student_summary($this->students[0], true);
1974 $this->assertNotEquals(false, strpos($output, '50.0'));
5047b0ea
TB
1975
1976 // Make sure the grade is pushed to the gradebook.
1977 $grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
1978 $this->assertEquals(50, (int)$grades[$this->students[0]->id]->rawgrade);
f8d107b3
DM
1979 }
1980
1981 public function test_markerallocation() {
1982 global $PAGE;
1983
1984 $this->setUser($this->editingteachers[0]);
13e82f1c 1985 $assign = $this->create_instance(array('markingworkflow'=>1, 'markingallocation'=>1));
f8d107b3
DM
1986 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
1987
13e82f1c 1988 // Allocate marker to submission.
f8d107b3
DM
1989 $data = new stdClass();
1990 $data->allocatedmarker = $this->teachers[0]->id;
1991 $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
1992
13e82f1c 1993 // Check the allocated marker can view the submission.
f8d107b3
DM
1994 $this->setUser($this->teachers[0]);
1995 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
1996 $output = $assign->get_renderer()->render($gradingtable);
1997 $this->assertEquals(true, strpos($output, $this->students[0]->lastname));
1998
13e82f1c 1999 // Check that other teachers can't view this submission.
f8d107b3
DM
2000 $this->setUser($this->teachers[1]);
2001 $gradingtable = new assign_grading_table($assign, 100, '', 0, true);
2002 $output = $assign->get_renderer()->render($gradingtable);
2003 $this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
2004 }
76e77b05 2005
3d1331be 2006
159b7f40 2007
57fbd5f9
DW
2008 public function test_teacher_submit_for_student() {
2009 global $PAGE;
2010
2011 $this->preventResetByRollback();
2012 $sink = $this->redirectMessages();
2013
2014 $this->setUser($this->editingteachers[0]);
2015
2016 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
2017 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
2018
2019 $this->setUser($this->students[0]);
2020 // Simulate a submission.
2021 $data = new stdClass();
2022 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2023 'text'=>'Student submission text',
2024 'format'=>FORMAT_MOODLE);
2025
2026 $notices = array();
2027 $assign->save_submission($data, $notices);
2028
2029 // Check that the submission text was saved.
2030 $output = $assign->view_student_summary($this->students[0], true);
2031 $this->assertContains('Student submission text', $output, 'Contains student submission text');
2032
2033 // Check that a teacher teacher with the extra capability can edit a students submission.
2034 $this->setUser($this->teachers[0]);
2035 $data = new stdClass();
2036 $data->userid = $this->students[0]->id;
2037 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2038 'text'=>'Teacher edited submission text',
2039 'format'=>FORMAT_MOODLE);
2040
2041 // Add the required capability.
2042 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
2043 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
2044 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
2045 accesslib_clear_all_caches_for_unit_testing();
2046
2047 // Try to save the submission.
2048 $notices = array();
2049 $assign->save_submission($data, $notices);
2050
2051 // Check that the teacher can submit the students work.
2052 $data = new stdClass();
2053 $data->userid = $this->students[0]->id;
2054 $notices = array();
2055 $assign->submit_for_grading($data, $notices);
2056
2057 // Revert to draft so the student can edit it.
2058 $assign->revert_to_draft($this->students[0]->id);
2059
2060 $this->setUser($this->students[0]);
2061
2062 // Check that the submission text was saved.
2063 $output = $assign->view_student_summary($this->students[0], true);
2064 $this->assertContains('Teacher edited submission text', $output, 'Contains student submission text');
2065
2066 // Check that the student can submit their work.
2067 $data = new stdClass();
2068 $assign->submit_for_grading($data, $notices);
2069
2070 $output = $assign->view_student_summary($this->students[0], true);
2071 $this->assertNotContains(get_string('addsubmission', 'assign'), $output);
2072
2073 // Set to a default editing teacher who should not be able to edit this submission.
2074 $this->setUser($this->editingteachers[1]);
2075
2076 // Revert to draft so the submission is editable.
2077 $assign->revert_to_draft($this->students[0]->id);
2078
2079 $data = new stdClass();
2080 $data->userid = $this->students[0]->id;
2081 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2082 'text'=>'Teacher 2 edited submission text',
2083 'format'=>FORMAT_MOODLE);
2084
2085 $notices = array();
2086 $this->setExpectedException('moodle_exception');
2087 $assign->save_submission($data, $notices);
2088
2089 $sink->close();
2090 }
2091
9054c04d 2092 public function test_disable_submit_after_cutoff_date() {
2093 global $PAGE;
2094
2095 $this->setUser($this->editingteachers[0]);
2096 $now = time();
2097 $tomorrow = $now + 24*60*60;
2098 $lastweek = $now - 7*24*60*60;
2099 $yesterday = $now - 24*60*60;
2100
2101 $assign = $this->create_instance(array('duedate'=>$yesterday,
2102 'cutoffdate'=>$tomorrow,
2103 'assignsubmission_onlinetext_enabled'=>1));
2104 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
2105
2106 // Student should be able to see an add submission button.
2107 $this->setUser($this->students[0]);
2108 $output = $assign->view_student_summary($this->students[0], true);
2109 $this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
2110
2111 // Add a submission but don't submit now.
2112 $submission = $assign->get_user_submission($this->students[0]->id, true);
2113 $data = new stdClass();
2114 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2115 'text'=>'Submission text',
2116 'format'=>FORMAT_MOODLE);
2117 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2118 $plugin->save($submission, $data);
2119
2120 // Create another instance with cut-off and due-date already passed.
2121 $this->setUser($this->editingteachers[0]);
2122 $now = time();
2123 $assign = $this->create_instance(array('duedate'=>$lastweek,
2124 'cutoffdate'=>$yesterday,
2125 'assignsubmission_onlinetext_enabled'=>1));
2126
2127 $this->setUser($this->students[0]);
2128 $output = $assign->view_student_summary($this->students[0], true);
2129 $this->assertNotContains($output, get_string('editsubmission', 'assign'),
2130 'Should not be able to edit after cutoff date.');
2131 $this->assertNotContains($output, get_string('submitassignment', 'assign'),
2132 'Should not be able to submit after cutoff date.');
2133 }
f159ad73 2134 /**
2135 * Testing for submission comment plugin settings
2136 */
2137 public function test_submission_comment_plugin_settings() {
2138 global $CFG;
2139
2140 $commentconfig = false;
2141 if (!empty($CFG->usecomments)) {
2142 $commentconfig = $CFG->usecomments;
2143 }
2144
2145 $CFG->usecomments = true;
2146 $assign = $this->create_instance();
2147 $plugin = $assign->get_submission_plugin_by_type('comments');
2148 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2149
2150 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
2151 $plugin = $assign->get_submission_plugin_by_type('comments');
2152 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2153
2154 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
2155 $plugin = $assign->get_submission_plugin_by_type('comments');
2156 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2157
2158 $CFG->usecomments = false;
2159 $assign = $this->create_instance();
2160 $plugin = $assign->get_submission_plugin_by_type('comments');
2161 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2162
2163 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 0));
2164 $plugin = $assign->get_submission_plugin_by_type('comments');
2165 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2166
2167 $assign = $this->create_instance(array('assignsubmission_comments_enabled' => 1));
2168 $plugin = $assign->get_submission_plugin_by_type('comments');
2169 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2170
2171 $CFG->usecomments = $commentconfig;
2172 }
2173
c7a73689
DW
2174 /**
2175 * Testing for comment inline settings
2176 */
2177 public function test_feedback_comment_commentinline() {
2178 global $CFG;
2179
2180 $sourcetext = "Hello!
2181
2182I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
2183
2184URL outside a tag: https://moodle.org/logo/logo-240x60.gif
2185Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
2186
2187External link 1:<img src='https://moodle.org/logo/logo-240x60.gif' alt='Moodle'/>
2188External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\"/>
2189Internal link 1:<img src='@@PLUGINFILE@@/logo-240x60.gif' alt='Moodle'/>
2190Internal link 2:<img alt=\"Moodle\" src=\"@@PLUGINFILE@@logo-240x60.gif\"/>
2191Anchor link 1:<a href=\"@@PLUGINFILE@@logo-240x60.gif\" alt=\"bananas\">Link text</a>
2192Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
2193";
2194
2195 // Note the internal images have been stripped and the html is purified (quotes fixed in this case).
2196 $filteredtext = "Hello!
2197
2198I'm writing to you from the Moodle Majlis in Muscat, Oman, where we just had several days of Moodle community goodness.
2199
2200URL outside a tag: https://moodle.org/logo/logo-240x60.gif
2201Plugin url outside a tag: @@PLUGINFILE@@/logo-240x60.gif
2202
2203External link 1:<img src=\"https://moodle.org/logo/logo-240x60.gif\" alt=\"Moodle\" />
2204External link 2:<img alt=\"Moodle\" src=\"https://moodle.org/logo/logo-240x60.gif\" />
2205Internal link 1:
2206Internal link 2:
2207Anchor link 1:Link text
2208Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
2209";
2210
2211 $this->setUser($this->editingteachers[0]);
2212 $params = array('assignsubmission_onlinetext_enabled' => 1,
2213 'assignfeedback_comments_enabled' => 1,
2214 'assignfeedback_comments_commentinline' => 1);
2215 $assign = $this->create_instance($params);
2216
2217 $this->setUser($this->students[0]);
2218 // Add a submission but don't submit now.
2219 $submission = $assign->get_user_submission($this->students[0]->id, true);
2220 $data = new stdClass();
2221
2222 // Test the internal link is stripped, but the external one is not.
2223 $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
2224 'text'=>$sourcetext,
2225 'format'=>FORMAT_MOODLE);
2226
2227 $plugin = $assign->get_submission_plugin_by_type('onlinetext');
2228 $plugin->save($submission, $data);
2229
2230 $this->setUser($this->editingteachers[0]);
2231
2232 $data = new stdClass();
2233 require_once($CFG->dirroot . '/mod/assign/gradeform.php');
2234 $pagination = array('userid'=>$this->students[0]->id,
2235 'rownum'=>0,
2236 'last'=>true,
3fca6937 2237 'useridlistid' => $assign->get_useridlist_key_id(),
c7a73689
DW
2238 'attemptnumber'=>0);
2239 $formparams = array($assign, $data, $pagination);
2240 $mform = new mod_assign_grade_form(null, $formparams);
2241
2242 $this->assertEquals($filteredtext, $data->assignfeedbackcomments_editor['text']);
2243 }
2244
f159ad73 2245 /**
2246 * Testing for feedback comment plugin settings
2247 */
2248 public function test_feedback_plugin_settings() {
2249
2250 $assign = $this->create_instance();
2251 $plugin = $assign->get_feedback_plugin_by_type('comments');
2252 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2253
2254 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 0));
2255 $plugin = $assign->get_feedback_plugin_by_type('comments');
2256 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2257
2258 $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
2259 $plugin = $assign->get_feedback_plugin_by_type('comments');
2260 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2261 }
456d7bc7
RT
2262
2263 /**
2264 * Testing if gradebook feedback plugin is enabled.
2265 */
2266 public function test_is_gradebook_feedback_enabled() {
2267 $adminconfig = get_config('assign');
2268 $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
2269
2270 // Create assignment with gradebook feedback enabled and grade = 0.
2271 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 1, 'grades' => 0));
2272
2273 // Get gradebook feedback plugin.
2274 $gradebookplugintype = str_replace('assignfeedback_', '', $gradebookplugin);
2275 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
2276 $this->assertEquals(1, $plugin->is_enabled('enabled'));
2277 $this->assertEquals(1, $assign->is_gradebook_feedback_enabled());
2278
2279 // Create assignment with gradebook feedback disabled and grade = 0.
2280 $assign = $this->create_instance(array($gradebookplugin . '_enabled' => 0, 'grades' => 0));
2281 $plugin = $assign->get_feedback_plugin_by_type($gradebookplugintype);
2282 $this->assertEquals(0, $plugin->is_enabled('enabled'));
2283 }
57fbd5f9
DW
2284
2285 /**
2286 * Testing can_edit_submission
2287 */
2288 public function test_can_edit_submission() {
2289 global $PAGE, $DB;
2290 $this->create_extra_users();
2291
2292 $this->setAdminUser();
2293 // Create assignment (onlinetext).
2294 $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1, 'submissiondrafts'=>1));
2295 $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
2296
2297 // Check student can edit their own submission.
2298 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id));
2299 // Check student cannot edit others submission.
2300 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id));
2301
2302 // Check teacher cannot (by default) edit a students submission.
2303 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
2304
2305 // Add the required capability to edit a student submission.
2306 $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
2307 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
2308 role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id);
2309 accesslib_clear_all_caches_for_unit_testing();
2310 // Retest - should now have access.
2311 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id));
2312
2313 // Force create an assignment with SEPARATEGROUPS.
2314 $data = new stdClass();
2315 $data->courseid = $this->course->id;
2316 $data->name = 'Grouping';
2317 $groupingid = groups_create_grouping($data);
2318 groups_assign_grouping($groupingid, $this->groups[0]->id);
2319 groups_assign_grouping($groupingid, $this->groups[1]->id);
2320 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
2321
2322 // Add the capability to the new assignment for extra students 0 and 1.
2323 assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id);
2324 role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id);
2325 role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id);
2326 accesslib_clear_all_caches_for_unit_testing();
2327
2328 // Verify the extra student does not have the capability to edit a submission not in their group.
2329 $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id));
2330 // Verify the extra student does have the capability to edit a submission in their group.
2331 $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id));
2332
2333 }
323f221b
MH
2334
2335 /**
2336 * Test if the view blind details capability works
2337 */
2338 public function test_can_view_blind_details() {
2339 global $PAGE, $DB;
2340 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
2341 $managerrole = $DB->get_record('role', array('shortname' => 'manager'));
2342
2343 $student = $this->students[0];// Get a student user.
2344 // Create a teacher. Shouldn't be able to view blind marking ID.
2345 $teacher = $this->getDataGenerator()->create_user();
2346
2347 $this->getDataGenerator()->enrol_user($teacher->id,
2348 $this->course->id,
2349 $teacherrole->id);
2350
2351 // Create a manager.. Should be able to view blind marking ID.
2352 $manager = $this->getDataGenerator()->create_user();
e28d6b29
MG
2353 $this->getDataGenerator()->enrol_user($manager->id,
2354 $this->course->id,
323f221b
MH
2355 $managerrole->id);
2356
2357 // Generate blind marking assignment.
e28d6b29 2358 $assign = $this->create_instance(array('blindmarking' => 1));
323f221b
MH
2359 $this->assertEquals(true, $assign->is_blind_marking());
2360
2361 // Test student names are hidden to teacher.
e28d6b29
MG
2362 $this->setUser($teacher);
2363 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
2364 $output = $assign->get_renderer()->render($gradingtable);
323f221b
MH
2365 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign'))); // "Participant" is somewhere on the page.
2366 $this->assertEquals(false, strpos($output, fullname($student))); // Students full name doesn't appear.
2367
2368 // Test student names are visible to manager.
e28d6b29
MG
2369 $this->setUser($manager);
2370 $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
2371 $output = $assign->get_renderer()->render($gradingtable);
59e95487
MH
2372 $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign')));
2373 $this->assertEquals(true, strpos($output, fullname($student)));
323f221b 2374 }
6d6e297b
DM
2375
2376 /**
2377 * Testing get_shared_group_members
2378 */
2379 public function test_get_shared_group_members() {
2380 $this->create_extra_users();
2381 $this->setAdminUser();
2382
2383 // Force create an assignment with SEPARATEGROUPS.
2384 $data = new stdClass();
2385 $data->courseid = $this->course->id;
2386 $data->name = 'Grouping';
2387 $groupingid = groups_create_grouping($data);
2388 groups_assign_grouping($groupingid, $this->groups[0]->id);
2389 groups_assign_grouping($groupingid, $this->groups[1]->id);
2390 $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
2391 $cm = $assign->get_course_module();
2392
2393 // Add the capability to access allgroups.
2394 $roleid = create_role('Access all groups role', 'accessallgroupsrole', '');
2395 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $assign->get_context()->id);
2396 role_assign($roleid, $this->extrastudents[3]->id, $assign->get_context()->id);
2397 accesslib_clear_all_caches_for_unit_testing();
2398
2399 // Get shared group members for students 0 and 1.
2400 $groupmembers = array();
2401 $groupmembers[0] = $assign->get_shared_group_members($cm, $this->students[0]->id);
2402 $groupmembers[1] = $assign->get_shared_group_members($cm, $this->students[1]->id);
2403
2404 // They should share groups with extrastudents 0 and 1.
2405 $this->assertTrue(in_array($this->extrastudents[0]->id, $groupmembers[0]));
2406 $this->assertFalse(in_array($this->extrastudents[0]->id, $groupmembers[1]));
2407 $this->assertTrue(in_array($this->extrastudents[1]->id, $groupmembers[1]));
2408 $this->assertFalse(in_array($this->extrastudents[1]->id, $groupmembers[0]));
2409
2410 // Lists of group members for students and extrastudents should be the same.
2411 $this->assertEquals($groupmembers[0], $assign->get_shared_group_members($cm, $this->extrastudents[0]->id));
2412 $this->assertEquals($groupmembers[1], $assign->get_shared_group_members($cm, $this->extrastudents[1]->id));
2413
2414 // Get all group members for extrastudent 3 wich can access all groups.
2415 $allgroupmembers = $assign->get_shared_group_members($cm, $this->extrastudents[3]->id);
2416
2417 // Extrastudent 3 should see students 0 and 1, extrastudent 0 and 1.
2418 $this->assertTrue(in_array($this->students[0]->id, $allgroupmembers));
2419 $this->assertTrue(in_array($this->students[1]->id, $allgroupmembers));
2420 $this->assertTrue(in_array($this->extrastudents[0]->id, $allgroupmembers));
2421 $this->assertTrue(in_array($this->extrastudents[1]->id , $allgroupmembers));
2422 }
47f48152 2423
92ea1fa0
JL
2424 /**
2425 * Test get plugins file areas
2426 */
2427 public function test_get_plugins_file_areas() {
2428 $this->setUser($this->editingteachers[0]);
2429 $assign = $this->create_instance();
2430
2431 // Test that all the submission and feedback plugins are returning the expected file aras.
2432 $usingfilearea = 0;
11ee4f71 2433 $coreplugins = core_plugin_manager::standard_plugins_list('assignsubmission');
92ea1fa0
JL
2434 foreach ($assign->get_submission_plugins() as $plugin) {
2435 $type = $plugin->get_type();
11ee4f71
AO
2436 if (!in_array($type, $coreplugins)) {
2437 continue;
2438 }
92ea1fa0
JL
2439 $fileareas = $plugin->get_file_areas();
2440
2441 if ($type == 'onlinetext') {
2442 $this->assertEquals(array('submissions_onlinetext' => 'Online text'), $fileareas);
2443 $usingfilearea++;
2444 } else if ($type == 'file') {
2445 $this->assertEquals(array('submission_files' => 'File submissions'), $fileareas);
2446 $usingfilearea++;
2447 } else {
2448 $this->assertEmpty($fileareas);
2449 }
2450 }
2451 $this->assertEquals(2, $usingfilearea);
2452
2453 $usingfilearea = 0;
11ee4f71 2454 $coreplugins = core_plugin_manager::standard_plugins_list('assignfeedback');
92ea1fa0
JL
2455 foreach ($assign->get_feedback_plugins() as $plugin) {
2456 $type = $plugin->get_type();
11ee4f71
AO
2457 if (!in_array($type, $coreplugins)) {
2458 continue;
2459 }
92ea1fa0
JL
2460 $fileareas = $plugin->get_file_areas();
2461
2462 if ($type == 'editpdf') {
2463 $this->assertEquals(array('download' => 'Annotate PDF'), $fileareas);
2464 $usingfilearea++;
2465 } else if ($type == 'file') {
2466 $this->assertEquals(array('feedback_files' => 'Feedback files'), $fileareas);
2467 $usingfilearea++;
2468 } else {
2469 $this->assertEmpty($fileareas);
2470 }
2471 }
2472 $this->assertEquals(2, $usingfilearea);
2473 }
2474
002864cc
EM
2475 /**
2476 * Test the quicksave grades processor
2477 */
2478 public function test_process_save_quick_grades() {
2479 $this->editingteachers[0]->ignoresesskey = true;
2480 $this->setUser($this->editingteachers[0]);
2481
2482 $assign = $this->create_instance(array('attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL));
2483
2484 // Initially grade the user.
2485 $grade = $assign->get_user_grade($this->students[0]->id, false);
2486 if (!$grade) {
2487 $grade = new stdClass();
2488 $grade->attemptnumber = '';
2489 $grade->timemodified = '';
2490 }
2491 $data = array(
2492 'grademodified_' . $this->students[0]->id => $grade->timemodified,
2493 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber,
2494 'quickgrade_' . $this->students[0]->id => '60.0'
2495 );
2496 $result = $assign->testable_process_save_quick_grades($data);
2497 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result);
2498 $grade = $assign->get_user_grade($this->students[0]->id, false);
2499 $this->assertEquals('60.0', $grade->grade);
2500
2501 // Attempt to grade with a past attempts grade info.
2502 $assign->testable_process_add_attempt($this->students[0]->id);
2503 $data = array(
2504 'grademodified_' . $this->students[0]->id => $grade->timemodified,
2505 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber,
2506 'quickgrade_' . $this->students[0]->id => '50.0'
2507 );
2508 $result = $assign->testable_process_save_quick_grades($data);
2509 $this->assertContains(get_string('errorrecordmodified', 'assign'), $result);
2510 $grade = $assign->get_user_grade($this->students[0]->id, false);
2511 $this->assertFalse($grade);
2512
2513 // Attempt to grade a the attempt.
2514 $submission = $assign->get_user_submission($this->students[0]->id, false);
2515 $data = array(
2516 'grademodified_' . $this->students[0]->id => '',
2517 'gradeattempt_' . $this->students[0]->id => $submission->attemptnumber,
2518 'quickgrade_' . $this->students[0]->id => '40.0'
2519 );
2520 $result = $assign->testable_process_save_quick_grades($data);
2521 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result);
2522 $grade = $assign->get_user_grade($this->students[0]->id, false);
2523 $this->assertEquals('40.0', $grade->grade);
2524
2525 // Catch grade update conflicts.
2526 // Save old data for later.
2527 $pastdata = $data;
2528 // Update the grade the 'good' way.
2529 $data = array(
2530 'grademodified_' . $this->students[0]->id => $grade->timemodified,
2531 'gradeattempt_' . $this->students[0]->id => $grade->attemptnumber,
2532 'quickgrade_' . $this->students[0]->id => '30.0'
2533 );
2534 $result = $assign->testable_process_save_quick_grades($data);
2535 $this->assertContains(get_string('quickgradingchangessaved', 'assign'), $result);
2536 $grade = $assign->get_user_grade($this->students[0]->id, false);
2537 $this->assertEquals('30.0', $grade->grade);
2538
2539 // Now update using 'old' data. Should fail.
2540 $result = $assign->testable_process_save_quick_grades($pastdata);
2541 $this->assertContains(get_string('errorrecordmodified', 'assign'), $result);
2542 $grade = $assign->get_user_grade($this->students[0]->id, false);
2543 $this->assertEquals('30.0', $grade->grade);
2544 }
2545}