MDL-74602 mod_assign: disable activity header on embedded grader page
[moodle.git] / completion / tests / completion_criteria_test.php
blobd7ffaacef57b3446c211db76d33dcad61f929aef
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.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 namespace core_completion;
19 /**
20 * Test completion criteria.
22 * @package core_completion
23 * @category test
24 * @copyright 2021 Mikhail Golenkov <mikhailgolenkov@catalyst-au.net>
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 class completion_criteria_test extends \advanced_testcase {
29 /**
30 * Test setup.
32 public function setUp(): void {
33 global $CFG;
34 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_course.php');
35 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_activity.php');
36 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_duration.php');
37 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_grade.php');
38 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_date.php');
40 $this->setAdminUser();
41 $this->resetAfterTest();
44 /**
45 * Test that activity completion dates are used when activity criteria is marked as completed.
47 public function test_completion_criteria_activity(): void {
48 global $DB;
49 $timestarted = time();
51 // Create a course, an activity and enrol a user.
52 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
53 $assign = $this->getDataGenerator()->create_module('assign', ['course' => $course->id], ['completion' => 1]);
54 $user = $this->getDataGenerator()->create_user();
55 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
56 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
58 // Set completion criteria and mark the user to complete the criteria.
59 $criteriadata = (object) [
60 'id' => $course->id,
61 'criteria_activity' => [$assign->cmid => 1],
63 $criterion = new \completion_criteria_activity();
64 $criterion->update_config($criteriadata);
65 $cmassign = get_coursemodule_from_id('assign', $assign->cmid);
66 $completion = new \completion_info($course);
67 $completion->update_state($cmassign, COMPLETION_COMPLETE, $user->id);
69 // Completion criteria for the user is supposed to be marked as completed at now().
70 $result = \core_completion_external::get_activities_completion_status($course->id, $user->id);
71 $actual = reset($result['statuses']);
72 $this->assertEquals(1, $actual['state']);
73 $this->assertGreaterThanOrEqual($timestarted, $actual['timecompleted']);
75 // And the whole course is marked as completed at now().
76 $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
77 $this->assertGreaterThanOrEqual($timestarted, $ccompletion->timecompleted);
78 $this->assertTrue($ccompletion->is_complete());
81 /**
82 * Test that enrolment timestart/timecreated are used when duration criteria is marked as completed.
84 public function test_completion_criteria_duration(): void {
85 global $DB;
86 $timestarted = 1610000000;
87 $timecreated = 1620000000;
88 $durationperiod = DAYSECS;
90 // Create a course and users.
91 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
92 $user1 = $this->getDataGenerator()->create_user();
93 $user2 = $this->getDataGenerator()->create_user();
94 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
96 // Enrol User 1 with time start = $timestarted.
97 $this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id, 'manual', $timestarted);
99 // Enrol User 2 with an empty time start, but update the record like it was created at $timecreated.
100 $this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
101 $DB->set_field('user_enrolments', 'timecreated', $timecreated, ['userid' => $user2->id]);
103 // Set completion criteria.
104 $criteriadata = (object) [
105 'id' => $course->id,
106 'criteria_duration' => 1,
107 'criteria_duration_days' => $durationperiod,
109 $criterion = new \completion_criteria_duration();
110 $criterion->update_config($criteriadata);
112 // Run completion scheduled task.
113 $task = new \core\task\completion_regular_task();
114 $this->expectOutputRegex("/Marking complete/");
115 $task->execute();
116 // Hopefully, some day MDL-33320 will be fixed and all these sleeps
117 // and double cron calls in behat and unit tests will be removed.
118 sleep(1);
119 $task->execute();
121 // The course for User 1 is supposed to be marked as completed at $timestarted + $durationperiod.
122 $ccompletion = new \completion_completion(['userid' => $user1->id, 'course' => $course->id]);
123 $this->assertEquals($timestarted + $durationperiod, $ccompletion->timecompleted);
124 $this->assertTrue($ccompletion->is_complete());
126 // The course for User 2 is supposed to be marked as completed at $timecreated + $durationperiod.
127 $ccompletion = new \completion_completion(['userid' => $user2->id, 'course' => $course->id]);
128 $this->assertEquals($timecreated + $durationperiod, $ccompletion->timecompleted);
129 $this->assertTrue($ccompletion->is_complete());
133 * Test that criteria date is used as a course completion date.
135 public function test_completion_criteria_date(): void {
136 global $DB;
137 $timeend = 1610000000;
139 // Create a course and enrol a user.
140 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
141 $user = $this->getDataGenerator()->create_user();
142 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
143 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
145 // Set completion criteria.
146 $criteriadata = (object) [
147 'id' => $course->id,
148 'criteria_date' => 1,
149 'criteria_date_value' => $timeend,
151 $criterion = new \completion_criteria_date();
152 $criterion->update_config($criteriadata);
154 // Run completion scheduled task.
155 $task = new \core\task\completion_regular_task();
156 $this->expectOutputRegex("/Marking complete/");
157 $task->execute();
158 // Hopefully, some day MDL-33320 will be fixed and all these sleeps
159 // and double cron calls in behat and unit tests will be removed.
160 sleep(1);
161 $task->execute();
163 // The course is supposed to be marked as completed at $timeend.
164 $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
165 $this->assertEquals($timeend, $ccompletion->timecompleted);
166 $this->assertTrue($ccompletion->is_complete());
170 * Test that grade timemodified is used when grade criteria is marked as completed.
172 public function test_completion_criteria_grade(): void {
173 global $DB;
174 $timegraded = 1610000000;
176 // Create a course and enrol a couple of users.
177 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
178 $user1 = $this->getDataGenerator()->create_user();
179 $user2 = $this->getDataGenerator()->create_user();
180 $studentrole = $DB->get_record('role', ['shortname' => 'student']);
181 $this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id);
182 $this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
184 // Set completion criteria.
185 $criteriadata = (object) [
186 'id' => $course->id,
187 'criteria_grade' => 1,
188 'criteria_grade_value' => 66,
190 $criterion = new \completion_criteria_grade();
191 $criterion->update_config($criteriadata);
193 $coursegradeitem = \grade_item::fetch_course_item($course->id);
195 // Grade User 1 with a passing grade.
196 $grade1 = new \grade_grade();
197 $grade1->itemid = $coursegradeitem->id;
198 $grade1->timemodified = $timegraded;
199 $grade1->userid = $user1->id;
200 $grade1->finalgrade = 80;
201 $grade1->insert();
203 // Grade User 2 with a non-passing grade.
204 $grade2 = new \grade_grade();
205 $grade2->itemid = $coursegradeitem->id;
206 $grade2->timemodified = $timegraded;
207 $grade2->userid = $user2->id;
208 $grade2->finalgrade = 40;
209 $grade2->insert();
211 // Run completion scheduled task.
212 $task = new \core\task\completion_regular_task();
213 $this->expectOutputRegex("/Marking complete/");
214 $task->execute();
215 // Hopefully, some day MDL-33320 will be fixed and all these sleeps
216 // and double cron calls in behat and unit tests will be removed.
217 sleep(1);
218 $task->execute();
220 // The course for User 1 is supposed to be marked as completed when the user was graded.
221 $ccompletion = new \completion_completion(['userid' => $user1->id, 'course' => $course->id]);
222 $this->assertEquals($timegraded, $ccompletion->timecompleted);
223 $this->assertTrue($ccompletion->is_complete());
225 // The course for User 2 is supposed to be marked as not completed.
226 $ccompletion = new \completion_completion(['userid' => $user2->id, 'course' => $course->id]);
227 $this->assertFalse($ccompletion->is_complete());