See Release Notes
Long Term Support Release
Differences Between: [Versions 400 and 401]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body