Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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_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 24 */ 25 26 namespace core_rating; 27 28 use rating_manager; 29 30 defined('MOODLE_INTERNAL') || die(); 31 32 // Include all the needed stuff. 33 global $CFG; 34 require_once($CFG->dirroot . '/rating/lib.php'); 35 36 37 /** 38 * Unit test case for all the rating/lib.php requiring DB mockup & manipulation 39 * 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 44 */ 45 class rating_test extends \advanced_testcase { 46 47 protected $syscontext; 48 protected $neededcaps = array('view', 'viewall', 'viewany', 'rate'); 49 protected $originaldefaultfrontpageroleid; 50 51 public function setUp(): void { 52 global $CFG; 53 parent::setUp(); 54 55 $this->resetAfterTest(true); 56 57 $CFG->defaultfrontpageroleid = null; 58 } 59 60 /** 61 * Test the current get_ratings method main sql 62 */ 63 public function test_get_ratings_sql() { 64 global $DB; 65 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), 79 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), 89 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), 100 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), 110 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), 121 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) 131 ); 132 foreach ($ratings as $rating) { 133 $DB->insert_record('rating', $rating); 134 } 135 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')); 145 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); 153 154 $rm = new mockup_rating_manager(); 155 156 // STEP 1: Retreive ratings using the current user. 157 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. 169 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. 181 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. 193 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. 206 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. 214 215 // STEP 2: Retrieve ratings by a specified user. 216 // We still expect complete aggregations and counts. 217 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. 229 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. 241 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. 254 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. 262 263 // STEP 3: Some special cases. 264 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. 273 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. 283 } 284 285 /** 286 * Data provider for get_aggregate_string tests. 287 * 288 * @return array 289 */ 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'], 297 '', 298 ], 299 'Aggregate count produces empty string' => [ 300 RATING_AGGREGATE_COUNT, 301 0, 302 null, 303 ['Foo', 'Bar'], 304 '', 305 ], 306 'Numeric SUM with non-numeric scale produces returns original value' => [ 307 RATING_AGGREGATE_SUM, 308 10, 309 false, 310 ['Foo', 'Bar'], 311 '10', 312 ], 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', 319 ], 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', 326 ], 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', 333 ], 334 'Numeric AVERAGE with non-numeric scale produces returns indexed value (0)' => [ 335 RATING_AGGREGATE_AVERAGE, 336 0, 337 false, 338 ['Foo', 'Bar'], 339 'Foo', 340 ], 341 'Numeric AVERAGE with non-numeric scale produces returns indexed value (1)' => [ 342 RATING_AGGREGATE_AVERAGE, 343 1, 344 false, 345 ['Foo', 'Bar'], 346 'Bar', 347 ], 348 ]; 349 } 350 351 /** 352 * Test the value returned by get_aggregate_string(). 353 * 354 * @dataProvider get_aggregate_string_provider 355 */ 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; 365 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; 371 372 $rating = new \rating($options); 373 $this->assertEquals($expectation, $rating->get_aggregate_string()); 374 } 375 } 376 377 /** 378 * rating_manager subclass for unit testing without requiring capabilities to be loaded 379 */ 380 class mockup_rating_manager extends rating_manager { 381 382 /** 383 * Overwrite get_plugin_permissions_array() so it always return granted perms for unit testing 384 */ 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); 391 } 392 393 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body