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 grade/report/user/lib.php.
19 *
20 * @package  core_grades
21 * @category phpunit
22 * @copyright 2012 Andrew Davis
23 * @license  http://www.gnu.org/copyleft/gpl.html GNU Public License
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->dirroot.'/grade/lib.php');
30require_once($CFG->dirroot.'/grade/report/user/lib.php');
31
32
33/**
34 * Tests grade_report_user (the gradebook's user report)
35 */
36class core_grade_reportuserlib_testcase extends advanced_testcase {
37
38    /**
39     * Tests grade_report_user::inject_rowspans()
40     *
41     * inject_rowspans() returns the count of the number of elements, sets maxdepth on the
42     *  report object and sets the rowspan property on any element that has children.
43     */
44    public function test_inject_rowspans() {
45        global $CFG, $USER, $DB;
46
47        parent::setUp();
48        $this->resetAfterTest(true);
49
50        $CFG->enableavailability = 1;
51        $CFG->enablecompletion = 1;
52
53        // Create a course.
54        $course = $this->getDataGenerator()->create_course();
55        $coursecategory = grade_category::fetch_course_category($course->id);
56        $coursecontext = context_course::instance($course->id);
57
58        // Create and enrol test users.
59        $student = $this->getDataGenerator()->create_user(array('username' => 'student_sam'));
60        $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
61        $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id);
62
63        $teacher = $this->getDataGenerator()->create_user(array('username' => 'teacher_t'));
64        $role = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
65        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $role->id);
66
67        // An array so we can test with both users in a loop.
68        $users = array($student, $teacher);
69
70        // Make the student the current user.
71        $this->setUser($student);
72
73        // Test an empty course.
74        $report = $this->create_report($course, $student, $coursecontext);
75        // a lead column that spans all children + course grade item = 2
76        $this->assertEquals(2, $report->inject_rowspans($report->gtree->top_element));
77        $this->assertEquals(2, $report->gtree->top_element['rowspan']);
78        $this->assertEquals(2, $report->maxdepth);
79
80        // Only elements with children should have rowspan set.
81        if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) {
82            $this->fail('Elements without children should not have rowspan set');
83        }
84
85        // Add 2 activities.
86        $data1 = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
87
88        $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
89        $forum1cm = get_coursemodule_from_id('forum', $forum1->cmid);
90        // Switch the stdClass instance for a grade item instance so grade_item::set_parent() is available.
91        $forum1 = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id));
92
93        $report = $this->create_report($course, $student, $coursecontext);
94        // Lead column + course + (2 x activity) = 4
95        $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element));
96        $this->assertEquals(4, $report->gtree->top_element['rowspan']);
97        // Lead column + 1 level (course + 2 activities) = 2
98        $this->assertEquals(2, $report->maxdepth);
99
100        // Only elements with children should have rowspan set.
101        if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) {
102            $this->fail('Elements without children should not have rowspan set');
103        }
104
105        // Hide the forum activity.
106        set_coursemodule_visible($forum1cm->id, 0);
107
108        foreach ($users as $user) {
109
110            $this->setUser($user);
111            $message = 'Testing with ' . $user->username;
112            accesslib_clear_all_caches_for_unit_testing();
113
114            $report = $this->create_report($course, $user, $coursecontext);
115            // Lead column + course + (2 x activity) = 4 (element count isn't affected by hiding)
116            $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element), $message);
117            $this->assertEquals(4, $report->gtree->top_element['rowspan'], $message);
118            // Lead column -> 1 level containing the course + 2 activities = 2
119            $this->assertEquals(2, $report->maxdepth, $message);
120        }
121
122        // Unhide the forum activity.
123        set_coursemodule_visible($forum1cm->id, 1);
124
125        // Create a category and put the forum in it.
126        $params = new stdClass();
127        $params->courseid = $course->id;
128        $params->fullname = 'unittestcategory';
129        $params->parent = $coursecategory->id;
130        $gradecategory = new grade_category($params, false);
131        $gradecategory->insert();
132
133        $forum1->set_parent($gradecategory->id);
134
135        $report = $this->create_report($course, $student, $coursecontext);
136        // Lead column + course + (category + category grade item) + (2 x activity) = 6
137        $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element));
138        $this->assertEquals(6, $report->gtree->top_element['rowspan']);
139        // Lead column -> the category -> the forum activity = 3
140        $this->assertEquals(3, $report->maxdepth);
141
142        // Check rowspan on the category. The category itself + category grade item + forum = 3
143        $this->assertEquals(3, $report->gtree->top_element['children'][4]['rowspan']);
144        // check the forum doesn't have rowspan set
145        if (array_key_exists('rowspan', $report->gtree->top_element['children'][4]['children'][3])) {
146            $this->fail('The forum has no children so should not have rowspan set');
147        }
148
149        // Conditional activity tests.
150        // Note: I have ported this test to the new conditional availability
151        // system, but it does not appear to actually test anything - in fact,
152        // if you remove the code that sets the condition, it still passes
153        // because it apparently is intended to have the same number of rows
154        // even when some are hidden. The  same is true of the
155        // set_coursemodule_visible test above. I don't feel this is a very
156        // good test; somebody with more knowledge of this report might want to
157        // fix it to check that the row actually is being hidden.
158        $DB->set_field('course_modules', 'availability', '{"op":"|","show":false,"c":[' .
159                '{"type":"grade","min":5.5,"id":37}]}', array('id' => $forum1cm->id));
160        get_fast_modinfo($course->id, 0, true);
161        foreach ($users as $user) {
162
163            $this->setUser($user);
164            $message = 'Testing with ' . $user->username;
165            accesslib_clear_all_caches_for_unit_testing();
166
167            $report = $this->create_report($course, $user, $coursecontext);
168            // Lead column + course + (category + category grade item) + (2 x activity) = 6
169            $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element), $message);
170            $this->assertEquals(6, $report->gtree->top_element['rowspan'], $message);
171            // Lead column -> the category -> the forum activity = 3
172            $this->assertEquals(3, $report->maxdepth, $message);
173        }
174    }
175
176    private function create_report($course, $user, $coursecontext) {
177
178        $gpr = new grade_plugin_return(array('type' => 'report', 'plugin'=>'user', 'courseid' => $course->id, 'userid' => $user->id));
179        $report = new grade_report_user($course->id, $gpr, $coursecontext, $user->id);
180
181        return $report;
182    }
183
184}
185
186