diff --git a/admin/tool/uploadcourse/tests/course_test.php b/admin/tool/uploadcourse/tests/course_test.php new file mode 100644 index 00000000000..ebf5c586b01 --- /dev/null +++ b/admin/tool/uploadcourse/tests/course_test.php @@ -0,0 +1,771 @@ +. + +/** + * File containing tests for the course class. + * + * @package tool_uploadcourse + * @copyright 2013 Frédéric Massart + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/processor.php'); +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/course.php'); +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/helper.php'); +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); +require_once($CFG->libdir . '/csvlib.class.php'); +require_once($CFG->libdir . '/coursecatlib.php'); + +/** + * Course test case. + */ +class tool_uploadcourse_course_testcase extends advanced_testcase { + + public function test_proceed_without_prepare() { + $this->resetAfterTest(true); + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + $data = array(); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->setExpectedException('coding_exception'); + $co->proceed(); + } + + public function test_proceed_when_prepare_failed() { + $this->resetAfterTest(true); + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + $data = array(); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + $this->setExpectedException('moodle_exception'); + $co->proceed(); + } + + public function test_create() { + global $DB; + $this->resetAfterTest(true); + + // Existing course. + $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1', 'summary' => 'Yay!')); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + + // Try to add a new course. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $data = array('shortname' => 'newcourse', 'fullname' => 'New course', 'summary' => 'New', 'category' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'newcourse'))); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'newcourse'))); + + // Try to add a new course, that already exists. + $coursecount = $DB->count_records('course', array()); + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $data = array('shortname' => 'c1', 'fullname' => 'C1FN', 'summary' => 'C1', 'category' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + $this->assertEquals($coursecount, $DB->count_records('course', array())); + $this->assertNotEquals('C1', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + + // Try to add new with shortname incrementation. + $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; + $data = array('shortname' => 'c1', 'fullname' => 'C1FN', 'summary' => 'C1', 'category' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c2'))); + } + + public function test_delete() { + global $DB; + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(); + $c2 = $this->getDataGenerator()->create_course(); + + $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'DoesNotExist'))); + + $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + + // Try delete when option not available. + $importoptions = array('candelete' => false); + $data = array('shortname' => $c1->shortname, 'delete' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); + + // Try delete when not requested. + $importoptions = array('candelete' => true); + $data = array('shortname' => $c1->shortname, 'delete' => 0); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); + + // Try delete when requested. + $importoptions = array('candelete' => true); + $data = array('shortname' => $c1->shortname, 'delete' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertFalse($DB->record_exists('course', array('shortname' => $c1->shortname))); + $this->assertTrue($DB->record_exists('course', array('shortname' => $c2->shortname))); + + // Try deleting non-existing record, this should not fail. + $data = array('shortname' => 'DoesNotExist', 'delete' => 1); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + } + + public function test_update() { + global $DB; + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1')); + + // Try to add with existing shortnames, not allowing creation, and updating nothing. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + $data = array('shortname' => 'c1', 'fullname' => 'New fullname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + + // Try to add with non-existing shortnames. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'DoesNotExist', 'fullname' => 'New fullname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + + // Try a proper update. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'c1', 'fullname' => 'New fullname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + // $this->assertTrue($co->prepare()); + $co->prepare(); + $co->proceed(); + $this->assertEquals('New fullname', $DB->get_field_select('course', 'fullname', 'shortname = :s', array('s' => 'c1'))); + + // Try a proper update with defaults. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; + $data = array('shortname' => 'c1', 'fullname' => 'Another fullname'); + $defaults = array('fullname' => 'Not this one', 'summary' => 'Awesome summary'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('Another fullname', $DB->get_field_select('course', 'fullname', 'shortname = :s', array('s' => 'c1'))); + $this->assertEquals('Awesome summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + + // Try a proper update missing only. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS; + $DB->set_field('course', 'summary', '', array('shortname' => 'c1')); + $this->assertEquals('', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + $data = array('shortname' => 'c1', 'summary' => 'Fill in summary'); + $defaults = array('summary' => 'Do not use this summary'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('Fill in summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + + // Try a proper update missing only using defaults. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS; + $DB->set_field('course', 'summary', '', array('shortname' => 'c1')); + $this->assertEquals('', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + $data = array('shortname' => 'c1'); + $defaults = array('summary' => 'Use this summary'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('Use this summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); + } + + public function test_data_saved() { + global $DB; + $this->resetAfterTest(true); + + // Create. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + $data = array( + 'shortname' => 'c1', + 'fullname' => 'Fullname', + 'category' => '1', + 'visible' => '0', + 'startdate' => '8 June 1990', + 'idnumber' => '123abc', + 'summary' => 'Summary', + 'format' => 'weeks', + 'theme' => 'afterburner', + 'lang' => 'en', + 'newsitems' => '7', + 'showgrades' => '0', + 'showreports' => '1', + 'legacyfiles' => '1', + 'maxbytes' => '1234', + 'groupmode' => '2', + 'groupmodeforce' => '1', + 'enablecompletion' => '1', + + 'role_teacher' => 'Knight', + 'role_manager' => 'Jedi', + + 'enrolment_1' => 'guest', + 'enrolment_2' => 'self', + 'enrolment_2_roleid' => '1', + 'enrolment_3' => 'manual', + 'enrolment_3_disable' => '1', + ); + + + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $course = $DB->get_record('course', array('shortname' => 'c1')); + $ctx = context_course::instance($course->id); + + $this->assertEquals($data['fullname'], $course->fullname); + $this->assertEquals($data['category'], $course->category); + $this->assertEquals($data['visible'], $course->visible); + $this->assertEquals(mktime(0, 0, 0, 6, 8, 1990), $course->startdate); + $this->assertEquals($data['idnumber'], $course->idnumber); + $this->assertEquals($data['summary'], $course->summary); + $this->assertEquals($data['format'], $course->format); + $this->assertEquals($data['theme'], $course->theme); + $this->assertEquals($data['lang'], $course->lang); + $this->assertEquals($data['newsitems'], $course->newsitems); + $this->assertEquals($data['showgrades'], $course->showgrades); + $this->assertEquals($data['showreports'], $course->showreports); + $this->assertEquals($data['legacyfiles'], $course->legacyfiles); + $this->assertEquals($data['maxbytes'], $course->maxbytes); + $this->assertEquals($data['groupmode'], $course->groupmode); + $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); + $this->assertEquals($data['enablecompletion'], $course->enablecompletion); + + // Roles. + $roleids = array(); + $roles = get_all_roles(); + foreach ($roles as $role) { + $roleids[$role->shortname] = $role->id; + } + $this->assertEquals('Knight', $DB->get_field_select('role_names', 'name', + 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); + $this->assertEquals('Jedi', $DB->get_field_select('role_names', 'name', + 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); + + // Enrolment methods. + $enroldata = array(); + $instances = enrol_get_instances($course->id, false); + $this->assertCount(3, $instances); + foreach ($instances as $instance) { + $enroldata[$instance->enrol] = $instance; + } + + $this->assertNotEmpty($enroldata['guest']); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['guest']->status); + $this->assertNotEmpty($enroldata['self']); + $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); + $this->assertNotEmpty($enroldata['manual']); + $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['manual']->status); + + // Update existing course. + $cat = $this->getDataGenerator()->create_category(); + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array( + 'shortname' => 'c1', + 'fullname' => 'Fullname 2', + 'category' => $cat->id, + 'visible' => '1', + 'startdate' => '11 June 1984', + 'idnumber' => 'changeidn', + 'summary' => 'Summary 2', + 'format' => 'topics', + 'theme' => 'clean', + 'lang' => '', + 'newsitems' => '2', + 'showgrades' => '1', + 'showreports' => '0', + 'legacyfiles' => '0', + 'maxbytes' => '4321', + 'groupmode' => '1', + 'groupmodeforce' => '0', + 'enablecompletion' => '0', + + 'role_teacher' => 'Teacher', + 'role_manager' => 'Manager', + + 'enrolment_1' => 'guest', + 'enrolment_1_disable' => '1', + 'enrolment_2' => 'self', + 'enrolment_2_roleid' => '2', + 'enrolment_3' => 'manual', + 'enrolment_3_delete' => '1', + ); + + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + $course = $DB->get_record('course', array('shortname' => 'c1')); + $ctx = context_course::instance($course->id); + + $this->assertEquals($data['fullname'], $course->fullname); + $this->assertEquals($data['category'], $course->category); + $this->assertEquals($data['visible'], $course->visible); + $this->assertEquals(mktime(0, 0, 0, 6, 11, 1984), $course->startdate); + $this->assertEquals($data['idnumber'], $course->idnumber); + $this->assertEquals($data['summary'], $course->summary); + $this->assertEquals($data['format'], $course->format); + $this->assertEquals($data['theme'], $course->theme); + $this->assertEquals($data['lang'], $course->lang); + $this->assertEquals($data['newsitems'], $course->newsitems); + $this->assertEquals($data['showgrades'], $course->showgrades); + $this->assertEquals($data['showreports'], $course->showreports); + $this->assertEquals($data['legacyfiles'], $course->legacyfiles); + $this->assertEquals($data['maxbytes'], $course->maxbytes); + $this->assertEquals($data['groupmode'], $course->groupmode); + $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); + $this->assertEquals($data['enablecompletion'], $course->enablecompletion); + + // Roles. + $roleids = array(); + $roles = get_all_roles(); + foreach ($roles as $role) { + $roleids[$role->shortname] = $role->id; + } + $this->assertEquals('Teacher', $DB->get_field_select('role_names', 'name', + 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); + $this->assertEquals('Manager', $DB->get_field_select('role_names', 'name', + 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); + + // Enrolment methods. + $enroldata = array(); + $instances = enrol_get_instances($course->id, false); + $this->assertCount(2, $instances); + foreach ($instances as $instance) { + $enroldata[$instance->enrol] = $instance; + } + + $this->assertNotEmpty($enroldata['guest']); + $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['guest']->status); + $this->assertNotEmpty($enroldata['self']); + $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); + } + + public function test_default_data_saved() { + global $DB; + $this->resetAfterTest(true); + + // Create. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; + $data = array( + 'shortname' => 'c1', + ); + $defaultdata = array( + 'fullname' => 'Fullname', + 'category' => '1', + 'visible' => '0', + 'startdate' => '8 June 1990', + 'idnumber' => '123abc', + 'summary' => 'Summary', + 'format' => 'weeks', + 'theme' => 'afterburner', + 'lang' => 'en', + 'newsitems' => '7', + 'showgrades' => '0', + 'showreports' => '1', + 'legacyfiles' => '1', + 'maxbytes' => '1234', + 'groupmode' => '2', + 'groupmodeforce' => '1', + 'enablecompletion' => '1', + ); + + + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $course = $DB->get_record('course', array('shortname' => 'c1')); + $ctx = context_course::instance($course->id); + + $this->assertEquals($defaultdata['fullname'], $course->fullname); + $this->assertEquals($defaultdata['category'], $course->category); + $this->assertEquals($defaultdata['visible'], $course->visible); + $this->assertEquals(mktime(0, 0, 0, 6, 8, 1990), $course->startdate); + $this->assertEquals($defaultdata['idnumber'], $course->idnumber); + $this->assertEquals($defaultdata['summary'], $course->summary); + $this->assertEquals($defaultdata['format'], $course->format); + $this->assertEquals($defaultdata['theme'], $course->theme); + $this->assertEquals($defaultdata['lang'], $course->lang); + $this->assertEquals($defaultdata['newsitems'], $course->newsitems); + $this->assertEquals($defaultdata['showgrades'], $course->showgrades); + $this->assertEquals($defaultdata['showreports'], $course->showreports); + $this->assertEquals($defaultdata['legacyfiles'], $course->legacyfiles); + $this->assertEquals($defaultdata['maxbytes'], $course->maxbytes); + $this->assertEquals($defaultdata['groupmode'], $course->groupmode); + $this->assertEquals($defaultdata['groupmodeforce'], $course->groupmodeforce); + $this->assertEquals($defaultdata['enablecompletion'], $course->enablecompletion); + + // Update. + $cat = $this->getDataGenerator()->create_category(); + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; + $data = array( + 'shortname' => 'c1', + ); + $defaultdata = array( + 'fullname' => 'Fullname 2', + 'category' => $cat->id, + 'visible' => '1', + 'startdate' => '11 June 1984', + 'idnumber' => 'changedid', + 'summary' => 'Summary 2', + 'format' => 'topics', + 'theme' => 'clean', + 'lang' => '', + 'newsitems' => '2', + 'showgrades' => '1', + 'showreports' => '0', + 'legacyfiles' => '0', + 'maxbytes' => '1111', + 'groupmode' => '1', + 'groupmodeforce' => '0', + 'enablecompletion' => '0', + ); + + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $course = $DB->get_record('course', array('shortname' => 'c1')); + $ctx = context_course::instance($course->id); + + $this->assertEquals($defaultdata['fullname'], $course->fullname); + $this->assertEquals($defaultdata['category'], $course->category); + $this->assertEquals($defaultdata['visible'], $course->visible); + $this->assertEquals(mktime(0, 0, 0, 6, 11, 1984), $course->startdate); + $this->assertEquals($defaultdata['idnumber'], $course->idnumber); + $this->assertEquals($defaultdata['summary'], $course->summary); + $this->assertEquals($defaultdata['format'], $course->format); + $this->assertEquals($defaultdata['theme'], $course->theme); + $this->assertEquals($defaultdata['lang'], $course->lang); + $this->assertEquals($defaultdata['newsitems'], $course->newsitems); + $this->assertEquals($defaultdata['showgrades'], $course->showgrades); + $this->assertEquals($defaultdata['showreports'], $course->showreports); + $this->assertEquals($defaultdata['legacyfiles'], $course->legacyfiles); + $this->assertEquals($defaultdata['maxbytes'], $course->maxbytes); + $this->assertEquals($defaultdata['groupmode'], $course->groupmode); + $this->assertEquals($defaultdata['groupmodeforce'], $course->groupmodeforce); + $this->assertEquals($defaultdata['enablecompletion'], $course->enablecompletion); + } + + public function test_rename() { + global $DB; + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1')); + + // Cannot rename when creating. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'c1', 'rename' => 'newshortname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + + // Cannot rename when creating. + $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'c1', 'rename' => 'newshortname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + + // Error when not allowed to rename the course. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => false); + $data = array('shortname' => 'c1', 'rename' => 'newshortname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + + // Can rename when updating. + $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'c1', 'rename' => 'newshortname'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('newshortname', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); + + // Can rename when updating. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'newshortname', 'rename' => 'newshortname2'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('newshortname2', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); + + // Error when course does not exist. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'DoesNotExist', 'rename' => 'c1'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + + // Renaming still updates the other values. + $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; + $importoptions = array('canrename' => true); + $data = array('shortname' => 'newshortname2', 'rename' => 'c1', 'fullname' => 'Another fullname!'); + $defaultdata = array('summary' => 'New summary!'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata, $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertEquals('c1', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); + $this->assertEquals('New summary!', $DB->get_field_select('course', 'summary', 'id = :id', array('id' => $c1->id))); + $this->assertEquals('Another fullname!', $DB->get_field_select('course', 'fullname', 'id = :id', array('id' => $c1->id))); + } + + public function test_restore_course() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $c1 = $this->getDataGenerator()->create_course(); + $c1f1 = $this->getDataGenerator()->create_module('forum', array('course' => $c1->id)); + + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'A1', 'templatecourse' => $c1->shortname, 'summary' => 'A', 'category' => 1, 'fullname' => 'A1'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + $course = $DB->get_record('course', array('shortname' => 'A1')); + $modinfo = get_fast_modinfo($course); + $found = false; + foreach ($modinfo->get_cms() as $cmid => $cm) { + if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { + $found = true; + break; + } + } + $this->assertTrue($found); + + // Restore the time limit to prevent warning. + set_time_limit(0); + } + + public function test_restore_file() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $c1 = $this->getDataGenerator()->create_course(); + $c1f1 = $this->getDataGenerator()->create_module('forum', array('course' => $c1->id)); + + // Restore from a file, checking that the file takes priority over the templatecourse. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'A1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz', + 'summary' => 'A', 'category' => 1, 'fullname' => 'A1', 'templatecourse' => $c1->shortname); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + $course = $DB->get_record('course', array('shortname' => 'A1')); + $modinfo = get_fast_modinfo($course); + $found = false; + foreach ($modinfo->get_cms() as $cmid => $cm) { + if ($cm->modname == 'glossary' && $cm->name == 'Imported Glossary') { + $found = true; + } else if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { + // We should not find this! + $this->assertTrue(false); + } + } + $this->assertTrue($found); + + // Restore the time limit to prevent warning. + set_time_limit(0); + } + + /** + * Testing the reset on groups, group members and enrolments. + */ + public function test_reset() { + global $DB; + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(); + $c1ctx = context_course::instance($c1->id); + $studentrole = $DB->get_record('role', array('shortname' => 'student')); + $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); + + $u1 = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($u1->id, $c1->id, $studentrole->id); + $this->assertCount(1, get_enrolled_users($c1ctx)); + + $g1 = $this->getDataGenerator()->create_group(array('courseid' => $c1->id)); + $this->getDataGenerator()->create_group_member(array('groupid' => $g1->id, 'userid' => $u1->id)); + $this->assertEquals(1, $DB->count_records('groups', array('courseid' => $c1->id))); + $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + + // Wrong mode. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'reset' => '1'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); + $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + $this->assertCount(1, get_enrolled_users($c1ctx)); + + // Reset not allowed. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'reset' => '1'); + $importoptions = array('canreset' => false); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertFalse($co->prepare()); + $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); + $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + $this->assertCount(1, get_enrolled_users($c1ctx)); + + // Reset allowed but not requested. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'reset' => '0'); + $importoptions = array('canreset' => true); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); + $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + $this->assertCount(1, get_enrolled_users($c1ctx)); + + // Reset passed as a default parameter, should not be taken in account. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname); + $importoptions = array('canreset' => true); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array('reset' => 1), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); + $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + $this->assertCount(1, get_enrolled_users($c1ctx)); + + // Reset executed from data. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'reset' => 1); + $importoptions = array('canreset' => true); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertFalse($DB->record_exists('groups', array('id' => $g1->id))); + $this->assertFalse($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); + $this->assertCount(0, get_enrolled_users($c1ctx)); + + // Reset executed from import option. + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'reset' => 0); + $importoptions = array('reset' => 1, 'canreset' => true); + $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); + + $g1 = $this->getDataGenerator()->create_group(array('courseid' => $c1->id)); + $this->getDataGenerator()->create_group_member(array('groupid' => $g1->id, 'userid' => $u1->id)); + $this->assertEquals(1, $DB->count_records('groups', array('courseid' => $c1->id))); + $this->assertTrue($co->prepare()); + $co->proceed(); + $this->assertFalse($DB->record_exists('groups', array('id' => $g1->id))); + } + + public function test_create_bad_category() { + $this->resetAfterTest(true); + + // Ensure fails when category cannot be resolved upon creation. + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'c1', 'summary' => 'summary', 'fullname' => 'FN', 'category' => 'Wrong cat'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors()); + + // Ensure fails when category cannot be resolved upon update. + $c1 = $this->getDataGenerator()->create_course(); + $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => $c1->shortname, 'category' => 'Wrong cat'); + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertFalse($co->prepare()); + $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors()); + } + + public function test_enrolment_data() { + $this->resetAfterTest(true); + + $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; + $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; + $data = array('shortname' => 'c1', 'summary' => 'S', 'fullname' => 'FN', 'category' => '1'); + $data['enrolment_1'] = 'manual'; + $data['enrolment_1_role'] = 'teacher'; + $data['enrolment_1_startdate'] = '2nd July 2013'; + $data['enrolment_1_enddate'] = '2nd August 2013'; + $data['enrolment_1_enrolperiod'] = '10 days'; + $co = new tool_uploadcourse_course($mode, $updatemode, $data); + $this->assertTrue($co->prepare()); + $co->proceed(); + + // Enrolment methods. + $enroldata = array(); + $instances = enrol_get_instances($co->get_id(), false); + foreach ($instances as $instance) { + $enroldata[$instance->enrol] = $instance; + } + + $this->assertNotEmpty($enroldata['manual']); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['manual']->status); + $this->assertEquals(strtotime($data['enrolment_1_startdate']), $enroldata['manual']->enrolstartdate); + $this->assertEquals(strtotime('1970-01-01 GMT + ' . $data['enrolment_1_enrolperiod']), $enroldata['manual']->enrolperiod); + $this->assertEquals(strtotime('12th July 2013'), $enroldata['manual']->enrolenddate); + } +} diff --git a/admin/tool/uploadcourse/tests/fixtures/backup.mbz b/admin/tool/uploadcourse/tests/fixtures/backup.mbz new file mode 100644 index 00000000000..25da1743542 Binary files /dev/null and b/admin/tool/uploadcourse/tests/fixtures/backup.mbz differ diff --git a/admin/tool/uploadcourse/tests/helper_test.php b/admin/tool/uploadcourse/tests/helper_test.php new file mode 100644 index 00000000000..e36728ed097 --- /dev/null +++ b/admin/tool/uploadcourse/tests/helper_test.php @@ -0,0 +1,353 @@ +. + +/** + * File containing tests for the helper. + * + * @package tool_uploadcourse + * @copyright 2013 Frédéric Massart + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/helper.php'); +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); + +/** + * Helper test case. + */ +class tool_uploadcourse_helper_testcase extends advanced_testcase { + + function test_generate_shortname() { + $data = (object) array('fullname' => 'Ah Bh Ch 01 02 03', 'idnumber' => 'ID123'); + + $this->assertSame($data->fullname, tool_uploadcourse_helper::generate_shortname($data, '%f')); + $this->assertSame($data->idnumber, tool_uploadcourse_helper::generate_shortname($data, '%i')); + $this->assertSame('AH BH CH', tool_uploadcourse_helper::generate_shortname($data, '%+8f')); + $this->assertSame('id123', tool_uploadcourse_helper::generate_shortname($data, '%-i')); + $this->assertSame('[Ah Bh Ch] = ID123', tool_uploadcourse_helper::generate_shortname($data, '[%8f] = %i')); + } + + function test_get_course_formats() { + $result = tool_uploadcourse_helper::get_course_formats(); + $this->assertSame(array_keys(get_plugin_list('format')), $result); + // Should be similar as first result, as cached. + $this->assertSame($result, tool_uploadcourse_helper::get_course_formats()); + } + + function test_get_enrolment_data() { + $this->resetAfterTest(true); + $data = array( + 'enrolment_1' => 'unknown', + 'enrolment_1_foo' => '1', + 'enrolment_1_bar' => '2', + 'enrolment_2' => 'self', + 'enrolment_2_delete' => '1', + 'enrolment_2_foo' => 'a', + 'enrolment_2_bar' => '1', + 'enrolment_3' => 'manual', + 'enrolment_3_disable' => '2', + 'enrolment_3_foo' => 'b', + 'enrolment_3_bar' => '2', + 'enrolment_4' => 'database', + 'enrolment_4_foo' => 'x', + 'enrolment_4_bar' => '3', + 'enrolment_5_test3' => 'test3', + 'enrolment_5_test2' => 'test2', + 'enrolment_5_test1' => 'test1', + 'enrolment_5' => 'flatfile', + ); + $expected = array( + 'self' => array( + 'delete' => '1', + 'foo' => 'a', + 'bar' => '1', + ), + 'manual' => array( + 'disable' => '2', + 'foo' => 'b', + 'bar' => '2', + ), + 'database' => array( + 'foo' => 'x', + 'bar' => '3', + ), + 'flatfile' => array( + 'test3' => 'test3', + 'test2' => 'test2', + 'test1' => 'test1', + ) + ); + $this->assertSame(tool_uploadcourse_helper::get_enrolment_data($data), $expected); + } + + function test_get_enrolment_plugins() { + $this->resetAfterTest(true); + $actual = tool_uploadcourse_helper::get_enrolment_plugins(); + $this->assertSame(array_keys(enrol_get_plugins(false)), array_keys($actual)); + // This should be identical as cached. + $secondactual = tool_uploadcourse_helper::get_enrolment_plugins(); + $this->assertSame($actual, $secondactual); + } + + function test_get_restore_content_dir() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + $c1 = $this->getDataGenerator()->create_course(); + $c2 = $this->getDataGenerator()->create_course((object) array('shortname' => 'Yay')); + + // Creating backup file. + $bc = new backup_controller(backup::TYPE_1COURSE, $c1->id, backup::FORMAT_MOODLE, + backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2); + $bc->execute_plan(); + $result = $bc->get_results(); + $this->assertTrue(isset($result['backup_destination'])); + $c1backupfile = $result['backup_destination']->copy_content_to_temp(); + $bc->destroy(); + + // Creating backup file. + $bc = new backup_controller(backup::TYPE_1COURSE, $c2->id, backup::FORMAT_MOODLE, + backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2); + $bc->execute_plan(); + $result = $bc->get_results(); + $this->assertTrue(isset($result['backup_destination'])); + $c2backupfile = $result['backup_destination']->copy_content_to_temp(); + $bc->destroy(); + + // Checking restore dir. + $dir = tool_uploadcourse_helper::get_restore_content_dir($c1backupfile, null); + $bcinfo = backup_general_helper::get_backup_information($dir); + $this->assertEquals($bcinfo->original_course_id, $c1->id); + $this->assertEquals($bcinfo->original_course_fullname, $c1->fullname); + + // Do it again, it should be the same directory. + $dir2 = tool_uploadcourse_helper::get_restore_content_dir($c1backupfile, null); + $this->assertEquals($dir, $dir2); + + // Get the second course. + $dir = tool_uploadcourse_helper::get_restore_content_dir($c2backupfile, null); + $bcinfo = backup_general_helper::get_backup_information($dir); + $this->assertEquals($bcinfo->original_course_id, $c2->id); + $this->assertEquals($bcinfo->original_course_fullname, $c2->fullname); + + + // Checking with a shortname. + $dir = tool_uploadcourse_helper::get_restore_content_dir(null, $c1->shortname); + $bcinfo = backup_general_helper::get_backup_information($dir); + $this->assertEquals($bcinfo->original_course_id, $c1->id); + $this->assertEquals($bcinfo->original_course_fullname, $c1->fullname); + + // Do it again, it should be the same directory. + $dir2 = tool_uploadcourse_helper::get_restore_content_dir(null, $c1->shortname); + $this->assertEquals($dir, $dir2); + + // Get the second course. + $dir = tool_uploadcourse_helper::get_restore_content_dir(null, $c2->shortname); + $bcinfo = backup_general_helper::get_backup_information($dir); + $this->assertEquals($bcinfo->original_course_id, $c2->id); + $this->assertEquals($bcinfo->original_course_fullname, $c2->fullname); + + // Restore the time limit to prevent warning. + set_time_limit(0); + } + + public function test_get_role_ids() { + $this->getDataGenerator(); + // Mimic function result. + $expected = array(); + $roles = get_all_roles(); + foreach ($roles as $role) { + $expected[$role->shortname] = $role->id; + } + + $actual = tool_uploadcourse_helper::get_role_ids(); + $this->assertSame($actual, $expected); + + // Check cache. + $this->assertSame($actual, tool_uploadcourse_helper::get_role_ids()); + } + + public function test_get_role_names() { + $this->resetAfterTest(true); + + create_role('Villain', 'villain', 'The bad guys'); + $data = array( + 'role_student' => 'Padawan', + 'role_teacher' => 'Guardian', + 'role_editingteacher' => 'Knight', + 'role_manager' => 'Master', + 'role_villain' => 'Jabba the Hutt', + 'role_android' => 'R2D2', + ); + + // Get the role IDs, but need to force the cache reset as a new role is defined. + $roleids = tool_uploadcourse_helper::get_role_ids(true); + + $expected = array( + 'role_' . $roleids['student'] => 'Padawan', + 'role_' . $roleids['teacher'] => 'Guardian', + 'role_' . $roleids['editingteacher'] => 'Knight', + 'role_' . $roleids['manager'] => 'Master', + 'role_' . $roleids['villain'] => 'Jabba the Hutt', + ); + + $actual = tool_uploadcourse_helper::get_role_names($data); + $this->assertSame($actual, $expected); + } + + public function test_increment_idnumber() { + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(array('idnumber' => 'C1')); + $c2 = $this->getDataGenerator()->create_course(array('idnumber' => 'C2')); + $c3 = $this->getDataGenerator()->create_course(array('idnumber' => 'Yo')); + + $this->assertEquals('C3', tool_uploadcourse_helper::increment_idnumber('C1')); + $this->assertEquals('Yo_2', tool_uploadcourse_helper::increment_idnumber('Yo')); + $this->assertEquals('DoesNotExist', tool_uploadcourse_helper::increment_idnumber('DoesNotExist')); + } + + public function test_increment_shortname() { + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'C1')); + $c2 = $this->getDataGenerator()->create_course(array('shortname' => 'C2')); + $c3 = $this->getDataGenerator()->create_course(array('shortname' => 'Yo')); + + // FYI: increment_shortname assumes that the course exists, and so increment the shortname immediately. + $this->assertEquals('C3', tool_uploadcourse_helper::increment_shortname('C1')); + $this->assertEquals('Yo_2', tool_uploadcourse_helper::increment_shortname('Yo')); + $this->assertEquals('DoesNotExist_2', tool_uploadcourse_helper::increment_shortname('DoesNotExist')); + } + + public function test_resolve_category() { + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_category(array('name' => 'First level')); + $c2 = $this->getDataGenerator()->create_category(array('name' => 'Second level', 'parent' => $c1->id)); + $c3 = $this->getDataGenerator()->create_category(array('idnumber' => 'C3')); + + $data = array( + 'category' => $c1->id, + 'category_path' => $c1->name . ' / ' . $c2->name, + 'category_idnumber' => $c3->idnumber, + ); + + $this->assertEquals($c1->id, tool_uploadcourse_helper::resolve_category($data)); + unset($data['category']); + $this->assertEquals($c3->id, tool_uploadcourse_helper::resolve_category($data)); + unset($data['category_idnumber']); + $this->assertEquals($c2->id, tool_uploadcourse_helper::resolve_category($data)); + + // Adding unexisting data. + $data['category_idnumber'] = 1234; + $this->assertEquals($c2->id, tool_uploadcourse_helper::resolve_category($data)); + $data['category'] = 1234; + $this->assertEquals($c2->id, tool_uploadcourse_helper::resolve_category($data)); + $data['category_path'] = 'Not exist'; + $this->assertEmpty(tool_uploadcourse_helper::resolve_category($data)); + } + + public function test_resolve_category_by_idnumber() { + $this->resetAfterTest(true); + + $c1 = $this->getDataGenerator()->create_category(array('idnumber' => 'C1')); + $c2 = $this->getDataGenerator()->create_category(array('idnumber' => 'C2')); + + // Doubled for cache check. + $this->assertEquals($c1->id, tool_uploadcourse_helper::resolve_category_by_idnumber('C1')); + $this->assertEquals($c1->id, tool_uploadcourse_helper::resolve_category_by_idnumber('C1')); + $this->assertEquals($c2->id, tool_uploadcourse_helper::resolve_category_by_idnumber('C2')); + $this->assertEquals($c2->id, tool_uploadcourse_helper::resolve_category_by_idnumber('C2')); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_idnumber('DoesNotExist')); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_idnumber('DoesNotExist')); + } + + public function test_resolve_category_by_path() { + $this->resetAfterTest(true); + + $cat1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 1')); + $cat1_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 1.1', 'parent' => $cat1->id)); + $cat1_1_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 1.1.1', 'parent' => $cat1_1->id)); + $cat1_1_2 = $this->getDataGenerator()->create_category(array('name' => 'Cat 1.1.2', 'parent' => $cat1_1->id)); + $cat1_2 = $this->getDataGenerator()->create_category(array('name' => 'Cat 1.2', 'parent' => $cat1->id)); + + $cat2 = $this->getDataGenerator()->create_category(array('name' => 'Cat 2')); + $cat2_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 2.1', 'parent' => $cat2->id, 'visible' => false)); + $cat2_1_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 2.1.1', 'parent' => $cat2_1->id)); + $cat2_1_2 = $this->getDataGenerator()->create_category(array('name' => 'Cat 2.1.2', 'parent' => $cat2_1->id)); + $cat2_2 = $this->getDataGenerator()->create_category(array('name' => 'Cat 2.2', 'parent' => $cat2->id)); + + $cat3 = $this->getDataGenerator()->create_category(array('name' => 'Cat 3')); + $cat3_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 3.1 Doubled', 'parent' => $cat3->id)); + $cat3_1b = $this->getDataGenerator()->create_category(array('name' => 'Cat 3.1 Doubled', 'parent' => $cat3->id)); + $cat3_1_1 = $this->getDataGenerator()->create_category(array('name' => 'Cat 3.1.1', 'parent' => $cat3_1->id)); + $cat3_fakedouble = $this->getDataGenerator()->create_category(array('name' => 'Cat 3.1.1', 'parent' => $cat3->id)); + + // Existing categories. Doubled for cache testing. + $path = array('Cat 1'); + $this->assertEquals($cat1->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat1->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 1', 'Cat 1.1', 'Cat 1.1.2'); + $this->assertEquals($cat1_1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat1_1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 1', 'Cat 1.2'); + $this->assertEquals($cat1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 2'); + $this->assertEquals($cat2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + // Hidden category. + $path = array('Cat 2', 'Cat 2.1'); + $this->assertEquals($cat2_1->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat2_1->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + // Hidden parent. + $path = array('Cat 2', 'Cat 2.1', 'Cat 2.1.2'); + $this->assertEquals($cat2_1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat2_1_2->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + + // Does not exist. + $path = array('No cat 3', 'Cat 1.2'); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 2', 'Cat 2.x'); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + + // Name conflict. + $path = array('Cat 3', 'Cat 3.1 Doubled'); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 3', 'Cat 3.1 Doubled', 'Cat 3.1.1'); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEmpty(tool_uploadcourse_helper::resolve_category_by_path($path)); + + $path = array('Cat 3', 'Cat 3.1.1'); + $this->assertEquals($cat3_fakedouble->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + $this->assertEquals($cat3_fakedouble->id, tool_uploadcourse_helper::resolve_category_by_path($path)); + } +} diff --git a/admin/tool/uploadcourse/tests/processor_test.php b/admin/tool/uploadcourse/tests/processor_test.php new file mode 100644 index 00000000000..1f61bfa7fb3 --- /dev/null +++ b/admin/tool/uploadcourse/tests/processor_test.php @@ -0,0 +1,170 @@ +. + +/** + * File containing tests for the processor. + * + * @package tool_uploadcourse + * @copyright 2013 Frédéric Massart + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/processor.php'); +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/course.php'); +require_once($CFG->dirroot . '/admin/tool/uploadcourse/classes/helper.php'); +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); +require_once($CFG->libdir . '/csvlib.class.php'); + +/** + * Processor test case. + */ +class tool_uploadcourse_processor_testcase extends advanced_testcase { + + public function test_basic() { + global $DB; + $this->resetAfterTest(true); + + $content = array( + "shortname,fullname,summary", + "c1,Course 1,Course 1 summary", + "c2,Course 2,Course 2 summary", + ); + $content = implode("\n", $content); + $iid = csv_import_reader::get_new_iid('uploadcourse'); + $cir = new csv_import_reader($iid, 'uploadcourse'); + $cir->load_csv_content($content, 'utf-8', 'comma'); + $cir->init(); + + $options = array('mode' => tool_uploadcourse_processor::MODE_CREATE_ALL); + $defaults = array('category' => '1'); + + $p = new tool_uploadcourse_processor($cir, $options, $defaults); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c2'))); + $p->execute(); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); + $this->assertTrue($DB->record_exists('course', array('shortname' => 'c2'))); + } + + public function test_restore_template_course() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $c1 = $this->getDataGenerator()->create_course(); + $c1f1 = $this->getDataGenerator()->create_module('forum', array('course' => $c1->id)); + + $content = array( + "shortname,fullname,summary", + "c2,Course 2,Course 2 summary", + ); + $content = implode("\n", $content); + $iid = csv_import_reader::get_new_iid('uploadcourse'); + $cir = new csv_import_reader($iid, 'uploadcourse'); + $cir->load_csv_content($content, 'utf-8', 'comma'); + $cir->init(); + + $options = array('mode' => tool_uploadcourse_processor::MODE_CREATE_NEW, 'templatecourse' => $c1->shortname); + $defaults = array('category' => '1'); + + $p = new tool_uploadcourse_processor($cir, $options, $defaults); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c2'))); + $p->execute(); + $c2 = $DB->get_record('course', array('shortname' => 'c2')); + $modinfo = get_fast_modinfo($c2); + $found = false; + foreach ($modinfo->get_cms() as $cmid => $cm) { + if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { + $found = true; + break; + } + } + $this->assertTrue($found); + + // Restore the time limit to prevent warning. + set_time_limit(0); + } + + public function test_restore_restore_file() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $content = array( + "shortname,fullname,summary", + "c1,Course 1,Course 1 summary", + ); + $content = implode("\n", $content); + $iid = csv_import_reader::get_new_iid('uploadcourse'); + $cir = new csv_import_reader($iid, 'uploadcourse'); + $cir->load_csv_content($content, 'utf-8', 'comma'); + $cir->init(); + + $options = array( + 'mode' => tool_uploadcourse_processor::MODE_CREATE_NEW, + 'restorefile' => __DIR__ . '/fixtures/backup.mbz', + 'templatecourse' => 'DoesNotExist' // Restorefile takes priority. + ); + $defaults = array('category' => '1'); + + $p = new tool_uploadcourse_processor($cir, $options, $defaults); + $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); + $p->execute(); + $c1 = $DB->get_record('course', array('shortname' => 'c1')); + $modinfo = get_fast_modinfo($c1); + $found = false; + foreach ($modinfo->get_cms() as $cmid => $cm) { + if ($cm->modname == 'glossary' && $cm->name == 'Imported Glossary') { + $found = true; + break; + } + } + $this->assertTrue($found); + + // Restore the time limit to prevent warning. + set_time_limit(0); + } + + public function test_shortname_template() { + global $DB; + $this->resetAfterTest(true); + + $content = array( + "shortname,fullname,summary,idnumber", + ",Course 1,C1 Summary,ID123", + ); + $content = implode("\n", $content); + $iid = csv_import_reader::get_new_iid('uploadcourse'); + $cir = new csv_import_reader($iid, 'uploadcourse'); + $cir->load_csv_content($content, 'utf-8', 'comma'); + $cir->init(); + + $options = array('mode' => tool_uploadcourse_processor::MODE_CREATE_NEW, 'shortnametemplate' => '%i: %f'); + $defaults = array('category' => '1'); + + $p = new tool_uploadcourse_processor($cir, $options, $defaults); + $this->assertFalse($DB->record_exists('course', array('idnumber' => 'ID123'))); + $p->execute(); + $this->assertTrue($DB->record_exists('course', array('idnumber' => 'ID123'))); + $c = $DB->get_record('course', array('idnumber' => 'ID123')); + $this->assertEquals('ID123: Course 1', $c->shortname); + } + +}