Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
     */
11 efrain 55
    public function test_get_ratings_sql(): void {
1 efrain 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
     */
11 efrain 348
    public function test_get_aggregate_string($method, $aggregate, $isnumeric, $scaleitems, $expectation): void {
1 efrain 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
}