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
declare(strict_types=1);
18
 
19
namespace core_course\reportbuilder\datasource;
20
 
1441 ariadna 21
use core\context\course;
1 efrain 22
use core_reportbuilder_generator;
1441 ariadna 23
use core_reportbuilder\local\filters\{boolean_select, date, select, tags, text};
24
use core_reportbuilder\tests\core_reportbuilder_testcase;
1 efrain 25
 
26
/**
27
 * Unit tests for courses datasources
28
 *
29
 * @package     core_course
30
 * @covers      \core_course\reportbuilder\datasource\courses
31
 * @copyright   2021 Paul Holden <paulh@moodle.com>
32
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 */
1441 ariadna 34
final class courses_test extends core_reportbuilder_testcase {
1 efrain 35
 
36
    /**
37
     * Test default datasource
38
     */
39
    public function test_datasource_default(): void {
40
        $this->resetAfterTest();
41
 
42
        // Test subject.
43
        $category = $this->getDataGenerator()->create_category(['name' => 'My cats']);
44
        $courseone = $this->getDataGenerator()->create_course([
45
            'category' => $category->id,
46
            'fullname' => 'Feline fine',
47
            'shortname' => 'C102',
48
            'idnumber' => 'CAT102'
49
        ]);
50
        $coursetwo = $this->getDataGenerator()->create_course([
51
            'category' => $category->id,
52
            'fullname' => 'All about cats',
53
            'shortname' => 'C101',
54
            'idnumber' => 'CAT101'
55
        ]);
56
 
57
        /** @var core_reportbuilder_generator $generator */
58
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
59
        $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 1]);
60
 
61
        $content = $this->get_custom_report_content($report->get('id'));
62
 
63
        // Default columns are category, shortname, fullname, idnumber. Sorted by category, shortname, fullname.
64
        $this->assertEquals([
65
            [$category->name, $coursetwo->shortname, $coursetwo->fullname, $coursetwo->idnumber],
66
            [$category->name, $courseone->shortname, $courseone->fullname, $courseone->idnumber],
67
        ], array_map('array_values', $content));
68
    }
69
 
70
    /**
71
     * Test datasource columns that aren't added by default
72
     */
73
    public function test_datasource_non_default_columns(): void {
74
        $this->resetAfterTest();
75
 
76
        $category = $this->getDataGenerator()->create_category([
77
            'name' => 'Animals',
78
            'idnumber' => 'CAT101',
79
            'description' => 'Category description',
80
        ]);
81
        $course = $this->getDataGenerator()->create_course([
82
            'category' => $category->id,
83
            'fullname' => 'Cats',
84
            'summary' => 'Course description',
1441 ariadna 85
            'lang' => 'en',
1 efrain 86
            'theme' => 'boost',
87
            'tags' => ['Horses'],
88
        ]);
89
 
90
        // Add a course image.
91
        get_file_storage()->create_file_from_string([
1441 ariadna 92
            'contextid' => course::instance($course->id)->id,
1 efrain 93
            'component' => 'course',
94
            'filearea' => 'overviewfiles',
95
            'itemid' => 0,
96
            'filepath' => '/',
97
            'filename' => 'HelloWorld.jpg',
98
        ], 'HelloWorld');
99
 
100
        /** @var core_reportbuilder_generator $generator */
101
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
102
        $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]);
103
 
104
        // Course.
105
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:coursefullnamewithlink']);
106
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseshortnamewithlink']);
107
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseidnumberewithlink']);
108
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:summary']);
109
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:format']);
110
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:startdate']);
111
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enddate']);
112
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:visible']);
113
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmode']);
114
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmodeforce']);
115
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:lang']);
116
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:calendartype']);
117
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:theme']);
118
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enablecompletion']);
119
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:downloadcontent']);
120
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:timecreated']);
121
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:timemodified']);
122
 
123
        // Tags.
124
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
125
 
126
        // File entity.
127
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'file:name']);
128
 
129
        $content = $this->get_custom_report_content($report->get('id'));
130
        $this->assertCount(1, $content);
131
 
132
        [
133
            $coursenamewithlink,
134
            $courseshortnamewithlink,
135
            $courseidnumberwithlink,
136
            $coursesummary,
137
            $courseformat,
138
            $coursestartdate,
139
            $courseenddate,
140
            $coursevisible,
141
            $coursegroupmode,
142
            $coursegroupmodeforce,
143
            $courselang,
144
            $coursecalendar,
145
            $coursetheme,
146
            $coursecompletion,
147
            $coursedownload,
148
            $coursetimecreated,
149
            $coursetimemodified,
150
            $tagname,
151
            $filename,
152
        ] = array_values($content[0]);
153
 
154
        // Course.
155
        $this->assertStringContainsString($course->fullname, $coursenamewithlink);
156
        $this->assertStringContainsString($course->shortname, $courseshortnamewithlink);
157
        $this->assertStringContainsString($course->idnumber, $courseidnumberwithlink);
158
        $this->assertEquals(format_text($course->summary, $course->summaryformat), $coursesummary);
159
        $this->assertEquals('Custom sections', $courseformat);
160
        $this->assertEquals(userdate($course->startdate), $coursestartdate);
161
        $this->assertEmpty($courseenddate);
162
        $this->assertEquals('Yes', $coursevisible);
163
        $this->assertEquals('No groups', $coursegroupmode);
164
        $this->assertEquals('No', $coursegroupmodeforce);
1441 ariadna 165
        $this->assertEquals('English ‎(en)‎', $courselang);
166
        $this->assertEquals('Do not force', $coursecalendar);
1 efrain 167
        $this->assertEquals('Boost', $coursetheme);
168
        $this->assertEquals('No', $coursecompletion);
169
        $this->assertEmpty($coursedownload);
170
        $this->assertEquals(userdate($course->timecreated), $coursetimecreated);
171
        $this->assertEquals(userdate($course->timemodified), $coursetimemodified);
172
 
173
        // Tags.
174
        $this->assertEquals('Horses', $tagname);
175
 
176
        // File.
177
        $this->assertEquals('HelloWorld.jpg', $filename);
178
    }
179
 
180
    /**
181
     * Tests courses datasource using multilang filters
182
     */
183
    public function test_courses_datasource_multilang_filters(): void {
184
        $this->resetAfterTest();
185
 
186
        filter_set_global_state('multilang', TEXTFILTER_ON);
187
        filter_set_applies_to_strings('multilang', true);
188
 
189
        // Test subject.
190
        $category = $this->getDataGenerator()->create_category([
191
            'name' => '<span class="multilang" lang="en">Cat (en)</span><span class="multilang" lang="es">Cat (es)</span>',
192
        ]);
193
        $course = $this->getDataGenerator()->create_course([
194
            'category' => $category->id,
195
            'fullname' => '<span class="multilang" lang="en">Crs (en)</span><span class="multilang" lang="es">Crs (es)</span>',
196
        ]);
197
 
198
        /** @var core_reportbuilder_generator $generator */
199
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
200
 
201
        // Create a report containing columns that support multilang content.
202
        $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]);
203
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:name']);
204
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
205
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:coursefullnamewithlink']);
206
 
207
        $content = $this->get_custom_report_content($report->get('id'));
208
        $this->assertCount(1, $content);
209
 
210
        $contentrow = array_values(reset($content));
211
        $this->assertEquals([
212
            'Cat (en)',
213
            'Crs (en)',
214
            '<a href="' . (string) course_get_url($course->id) . '">Crs (en)</a>',
215
        ], $contentrow);
216
    }
217
 
218
    /**
219
     * Data provider for {@see test_datasource_filters}
220
     *
221
     * @return array[]
222
     */
1441 ariadna 223
    public static function datasource_filters_provider(): array {
1 efrain 224
        return [
225
            // Category.
226
            'Filter category name' => ['course_category:text', [
227
                'course_category:text_operator' => text::IS_EQUAL_TO,
228
                'course_category:text_value' => 'Animals',
229
            ], true],
230
            'Filter category name (no match)' => ['course_category:text', [
231
                'course_category:text_operator' => text::IS_EQUAL_TO,
232
                'course_category:text_value' => 'Fruit',
233
            ], false],
234
 
235
            // Course.
236
            'Filter course' => ['course:courseselector', [
237
                'course:courseselector_values' => [-1],
238
            ], false],
239
            'Filter course fullname' => ['course:fullname', [
240
                'course:fullname_operator' => text::IS_EQUAL_TO,
241
                'course:fullname_value' => 'Equine',
242
            ], true],
243
            'Filter course fullname (no match)' => ['course:fullname', [
244
                'course:fullname_operator' => text::IS_EQUAL_TO,
245
                'course:fullname_value' => 'Foxes',
246
            ], false],
247
            'Filter course shortname' => ['course:shortname', [
248
                'course:shortname_operator' => text::IS_EQUAL_TO,
249
                'course:shortname_value' => 'EQ101',
250
            ], true],
251
            'Filter course shortname (no match)' => ['course:shortname', [
252
                'course:shortname_operator' => text::IS_EQUAL_TO,
253
                'course:shortname_value' => 'FX101',
254
            ], false],
255
            'Filter course idnumber' => ['course:idnumber', [
256
                'course:idnumber_operator' => text::IS_EQUAL_TO,
257
                'course:idnumber_value' => 'E-101AB',
258
            ], true],
259
            'Filter course idnumber (no match)' => ['course:idnumber', [
260
                'course:idnumber_operator' => text::IS_EQUAL_TO,
261
                'course:idnumber_value' => 'F-101XT',
262
            ], false],
263
            'Filter course summary' => ['course:summary', [
264
                'course:summary_operator' => text::CONTAINS,
265
                'course:summary_value' => 'Lorem ipsum',
266
            ], true],
267
            'Filter course summary (no match)' => ['course:summary', [
268
                'course:summary_operator' => text::IS_EQUAL_TO,
269
                'course:summary_value' => 'Fiat',
270
            ], false],
271
            'Filter course format' => ['course:format', [
272
                'course:format_operator' => select::EQUAL_TO,
273
                'course:format_value' => 'topics',
274
            ], true],
275
            'Filter course format (no match)' => ['course:format', [
276
                'course:format_operator' => select::EQUAL_TO,
1441 ariadna 277
                'course:format_value' => 'weeks',
1 efrain 278
            ], false],
279
            'Filter course startdate' => ['course:startdate', [
280
                'course:startdate_operator' => date::DATE_RANGE,
281
                'course:startdate_from' => 1622502000,
282
            ], true],
283
            'Filter course startdate (no match)' => ['course:startdate', [
284
                'course:startdate_operator' => date::DATE_RANGE,
285
                'course:startdate_to' => 1622502000,
286
            ], false],
287
            'Filter course enddate' => ['course:enddate', [
288
                'course:enddate_operator' => date::DATE_EMPTY,
289
            ], true],
290
            'Filter course enddate (no match)' => ['course:enddate', [
291
                'course:enddate_operator' => date::DATE_NOT_EMPTY,
292
            ], false],
293
            'Filter course visible' => ['course:visible', [
294
                'course:visible_operator' => boolean_select::CHECKED,
295
            ], true],
296
            'Filter course visible (no match)' => ['course:visible', [
297
                'course:visible_operator' => boolean_select::NOT_CHECKED,
298
            ], false],
299
            'Filter course groupmode' => ['course:groupmode', [
300
                'course:groupmode_operator' => select::EQUAL_TO,
301
                'course:groupmode_value' => 0, // No groups.
302
            ], true],
303
            'Filter course groupmode (no match)' => ['course:groupmode', [
304
                'course:groupmode_operator' => select::EQUAL_TO,
305
                'course:groupmode_value' => 1, // Separate groups.
306
            ], false],
307
            'Filter course groupmodeforce' => ['course:groupmodeforce', [
308
                'course:groupmodeforce_operator' => boolean_select::NOT_CHECKED,
309
            ], true],
310
            'Filter course groupmodeforce (no match)' => ['course:groupmodeforce', [
311
                'course:groupmodeforce_operator' => boolean_select::CHECKED,
312
            ], false],
313
            'Filter course lang' => ['course:lang', [
314
                'course:lang_operator' => select::EQUAL_TO,
315
                'course:lang_value' => 'en',
316
            ], true],
317
            'Filter course lang (no match)' => ['course:lang', [
318
                'course:lang_operator' => select::EQUAL_TO,
1441 ariadna 319
                'course:lang_value' => '',
1 efrain 320
            ], false],
321
            'Filter course calendartype' => ['course:calendartype', [
322
                'course:calendartype_operator' => select::EQUAL_TO,
323
                'course:calendartype_value' => 'gregorian',
324
            ], true],
325
            'Filter course calendartype (no match)' => ['course:calendartype', [
326
                'course:calendartype_operator' => select::EQUAL_TO,
1441 ariadna 327
                'course:calendartype_value' => '',
1 efrain 328
            ], false],
329
            'Filter course theme' => ['course:theme', [
330
                'course:theme_operator' => select::EQUAL_TO,
331
                'course:theme_value' => 'boost',
332
            ], true],
333
            'Filter course theme (no match)' => ['course:theme', [
334
                'course:theme_operator' => select::EQUAL_TO,
335
                'course:theme_value' => 'classic',
336
            ], false],
337
            'Filter course enablecompletion' => ['course:enablecompletion', [
338
                'course:enablecompletion_operator' => boolean_select::NOT_CHECKED,
339
            ], true],
340
            'Filter course enablecompletion (no match)' => ['course:enablecompletion', [
341
                'course:enablecompletion_operator' => boolean_select::CHECKED,
342
            ], false],
343
            'Filter course downloadcontent' => ['course:downloadcontent', [
344
                'course:downloadcontent_operator' => boolean_select::CHECKED,
345
            ], true],
346
            'Filter course downloadcontent (no match)' => ['course:downloadcontent', [
347
                'course:downloadcontent_operator' => boolean_select::NOT_CHECKED,
348
            ], false],
349
            'Filter course timecreated' => ['course:timecreated', [
350
                'course:timecreated_operator' => date::DATE_RANGE,
351
                'course:timecreated_from' => 1622502000,
352
            ], true],
353
            'Filter course timecreated (no match)' => ['course:timecreated', [
354
                'course:timecreated_operator' => date::DATE_RANGE,
355
                'course:timecreated_to' => 1622502000,
356
            ], false],
357
            'Filter course timemodified' => ['course:timemodified', [
358
                'course:timemodified_operator' => date::DATE_RANGE,
359
                'course:timemodified_from' => 1622502000,
360
            ], true],
361
            'Filter course timemodified (no match)' => ['course:timemodified', [
362
                'course:timemodified_operator' => date::DATE_RANGE,
363
                'course:timemodified_to' => 1622502000,
364
            ], false],
365
 
366
            // Tags.
367
            'Filter tag name' => ['tag:name', [
368
                'tag:name_operator' => tags::EQUAL_TO,
369
                'tag:name_value' => [-1],
370
            ], false],
371
            'Filter tag name not empty' => ['tag:name', [
372
                'tag:name_operator' => tags::NOT_EMPTY,
373
            ], true],
374
 
375
            // File.
376
            'Filter file name empty' => ['file:name', [
377
                'file:name_operator' => text::IS_EMPTY,
378
            ], true],
379
        ];
380
    }
381
 
382
    /**
383
     * Test datasource filters
384
     *
385
     * @param string $filtername
386
     * @param array $filtervalues
387
     * @param bool $expectmatch
388
     *
389
     * @dataProvider datasource_filters_provider
390
     */
391
    public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
392
        $this->resetAfterTest();
393
 
394
        $category = $this->getDataGenerator()->create_category(['name' => 'Animals']);
395
        $course = $this->getDataGenerator()->create_course([
396
            'category' => $category->id,
397
            'fullname' => 'Equine',
398
            'shortname' => 'EQ101',
399
            'idnumber' => 'E-101AB',
400
            'lang' => 'en',
401
            'calendartype' => 'gregorian',
402
            'theme' => 'boost',
403
            'downloadcontent' => 1,
404
            'tags' => ['Horses'],
405
        ]);
406
 
407
        /** @var core_reportbuilder_generator $generator */
408
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
409
 
410
        // Create report containing single column, and given filter.
1441 ariadna 411
        $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]);
1 efrain 412
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
413
 
414
        // Add filter, set it's values.
415
        $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
416
        $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
417
 
418
        if ($expectmatch) {
419
            $this->assertCount(1, $content);
420
            $this->assertEquals($course->fullname, reset($content[0]));
421
        } else {
422
            $this->assertEmpty($content);
423
        }
424
    }
425
 
426
    /**
427
     * Stress test datasource
428
     *
429
     * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php
430
     */
431
    public function test_stress_datasource(): void {
432
        if (!PHPUNIT_LONGTEST) {
433
            $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
434
        }
435
 
436
        $this->resetAfterTest();
437
 
438
        $category = $this->getDataGenerator()->create_category();
439
        $course = $this->getDataGenerator()->create_course(['category' => $category->id]);
440
 
441
        $this->datasource_stress_test_columns(courses::class);
442
        $this->datasource_stress_test_columns_aggregation(courses::class);
443
        $this->datasource_stress_test_conditions(courses::class, 'course:idnumber');
444
    }
445
}