Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
  • Differences Between: [Versions 311 and 400]

       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;
      18  
      19  /**
      20   * Test data generator
      21   *
      22   * @package    core
      23   * @category   phpunit
      24   * @copyright  2012 Petr Skoda {@link http://skodak.org}
      25   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      26   */
      27  class testing_generator_test extends \advanced_testcase {
      28      public function test_get_plugin_generator_good_case() {
      29          $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
      30          $this->assertInstanceOf('core_question_generator', $generator);
      31      }
      32  
      33      public function test_get_plugin_generator_sloppy_name() {
      34          $generator = $this->getDataGenerator()->get_plugin_generator('quiz');
      35          $this->assertDebuggingCalled('Please specify the component you want a generator for as ' .
      36                      'mod_quiz, not quiz.', DEBUG_DEVELOPER);
      37          $this->assertInstanceOf('mod_quiz_generator', $generator);
      38      }
      39  
      40      public function test_get_default_generator() {
      41          $generator = $this->getDataGenerator()->get_plugin_generator('block_somethingthatdoesnotexist');
      42          $this->assertInstanceOf('default_block_generator', $generator);
      43      }
      44  
      45      /**
      46       * Test plugin generator, with no component directory.
      47       */
      48      public function test_get_plugin_generator_no_component_dir() {
      49          $this->expectException(\coding_exception::class);
      50          $this->expectExceptionMessage('Component core_completion does not support generators yet. Missing tests/generator/lib.php.');
      51          $generator = $this->getDataGenerator()->get_plugin_generator('core_completion');
      52      }
      53  
      54      public function test_create_user() {
      55          global $DB, $CFG;
      56          require_once($CFG->dirroot.'/user/lib.php');
      57  
      58          $this->resetAfterTest(true);
      59          $generator = $this->getDataGenerator();
      60  
      61          $count = $DB->count_records('user');
      62          $this->setCurrentTimeStart();
      63          $user = $generator->create_user();
      64          $this->assertEquals($count + 1, $DB->count_records('user'));
      65          $this->assertSame($user->username, \core_user::clean_field($user->username, 'username'));
      66          $this->assertSame($user->email, \core_user::clean_field($user->email, 'email'));
      67          $this->assertNotEmpty($user->firstnamephonetic);
      68          $this->assertNotEmpty($user->lastnamephonetic);
      69          $this->assertNotEmpty($user->alternatename);
      70          $this->assertNotEmpty($user->middlename);
      71          $this->assertSame('manual', $user->auth);
      72          $this->assertSame('en', $user->lang);
      73          $this->assertSame('1', $user->confirmed);
      74          $this->assertSame('0', $user->deleted);
      75          $this->assertTimeCurrent($user->timecreated);
      76          $this->assertSame($user->timecreated, $user->timemodified);
      77          $this->assertSame('0.0.0.0', $user->lastip);
      78  
      79          $record = array(
      80              'auth' => 'email',
      81              'firstname' => 'Žluťoučký',
      82              'lastname' => 'Koníček',
      83              'firstnamephonetic' => 'Zhlutyoucky',
      84              'lastnamephonetic' => 'Koniiczek',
      85              'middlename' => 'Hopper',
      86              'alternatename' => 'horse',
      87              'idnumber' => 'abc1',
      88              'mnethostid' => (string)$CFG->mnet_localhost_id,
      89              'username' => 'konic666',
      90              'password' => 'password1',
      91              'email' => 'email@example.com',
      92              'confirmed' => '1',
      93              'maildisplay' => '1',
      94              'mailformat' => '0',
      95              'maildigest' => '1',
      96              'autosubscribe' => '0',
      97              'trackforums' => '0',
      98              'deleted' => '0',
      99              'timecreated' => '666',
     100          );
     101          $user = $generator->create_user($record);
     102          $this->assertEquals($count + 2, $DB->count_records('user'));
     103          foreach ($record as $k => $v) {
     104              if ($k === 'password') {
     105                  $this->assertTrue(password_verify($v, $user->password));
     106              } else {
     107                  $this->assertSame($v, $user->{$k});
     108              }
     109          }
     110  
     111          $record = array(
     112              'firstname' => 'Some',
     113              'lastname' => 'User',
     114              'idnumber' => 'def',
     115              'username' => 'user666',
     116              'email' => 'email666@example.com',
     117              'deleted' => '1',
     118          );
     119          $user = $generator->create_user($record);
     120          $this->assertEquals($count + 3, $DB->count_records('user'));
     121          $this->assertSame('', $user->idnumber);
     122          $this->assertSame(md5($record['username']), $user->email);
     123          $this->assertEquals(1, $user->deleted);
     124  
     125          // Test generating user with interests.
     126          $user = $generator->create_user(array('interests' => 'Cats, Dogs'));
     127          $userdetails = user_get_user_details($user);
     128          $this->assertSame('Cats, Dogs', $userdetails['interests']);
     129      }
     130  
     131      public function test_create() {
     132          global $DB;
     133  
     134          $this->resetAfterTest(true);
     135          $generator = $this->getDataGenerator();
     136  
     137          $count = $DB->count_records('course_categories');
     138          $category = $generator->create_category();
     139          $this->assertEquals($count+1, $DB->count_records('course_categories'));
     140          $this->assertMatchesRegularExpression('/^Course category \d/', $category->name);
     141          $this->assertSame('', $category->idnumber);
     142          $this->assertMatchesRegularExpression('/^Test course category \d/', $category->description);
     143          $this->assertSame(FORMAT_MOODLE, $category->descriptionformat);
     144  
     145          $count = $DB->count_records('cohort');
     146          $cohort = $generator->create_cohort();
     147          $this->assertEquals($count+1, $DB->count_records('cohort'));
     148          $this->assertEquals(\context_system::instance()->id, $cohort->contextid);
     149          $this->assertMatchesRegularExpression('/^Cohort \d/', $cohort->name);
     150          $this->assertSame('', $cohort->idnumber);
     151          $this->assertMatchesRegularExpression("/^Description for '{$cohort->name}' \\n/", $cohort->description);
     152          $this->assertSame(FORMAT_MOODLE, $cohort->descriptionformat);
     153          $this->assertSame('', $cohort->component);
     154          $this->assertLessThanOrEqual(time(), $cohort->timecreated);
     155          $this->assertSame($cohort->timecreated, $cohort->timemodified);
     156  
     157          $count = $DB->count_records('course');
     158          $course = $generator->create_course();
     159          $this->assertEquals($count+1, $DB->count_records('course'));
     160          $this->assertMatchesRegularExpression('/^Test course \d/', $course->fullname);
     161          $this->assertMatchesRegularExpression('/^tc_\d/', $course->shortname);
     162          $this->assertSame('', $course->idnumber);
     163          $this->assertSame('topics', $course->format);
     164          $this->assertEquals(0, $course->newsitems);
     165          $this->assertEquals(5, course_get_format($course)->get_last_section_number());
     166          $this->assertMatchesRegularExpression('/^Test course \d/', $course->summary);
     167          $this->assertSame(FORMAT_MOODLE, $course->summaryformat);
     168  
     169          $section = $generator->create_course_section(array('course'=>$course->id, 'section'=>3));
     170          $this->assertEquals($course->id, $section->course);
     171  
     172          $course = $generator->create_course(array('tags' => 'Cat, Dog'));
     173          $this->assertEquals(array('Cat', 'Dog'), array_values(\core_tag_tag::get_item_tags_array('core', 'course', $course->id)));
     174  
     175          $scale = $generator->create_scale();
     176          $this->assertNotEmpty($scale);
     177      }
     178  
     179      public function test_create_module() {
     180          global $CFG, $SITE, $DB;
     181  
     182          $this->setAdminUser();
     183  
     184          if (!file_exists("$CFG->dirroot/mod/page/")) {
     185              $this->markTestSkipped('Can not find standard Page module');
     186          }
     187  
     188          $this->resetAfterTest(true);
     189          $generator = $this->getDataGenerator();
     190  
     191          $page = $generator->create_module('page', array('course'=>$SITE->id));
     192          $this->assertNotEmpty($page);
     193          $cm = get_coursemodule_from_instance('page', $page->id, $SITE->id, true);
     194          $this->assertEquals(0, $cm->sectionnum);
     195  
     196          $page = $generator->create_module('page', array('course'=>$SITE->id), array('section'=>3));
     197          $this->assertNotEmpty($page);
     198          $cm = get_coursemodule_from_instance('page', $page->id, $SITE->id, true);
     199          $this->assertEquals(3, $cm->sectionnum);
     200  
     201          $page = $generator->create_module('page', array('course' => $SITE->id, 'tags' => 'Cat, Dog'));
     202          $this->assertEquals(array('Cat', 'Dog'),
     203              array_values(\core_tag_tag::get_item_tags_array('core', 'course_modules', $page->cmid)));
     204  
     205          // Prepare environment to generate modules with all possible options.
     206  
     207          // Enable advanced functionality.
     208          $CFG->enablecompletion = 1;
     209          $CFG->enableavailability = 1;
     210          $CFG->enableoutcomes = 1;
     211          require_once($CFG->libdir.'/gradelib.php');
     212          require_once($CFG->libdir.'/completionlib.php');
     213          require_once($CFG->dirroot.'/rating/lib.php');
     214  
     215          // Create a course with enabled completion.
     216          $course = $generator->create_course(array('enablecompletion' => true));
     217  
     218          // Create new grading category in this course.
     219          $grade_category = new \grade_category();
     220          $grade_category->courseid = $course->id;
     221          $grade_category->fullname = 'Grade category';
     222          $grade_category->insert();
     223  
     224          // Create group and grouping.
     225          $group = $generator->create_group(array('courseid' => $course->id));
     226          $grouping = $generator->create_grouping(array('courseid' => $course->id));
     227          $generator->create_grouping_group(array('groupid' => $group->id, 'groupingid' => $grouping->id));
     228  
     229          // Prepare arrays with properties that we can both use for creating modules and asserting the data in created modules.
     230  
     231          // General properties.
     232          $optionsgeneral = array(
     233              'visible' => 0, // Note: 'visibleold' will always be set to the same value as 'visible'.
     234              'section' => 3, // Note: section will be created if does not exist.
     235              // Module supports FEATURE_IDNUMBER.
     236              'cmidnumber' => 'IDNUM', // Note: alternatively can have key 'idnumber'.
     237              // Module supports FEATURE_GROUPS;
     238              'groupmode' => SEPARATEGROUPS, // Note: will be reset to 0 if course groupmodeforce is set.
     239              // Module supports FEATURE_GROUPINGS.
     240              'groupingid' => $grouping->id,
     241          );
     242  
     243          // In case completion is enabled on site and for course every module can have manual completion.
     244          $featurecompletionmanual = array(
     245              'completion' => COMPLETION_TRACKING_MANUAL, // "Students can manually mark activity as completed."
     246              'completionexpected' => time() + 7 * DAYSECS,
     247          );
     248  
     249          // Automatic completion is possible if module supports FEATURE_COMPLETION_TRACKS_VIEWS or FEATURE_GRADE_HAS_GRADE.
     250          // Note: completionusegrade is stored in DB and can be found in cm_info as 'completiongradeitemnumber' - either NULL or 0.
     251          // Note: module can have more autocompletion rules as defined in moodleform_mod::add_completion_rules().
     252          $featurecompletionautomatic = array(
     253              'completion' => COMPLETION_TRACKING_AUTOMATIC, // "Show activity as complete when conditions are met."
     254              'completionview' => 1, // "Student must view this activity to complete it"
     255              'completionusegrade' => 1, // "Student must receive a grade to complete this activity"
     256          );
     257  
     258          // Module supports FEATURE_RATE:
     259          $featurerate = array(
     260              'assessed' => RATING_AGGREGATE_AVERAGE, // "Aggregate type"
     261              'scale' => 100, // Either max grade or negative number for scale id.
     262              'ratingtime' => 1, // "Restrict ratings to items with dates in this range".
     263              'assesstimestart' => time() - DAYSECS, // Note: Will be ignored if neither 'assessed' nor 'ratingtime' is set.
     264              'assesstimefinish' => time() + DAYSECS, // Note: Will be ignored if neither 'assessed' nor 'ratingtime' is set.
     265          );
     266  
     267          // Module supports FEATURE_GRADE_HAS_GRADE:
     268          $featuregrade = array(
     269              'grade' => 10,
     270              'gradecat' => $grade_category->id, // Note: if $CFG->enableoutcomes is set, this can be set to -1 to automatically create new grade category.
     271          );
     272  
     273          // Now let's create several modules with different options.
     274          $m1 = $generator->create_module('assign',
     275              array('course' => $course->id) +
     276              $optionsgeneral);
     277          $m2 = $generator->create_module('data',
     278              array('course' => $course->id) +
     279              $featurecompletionmanual +
     280              $featurerate);
     281          $m3 = $generator->create_module('assign',
     282              array('course' => $course->id) +
     283              $featurecompletionautomatic +
     284              $featuregrade);
     285  
     286          // We need id of the grading item for the second module to create availability dependency in the 3rd module.
     287          $gradingitem = \grade_item::fetch(array('courseid'=>$course->id, 'itemtype'=>'mod', 'itemmodule' => 'assign', 'iteminstance' => $m3->id));
     288  
     289          // Now prepare option to create the 4th module with an availability condition.
     290          $optionsavailability = array(
     291              'availability' => '{"op":"&","showc":[true],"c":[' .
     292                  '{"type":"date","d":">=","t":' . (time() - WEEKSECS) . '}]}',
     293          );
     294  
     295          // Create module with conditional availability.
     296          $m4 = $generator->create_module('assign',
     297                  array('course' => $course->id) +
     298                  $optionsavailability
     299          );
     300  
     301          // Verifying that everything is generated correctly.
     302          $modinfo = get_fast_modinfo($course->id);
     303          $cm1 = $modinfo->cms[$m1->cmid];
     304          $this->assertEquals($optionsgeneral['visible'], $cm1->visible);
     305          $this->assertEquals($optionsgeneral['section'], $cm1->sectionnum); // Note difference in key.
     306          $this->assertEquals($optionsgeneral['cmidnumber'], $cm1->idnumber); // Note difference in key.
     307          $this->assertEquals($optionsgeneral['groupmode'], $cm1->groupmode);
     308          $this->assertEquals($optionsgeneral['groupingid'], $cm1->groupingid);
     309  
     310          $cm2 = $modinfo->cms[$m2->cmid];
     311          $this->assertEquals($featurecompletionmanual['completion'], $cm2->completion);
     312          $this->assertEquals($featurecompletionmanual['completionexpected'], $cm2->completionexpected);
     313          $this->assertEquals(null, $cm2->completiongradeitemnumber);
     314          // Rating info is stored in the module's table (in our test {data}).
     315          $data = $DB->get_record('data', array('id' => $m2->id));
     316          $this->assertEquals($featurerate['assessed'], $data->assessed);
     317          $this->assertEquals($featurerate['scale'], $data->scale);
     318          $this->assertEquals($featurerate['assesstimestart'], $data->assesstimestart);
     319          $this->assertEquals($featurerate['assesstimefinish'], $data->assesstimefinish);
     320          // No validation for 'ratingtime'. It is only used in to enable/disable assesstime* when adding module.
     321  
     322          $cm3 = $modinfo->cms[$m3->cmid];
     323          $this->assertEquals($featurecompletionautomatic['completion'], $cm3->completion);
     324          $this->assertEquals($featurecompletionautomatic['completionview'], $cm3->completionview);
     325          $this->assertEquals(0, $cm3->completiongradeitemnumber); // Zero instead of default null since 'completionusegrade' was set.
     326          $gradingitem = \grade_item::fetch(array('courseid'=>$course->id, 'itemtype'=>'mod', 'itemmodule' => 'assign', 'iteminstance' => $m3->id));
     327          $this->assertEquals(0, $gradingitem->grademin);
     328          $this->assertEquals($featuregrade['grade'], $gradingitem->grademax);
     329          $this->assertEquals($featuregrade['gradecat'], $gradingitem->categoryid);
     330  
     331          $cm4 = $modinfo->cms[$m4->cmid];
     332          $this->assertEquals($optionsavailability['availability'], $cm4->availability);
     333      }
     334  
     335      public function test_create_block() {
     336          global $CFG;
     337          if (!file_exists("$CFG->dirroot/blocks/online_users/")) {
     338              $this->markTestSkipped('Can not find standard Online users block');
     339          }
     340  
     341          $this->resetAfterTest(true);
     342          $generator = $this->getDataGenerator();
     343  
     344          $page = $generator->create_block('online_users');
     345          $this->assertNotEmpty($page);
     346      }
     347  
     348      public function test_enrol_user() {
     349          global $DB;
     350  
     351          $this->resetAfterTest();
     352  
     353          $selfplugin = enrol_get_plugin('self');
     354          $this->assertNotEmpty($selfplugin);
     355  
     356          $manualplugin = enrol_get_plugin('manual');
     357          $this->assertNotEmpty($manualplugin);
     358  
     359          // Prepare some data.
     360  
     361          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
     362          $this->assertNotEmpty($studentrole);
     363          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
     364          $this->assertNotEmpty($teacherrole);
     365  
     366          $course1 = $this->getDataGenerator()->create_course();
     367          $course2 = $this->getDataGenerator()->create_course();
     368          $course3 = $this->getDataGenerator()->create_course();
     369  
     370          $context1 = \context_course::instance($course1->id);
     371          $context2 = \context_course::instance($course2->id);
     372          $context3 = \context_course::instance($course3->id);
     373  
     374          $user1 = $this->getDataGenerator()->create_user();
     375          $user2 = $this->getDataGenerator()->create_user();
     376          $user3 = $this->getDataGenerator()->create_user();
     377          $user4 = $this->getDataGenerator()->create_user();
     378  
     379          $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'self')));
     380          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
     381          $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
     382          $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
     383  
     384          $this->assertEquals($studentrole->id, $instance1->roleid);
     385          $this->assertEquals($studentrole->id, $instance2->roleid);
     386          $this->assertEquals($studentrole->id, $instance3->roleid);
     387  
     388          $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'manual')));
     389          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     390          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     391          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     392          $maninstance3->roleid = $teacherrole->id;
     393          $DB->update_record('enrol', $maninstance3, array('id'=>$maninstance3->id));
     394  
     395          $this->assertEquals($studentrole->id, $maninstance1->roleid);
     396          $this->assertEquals($studentrole->id, $maninstance2->roleid);
     397          $this->assertEquals($teacherrole->id, $maninstance3->roleid);
     398  
     399          $result = $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
     400          $this->assertTrue($result);
     401          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user1->id)));
     402          $this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id)));
     403  
     404          $result = $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $teacherrole->id, 'manual');
     405          $this->assertTrue($result);
     406          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance2->id, 'userid'=>$user1->id)));
     407          $this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
     408  
     409          $result = $this->getDataGenerator()->enrol_user($user4->id, $course2->id, 'teacher', 'manual');
     410          $this->assertTrue($result);
     411          $this->assertTrue($DB->record_exists('user_enrolments',
     412                  array('enrolid' => $maninstance2->id, 'userid' => $user4->id)));
     413          $this->assertTrue($DB->record_exists('role_assignments',
     414                  array('contextid' => $context2->id, 'userid' => $user4->id, 'roleid' => $teacherrole->id)));
     415  
     416          $result = $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 0, 'manual');
     417          $this->assertTrue($result);
     418          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance3->id, 'userid'=>$user1->id)));
     419          $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user1->id)));
     420  
     421          $result = $this->getDataGenerator()->enrol_user($user2->id, $course1->id, null, 'self');
     422          $this->assertTrue($result);
     423          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user2->id)));
     424          $this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user2->id, 'roleid'=>$studentrole->id)));
     425  
     426          $selfplugin->add_instance($course2, array('status'=>ENROL_INSTANCE_ENABLED, 'roleid'=>$teacherrole->id));
     427          $result = $this->getDataGenerator()->enrol_user($user2->id, $course2->id, null, 'self');
     428          $this->assertFalse($result);
     429  
     430          $DB->delete_records('enrol', array('enrol'=>'self', 'courseid'=>$course3->id));
     431          $result = $this->getDataGenerator()->enrol_user($user2->id, $course3->id, null, 'self');
     432          $this->assertFalse($result);
     433      }
     434  
     435      public function test_create_grade_category() {
     436          global $DB, $CFG;
     437          require_once $CFG->libdir . '/grade/constants.php';
     438  
     439          $this->resetAfterTest(true);
     440          $generator = $this->getDataGenerator();
     441          $course = $generator->create_course();
     442  
     443          // Generate category and make sure number of records in DB table increases.
     444          // Note we only count grade cats with depth > 1 because the course grade category
     445          // is lazily created.
     446          $count = $DB->count_records_select('grade_categories', 'depth <> 1');
     447          $gradecategory = $generator->create_grade_category(array('courseid'=>$course->id));
     448          $this->assertEquals($count+1, $DB->count_records_select('grade_categories', 'depth <> 1'));
     449          $this->assertEquals(2, $gradecategory->depth);
     450          $this->assertEquals($course->id, $gradecategory->courseid);
     451          $this->assertEquals('Grade category 1', $gradecategory->fullname);
     452  
     453          // Generate category and make sure aggregation is set.
     454          $gradecategory = $generator->create_grade_category(
     455                  array('courseid' => $course->id, 'aggregation' => GRADE_AGGREGATE_MEDIAN));
     456          $this->assertEquals(GRADE_AGGREGATE_MEDIAN, $gradecategory->aggregation);
     457  
     458          // Generate category and make sure parent is set.
     459          $gradecategory2 = $generator->create_grade_category(
     460                  array('courseid' => $course->id,
     461                      'parent' => $gradecategory->id));
     462          $this->assertEquals($gradecategory->id, $gradecategory2->parent);
     463      }
     464  
     465      public function test_create_custom_profile_field_category() {
     466          global $DB;
     467  
     468          $this->resetAfterTest();
     469          $generator = $this->getDataGenerator();
     470  
     471          // Insert first category without specified sortorder.
     472          $result = $generator->create_custom_profile_field_category(['name' => 'Frogs']);
     473          $record = $DB->get_record('user_info_category', ['name' => 'Frogs']);
     474          $this->assertEquals(1, $record->sortorder);
     475  
     476          // Also check the return value.
     477          $this->assertEquals(1, $result->sortorder);
     478          $this->assertEquals('Frogs', $result->name);
     479          $this->assertEquals($record->id, $result->id);
     480  
     481          // Insert next category without specified sortorder.
     482          $generator->create_custom_profile_field_category(['name' => 'Zombies']);
     483          $record = $DB->get_record('user_info_category', ['name' => 'Zombies']);
     484          $this->assertEquals(2, $record->sortorder);
     485  
     486          // Insert category with specified sortorder.
     487          $generator->create_custom_profile_field_category(['name' => 'Toads', 'sortorder' => 9]);
     488          $record = $DB->get_record('user_info_category', ['name' => 'Toads']);
     489          $this->assertEquals(9, $record->sortorder);
     490  
     491          // Insert another with unspecified sortorder.
     492          $generator->create_custom_profile_field_category(['name' => 'Werewolves']);
     493          $record = $DB->get_record('user_info_category', ['name' => 'Werewolves']);
     494          $this->assertEquals(10, $record->sortorder);
     495      }
     496  
     497      public function test_create_custom_profile_field() {
     498          global $DB;
     499  
     500          $this->resetAfterTest();
     501          $generator = $this->getDataGenerator();
     502  
     503          // Insert minimal field without specified category.
     504          $field1 = $generator->create_custom_profile_field(
     505                  ['datatype' => 'text', 'shortname' => 'colour', 'name' => 'Colour']);
     506          $record = $DB->get_record('user_info_field', ['shortname' => 'colour']);
     507  
     508          // Check specified values.
     509          $this->assertEquals('Colour', $record->name);
     510          $this->assertEquals('text', $record->datatype);
     511  
     512          // Check sortorder (first in category).
     513          $this->assertEquals(1, $record->sortorder);
     514  
     515          // Check shared defaults for most datatypes.
     516          $this->assertEquals('', $record->description);
     517          $this->assertEquals(0, $record->descriptionformat);
     518          $this->assertEquals(0, $record->required);
     519          $this->assertEquals(0, $record->locked);
     520          $this->assertEquals(PROFILE_VISIBLE_ALL, $record->visible);
     521          $this->assertEquals(0, $record->forceunique);
     522          $this->assertEquals(0, $record->signup);
     523          $this->assertEquals('', $record->defaultdata);
     524          $this->assertEquals(0, $record->defaultdataformat);
     525  
     526          // Check specific defaults for text datatype.
     527          $this->assertEquals(30, $record->param1);
     528          $this->assertEquals(2048, $record->param2);
     529  
     530          // Check the returned value matches the database data.
     531          $this->assertEquals($record, $field1);
     532  
     533          // The category should relate to a new 'testing' category.
     534          $catrecord = $DB->get_record('user_info_category', ['id' => $record->categoryid]);
     535          $this->assertEquals('Testing', $catrecord->name);
     536          $this->assertEquals(1, $catrecord->sortorder);
     537  
     538          // Create another field, this time supplying values for a few of the fields.
     539          $generator->create_custom_profile_field(
     540                  ['datatype' => 'text', 'shortname' => 'brightness', 'name' => 'Brightness',
     541                  'required' => 1, 'forceunique' => 1]);
     542          $record = $DB->get_record('user_info_field', ['shortname' => 'brightness']);
     543  
     544          // Same testing category, next sortorder.
     545          $this->assertEquals($catrecord->id, $record->categoryid);
     546          $this->assertEquals(2, $record->sortorder);
     547  
     548          // Check modified fields.
     549          $this->assertEquals(1, $record->required);
     550          $this->assertEquals(1, $record->forceunique);
     551  
     552          // Create a field in specified category by id or name...
     553          $category = $generator->create_custom_profile_field_category(['name' => 'Amphibians']);
     554          $field3 = $generator->create_custom_profile_field(
     555                  ['datatype' => 'text', 'shortname' => 'frog', 'name' => 'Frog',
     556                  'categoryid' => $category->id]);
     557          $this->assertEquals($category->id, $field3->categoryid);
     558          $this->assertEquals(1, $field3->sortorder);
     559          $field4 = $generator->create_custom_profile_field(
     560                  ['datatype' => 'text', 'shortname' => 'toad', 'name' => 'Toad',
     561                  'category' => 'Amphibians', 'sortorder' => 4]);
     562          $this->assertEquals($category->id, $field4->categoryid);
     563          $this->assertEquals(4, $field4->sortorder);
     564  
     565          // Check defaults for menu, datetime, and checkbox.
     566          $field5 = $generator->create_custom_profile_field(
     567                  ['datatype' => 'menu', 'shortname' => 'cuisine', 'name' => 'Cuisine']);
     568          $this->assertEquals("Yes\nNo", $field5->param1);
     569          $this->assertEquals('No', $field5->defaultdata);
     570          $field6 = $generator->create_custom_profile_field(
     571                  ['datatype' => 'datetime', 'shortname' => 'epoch', 'name' => 'Epoch']);
     572          $this->assertEquals(2010, $field6->param1);
     573          $this->assertEquals(2015, $field6->param2);
     574          $this->assertEquals(1, $field6->param3);
     575          $field7 = $generator->create_custom_profile_field(
     576                  ['datatype' => 'checkbox', 'shortname' => 'areyousure', 'name' => 'Are you sure?']);
     577          $this->assertEquals(0, $field7->defaultdata);
     578      }
     579  }