MDL-53966 lesson: Allow maximum number of attempts to be unlimited
[moodle.git] / mod / lesson / tests / locallib_test.php
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/>.
17 /**
18  * locallib tests.
19  *
20  * @package    mod_lesson
21  * @category   test
22  * @copyright  2016 Adrian Greeve <adrian@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot.'/mod/lesson/locallib.php');
32 /**
33  * locallib testcase.
34  *
35  * @package    mod_lesson
36  * @category   test
37  * @copyright  2016 Adrian Greeve <adrian@moodle.com>
38  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class mod_lesson_locallib_testcase extends advanced_testcase {
42     /**
43      * Test duplicating a lesson page element.
44      */
45     public function test_duplicate_page() {
46         global $DB;
48         $this->resetAfterTest();
49         $this->setAdminUser();
50         $course = $this->getDataGenerator()->create_course();
51         $lessonmodule = $this->getDataGenerator()->create_module('lesson', array('course' => $course->id));
52         // Convert to a lesson object.
53         $lesson = new lesson($lessonmodule);
55         // Set up a generator to create content.
56         $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
57         $tfrecord = $generator->create_question_truefalse($lesson);
58         $lesson->duplicate_page($tfrecord->id);
60         // Lesson pages.
61         $records = $DB->get_records('lesson_pages', array('qtype' => 2));
62         $sameelements = array('lessonid', 'qtype', 'qoption', 'layout', 'display', 'title', 'contents', 'contentsformat');
63         $baserecord = array_shift($records);
64         $secondrecord = array_shift($records);
65         foreach ($sameelements as $element) {
66             $this->assertEquals($baserecord->$element, $secondrecord->$element);
67         }
68         // Need lesson answers as well.
69         $baserecordanswers = array_values($DB->get_records('lesson_answers', array('pageid' => $baserecord->id)));
70         $secondrecordanswers = array_values($DB->get_records('lesson_answers', array('pageid' => $secondrecord->id)));
71         $sameanswerelements = array('lessonid', 'jumpto', 'grade', 'score', 'flags', 'answer', 'answerformat', 'response',
72                 'responseformat');
73         foreach ($baserecordanswers as $key => $baseanswer) {
74             foreach ($sameanswerelements as $element) {
75                 $this->assertEquals($baseanswer->$element, $secondrecordanswers[$key]->$element);
76             }
77         }
78     }
80     /**
81      * Test test_lesson_get_user_deadline().
82      */
83     public function test_lesson_get_user_deadline() {
84         global $DB;
86         $this->resetAfterTest();
87         $this->setAdminUser();
89         $basetimestamp = time(); // The timestamp we will base the enddates on.
91         // Create generator, course and lessons.
92         $student1 = $this->getDataGenerator()->create_user();
93         $student2 = $this->getDataGenerator()->create_user();
94         $student3 = $this->getDataGenerator()->create_user();
95         $teacher = $this->getDataGenerator()->create_user();
96         $course = $this->getDataGenerator()->create_course();
97         $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
99         // Both lessons close in two hours.
100         $lesson1 = $lessongenerator->create_instance(array('course' => $course->id, 'deadline' => $basetimestamp + 7200));
101         $lesson2 = $lessongenerator->create_instance(array('course' => $course->id, 'deadline' => $basetimestamp + 7200));
102         $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
103         $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
105         $student1id = $student1->id;
106         $student2id = $student2->id;
107         $student3id = $student3->id;
108         $teacherid = $teacher->id;
110         // Users enrolments.
111         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
112         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
113         $this->getDataGenerator()->enrol_user($student1id, $course->id, $studentrole->id, 'manual');
114         $this->getDataGenerator()->enrol_user($student2id, $course->id, $studentrole->id, 'manual');
115         $this->getDataGenerator()->enrol_user($student3id, $course->id, $studentrole->id, 'manual');
116         $this->getDataGenerator()->enrol_user($teacherid, $course->id, $teacherrole->id, 'manual');
118         // Create groups.
119         $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
120         $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
121         $group1id = $group1->id;
122         $group2id = $group2->id;
123         $this->getDataGenerator()->create_group_member(array('userid' => $student1id, 'groupid' => $group1id));
124         $this->getDataGenerator()->create_group_member(array('userid' => $student2id, 'groupid' => $group2id));
126         // Group 1 gets an group override for lesson 1 to close in three hours.
127         $record1 = (object) [
128             'lessonid' => $lesson1->id,
129             'groupid' => $group1id,
130             'deadline' => $basetimestamp + 10800 // In three hours.
131         ];
132         $DB->insert_record('lesson_overrides', $record1);
134         // Let's test lesson 1 closes in three hours for user student 1 since member of group 1.
135         // lesson 2 closes in two hours.
136         $this->setUser($student1id);
137         $params = new stdClass();
139         $comparearray = array();
140         $object = new stdClass();
141         $object->id = $lesson1->id;
142         $object->userdeadline = $basetimestamp + 10800; // The overriden deadline for lesson 1.
144         $comparearray[$lesson1->id] = $object;
146         $object = new stdClass();
147         $object->id = $lesson2->id;
148         $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
150         $comparearray[$lesson2->id] = $object;
152         $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
154         // Let's test lesson 1 closes in two hours (the original value) for user student 3 since member of no group.
155         $this->setUser($student3id);
156         $params = new stdClass();
158         $comparearray = array();
159         $object = new stdClass();
160         $object->id = $lesson1->id;
161         $object->userdeadline = $basetimestamp + 7200; // The original deadline for lesson 1.
163         $comparearray[$lesson1->id] = $object;
165         $object = new stdClass();
166         $object->id = $lesson2->id;
167         $object->userdeadline = $basetimestamp + 7200; // The original deadline for lesson 2.
169         $comparearray[$lesson2->id] = $object;
171         $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
173         // User 2 gets an user override for lesson 1 to close in four hours.
174         $record2 = (object) [
175             'lessonid' => $lesson1->id,
176             'userid' => $student2id,
177             'deadline' => $basetimestamp + 14400 // In four hours.
178         ];
179         $DB->insert_record('lesson_overrides', $record2);
181         // Let's test lesson 1 closes in four hours for user student 2 since personally overriden.
182         // lesson 2 closes in two hours.
183         $this->setUser($student2id);
185         $comparearray = array();
186         $object = new stdClass();
187         $object->id = $lesson1->id;
188         $object->userdeadline = $basetimestamp + 14400; // The overriden deadline for lesson 1.
190         $comparearray[$lesson1->id] = $object;
192         $object = new stdClass();
193         $object->id = $lesson2->id;
194         $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
196         $comparearray[$lesson2->id] = $object;
198         $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
200         // Let's test a teacher sees the original times.
201         // lesson 1 and lesson 2 close in two hours.
202         $this->setUser($teacherid);
204         $comparearray = array();
205         $object = new stdClass();
206         $object->id = $lesson1->id;
207         $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 1.
209         $comparearray[$lesson1->id] = $object;
211         $object = new stdClass();
212         $object->id = $lesson2->id;
213         $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
215         $comparearray[$lesson2->id] = $object;
217         $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
218     }
220     public function test_is_participant() {
221         global $USER, $DB;
222         $this->resetAfterTest();
223         $this->setAdminUser();
224         $course = $this->getDataGenerator()->create_course();
225         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
226         $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student', [], 'manual', 0, 0, ENROL_USER_SUSPENDED);
227         $lessonmodule = $this->getDataGenerator()->create_module('lesson', array('course' => $course->id));
229         // Login as student.
230         $this->setUser($student);
231         // Convert to a lesson object.
232         $lesson = new lesson($lessonmodule);
233         $this->assertEquals(true, $lesson->is_participant($student->id),
234             'Student is enrolled, active and can participate');
236         // Login as student2.
237         $this->setUser($student2);
238         $this->assertEquals(false, $lesson->is_participant($student2->id),
239             'Student is enrolled, suspended and can NOT participate');
241         // Login as an admin.
242         $this->setAdminUser();
243         $this->assertEquals(false, $lesson->is_participant($USER->id),
244             'Admin is not enrolled and can NOT participate');
246         $this->getDataGenerator()->enrol_user(2, $course->id);
247         $this->assertEquals(true, $lesson->is_participant($USER->id),
248             'Admin is enrolled and can participate');
250         $this->getDataGenerator()->enrol_user(2, $course->id, [], 'manual', 0, 0, ENROL_USER_SUSPENDED);
251         $this->assertEquals(true, $lesson->is_participant($USER->id),
252             'Admin is enrolled, suspended and can participate');
253     }
255     /**
256      * Data provider for test_get_last_attempt.
257      *
258      * @return array
259      */
260     public function test_get_last_attempt_dataprovider() {
261         return [
262             [0, [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]], (object)['id' => 3]],
263             [1, [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]], (object)['id' => 1]],
264             [2, [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]], (object)['id' => 2]],
265             [3, [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]], (object)['id' => 3]],
266             [4, [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]], (object)['id' => 3]],
267         ];
268     }
270     /**
271      * Test the get_last_attempt() method.
272      *
273      * @dataProvider test_get_last_attempt_dataprovider
274      * @param int $maxattempts Lesson setting.
275      * @param array $attempts The list of student attempts.
276      * @param object $expected Expected result.
277      */
278     public function test_get_last_attempt($maxattempts, $attempts, $expected) {
279         $this->resetAfterTest();
280         $this->setAdminUser();
281         $course = $this->getDataGenerator()->create_course();
282         $lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course, 'maxattempts' => $maxattempts]);
283         $lesson = new lesson($lesson);
284         $this->assertEquals($expected, $lesson->get_last_attempt($attempts));
285     }