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