Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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 API.
21
 *
22
 * @package core_completion
23
 * @category test
24
 * @copyright 2017 Mark Nelson <markn@moodle.com>
25
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
class api_test extends \advanced_testcase {
28
 
29
    /**
30
     * Test setup.
31
     */
32
    public function setUp(): void {
33
        $this->resetAfterTest();
34
    }
35
 
11 efrain 36
    public function test_update_completion_date_event(): void {
1 efrain 37
        global $CFG, $DB;
38
 
39
        $this->setAdminUser();
40
 
41
        // Create a course.
42
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
43
 
44
        // Create an assign activity.
45
        $time = time();
46
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
47
 
48
        // Create the completion event.
49
        $CFG->enablecompletion = true;
50
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
51
 
52
        // Check that there is now an event in the database.
53
        $events = $DB->get_records('event');
54
        $this->assertCount(1, $events);
55
 
56
        // Get the event.
57
        $event = reset($events);
58
 
59
        // Confirm the event is correct.
60
        $this->assertEquals('assign', $event->modulename);
61
        $this->assertEquals($assign->id, $event->instance);
62
        $this->assertEquals(CALENDAR_EVENT_TYPE_ACTION, $event->type);
63
        $this->assertEquals(\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED, $event->eventtype);
64
        $this->assertEquals($time, $event->timestart);
65
        $this->assertEquals($time, $event->timesort);
66
 
67
        require_once($CFG->dirroot . '/course/lib.php');
68
        // Delete the module.
69
        course_delete_module($assign->cmid);
70
 
71
        // Check we don't get a failure when called on a deleted module.
72
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', null, $time);
73
    }
74
 
11 efrain 75
    public function test_update_completion_date_event_update(): void {
1 efrain 76
        global $CFG, $DB;
77
 
78
        $this->setAdminUser();
79
 
80
        // Create a course.
81
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
82
 
83
        // Create an assign activity.
84
        $time = time();
85
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
86
 
87
        // Create the event.
88
        $CFG->enablecompletion = true;
89
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
90
 
91
        // Call it again, but this time with a different time.
92
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time + DAYSECS);
93
 
94
        // Check that there is still only one event in the database.
95
        $events = $DB->get_records('event');
96
        $this->assertCount(1, $events);
97
 
98
        // Get the event.
99
        $event = reset($events);
100
 
101
        // Confirm that the event has been updated.
102
        $this->assertEquals('assign', $event->modulename);
103
        $this->assertEquals($assign->id, $event->instance);
104
        $this->assertEquals(CALENDAR_EVENT_TYPE_ACTION, $event->type);
105
        $this->assertEquals(\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED, $event->eventtype);
106
        $this->assertEquals($time + DAYSECS, $event->timestart);
107
        $this->assertEquals($time + DAYSECS, $event->timesort);
108
    }
109
 
11 efrain 110
    public function test_update_completion_date_event_delete(): void {
1 efrain 111
        global $CFG, $DB;
112
 
113
        $this->setAdminUser();
114
 
115
        // Create a course.
116
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
117
 
118
        // Create an assign activity.
119
        $time = time();
120
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
121
 
122
        // Create the event.
123
        $CFG->enablecompletion = true;
124
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
125
 
126
        // Call it again, but the time specified as null.
127
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, null);
128
 
129
        // Check that there is no event in the database.
130
        $this->assertEquals(0, $DB->count_records('event'));
131
    }
132
 
11 efrain 133
    public function test_update_completion_date_event_completion_disabled(): void {
1 efrain 134
        global $CFG, $DB;
135
 
136
        $this->setAdminUser();
137
 
138
        // Create a course.
139
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
140
 
141
        // Create an assign activity.
142
        $time = time();
143
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
144
 
145
        // Try and create the completion event with completion disabled.
146
        $CFG->enablecompletion = false;
147
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
148
 
149
        // Check that there is no event in the database.
150
        $this->assertEquals(0, $DB->count_records('event'));
151
    }
152
 
11 efrain 153
    public function test_update_completion_date_event_update_completion_disabled(): void {
1 efrain 154
        global $CFG, $DB;
155
 
156
        $this->setAdminUser();
157
 
158
        // Create a course.
159
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
160
 
161
        // Create an assign activity.
162
        $time = time();
163
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
164
 
165
        // Create the completion event.
166
        $CFG->enablecompletion = true;
167
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
168
 
169
        // Disable completion.
170
        $CFG->enablecompletion = false;
171
 
172
        // Try and update the completion date.
173
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time + DAYSECS);
174
 
175
        // Check that there is an event in the database.
176
        $events = $DB->get_records('event');
177
        $this->assertCount(1, $events);
178
 
179
        // Get the event.
180
        $event = reset($events);
181
 
182
        // Confirm the event has not changed.
183
        $this->assertEquals('assign', $event->modulename);
184
        $this->assertEquals($assign->id, $event->instance);
185
        $this->assertEquals(CALENDAR_EVENT_TYPE_ACTION, $event->type);
186
        $this->assertEquals(\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED, $event->eventtype);
187
        $this->assertEquals($time, $event->timestart);
188
        $this->assertEquals($time, $event->timesort);
189
    }
190
 
11 efrain 191
    public function test_update_completion_date_event_delete_completion_disabled(): void {
1 efrain 192
        global $CFG, $DB;
193
 
194
        $this->setAdminUser();
195
 
196
        // Create a course.
197
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
198
 
199
        // Create an assign activity.
200
        $time = time();
201
        $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
202
 
203
        // Create the completion event.
204
        $CFG->enablecompletion = true;
205
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, $time);
206
 
207
        // Disable completion.
208
        $CFG->enablecompletion = false;
209
 
210
        // Should still be able to delete completion events even when completion is disabled.
211
        \core_completion\api::update_completion_date_event($assign->cmid, 'assign', $assign, null);
212
 
213
        // Check that there is now no event in the database.
214
        $this->assertEquals(0, $DB->count_records('event'));
215
    }
216
 
217
    /**
218
     * Test for mark_course_completions_activity_criteria().
219
     */
11 efrain 220
    public function test_mark_course_completions_activity_criteria(): void {
1 efrain 221
        global $DB, $CFG;
222
        require_once($CFG->dirroot.'/completion/criteria/completion_criteria_activity.php');
223
        $this->resetAfterTest(true);
224
 
225
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
226
        $student1 = $this->getDataGenerator()->create_user();
227
        $student2 = $this->getDataGenerator()->create_user();
228
 
229
        $teacher = $this->getDataGenerator()->create_user();
230
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
231
        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
232
 
233
        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
234
        $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
235
        $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
236
 
237
        $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id),
238
            array('completion' => 1));
239
        $cmdata = get_coursemodule_from_id('data', $data->cmid);
240
        $cm = get_coursemodule_from_instance('data', $data->id);
241
        $c = new \completion_info($course);
242
 
243
        // Add activity completion criteria.
244
        $criteriadata = new \stdClass();
245
        $criteriadata->id = $course->id;
246
        $criteriadata->criteria_activity = array();
247
        // Some activities.
248
        $criteriadata->criteria_activity[$cmdata->id] = 1;
249
        $criterion = new \completion_criteria_activity();
250
        $criterion->update_config($criteriadata);
251
 
252
        $this->setUser($teacher);
253
 
254
        // Mark activity complete for both users.
255
        $completion = new \stdClass();
256
        $completion->coursemoduleid = $cm->id;
257
        $completion->completionstate = COMPLETION_COMPLETE;
258
        $completion->timemodified = time();
259
        $completion->viewed = COMPLETION_NOT_VIEWED;
260
        $completion->overrideby = null;
261
 
262
        $completion->id = 0;
263
        $completion->userid = $student1->id;
264
        $c->internal_set_data($cm, $completion, true);
265
 
266
        $completion->id = 0;
267
        $completion->userid = $student2->id;
268
        $c->internal_set_data($cm, $completion, true);
269
 
270
        // Run instant course completions for student1. Only student1 will be marked as completed a course.
271
        $userdata = ['userid' => $student1->id, 'courseid' => $course->id];
272
        $actual = $DB->get_records('course_completions');
273
        $this->assertEmpty($actual);
274
 
275
        $coursecompletionid = \core_completion\api::mark_course_completions_activity_criteria($userdata);
276
 
277
        $actual = $DB->get_records('course_completions');
278
        $this->assertEquals(reset($actual)->id, $coursecompletionid);
279
        $this->assertEquals(1, count($actual));
280
        $this->assertEquals($student1->id, reset($actual)->userid);
281
 
282
        // Run course completions cron. Both students will be marked as completed a course.
283
        $coursecompletionid = \core_completion\api::mark_course_completions_activity_criteria();
284
        $this->assertEquals(0, $coursecompletionid);
285
        $actual = $DB->get_records('course_completions');
286
        $students = [$student1->id, $student2->id];
287
        $this->assertEquals(2, count($actual));
288
        $this->assertContains(reset($actual)->userid, $students);
289
        $this->assertContains(end($actual)->userid, $students);
290
    }
291
 
292
    /**
293
     * Test for mark_course_completions_activity_criteria() with different completionpassgrade settings.
294
     * @covers ::mark_course_completions_activity_criteria
295
     */
11 efrain 296
    public function test_mark_course_completions_activity_criteria_completion_states(): void {
1 efrain 297
        global $DB, $CFG;
298
        require_once($CFG->dirroot . '/completion/criteria/completion_criteria_activity.php');
299
        $this->resetAfterTest(true);
300
 
301
        $courses[] = $this->getDataGenerator()->create_course(['shortname' => 'completionpassgradenotset',
302
            'enablecompletion' => 1]);
303
        $courses[] = $this->getDataGenerator()->create_course(['shortname' => 'completionpassgradeset',
304
            'enablecompletion' => 1]);
305
 
306
        $student1 = $this->getDataGenerator()->create_user();
307
        $student2 = $this->getDataGenerator()->create_user();
308
 
309
        $teacher = $this->getDataGenerator()->create_user();
310
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
311
        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
312
 
313
        foreach ($courses as $course) {
314
            $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
315
            $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
316
            $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
317
 
318
            $completioncriteria = [
319
                'completionusegrade' => 1,
320
                'gradepass' => 50
321
            ];
322
 
323
            if ($course->shortname == 'completionpassgradeset') {
324
                $completioncriteria['completionpassgrade'] = 1;
325
            }
326
 
327
            /** @var \mod_assign_generator $assigngenerator */
328
            $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
329
            $assign = $assigngenerator->create_instance([
330
                    'course' => $course->id,
331
                    'completion' => COMPLETION_ENABLED,
332
                ] + $completioncriteria);
333
 
334
            $cmassing = get_coursemodule_from_id('assign', $assign->cmid);
335
            $cm = get_coursemodule_from_instance('assign', $assign->id);
336
            $c = new \completion_info($course);
337
 
338
            // Add activity completion criteria.
339
            $criteriadata = new \stdClass();
340
            $criteriadata->id = $course->id;
341
            $criteriadata->criteria_activity = array();
342
            // Some activities.
343
            $criteriadata->criteria_activity[$cmassing->id] = 1;
344
            $criterion = new \completion_criteria_activity();
345
            $criterion->update_config($criteriadata);
346
 
347
            $this->setUser($teacher);
348
 
349
            // Mark user completions.
350
            $completion = new \stdClass();
351
            $completion->coursemoduleid = $cm->id;
352
            $completion->timemodified = time();
353
            $completion->viewed = COMPLETION_NOT_VIEWED;
354
            $completion->overrideby = null;
355
 
356
            // Student1 achieved passgrade.
357
            $completion->id = 0;
358
            $completion->completionstate = COMPLETION_COMPLETE_PASS;
359
            $completion->userid = $student1->id;
360
            $c->internal_set_data($cm, $completion, true);
361
 
362
            // Student2 has not achieved passgrade.
363
            $completion->id = 0;
364
            $completion->completionstate = COMPLETION_COMPLETE_FAIL;
365
            $completion->userid = $student2->id;
366
            $c->internal_set_data($cm, $completion, true);
367
 
368
            $actual = $DB->get_records('course_completions', ['course' => $course->id]);
369
            $this->assertEmpty($actual);
370
 
371
            // Run course completions cron.
372
            $coursecompletionid = \core_completion\api::mark_course_completions_activity_criteria();
373
            $this->assertEquals(0, $coursecompletionid);
374
            $actual = $DB->get_records('course_completions', ['course' => $course->id]);
375
 
376
            if ($course->shortname == 'completionpassgradeset') {
377
                // Only student1 has completed a course.
378
                $this->assertEquals(1, count($actual));
379
                $this->assertEquals($student1->id, reset($actual)->userid);
380
            } else {
381
                // Both students completed a course.
382
                $students = [$student1->id, $student2->id];
383
                $this->assertEquals(2, count($actual));
384
                $this->assertContains(reset($actual)->userid, $students);
385
                $this->assertContains(end($actual)->userid, $students);
386
            }
387
        }
388
    }
389
}