Proyectos de Subversion Moodle

Rev

| 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_reportbuilder\local\helpers;
20
 
21
use core_reportbuilder_generator;
22
use core_reportbuilder_testcase;
23
use core_reportbuilder\local\entities\user;
24
use core_reportbuilder\local\filters\boolean_select;
25
use core_reportbuilder\local\filters\date;
26
use core_reportbuilder\local\filters\select;
27
use core_reportbuilder\local\filters\text;
28
use core_reportbuilder\local\report\column;
29
use core_reportbuilder\local\report\filter;
30
use core_user\reportbuilder\datasource\users;
31
 
32
defined('MOODLE_INTERNAL') || die();
33
 
34
global $CFG;
35
require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
36
 
37
/**
38
 * Unit tests for user profile fields helper
39
 *
40
 * @package     core_reportbuilder
41
 * @covers      \core_reportbuilder\local\helpers\user_profile_fields
42
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
43
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44
 */
45
class user_profile_fields_test extends core_reportbuilder_testcase {
46
 
47
    /**
48
     * Generate custom profile fields, one of each type
49
     *
50
     * @return user_profile_fields
51
     */
52
    private function generate_userprofilefields(): user_profile_fields {
53
        $this->getDataGenerator()->create_custom_profile_field([
54
            'shortname' => 'checkbox', 'name' => 'Checkbox field', 'datatype' => 'checkbox']);
55
 
56
        $this->getDataGenerator()->create_custom_profile_field([
57
            'shortname' => 'datetime', 'name' => 'Date field', 'datatype' => 'datetime', 'param2' => 2022, 'param3' => 0]);
58
 
59
        $this->getDataGenerator()->create_custom_profile_field([
60
            'shortname' => 'menu', 'name' => 'Menu field', 'datatype' => 'menu', 'param1' => "Cat\nDog"]);
61
 
62
        $this->getDataGenerator()->create_custom_profile_field([
63
            'shortname' => 'Social', 'name' => 'msn', 'datatype' => 'social', 'param1' => 'msn']);
64
 
65
        $this->getDataGenerator()->create_custom_profile_field([
66
            'shortname' => 'text', 'name' => 'Text field', 'datatype' => 'text']);
67
 
68
        $this->getDataGenerator()->create_custom_profile_field([
69
            'shortname' => 'textarea', 'name' => 'Textarea field', 'datatype' => 'textarea']);
70
 
71
        $userentity = new user();
72
        $useralias = $userentity->get_table_alias('user');
73
 
74
        // Create an instance of the userprofilefield helper.
75
        return new user_profile_fields("$useralias.id", $userentity->get_entity_name());
76
    }
77
 
78
    /**
79
     * Test for get_columns
80
     */
81
    public function test_get_columns(): void {
82
        $this->resetAfterTest();
83
 
84
        $userentity = new user();
85
        $useralias = $userentity->get_table_alias('user');
86
 
87
        // Get pre-existing user profile fields.
88
        $initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name());
89
        $initialcolumns = $initialuserprofilefields->get_columns();
90
        $initialcolumntitles = array_map(static function(column $column): string {
91
            return $column->get_title();
92
        }, $initialcolumns);
93
        $initialcolumntypes = array_map(static function(column $column): int {
94
            return $column->get_type();
95
        }, $initialcolumns);
96
 
97
        // Add new custom profile fields.
98
        $userprofilefields = $this->generate_userprofilefields();
99
        $columns = $userprofilefields->get_columns();
100
 
101
        // Columns count should be equal to start + 6.
102
        $this->assertCount(count($initialcolumns) + 6, $columns);
103
        $this->assertContainsOnlyInstancesOf(column::class, $columns);
104
 
105
        // Assert column titles.
106
        $columntitles = array_map(static function(column $column): string {
107
            return $column->get_title();
108
        }, $columns);
109
        $expectedcolumntitles = array_merge($initialcolumntitles, [
110
            'Checkbox field',
111
            'Date field',
112
            'Menu field',
113
            'MSN ID',
114
            'Text field',
115
            'Textarea field',
116
        ]);
117
        $this->assertEquals($expectedcolumntitles, $columntitles);
118
 
119
        // Assert column types.
120
        $columntypes = array_map(static function(column $column): int {
121
            return $column->get_type();
122
        }, $columns);
123
        $expectedcolumntypes = array_merge($initialcolumntypes, [
124
            column::TYPE_BOOLEAN,
125
            column::TYPE_TIMESTAMP,
126
            column::TYPE_TEXT,
127
            column::TYPE_TEXT,
128
            column::TYPE_TEXT,
129
            column::TYPE_LONGTEXT,
130
        ]);
131
        $this->assertEquals($expectedcolumntypes, $columntypes);
132
    }
133
 
134
    /**
135
     * Test for add_join
136
     */
137
    public function test_add_join(): void {
138
        $this->resetAfterTest();
139
 
140
        $userprofilefields = $this->generate_userprofilefields();
141
        $columns = $userprofilefields->get_columns();
142
        $this->assertCount(1, ($columns[0])->get_joins());
143
 
144
        $userprofilefields->add_join('JOIN {test} t ON t.id = id');
145
        $columns = $userprofilefields->get_columns();
146
        $this->assertCount(2, ($columns[0])->get_joins());
147
    }
148
 
149
    /**
150
     * Test for add_joins
151
     */
152
    public function test_add_joins(): void {
153
        $this->resetAfterTest();
154
 
155
        $userprofilefields = $this->generate_userprofilefields();
156
        $columns = $userprofilefields->get_columns();
157
        $this->assertCount(1, ($columns[0])->get_joins());
158
 
159
        $userprofilefields->add_joins(['JOIN {test} t ON t.id = id', 'JOIN {test2} t2 ON t2.id = id']);
160
        $columns = $userprofilefields->get_columns();
161
        $this->assertCount(3, ($columns[0])->get_joins());
162
    }
163
 
164
    /**
165
     * Test for get_filters
166
     */
167
    public function test_get_filters(): void {
168
        $this->resetAfterTest();
169
 
170
        $userentity = new user();
171
        $useralias = $userentity->get_table_alias('user');
172
 
173
        // Get pre-existing user profile fields.
174
        $initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name());
175
        $initialfilters = $initialuserprofilefields->get_filters();
176
        $initialfilterheaders = array_map(static function(filter $filter): string {
177
            return $filter->get_header();
178
        }, $initialfilters);
179
 
180
        // Add new custom profile fields.
181
        $userprofilefields = $this->generate_userprofilefields();
182
        $filters = $userprofilefields->get_filters();
183
 
184
        // Filters count should be equal to start + 6.
185
        $this->assertCount(count($initialfilters) + 6, $filters);
186
        $this->assertContainsOnlyInstancesOf(filter::class, $filters);
187
 
188
        // Assert filter headers.
189
        $filterheaders = array_map(static function(filter $filter): string {
190
            return $filter->get_header();
191
        }, $filters);
192
        $expectedfilterheaders = array_merge($initialfilterheaders, [
193
            'Checkbox field',
194
            'Date field',
195
            'Menu field',
196
            'MSN ID',
197
            'Text field',
198
            'Textarea field',
199
        ]);
200
        $this->assertEquals($expectedfilterheaders, $filterheaders);
201
    }
202
 
203
    /**
204
     * Test that adding user profile field columns to a report returns expected values
205
     */
206
    public function test_custom_report_content(): void {
207
        $this->resetAfterTest();
208
 
209
        $userprofilefields = $this->generate_userprofilefields();
210
 
211
        // Create test subject with user profile fields content.
212
        $user = $this->getDataGenerator()->create_user([
213
            'firstname' => 'Zebedee',
214
            'profile_field_checkbox' => true,
215
            'profile_field_datetime' => '2021-12-09',
216
            'profile_field_menu' => 'Cat',
217
            'profile_field_Social' => 12345,
218
            'profile_field_text' => 'Hello',
219
            'profile_field_textarea' => 'Goodbye',
220
        ]);
221
 
222
        /** @var core_reportbuilder_generator $generator */
223
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
224
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
225
 
226
        // Add user profile field columns to the report.
227
        $firstname = $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']);
228
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_checkbox']);
229
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_datetime']);
230
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_menu']);
231
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_social']);
232
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_text']);
233
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_textarea']);
234
 
235
        // Sort the report, Admin -> Zebedee for consistency.
236
        report::toggle_report_column_sorting($report->get('id'), $firstname->get('id'), true);
237
 
238
        $content = $this->get_custom_report_content($report->get('id'));
239
        $this->assertEquals([
240
            [
241
                'c0_firstname' => 'Admin',
242
                'c1_data' => '',
243
                'c2_data' => '',
244
                'c3_data' => '',
245
                'c4_data' => '',
246
                'c5_data' => '',
247
                'c6_data' => '',
248
            ], [
249
                'c0_firstname' => 'Zebedee',
250
                'c1_data' => 'Yes',
251
                'c2_data' => '9 December 2021',
252
                'c3_data' => 'Cat',
253
                'c4_data' => '12345',
254
                'c5_data' => 'Hello',
255
                'c6_data' => '<div class="no-overflow">Goodbye</div>',
256
            ],
257
        ], $content);
258
    }
259
 
260
    /**
261
     * Data provider for {@see test_custom_report_filter}
262
     *
263
     * @return array[]
264
     */
265
    public function custom_report_filter_provider(): array {
266
        return [
267
            'Filter by checkbox profile field' => ['user:profilefield_checkbox', [
268
                'user:profilefield_checkbox_operator' => boolean_select::CHECKED,
269
            ], 'testuser'],
270
            'Filter by checkbox profile field (empty)' => ['user:profilefield_checkbox', [
271
                'user:profilefield_checkbox_operator' => boolean_select::NOT_CHECKED,
272
            ], 'admin'],
273
            'Filter by datetime profile field' => ['user:profilefield_datetime', [
274
                'user:profilefield_datetime_operator' => date::DATE_RANGE,
275
                'user:profilefield_datetime_from' => 1622502000,
276
            ], 'testuser'],
277
            'Filter by datetime profile field (empty)' => ['user:profilefield_datetime', [
278
                'user:profilefield_datetime_operator' => date::DATE_EMPTY,
279
            ], 'admin'],
280
            'Filter by menu profile field' => ['user:profilefield_menu', [
281
                'user:profilefield_menu_operator' => select::EQUAL_TO,
282
                'user:profilefield_menu_value' => 'Dog',
283
            ], 'testuser'],
284
            'Filter by menu profile field (empty)' => ['user:profilefield_menu', [
285
                'user:profilefield_menu_operator' => select::NOT_EQUAL_TO,
286
                'user:profilefield_menu_value' => 'Dog',
287
            ], 'admin'],
288
            'Filter by social profile field' => ['user:profilefield_social', [
289
                'user:profilefield_social_operator' => text::IS_EQUAL_TO,
290
                'user:profilefield_social_value' => '12345',
291
            ], 'testuser'],
292
            'Filter by social profile field (empty)' => ['user:profilefield_social', [
293
                'user:profilefield_social_operator' => text::IS_EMPTY,
294
            ], 'admin'],
295
            'Filter by text profile field' => ['user:profilefield_text', [
296
                'user:profilefield_text_operator' => text::IS_EQUAL_TO,
297
                'user:profilefield_text_value' => 'Hello',
298
            ], 'testuser'],
299
            'Filter by text profile field (empty)' => ['user:profilefield_text', [
300
                'user:profilefield_text_operator' => text::IS_NOT_EQUAL_TO,
301
                'user:profilefield_text_value' => 'Hello',
302
            ], 'admin'],
303
            'Filter by textarea profile field' => ['user:profilefield_textarea', [
304
                'user:profilefield_textarea_operator' => text::IS_EQUAL_TO,
305
                'user:profilefield_textarea_value' => 'Goodbye',
306
            ], 'testuser'],
307
            'Filter by textarea profile field (empty)' => ['user:profilefield_textarea', [
308
                'user:profilefield_textarea_operator' => text::DOES_NOT_CONTAIN,
309
                'user:profilefield_textarea_value' => 'Goodbye',
310
            ], 'admin'],
311
        ];
312
    }
313
 
314
    /**
315
     * Test filtering report by custom profile fields
316
     *
317
     * @param string $filtername
318
     * @param array $filtervalues
319
     * @param string $expectmatchuser
320
     *
321
     * @dataProvider custom_report_filter_provider
322
     */
323
    public function test_custom_report_filter(string $filtername, array $filtervalues, string $expectmatchuser): void {
324
        $this->resetAfterTest();
325
 
326
        $userprofilefields = $this->generate_userprofilefields();
327
 
328
        // Create test subject with user profile fields content.
329
        $user = $this->getDataGenerator()->create_user([
330
            'username' => 'testuser',
331
            'profile_field_checkbox' => true,
332
            'profile_field_datetime' => '2021-12-09',
333
            'profile_field_menu' => 'Dog',
334
            'profile_field_Social' => '12345',
335
            'profile_field_text' => 'Hello',
336
            'profile_field_textarea' => 'Goodbye',
337
        ]);
338
 
339
        /** @var core_reportbuilder_generator $generator */
340
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
341
 
342
        // Create report containing single column, and given filter.
343
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
344
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:username']);
345
 
346
        // Add filter, set it's values.
347
        $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
348
        $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
349
 
350
        $this->assertCount(1, $content);
351
        $this->assertEquals($expectmatchuser, reset($content[0]));
352
    }
353
 
354
    /**
355
     * Stress test user datasource using profile fields
356
     *
357
     * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php
358
     */
359
    public function test_stress_datasource(): void {
360
        if (!PHPUNIT_LONGTEST) {
361
            $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
362
        }
363
 
364
        $this->resetAfterTest();
365
 
366
        $userprofilefields = $this->generate_userprofilefields();
367
        $user = $this->getDataGenerator()->create_user([
368
            'profile_field_checkbox' => true,
369
            'profile_field_datetime' => '2021-12-09',
370
            'profile_field_menu' => 'Dog',
371
            'profile_field_Social' => '12345',
372
            'profile_field_text' => 'Hello',
373
            'profile_field_textarea' => 'Goodbye',
374
        ]);
375
 
376
        $this->datasource_stress_test_columns(users::class);
377
        $this->datasource_stress_test_columns_aggregation(users::class);
378
        $this->datasource_stress_test_conditions(users::class, 'user:idnumber');
379
    }
380
}