MDL-75055 theme_boost: Darken close button colour in notification alerts
[moodle.git] / rating / tests / rating_test.php
blobf60107dc8657899689c77c8c693e933a84d115d3
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.
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 * Unit tests for rating/lib.php
20 * @package core_rating
21 * @category test
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
26 namespace core_rating;
28 use rating_manager;
30 defined('MOODLE_INTERNAL') || die();
32 // Include all the needed stuff.
33 global $CFG;
34 require_once($CFG->dirroot . '/rating/lib.php');
37 /**
38 * Unit test case for all the rating/lib.php requiring DB mockup & manipulation
40 * @package core_rating
41 * @category test
42 * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 class rating_test extends \advanced_testcase {
47 protected $syscontext;
48 protected $neededcaps = array('view', 'viewall', 'viewany', 'rate');
49 protected $originaldefaultfrontpageroleid;
51 public function setUp(): void {
52 global $CFG;
53 parent::setUp();
55 $this->resetAfterTest(true);
57 $CFG->defaultfrontpageroleid = null;
60 /**
61 * Test the current get_ratings method main sql
63 public function test_get_ratings_sql() {
64 global $DB;
66 // We load 3 items. Each is rated twice. For simplicity itemid == user id of the item owner.
67 $ctxid = \context_system::instance()->id;
68 $ratings = array(
69 // User 1's items. Average == 2.
70 array('contextid' => $ctxid,
71 'component' => 'mod_forum',
72 'ratingarea' => 'post',
73 'itemid' => 1,
74 'scaleid' => 10,
75 'rating' => 1,
76 'userid' => 2,
77 'timecreated' => 1,
78 'timemodified' => 1),
80 array('contextid' => $ctxid,
81 'component' => 'mod_forum',
82 'ratingarea' => 'post',
83 'itemid' => 1,
84 'scaleid' => 10,
85 'rating' => 3,
86 'userid' => 3,
87 'timecreated' => 1,
88 'timemodified' => 1),
90 // User 2's items. Average == 3.
91 array('contextid' => $ctxid,
92 'component' => 'mod_forum',
93 'ratingarea' => 'post',
94 'itemid' => 2,
95 'scaleid' => 10,
96 'rating' => 1,
97 'userid' => 1,
98 'timecreated' => 1,
99 'timemodified' => 1),
101 array('contextid' => $ctxid,
102 'component' => 'mod_forum',
103 'ratingarea' => 'post',
104 'itemid' => 2,
105 'scaleid' => 10,
106 'rating' => 5,
107 'userid' => 3,
108 'timecreated' => 1,
109 'timemodified' => 1),
111 // User 3's items. Average == 4.
112 array('contextid' => $ctxid,
113 'component' => 'mod_forum',
114 'ratingarea' => 'post',
115 'itemid' => 3,
116 'scaleid' => 10,
117 'rating' => 3,
118 'userid' => 1,
119 'timecreated' => 1,
120 'timemodified' => 1),
122 array('contextid' => $ctxid,
123 'component' => 'mod_forum',
124 'ratingarea' => 'post',
125 'itemid' => 3,
126 'scaleid' => 10,
127 'rating' => 5,
128 'userid' => 2,
129 'timecreated' => 1,
130 'timemodified' => 1)
132 foreach ($ratings as $rating) {
133 $DB->insert_record('rating', $rating);
136 // A post (item) by user 1 (rated above by user 2 and 3 with average = 2).
137 $user1posts = array(
138 (object)array('id' => 1, 'userid' => 1, 'message' => 'hello'));
139 // A post (item) by user 2 (rated above by user 1 and 3 with average = 3).
140 $user2posts = array(
141 (object)array('id' => 2, 'userid' => 2, 'message' => 'world'));
142 // A post (item) by user 3 (rated above by user 1 and 2 with average = 4).
143 $user3posts = array(
144 (object)array('id' => 3, 'userid' => 3, 'message' => 'moodle'));
146 // Prepare the default options.
147 $defaultoptions = array (
148 'context' => \context_system::instance(),
149 'component' => 'mod_forum',
150 'ratingarea' => 'post',
151 'scaleid' => 10,
152 'aggregate' => RATING_AGGREGATE_AVERAGE);
154 $rm = new mockup_rating_manager();
156 // STEP 1: Retreive ratings using the current user.
158 // Get results for user 1's item (expected average 1 + 3 / 2 = 2).
159 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts));
160 $result = $rm->get_ratings($toptions);
161 $this->assertEquals(count($result), count($user1posts));
162 $this->assertEquals($result[0]->id, $user1posts[0]->id);
163 $this->assertEquals($result[0]->userid, $user1posts[0]->userid);
164 $this->assertEquals($result[0]->message, $user1posts[0]->message);
165 $this->assertEquals($result[0]->rating->count, 2);
166 $this->assertEquals($result[0]->rating->aggregate, 2);
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.
170 // Get results for items of user 2 (expected average 1 + 5 / 2 = 3).
171 $toptions = (object)array_merge($defaultoptions, array('items' => $user2posts));
172 $result = $rm->get_ratings($toptions);
173 $this->assertEquals(count($result), count($user2posts));
174 $this->assertEquals($result[0]->id, $user2posts[0]->id);
175 $this->assertEquals($result[0]->userid, $user2posts[0]->userid);
176 $this->assertEquals($result[0]->message, $user2posts[0]->message);
177 $this->assertEquals($result[0]->rating->count, 2);
178 $this->assertEquals($result[0]->rating->aggregate, 3);
179 // Note that $result[0]->rating->rating is somewhat random.
180 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests.
182 // Get results for items of user 3 (expected average 3 + 5 / 2 = 4).
183 $toptions = (object)array_merge($defaultoptions, array('items' => $user3posts));
184 $result = $rm->get_ratings($toptions);
185 $this->assertEquals(count($result), count($user3posts));
186 $this->assertEquals($result[0]->id, $user3posts[0]->id);
187 $this->assertEquals($result[0]->userid, $user3posts[0]->userid);
188 $this->assertEquals($result[0]->message, $user3posts[0]->message);
189 $this->assertEquals($result[0]->rating->count, 2);
190 $this->assertEquals($result[0]->rating->aggregate, 4);
191 // Note that $result[0]->rating->rating is somewhat random.
192 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests.
194 // Get results for items of user 1 & 2 together (expected averages are 2 and 3, as tested above).
195 $posts = array_merge($user1posts, $user2posts);
196 $toptions = (object)array_merge($defaultoptions, array('items' => $posts));
197 $result = $rm->get_ratings($toptions);
198 $this->assertEquals(count($result), count($posts));
199 $this->assertEquals($result[0]->id, $posts[0]->id);
200 $this->assertEquals($result[0]->userid, $posts[0]->userid);
201 $this->assertEquals($result[0]->message, $posts[0]->message);
202 $this->assertEquals($result[0]->rating->count, 2);
203 $this->assertEquals($result[0]->rating->aggregate, 2);
204 // Note that $result[0]->rating->rating is somewhat random.
205 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests.
207 $this->assertEquals($result[1]->id, $posts[1]->id);
208 $this->assertEquals($result[1]->userid, $posts[1]->userid);
209 $this->assertEquals($result[1]->message, $posts[1]->message);
210 $this->assertEquals($result[1]->rating->count, 2);
211 $this->assertEquals($result[1]->rating->aggregate, 3);
212 // Note that $result[0]->rating->rating is somewhat random.
213 // We didn't supply a user ID so $USER was used which will vary depending on who runs the tests.
215 // STEP 2: Retrieve ratings by a specified user.
216 // We still expect complete aggregations and counts.
218 // Get results for items of user 1 rated by user 2 (avg 2, rating 1).
219 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts, 'userid' => 2));
220 $result = $rm->get_ratings($toptions);
221 $this->assertEquals(count($result), count($user1posts));
222 $this->assertEquals($result[0]->id, $user1posts[0]->id);
223 $this->assertEquals($result[0]->userid, $user1posts[0]->userid);
224 $this->assertEquals($result[0]->message, $user1posts[0]->message);
225 $this->assertEquals($result[0]->rating->count, 2);
226 $this->assertEquals($result[0]->rating->aggregate, 2);
227 $this->assertEquals($result[0]->rating->rating, 1); // User 2 rated user 1 "1".
228 $this->assertEquals($result[0]->rating->userid, $toptions->userid); // Must be the passed userid.
230 // Get results for items of user 1 rated by user 3.
231 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts, 'userid' => 3));
232 $result = $rm->get_ratings($toptions);
233 $this->assertEquals(count($result), count($user1posts));
234 $this->assertEquals($result[0]->id, $user1posts[0]->id);
235 $this->assertEquals($result[0]->userid, $user1posts[0]->userid);
236 $this->assertEquals($result[0]->message, $user1posts[0]->message);
237 $this->assertEquals($result[0]->rating->count, 2);
238 $this->assertEquals($result[0]->rating->aggregate, 2);
239 $this->assertEquals($result[0]->rating->rating, 3); // User 3 rated user 1 "3".
240 $this->assertEquals($result[0]->rating->userid, $toptions->userid); // Must be the passed userid.
242 // Get results for items of user 1 & 2 together rated by user 3.
243 $posts = array_merge($user1posts, $user2posts);
244 $toptions = (object)array_merge($defaultoptions, array('items' => $posts, 'userid' => 3));
245 $result = $rm->get_ratings($toptions);
246 $this->assertEquals(count($result), count($posts));
247 $this->assertEquals($result[0]->id, $posts[0]->id);
248 $this->assertEquals($result[0]->userid, $posts[0]->userid);
249 $this->assertEquals($result[0]->message, $posts[0]->message);
250 $this->assertEquals($result[0]->rating->count, 2);
251 $this->assertEquals($result[0]->rating->aggregate, 2);
252 $this->assertEquals($result[0]->rating->rating, 3); // User 3 rated user 1 "3".
253 $this->assertEquals($result[0]->rating->userid, $toptions->userid); // Must be the passed userid.
255 $this->assertEquals($result[1]->id, $posts[1]->id);
256 $this->assertEquals($result[1]->userid, $posts[1]->userid);
257 $this->assertEquals($result[1]->message, $posts[1]->message);
258 $this->assertEquals($result[1]->rating->count, 2);
259 $this->assertEquals($result[1]->rating->aggregate, 3);
260 $this->assertEquals($result[0]->rating->rating, 3); // User 3 rated user 2 "5".
261 $this->assertEquals($result[1]->rating->userid, $toptions->userid); // Must be the passed userid.
263 // STEP 3: Some special cases.
265 // Get results for user 1's items (expected average 1 + 3 / 2 = 2).
266 // Supplying a non-existent user id so no rating from that user should be found.
267 $toptions = (object)array_merge($defaultoptions, array('items' => $user1posts));
268 $toptions->userid = 123456; // Non-existent user.
269 $result = $rm->get_ratings($toptions);
270 $this->assertNull($result[0]->rating->userid);
271 $this->assertNull($result[0]->rating->rating);
272 $this->assertEquals($result[0]->rating->aggregate, 2); // Should still get the aggregate.
274 // Get results for items of user 2 (expected average 1 + 5 / 2 = 3).
275 // Supplying the user id of the user who owns the items so no rating should be found.
276 $toptions = (object)array_merge($defaultoptions, array('items' => $user2posts));
277 $toptions->userid = 2; // User 2 viewing the ratings of their own item.
278 $result = $rm->get_ratings($toptions);
279 // These should be null as the user is viewing their own item and thus cannot rate.
280 $this->assertNull($result[0]->rating->userid);
281 $this->assertNull($result[0]->rating->rating);
282 $this->assertEquals($result[0]->rating->aggregate, 3); // Should still get the aggregate.
286 * Data provider for get_aggregate_string tests.
288 * @return array
290 public function get_aggregate_string_provider() {
291 return [
292 'Non-numeric aggregate produces empty string' => [
293 RATING_AGGREGATE_NONE,
294 'string',
295 null,
296 ['Foo', 'Bar'],
299 'Aggregate count produces empty string' => [
300 RATING_AGGREGATE_COUNT,
302 null,
303 ['Foo', 'Bar'],
306 'Numeric SUM with non-numeric scale produces returns original value' => [
307 RATING_AGGREGATE_SUM,
309 false,
310 ['Foo', 'Bar'],
311 '10',
313 'Numeric SUM with non-numeric scale produces returns rounded value' => [
314 RATING_AGGREGATE_SUM,
315 10.45,
316 false,
317 ['Foo', 'Bar'],
318 '10.5',
320 'Numeric SUM with numeric scale produces returns rounded value' => [
321 RATING_AGGREGATE_SUM,
322 10.45,
323 true,
324 ['Foo', 'Bar'],
325 '10.5',
327 'Numeric AVERAGE with numeric scale produces returns rounded value' => [
328 RATING_AGGREGATE_AVERAGE,
329 10.45,
330 true,
331 ['Foo', 'Bar'],
332 '10.5',
334 'Numeric AVERAGE with non-numeric scale produces returns indexed value (0)' => [
335 RATING_AGGREGATE_AVERAGE,
337 false,
338 ['Foo', 'Bar'],
339 'Foo',
341 'Numeric AVERAGE with non-numeric scale produces returns indexed value (1)' => [
342 RATING_AGGREGATE_AVERAGE,
344 false,
345 ['Foo', 'Bar'],
346 'Bar',
352 * Test the value returned by get_aggregate_string().
354 * @dataProvider get_aggregate_string_provider
356 public function test_get_aggregate_string($method, $aggregate, $isnumeric, $scaleitems, $expectation) {
357 $options = new \stdClass();
358 $options->aggregate = $aggregate;
359 $options->context = null;
360 $options->component = null;
361 $options->ratingarea = null;
362 $options->itemid = null;
363 $options->scaleid = null;
364 $options->userid = null;
366 $options->settings = new \stdClass();
367 $options->settings->aggregationmethod = $method;
368 $options->settings->scale = new \stdClass();
369 $options->settings->scale->isnumeric = $isnumeric;
370 $options->settings->scale->scaleitems = $scaleitems;
372 $rating = new \rating($options);
373 $this->assertEquals($expectation, $rating->get_aggregate_string());
378 * rating_manager subclass for unit testing without requiring capabilities to be loaded
380 class mockup_rating_manager extends rating_manager {
383 * Overwrite get_plugin_permissions_array() so it always return granted perms for unit testing
385 public function get_plugin_permissions_array($contextid, $component, $ratingarea) {
386 return array(
387 'rate' => true,
388 'view' => true,
389 'viewany' => true,
390 'viewall' => true);