See Release Notes
Long Term Support Release
<?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. declare(strict_types=1); namespace core_reportbuilder\local\helpers; use core_reportbuilder_generator; use core_reportbuilder_testcase; use core_reportbuilder\local\entities\user; use core_reportbuilder\local\filters\boolean_select; use core_reportbuilder\local\filters\date; use core_reportbuilder\local\filters\select; use core_reportbuilder\local\filters\text;< use core_reportbuilder\local\helpers\user_filter_manager;use core_reportbuilder\local\report\column; use core_reportbuilder\local\report\filter; use core_user\reportbuilder\datasource\users; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); /** * Unit tests for user profile fields helper * * @package core_reportbuilder * @covers \core_reportbuilder\local\helpers\user_profile_fields * @copyright 2021 David Matamoros <davidmc@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_profile_fields_test extends core_reportbuilder_testcase { /** * Generate custom profile fields, one of each type * * @return user_profile_fields */ private function generate_userprofilefields(): user_profile_fields { $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'checkbox', 'name' => 'Checkbox field', 'datatype' => 'checkbox']); $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'datetime', 'name' => 'Date field', 'datatype' => 'datetime', 'param2' => 2022, 'param3' => 0]); $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'menu', 'name' => 'Menu field', 'datatype' => 'menu', 'param1' => "Cat\nDog"]); $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'Social', 'name' => 'msn', 'datatype' => 'social', 'param1' => 'msn']); $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'text', 'name' => 'Text field', 'datatype' => 'text']); $this->getDataGenerator()->create_custom_profile_field([ 'shortname' => 'textarea', 'name' => 'Textarea field', 'datatype' => 'textarea']); $userentity = new user(); $useralias = $userentity->get_table_alias('user'); // Create an instance of the userprofilefield helper. return new user_profile_fields("$useralias.id", $userentity->get_entity_name()); } /** * Test for get_columns */ public function test_get_columns(): void { $this->resetAfterTest(); $userentity = new user(); $useralias = $userentity->get_table_alias('user'); // Get pre-existing user profile fields. $initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name()); $initialcolumns = $initialuserprofilefields->get_columns(); $initialcolumntitles = array_map(static function(column $column): string { return $column->get_title(); }, $initialcolumns); $initialcolumntypes = array_map(static function(column $column): int { return $column->get_type(); }, $initialcolumns); // Add new custom profile fields. $userprofilefields = $this->generate_userprofilefields(); $columns = $userprofilefields->get_columns(); // Columns count should be equal to start + 6. $this->assertCount(count($initialcolumns) + 6, $columns); $this->assertContainsOnlyInstancesOf(column::class, $columns); // Assert column titles. $columntitles = array_map(static function(column $column): string { return $column->get_title(); }, $columns); $expectedcolumntitles = array_merge($initialcolumntitles, [ 'Checkbox field', 'Date field', 'Menu field', 'MSN ID', 'Text field', 'Textarea field', ]); $this->assertEquals($expectedcolumntitles, $columntitles); // Assert column types. $columntypes = array_map(static function(column $column): int { return $column->get_type(); }, $columns); $expectedcolumntypes = array_merge($initialcolumntypes, [ column::TYPE_BOOLEAN, column::TYPE_TIMESTAMP, column::TYPE_TEXT, column::TYPE_TEXT, column::TYPE_TEXT, column::TYPE_LONGTEXT, ]); $this->assertEquals($expectedcolumntypes, $columntypes); } /** * Test for add_join */ public function test_add_join(): void { $this->resetAfterTest(); $userprofilefields = $this->generate_userprofilefields(); $columns = $userprofilefields->get_columns(); $this->assertCount(1, ($columns[0])->get_joins()); $userprofilefields->add_join('JOIN {test} t ON t.id = id'); $columns = $userprofilefields->get_columns(); $this->assertCount(2, ($columns[0])->get_joins()); } /** * Test for add_joins */ public function test_add_joins(): void { $this->resetAfterTest(); $userprofilefields = $this->generate_userprofilefields(); $columns = $userprofilefields->get_columns(); $this->assertCount(1, ($columns[0])->get_joins()); $userprofilefields->add_joins(['JOIN {test} t ON t.id = id', 'JOIN {test2} t2 ON t2.id = id']); $columns = $userprofilefields->get_columns(); $this->assertCount(3, ($columns[0])->get_joins()); } /** * Test for get_filters */ public function test_get_filters(): void { $this->resetAfterTest(); $userentity = new user(); $useralias = $userentity->get_table_alias('user'); // Get pre-existing user profile fields. $initialuserprofilefields = new user_profile_fields("$useralias.id", $userentity->get_entity_name()); $initialfilters = $initialuserprofilefields->get_filters(); $initialfilterheaders = array_map(static function(filter $filter): string { return $filter->get_header(); }, $initialfilters); // Add new custom profile fields. $userprofilefields = $this->generate_userprofilefields(); $filters = $userprofilefields->get_filters(); // Filters count should be equal to start + 6. $this->assertCount(count($initialfilters) + 6, $filters); $this->assertContainsOnlyInstancesOf(filter::class, $filters); // Assert filter headers. $filterheaders = array_map(static function(filter $filter): string { return $filter->get_header(); }, $filters); $expectedfilterheaders = array_merge($initialfilterheaders, [ 'Checkbox field', 'Date field', 'Menu field', 'MSN ID', 'Text field', 'Textarea field', ]); $this->assertEquals($expectedfilterheaders, $filterheaders); } /** * Test that adding user profile field columns to a report returns expected values */ public function test_custom_report_content(): void { $this->resetAfterTest(); $userprofilefields = $this->generate_userprofilefields(); // Create test subject with user profile fields content. $user = $this->getDataGenerator()->create_user([ 'firstname' => 'Zebedee', 'profile_field_checkbox' => true, 'profile_field_datetime' => '2021-12-09', 'profile_field_menu' => 'Cat', 'profile_field_Social' => 12345, 'profile_field_text' => 'Hello', 'profile_field_textarea' => 'Goodbye', ]); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]); // Add user profile field columns to the report. $firstname = $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_checkbox']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_datetime']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_menu']);< $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_Social']);> $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_social']);$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_text']); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:profilefield_textarea']); // Sort the report, Admin -> Zebedee for consistency. report::toggle_report_column_sorting($report->get('id'), $firstname->get('id'), true); $content = $this->get_custom_report_content($report->get('id')); $this->assertEquals([ [ 'c0_firstname' => 'Admin', 'c1_data' => '',< 'c2_data' => 'Not set',> 'c2_data' => '','c3_data' => '', 'c4_data' => '', 'c5_data' => '', 'c6_data' => '', ], [ 'c0_firstname' => 'Zebedee', 'c1_data' => 'Yes', 'c2_data' => '9 December 2021', 'c3_data' => 'Cat', 'c4_data' => '12345', 'c5_data' => 'Hello', 'c6_data' => '<div class="no-overflow">Goodbye</div>', ], ], $content); } /** * Data provider for {@see test_custom_report_filter} * * @return array[] */ public function custom_report_filter_provider(): array { return [ 'Filter by checkbox profile field' => ['user:profilefield_checkbox', [ 'user:profilefield_checkbox_operator' => boolean_select::CHECKED, ], 'testuser'], 'Filter by checkbox profile field (empty)' => ['user:profilefield_checkbox', [ 'user:profilefield_checkbox_operator' => boolean_select::NOT_CHECKED, ], 'admin'], 'Filter by datetime profile field' => ['user:profilefield_datetime', [ 'user:profilefield_datetime_operator' => date::DATE_RANGE, 'user:profilefield_datetime_from' => 1622502000, ], 'testuser'], 'Filter by datetime profile field (empty)' => ['user:profilefield_datetime', [ 'user:profilefield_datetime_operator' => date::DATE_EMPTY, ], 'admin'], 'Filter by menu profile field' => ['user:profilefield_menu', [ 'user:profilefield_menu_operator' => select::EQUAL_TO, 'user:profilefield_menu_value' => 'Dog', ], 'testuser'], 'Filter by menu profile field (empty)' => ['user:profilefield_menu', [ 'user:profilefield_menu_operator' => select::NOT_EQUAL_TO, 'user:profilefield_menu_value' => 'Dog', ], 'admin'],< 'Filter by social profile field' => ['user:profilefield_Social', [ < 'user:profilefield_Social_operator' => text::IS_EQUAL_TO, < 'user:profilefield_Social_value' => '12345',> 'Filter by social profile field' => ['user:profilefield_social', [ > 'user:profilefield_social_operator' => text::IS_EQUAL_TO, > 'user:profilefield_social_value' => '12345',], 'testuser'],< 'Filter by social profile field (empty)' => ['user:profilefield_Social', [ < 'user:profilefield_Social_operator' => text::IS_EMPTY,> 'Filter by social profile field (empty)' => ['user:profilefield_social', [ > 'user:profilefield_social_operator' => text::IS_EMPTY,], 'admin'], 'Filter by text profile field' => ['user:profilefield_text', [ 'user:profilefield_text_operator' => text::IS_EQUAL_TO, 'user:profilefield_text_value' => 'Hello', ], 'testuser'], 'Filter by text profile field (empty)' => ['user:profilefield_text', [ 'user:profilefield_text_operator' => text::IS_NOT_EQUAL_TO, 'user:profilefield_text_value' => 'Hello', ], 'admin'], 'Filter by textarea profile field' => ['user:profilefield_textarea', [ 'user:profilefield_textarea_operator' => text::IS_EQUAL_TO, 'user:profilefield_textarea_value' => 'Goodbye', ], 'testuser'], 'Filter by textarea profile field (empty)' => ['user:profilefield_textarea', [ 'user:profilefield_textarea_operator' => text::DOES_NOT_CONTAIN, 'user:profilefield_textarea_value' => 'Goodbye', ], 'admin'], ]; } /** * Test filtering report by custom profile fields * * @param string $filtername * @param array $filtervalues * @param string $expectmatchuser * * @dataProvider custom_report_filter_provider */ public function test_custom_report_filter(string $filtername, array $filtervalues, string $expectmatchuser): void { $this->resetAfterTest(); $userprofilefields = $this->generate_userprofilefields(); // Create test subject with user profile fields content. $user = $this->getDataGenerator()->create_user([ 'username' => 'testuser', 'profile_field_checkbox' => true, 'profile_field_datetime' => '2021-12-09', 'profile_field_menu' => 'Dog', 'profile_field_Social' => '12345', 'profile_field_text' => 'Hello', 'profile_field_textarea' => 'Goodbye', ]); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); // Create report containing single column, and given filter. $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]); $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:username']); // Add filter, set it's values. $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);< user_filter_manager::set($report->get('id'), $filtervalues); < < $content = $this->get_custom_report_content($report->get('id'));> $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);$this->assertCount(1, $content); $this->assertEquals($expectmatchuser, reset($content[0]));> } } > } > /** > * Stress test user datasource using profile fields > * > * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php > */ > public function test_stress_datasource(): void { > if (!PHPUNIT_LONGTEST) { > $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); > } > > $this->resetAfterTest(); > > $userprofilefields = $this->generate_userprofilefields(); > $user = $this->getDataGenerator()->create_user([ > 'profile_field_checkbox' => true, > 'profile_field_datetime' => '2021-12-09', > 'profile_field_menu' => 'Dog', > 'profile_field_Social' => '12345', > 'profile_field_text' => 'Hello', > 'profile_field_textarea' => 'Goodbye', > ]); > > $this->datasource_stress_test_columns(users::class); > $this->datasource_stress_test_columns_aggregation(users::class); > $this->datasource_stress_test_conditions(users::class, 'user:idnumber');