MDL-29478 unittest - fix rating tests so they can be executed with accesslib caches...
[moodle.git] / rating / simpletest / testrating.php
CommitLineData
d8c71388
EL
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 rating/lib.php
19 *
20 * @package moodlecore
21 * @subpackage rating
22 * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28// Include all the needed stuff
29require_once($CFG->dirroot . '/rating/lib.php');
30
31/**
32 * Unit test case for all the rating/lib.php requiring DB mockup & manipulation
33 */
34class rating_db_test extends UnitTestCaseUsingDatabase {
35
36 public static $includecoverage = array(
37 'rating/lib.php'
38 );
39
40 protected $testtables = array(
41 'lib' => array(
e437d9f1
EL
42 'rating', 'scale', 'context', 'capabilities', 'role_assignments', 'role_capabilities', 'course'));
43
44 protected $syscontext;
45 protected $neededcaps = array('view', 'viewall', 'viewany', 'rate');
46 protected $originaldefaultfrontpageroleid;
d8c71388
EL
47
48 public function setUp() {
e437d9f1 49 global $CFG;
d8c71388
EL
50 parent::setUp();
51
e437d9f1
EL
52 // Make sure accesslib has cached a sensible system context object
53 // before we switch to the test DB.
54 $this->syscontext = get_context_instance(CONTEXT_SYSTEM);
d8c71388
EL
55
56 foreach ($this->testtables as $dir => $tables) {
57 $this->create_test_tables($tables, $dir); // Create tables
58 }
e437d9f1
EL
59
60 $this->switch_to_test_db(); // Switch to test DB for all the execution
61
62 $this->fill_records();
63
64 // Ignore any frontpageroleid, that would require to crete more contexts
65 $this->originaldefaultfrontpageroleid = $CFG->defaultfrontpageroleid;
66 $CFG->defaultfrontpageroleid = null;
67 }
68
69 public function tearDown() {
70 global $CFG;
71 // Recover original frontpageroleid
72 $CFG->defaultfrontpageroleid = $this->originaldefaultfrontpageroleid;
73 parent::tearDown();
74 }
75
76 private function fill_records() {
77 global $DB;
78
79 // Set up systcontext in the test database.
80 $this->syscontext->id = $this->testdb->insert_record('context', $this->syscontext);
81
82 // Add the capabilities used by ratings
83 foreach ($this->neededcaps as $neededcap) {
84 $this->testdb->insert_record('capabilities', (object)array('name' => 'moodle/rating:' . $neededcap,
85 'contextlevel' => CONTEXT_COURSE));
86 }
d8c71388
EL
87 }
88
89 /**
90 * Test the current get_ratings method main sql
91 */
92 function test_get_ratings_sql() {
93
a924c53e 94 // We load 3 items. Each is rated twice. For simplicity itemid == user id of the item owner
e437d9f1 95 $ctxid = $this->syscontext->id;
d8c71388
EL
96 $this->load_test_data('rating',
97 array('contextid', 'component', 'ratingarea', 'itemid', 'scaleid', 'rating', 'userid', 'timecreated', 'timemodified'), array(
a924c53e
AD
98
99 //user 1's items. Average == 2
d8c71388 100 array( $ctxid , 'mod_forum', 'post', 1 , 10 , 1 , 2 , 1 , 1),
d8c71388 101 array( $ctxid , 'mod_forum', 'post', 1 , 10 , 3 , 3 , 1 , 1),
d8c71388 102
a924c53e
AD
103 //user 2's items. Average == 3
104 array( $ctxid , 'mod_forum', 'post', 2 , 10 , 1 , 1 , 1 , 1),
105 array( $ctxid , 'mod_forum', 'post', 2 , 10 , 5 , 3 , 1 , 1),
106
107 //user 3's items. Average == 4
108 array( $ctxid , 'mod_forum', 'post', 3 , 10 , 3 , 1 , 1 , 1),
109 array( $ctxid , 'mod_forum', 'post', 3 , 10 , 5 , 2 , 1 , 1)
110 ));
111
112 // a post (item) by user 1 (rated above by user 2 and 3 with average = 2)
d8c71388
EL
113 $user1posts = array(
114 (object)array('id' => 1, 'userid' => 1, 'message' => 'hello'));
a924c53e 115 // a post (item) by user 2 (rated above by user 1 and 3 with average = 3)
d8c71388
EL
116 $user2posts = array(
117 (object)array('id' => 2, 'userid' => 2, 'message' => 'world'));
a924c53e 118 // a post (item) by user 3 (rated above by user 1 and 2 with average = 4)
d8c71388
EL
119 $user3posts = array(
120 (object)array('id' => 3, 'userid' => 3, 'message' => 'moodle'));
121
122 // Prepare the default options
123 $defaultoptions = array (
e437d9f1 124 'context' => $this->syscontext,
d8c71388
EL
125 'component' => 'mod_forum',
126 'ratingarea' => 'post',
127 'scaleid' => 10,
128 'aggregate' => RATING_AGGREGATE_AVERAGE);
129
e437d9f1 130 $rm = new mockup_rating_manager();
d8c71388 131
a924c53e 132 // STEP 1: Retreive ratings using the current user
d8c71388 133
a924c53e 134 // Get results for user 1's item (expected average 1 + 3 / 2 = 2)
d8c71388
EL
135 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts));
136 $result = $rm->get_ratings($toptions);
137 $this->assertEqual(count($result), count($user1posts));
138 $this->assertEqual($result[0]->id, $user1posts[0]->id);
139 $this->assertEqual($result[0]->userid, $user1posts[0]->userid);
140 $this->assertEqual($result[0]->message, $user1posts[0]->message);
141 $this->assertEqual($result[0]->rating->count, 2);
142 $this->assertEqual($result[0]->rating->aggregate, 2);
a924c53e
AD
143 // Note that $result[0]->rating->rating is somewhat random
144 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests
d8c71388
EL
145
146 // Get results for items of user 2 (expected average 1 + 5 / 2 = 3)
147 $toptions = (object)array_merge($defaultoptions, array('items' => $user2posts));
148 $result = $rm->get_ratings($toptions);
149 $this->assertEqual(count($result), count($user2posts));
150 $this->assertEqual($result[0]->id, $user2posts[0]->id);
151 $this->assertEqual($result[0]->userid, $user2posts[0]->userid);
152 $this->assertEqual($result[0]->message, $user2posts[0]->message);
153 $this->assertEqual($result[0]->rating->count, 2);
154 $this->assertEqual($result[0]->rating->aggregate, 3);
a924c53e
AD
155 // Note that $result[0]->rating->rating is somewhat random
156 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests
d8c71388
EL
157
158 // Get results for items of user 3 (expected average 3 + 5 / 2 = 4)
159 $toptions = (object)array_merge($defaultoptions, array('items' => $user3posts));
160 $result = $rm->get_ratings($toptions);
161 $this->assertEqual(count($result), count($user3posts));
162 $this->assertEqual($result[0]->id, $user3posts[0]->id);
163 $this->assertEqual($result[0]->userid, $user3posts[0]->userid);
164 $this->assertEqual($result[0]->message, $user3posts[0]->message);
165 $this->assertEqual($result[0]->rating->count, 2);
166 $this->assertEqual($result[0]->rating->aggregate, 4);
a924c53e
AD
167 // Note that $result[0]->rating->rating is somewhat random
168 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests
d8c71388
EL
169
170 // Get results for items of user 1 & 2 together (expected averages are 2 and 3, as tested above)
171 $posts = array_merge($user1posts, $user2posts);
172 $toptions = (object)array_merge($defaultoptions, array('items' => $posts));
173 $result = $rm->get_ratings($toptions);
174 $this->assertEqual(count($result), count($posts));
175 $this->assertEqual($result[0]->id, $posts[0]->id);
176 $this->assertEqual($result[0]->userid, $posts[0]->userid);
177 $this->assertEqual($result[0]->message, $posts[0]->message);
178 $this->assertEqual($result[0]->rating->count, 2);
179 $this->assertEqual($result[0]->rating->aggregate, 2);
a924c53e
AD
180 // Note that $result[0]->rating->rating is somewhat random
181 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests
d8c71388
EL
182
183 $this->assertEqual($result[1]->id, $posts[1]->id);
184 $this->assertEqual($result[1]->userid, $posts[1]->userid);
185 $this->assertEqual($result[1]->message, $posts[1]->message);
186 $this->assertEqual($result[1]->rating->count, 2);
187 $this->assertEqual($result[1]->rating->aggregate, 3);
a924c53e
AD
188 // Note that $result[0]->rating->rating is somewhat random
189 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests
d8c71388 190
a924c53e
AD
191 // STEP 2: Retrieve ratings by a specified user
192 // We still expect complete aggregations and counts
d8c71388 193
a924c53e 194 // Get results for items of user 1 rated by user 2 (avg 2, rating 1)
d8c71388
EL
195 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts, 'userid' => 2));
196 $result = $rm->get_ratings($toptions);
197 $this->assertEqual(count($result), count($user1posts));
198 $this->assertEqual($result[0]->id, $user1posts[0]->id);
199 $this->assertEqual($result[0]->userid, $user1posts[0]->userid);
200 $this->assertEqual($result[0]->message, $user1posts[0]->message);
201 $this->assertEqual($result[0]->rating->count, 2);
202 $this->assertEqual($result[0]->rating->aggregate, 2);
a924c53e 203 $this->assertEqual($result[0]->rating->rating, 1); //user 2 rated user 1 "1"
d8c71388
EL
204 $this->assertEqual($result[0]->rating->userid, $toptions->userid); // Must be the passed userid
205
a924c53e 206 // Get results for items of user 1 rated by user 3
d8c71388
EL
207 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts, 'userid' => 3));
208 $result = $rm->get_ratings($toptions);
209 $this->assertEqual(count($result), count($user1posts));
210 $this->assertEqual($result[0]->id, $user1posts[0]->id);
211 $this->assertEqual($result[0]->userid, $user1posts[0]->userid);
212 $this->assertEqual($result[0]->message, $user1posts[0]->message);
213 $this->assertEqual($result[0]->rating->count, 2);
214 $this->assertEqual($result[0]->rating->aggregate, 2);
a924c53e 215 $this->assertEqual($result[0]->rating->rating, 3); //user 3 rated user 1 "3"
d8c71388
EL
216 $this->assertEqual($result[0]->rating->userid, $toptions->userid); // Must be the passed userid
217
a924c53e 218 // Get results for items of user 1 & 2 together rated by user 3
d8c71388
EL
219 $posts = array_merge($user1posts, $user2posts);
220 $toptions = (object)array_merge($defaultoptions, array('items' => $posts, 'userid' => 3));
221 $result = $rm->get_ratings($toptions);
222 $this->assertEqual(count($result), count($posts));
223 $this->assertEqual($result[0]->id, $posts[0]->id);
224 $this->assertEqual($result[0]->userid, $posts[0]->userid);
225 $this->assertEqual($result[0]->message, $posts[0]->message);
226 $this->assertEqual($result[0]->rating->count, 2);
227 $this->assertEqual($result[0]->rating->aggregate, 2);
a924c53e 228 $this->assertEqual($result[0]->rating->rating, 3); //user 3 rated user 1 "3"
d8c71388
EL
229 $this->assertEqual($result[0]->rating->userid, $toptions->userid); // Must be the passed userid
230
231 $this->assertEqual($result[1]->id, $posts[1]->id);
232 $this->assertEqual($result[1]->userid, $posts[1]->userid);
233 $this->assertEqual($result[1]->message, $posts[1]->message);
234 $this->assertEqual($result[1]->rating->count, 2);
235 $this->assertEqual($result[1]->rating->aggregate, 3);
a924c53e 236 $this->assertEqual($result[0]->rating->rating, 3); //user 3 rated user 2 "5"
d8c71388
EL
237 $this->assertEqual($result[1]->rating->userid, $toptions->userid); // Must be the passed userid
238
a924c53e 239 // STEP 3: Some special cases
d8c71388 240
a924c53e
AD
241 // Get results for user 1's items (expected average 1 + 3 / 2 = 2)
242 // supplying a non-existent user id so no rating from that user should be found
d8c71388 243 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts));
a924c53e 244 $toptions->userid = 123456; //non-existent user
d8c71388 245 $result = $rm->get_ratings($toptions);
a924c53e
AD
246 $this->assertNull($result[0]->rating->userid);
247 $this->assertNull($result[0]->rating->rating);
248 $this->assertEqual($result[0]->rating->aggregate, 2);//should still get the aggregate
d8c71388
EL
249
250 // Get results for items of user 2 (expected average 1 + 5 / 2 = 3)
a924c53e 251 // Supplying the user id of the user who owns the items so no rating should be found
d8c71388 252 $toptions = (object)array_merge($defaultoptions, array('items' => $user2posts));
a924c53e 253 $toptions->userid = 2; //user 2 viewing the ratings of their own item
d8c71388 254 $result = $rm->get_ratings($toptions);
a924c53e
AD
255 //these should be null as the user is viewing their own item and thus cannot rate
256 $this->assertNull($result[0]->rating->userid);
257 $this->assertNull($result[0]->rating->rating);
258 $this->assertEqual($result[0]->rating->aggregate, 3);//should still get the aggregate
d8c71388
EL
259 }
260}
e437d9f1
EL
261
262/**
263 * rating_manager subclass for unit testing without requiring capabilities to be loaded
264 */
265class mockup_rating_manager extends rating_manager {
266
267 /**
268 * Overwrite get_plugin_permissions_array() so it always return granted perms for unit testing
269 */
270 public function get_plugin_permissions_array($contextid, $component, $ratingarea) {
271 return array(
272 'rate' => true,
273 'view' => true,
274 'viewany' => true,
275 'viewall' => true);
276 }
277
278}