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