Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace core_completion;
18
 
19
/**
20
 * Test completion criteria.
21
 *
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
26
 */
27
class completion_criteria_test extends \advanced_testcase {
28
 
29
    /**
30
     * Test setup.
31
     */
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');
39
 
40
        $this->setAdminUser();
41
        $this->resetAfterTest();
42
    }
43
 
44
    /**
45
     * Test that activity completion dates are used when activity criteria is marked as completed.
46
     */
47
    public function test_completion_criteria_activity(): void {
48
        global $DB;
49
        $timestarted = time();
50
 
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);
57
 
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],
62
        ];
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);
68
 
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']);
74
 
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());
79
    }
80
 
81
    /**
82
     * Test that enrolment timestart are used when duration criteria is marked as completed.
83
     */
84
    public function test_completion_criteria_duration_timestart(): void {
85
        global $DB;
86
        $timestarted = 1610000000;
87
        $durationperiod = DAYSECS;
88
 
89
        // Create a course and users.
90
        $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
91
        $user = $this->getDataGenerator()->create_and_enrol($course, 'student', null, 'manual', $timestarted);
92
 
93
        // Set completion criteria.
94
        $criteriadata = (object) [
95
            'id' => $course->id,
96
            'criteria_duration' => 1,
97
            'criteria_duration_days' => $durationperiod,
98
        ];
99
        $criterion = new \completion_criteria_duration();
100
        $criterion->update_config($criteriadata);
101
 
102
        // Run completion scheduled task.
103
        $task = new \core\task\completion_regular_task();
104
        $this->expectOutputRegex("/Marking complete/");
105
        $task->execute();
106
        // Hopefully, some day MDL-33320 will be fixed and all these sleeps
107
        // and double cron calls in behat and unit tests will be removed.
108
        sleep(1);
109
        $task->execute();
110
 
111
        // The course for User is supposed to be marked as completed at $timestarted + $durationperiod.
112
        $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
113
        $this->assertEquals($timestarted + $durationperiod, $ccompletion->timecompleted);
114
        $this->assertTrue($ccompletion->is_complete());
115
    }
116
 
117
    /**
118
     * Test that enrolment timecreated are used when duration criteria is marked as completed.
119
     */
120
    public function test_completion_criteria_duration_timecreated(): void {
121
        global $DB;
122
 
123
        $timecreated = 1620000000;
124
        $durationperiod = DAYSECS;
125
 
126
        // Create a course and users.
127
        $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
128
 
129
        // Create and enrol user with an empty time start, but update the record like it was created at $timecreated.
130
        $user = $this->getDataGenerator()->create_and_enrol($course);
131
        $DB->set_field('user_enrolments', 'timecreated', $timecreated, ['userid' => $user->id]);
132
 
133
        // Set completion criteria.
134
        $criteriadata = (object) [
135
            'id' => $course->id,
136
            'criteria_duration' => 1,
137
            'criteria_duration_days' => $durationperiod,
138
        ];
139
        $criterion = new \completion_criteria_duration();
140
        $criterion->update_config($criteriadata);
141
 
142
        // Run completion scheduled task.
143
        $task = new \core\task\completion_regular_task();
144
        $this->expectOutputRegex("/Marking complete/");
145
        $task->execute();
146
 
147
        // Hopefully, some day MDL-33320 will be fixed and all these sleeps
148
        // and double cron calls in behat and unit tests will be removed.
149
        sleep(1);
150
        $task->execute();
151
 
152
        // The course for user is supposed to be marked as completed at $timecreated + $durationperiod.
153
        $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
154
        $this->assertEquals($timecreated + $durationperiod, $ccompletion->timecompleted);
155
        $this->assertTrue($ccompletion->is_complete());
156
    }
157
 
158
    /**
159
     * Test that criteria date is used as a course completion date.
160
     */
161
    public function test_completion_criteria_date(): void {
162
        global $DB;
163
        $timeend = 1610000000;
164
 
165
        // Create a course and enrol a user.
166
        $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
167
        $user = $this->getDataGenerator()->create_user();
168
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
169
        $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
170
 
171
        // Set completion criteria.
172
        $criteriadata = (object) [
173
            'id' => $course->id,
174
            'criteria_date' => 1,
175
            'criteria_date_value' => $timeend,
176
        ];
177
        $criterion = new \completion_criteria_date();
178
        $criterion->update_config($criteriadata);
179
 
180
        // Run completion scheduled task.
181
        $task = new \core\task\completion_regular_task();
182
        $this->expectOutputRegex("/Marking complete/");
183
        $task->execute();
184
        // Hopefully, some day MDL-33320 will be fixed and all these sleeps
185
        // and double cron calls in behat and unit tests will be removed.
186
        sleep(1);
187
        $task->execute();
188
 
189
        // The course is supposed to be marked as completed at $timeend.
190
        $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]);
191
        $this->assertEquals($timeend, $ccompletion->timecompleted);
192
        $this->assertTrue($ccompletion->is_complete());
193
    }
194
 
195
    /**
196
     * Test that grade timemodified is used when grade criteria is marked as completed.
197
     */
198
    public function test_completion_criteria_grade(): void {
199
        global $DB;
200
        $timegraded = 1610000000;
201
 
202
        // Create a course and enrol a couple of users.
203
        $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
204
        $user1 = $this->getDataGenerator()->create_user();
205
        $user2 = $this->getDataGenerator()->create_user();
206
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
207
        $this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id);
208
        $this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id);
209
 
210
        // Set completion criteria.
211
        $criteriadata = (object) [
212
            'id' => $course->id,
213
            'criteria_grade' => 1,
214
            'criteria_grade_value' => 66,
215
        ];
216
        $criterion = new \completion_criteria_grade();
217
        $criterion->update_config($criteriadata);
218
 
219
        $coursegradeitem = \grade_item::fetch_course_item($course->id);
220
 
221
        // Grade User 1 with a passing grade.
222
        $grade1 = new \grade_grade();
223
        $grade1->itemid = $coursegradeitem->id;
224
        $grade1->timemodified = $timegraded;
225
        $grade1->userid = $user1->id;
226
        $grade1->finalgrade = 80;
227
        $grade1->insert();
228
 
229
        // Grade User 2 with a non-passing grade.
230
        $grade2 = new \grade_grade();
231
        $grade2->itemid = $coursegradeitem->id;
232
        $grade2->timemodified = $timegraded;
233
        $grade2->userid = $user2->id;
234
        $grade2->finalgrade = 40;
235
        $grade2->insert();
236
 
237
        // Run completion scheduled task.
238
        $task = new \core\task\completion_regular_task();
239
        $this->expectOutputRegex("/Marking complete/");
240
        $task->execute();
241
        // Hopefully, some day MDL-33320 will be fixed and all these sleeps
242
        // and double cron calls in behat and unit tests will be removed.
243
        sleep(1);
244
        $task->execute();
245
 
246
        // The course for User 1 is supposed to be marked as completed when the user was graded.
247
        $ccompletion = new \completion_completion(['userid' => $user1->id, 'course' => $course->id]);
248
        $this->assertEquals($timegraded, $ccompletion->timecompleted);
249
        $this->assertTrue($ccompletion->is_complete());
250
 
251
        // The course for User 2 is supposed to be marked as not completed.
252
        $ccompletion = new \completion_completion(['userid' => $user2->id, 'course' => $course->id]);
253
        $this->assertFalse($ccompletion->is_complete());
254
    }
255
}