From b28bb7e8c7e7e420d620f34ebc0c7d74f8dbf319 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 21 Feb 2013 11:30:12 +1100 Subject: [PATCH] MDL-38147 Added coursecatlib_test.php, changed other tests to use coursecat::create() for creating category --- course/tests/courselib_test.php | 48 ---- lib/testing/generator/data_generator.php | 38 +-- lib/tests/blocklib_test.php | 12 +- lib/tests/coursecatlib_test.php | 322 +++++++++++++++++++++++ lib/tests/pagelib_test.php | 11 +- 5 files changed, 337 insertions(+), 94 deletions(-) create mode 100644 lib/tests/coursecatlib_test.php diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 6fc792a2453..f63d8b72dab 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -785,54 +785,6 @@ class courselib_testcase extends advanced_testcase { $this->assertEquals('FROG101 Introduction to pond life', get_course_display_name_for_list($course)); } - public function test_create_course_category() { - global $CFG, $DB; - $this->resetAfterTest(true); - - // Create the category - $data = new stdClass(); - $data->name = 'aaa'; - $data->description = 'aaa'; - $data->idnumber = ''; - - $category1 = create_course_category($data); - - // Initially confirm that base data was inserted correctly - $this->assertEquals($data->name, $category1->name); - $this->assertEquals($data->description, $category1->description); - $this->assertEquals($data->idnumber, $category1->idnumber); - - // sortorder should be blank initially - $this->assertEmpty($category1->sortorder); - - // Calling fix_course_sortorder() should provide a new sortorder - fix_course_sortorder(); - $category1 = $DB->get_record('course_categories', array('id' => $category1->id)); - - $this->assertGreaterThanOrEqual(1, $category1->sortorder); - - // Create two more categories and test the sortorder worked correctly - $data->name = 'ccc'; - $category2 = create_course_category($data); - $this->assertEmpty($category2->sortorder); - - $data->name = 'bbb'; - $category3 = create_course_category($data); - $this->assertEmpty($category3->sortorder); - - // Calling fix_course_sortorder() should provide a new sortorder to give category1, - // category2, category3. New course categories are ordered by id not name - fix_course_sortorder(); - - $category1 = $DB->get_record('course_categories', array('id' => $category1->id)); - $category2 = $DB->get_record('course_categories', array('id' => $category2->id)); - $category3 = $DB->get_record('course_categories', array('id' => $category3->id)); - - $this->assertGreaterThanOrEqual($category1->sortorder, $category2->sortorder); - $this->assertGreaterThanOrEqual($category2->sortorder, $category3->sortorder); - $this->assertGreaterThanOrEqual($category1->sortorder, $category3->sortorder); - } - public function test_move_module_in_course() { global $DB; diff --git a/lib/testing/generator/data_generator.php b/lib/testing/generator/data_generator.php index 425dbf138ca..cf8415e9a55 100644 --- a/lib/testing/generator/data_generator.php +++ b/lib/testing/generator/data_generator.php @@ -232,11 +232,11 @@ EOD; * Create a test course category * @param array|stdClass $record * @param array $options - * @return stdClass course category record + * @return coursecat course category record */ public function create_category($record=null, array $options=null) { global $DB, $CFG; - require_once("$CFG->dirroot/course/lib.php"); + require_once("$CFG->libdir/coursecatlib.php"); $this->categorycount++; $i = $this->categorycount; @@ -247,43 +247,15 @@ EOD; $record['name'] = 'Course category '.$i; } - if (!isset($record['idnumber'])) { - $record['idnumber'] = ''; - } - if (!isset($record['description'])) { $record['description'] = "Test course category $i\n$this->loremipsum"; } - if (!isset($record['descriptionformat'])) { - $record['descriptionformat'] = FORMAT_MOODLE; + if (!isset($record['idnumber'])) { + $record['idnumber'] = ''; } - if (!isset($record['parent'])) { - $record['parent'] = 0; - } - - if (empty($record['parent'])) { - $parent = new stdClass(); - $parent->path = ''; - $parent->depth = 0; - } else { - $parent = $DB->get_record('course_categories', array('id'=>$record['parent']), '*', MUST_EXIST); - } - $record['depth'] = $parent->depth+1; - - $record['sortorder'] = 0; - $record['timemodified'] = time(); - $record['timecreated'] = $record['timemodified']; - - $catid = $DB->insert_record('course_categories', $record); - $path = $parent->path . '/' . $catid; - $DB->set_field('course_categories', 'path', $path, array('id'=>$catid)); - context_coursecat::instance($catid); - - fix_course_sortorder(); - - return $DB->get_record('course_categories', array('id'=>$catid), '*', MUST_EXIST); + return coursecat::create($record); } /** diff --git a/lib/tests/blocklib_test.php b/lib/tests/blocklib_test.php index 471e908cf05..6fede7b045f 100644 --- a/lib/tests/blocklib_test.php +++ b/lib/tests/blocklib_test.php @@ -253,20 +253,12 @@ class moodle_block_manager_test_saving_loading_testcase extends advanced_testcas } public function test_block_not_included_in_different_context() { - global $DB; $this->purge_blocks(); // Set up fixture. $syscontext = context_system::instance(); - $cat = new stdClass(); - $cat->name = 'testcategory'; - $cat->parent = 0; - $cat->depth = 1; - $cat->sortorder = 100; - $cat->timemodified = time(); - $catid = $DB->insert_record('course_categories', $cat); - $DB->set_field('course_categories', 'path', '/' . $catid, array('id' => $catid)); - $fakecontext = context_coursecat::instance($catid); + $cat = $this->getDataGenerator()->create_category(array('name' => 'testcategory')); + $fakecontext = context_coursecat::instance($cat->id); $regionname = 'a-region'; $blockname = $this->get_a_known_block_type(); diff --git a/lib/tests/coursecatlib_test.php b/lib/tests/coursecatlib_test.php new file mode 100644 index 00000000000..81928c0beea --- /dev/null +++ b/lib/tests/coursecatlib_test.php @@ -0,0 +1,322 @@ +. + +/** + * Tests for class coursecat from lib/coursecatlib.php + * + * @package core + * @category phpunit + * @copyright 2013 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/coursecatlib.php'); + +/** + * Functional test for accesslib.php + * + * Note: execution may take many minutes especially on slower servers. + */ +class coursecatlib_testcase extends advanced_testcase { + + var $roles; + + public function setUp() { + parent::setUp(); + $this->resetAfterTest(true); + $user = $this->getDataGenerator()->create_user(); + $this->setUser($user); + } + + protected function get_roleid($context = null) { + global $USER; + if ($context === null) { + $context = context_system::instance(); + } + if (is_object($context)) { + $context = $context->id; + } + if (empty($this->roles)) { + $this->roles = array(); + } + if (empty($this->roles[$USER->id])) { + $this->roles[$USER->id] = array(); + } + if (empty($this->roles[$USER->id][$context])) { + $this->roles[$USER->id][$context] = create_role('Role for '.$USER->id.' in '.$context, 'role'.$USER->id.'-'.$context, '-'); + role_assign($this->roles[$USER->id][$context], $USER->id, $context); + } + return $this->roles[$USER->id][$context]; + } + + protected function assign_capability($capability, $permission = CAP_ALLOW, $contextid = null) { + if ($contextid === null) { + $contextid = context_system::instance(); + } + if (is_object($contextid)) { + $contextid = $contextid->id; + } + assign_capability($capability, $permission, $this->get_roleid($contextid), $contextid, true); + accesslib_clear_all_caches_for_unit_testing(); + } + + public function test_create_coursecat() { + // Create the category + $data = new stdClass(); + $data->name = 'aaa'; + $data->description = 'aaa'; + $data->idnumber = ''; + + $category1 = coursecat::create($data); + + // Initially confirm that base data was inserted correctly + $this->assertEquals($data->name, $category1->name); + $this->assertEquals($data->description, $category1->description); + $this->assertEquals($data->idnumber, $category1->idnumber); + + $this->assertGreaterThanOrEqual(1, $category1->sortorder); + + // Create two more categories and test the sortorder worked correctly + $data->name = 'ccc'; + $category2 = coursecat::create($data); + + $data->name = 'bbb'; + $category3 = coursecat::create($data); + + $this->assertGreaterThan($category1->sortorder, $category2->sortorder); + $this->assertGreaterThan($category2->sortorder, $category3->sortorder); + } + + public function test_name_idnumber_exceptions() { + try { + coursecat::create(array('name' => '')); + $this->fail('Missing category name exception expected in coursecat::create'); + } catch (moodle_exception $e) { + } + $cat1 = coursecat::create(array('name' => 'Cat1', 'idnumber' => '1')); + try { + $cat1->update(array('name' => '')); + $this->fail('Missing category name exception expected in coursecat::update'); + } catch (moodle_exception $e) { + } + try { + coursecat::create(array('name' => 'Cat2', 'idnumber' => '1')); + $this->fail('Duplicate idnumber exception expected in coursecat::create'); + } catch (moodle_exception $e) { + } + $cat2 = coursecat::create(array('name' => 'Cat2', 'idnumber' => '2')); + try { + $cat2->update(array('idnumber' => '1')); + $this->fail('Duplicate idnumber exception expected in coursecat::update'); + } catch (moodle_exception $e) { + } + } + + public function test_visibility() { + $this->assign_capability('moodle/category:viewhiddencategories'); + $this->assign_capability('moodle/category:manage'); + + // create category 1 initially hidden + $category1 = coursecat::create(array('name' => 'Cat1', 'visible' => 0)); + $this->assertEquals(0, $category1->visible); + $this->assertEquals(0, $category1->visibleold); + + // create category 2 initially hidden as a child of hidden category 1 + $category2 = coursecat::create(array('name' => 'Cat2', 'visible' => 0, 'parent' => $category1->id)); + $this->assertEquals(0, $category2->visible); + $this->assertEquals(0, $category2->visibleold); + + // create category 3 initially visible as a child of hidden category 1 + $category3 = coursecat::create(array('name' => 'Cat3', 'visible' => 1, 'parent' => $category1->id)); + $this->assertEquals(0, $category3->visible); + $this->assertEquals(1, $category3->visibleold); + + // show category 1 and make sure that category 2 is hidden and category 3 is visible + $category1->show(); + $this->assertEquals(1, coursecat::get($category1->id)->visible); + $this->assertEquals(0, coursecat::get($category2->id)->visible); + $this->assertEquals(1, coursecat::get($category3->id)->visible); + + // create visible category 4 + $category4 = coursecat::create(array('name' => 'Cat4')); + $this->assertEquals(1, $category4->visible); + $this->assertEquals(1, $category4->visibleold); + + // create visible category 5 as a child of visible category 4 + $category5 = coursecat::create(array('name' => 'Cat5', 'parent' => $category4->id)); + $this->assertEquals(1, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + + // hide category 4 and make sure category 5 is hidden too + $category4->hide(); + $this->assertEquals(0, $category4->visible); + $this->assertEquals(0, $category4->visibleold); + $category5 = coursecat::get($category5->id); // we have to re-read from DB + $this->assertEquals(0, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + + // show category 4 and make sure category 5 is visible too + $category4->show(); + $this->assertEquals(1, $category4->visible); + $this->assertEquals(1, $category4->visibleold); + $category5 = coursecat::get($category5->id); // we have to re-read from DB + $this->assertEquals(1, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + + // move category 5 under hidden category 2 and make sure it became hidden + $category5->change_parent($category2->id); + $this->assertEquals(0, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + + // re-read object for category 5 from DB and check again + $category5 = coursecat::get($category5->id); + $this->assertEquals(0, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + + // tricky one! Move hidden category 5 under visible category ("Top") and make sure it is still hidden + // WHY? Well, different people may expect different behaviour here. So better keep it hidden + $category5->change_parent(0); + $this->assertEquals(0, $category5->visible); + $this->assertEquals(1, $category5->visibleold); + } + + public function test_hierarchy() { + $this->assign_capability('moodle/category:viewhiddencategories'); + $this->assign_capability('moodle/category:manage'); + + $category1 = coursecat::create(array('name' => 'Cat1')); + $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id)); + $category3 = coursecat::create(array('name' => 'Cat3', 'parent' => $category1->id)); + $category4 = coursecat::create(array('name' => 'Cat4', 'parent' => $category2->id)); + + // check function get_children() + $this->assertEquals(array($category2->id, $category3->id), array_keys($category1->get_children())); + // check function get_all_parents() + $this->assertEquals(array($category1->id, $category2->id), array_keys($category4->get_all_parents())); + + // can not move category to itself or to it's children + $this->assertFalse($category1->can_change_parent($category2->id)); + $this->assertFalse($category2->can_change_parent($category2->id)); + // can move category to grandparent + $this->assertTrue($category4->can_change_parent($category1->id)); + + try { + $category2->change_parent($category4->id); + $this->fail('Exception expected - can not move category'); + } catch (moodle_exception $e) { + } + + $category4->change_parent(0); + $this->assertEquals(array(), array_keys($category4->get_all_parents())); + $this->assertEquals(array($category2->id, $category3->id), array_keys($category1->get_children())); + $this->assertEquals(array(), array_keys($category2->get_children())); + } + + public function test_update() { + $category1 = coursecat::create(array('name' => 'Cat1')); + $timecreated = $category1->timemodified; + $this->assertEquals('Cat1', $category1->name); + $this->assertTrue(empty($category1->description)); + sleep(2); + $testdescription = 'This is cat 1 а также русский текст'; + $category1->update(array('description' => $testdescription)); + $this->assertEquals($testdescription, $category1->description); + $category1 = coursecat::get($category1->id); + $this->assertEquals($testdescription, $category1->description); + coursecat::purge_cache(); + $category1 = coursecat::get($category1->id); + $this->assertEquals($testdescription, $category1->description); + + $this->assertGreaterThan($timecreated, $category1->timemodified); + } + + public function test_delete() { + global $DB; + + $this->assign_capability('moodle/category:manage'); + $this->assign_capability('moodle/course:create'); + + $initialcatid = $DB->get_field_sql('SELECT max(id) from {course_categories}'); + + $category1 = coursecat::create(array('name' => 'Cat1')); + $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id)); + $category3 = coursecat::create(array('name' => 'Cat3')); + $category4 = coursecat::create(array('name' => 'Cat4', 'parent' => $category2->id)); + + $course1 = $this->getDataGenerator()->create_course(array('category' => $category2->id)); + $course2 = $this->getDataGenerator()->create_course(array('category' => $category4->id)); + $course3 = $this->getDataGenerator()->create_course(array('category' => $category4->id)); + $course4 = $this->getDataGenerator()->create_course(array('category' => $category1->id)); + + // Now we have + // $category1 + // $category2 + // $category4 + // $course2 + // $course3 + // $course1 + // $course4 + // $category3 + + // Login as another user to test course:delete capability (user who created course can delete it within 24h even without cap) + $this->setUser($this->getDataGenerator()->create_user()); + + // Delete category 2 and move content to category 3 + $this->assertFalse($category2->can_move_content_to($category3->id)); // no luck! + // add necessary capabilities + $this->assign_capability('moodle/course:create', CAP_ALLOW, context_coursecat::instance($category3->id)); + $this->assign_capability('moodle/category:manage'); + $this->assertTrue($category2->can_move_content_to($category3->id)); // hurray! + $category2->delete_move($category3->id); + + // Make sure we have: + // $category1 + // $course4 + // $category3 + // $category4 + // $course2 + // $course3 + // $course1 + + $this->assertNull(coursecat::get($category2->id, IGNORE_MISSING, true)); + $this->assertEquals(array(), $category1->get_children()); + $this->assertEquals(array($category4->id), array_keys($category3->get_children())); + $this->assertEquals($category4->id, $DB->get_field('course', 'category', array('id' => $course2->id))); + $this->assertEquals($category4->id, $DB->get_field('course', 'category', array('id' => $course3->id))); + $this->assertEquals($category3->id, $DB->get_field('course', 'category', array('id' => $course1->id))); + + // Delete category 3 completely + $this->assertFalse($category3->can_delete_full()); // no luck! + // add necessary capabilities + $this->assign_capability('moodle/course:delete', CAP_ALLOW, context_coursecat::instance($category3->id)); + $this->assertTrue($category3->can_delete_full()); // hurray! + $category3->delete_full(); + + // Make sure we have: + // $category1 + // $course4 + + // Note that we also have default 'Miscellaneous' category and default 'site' course + $this->assertEquals(1, $DB->get_field_sql('SELECT count(*) FROM {course_categories} WHERE id > ?', array($initialcatid))); + $this->assertEquals($category1->id, $DB->get_field_sql('SELECT max(id) FROM {course_categories}')); + $this->assertEquals(1, $DB->get_field_sql('SELECT count(*) FROM {course} WHERE id <> ?', array(SITEID))); + $this->assertEquals(array('id' => $course4->id, 'category' => $category1->id), + (array)$DB->get_record_sql('SELECT id, category from {course} where id <> ?', array(SITEID))); + } +} \ No newline at end of file diff --git a/lib/tests/pagelib_test.php b/lib/tests/pagelib_test.php index a7158e71c8c..95bbbc50acb 100644 --- a/lib/tests/pagelib_test.php +++ b/lib/tests/pagelib_test.php @@ -380,26 +380,31 @@ class moodle_page_categories_test extends advanced_testcase { } public function test_set_category_top_level() { + global $DB; // Setup fixture $cat = $this->getDataGenerator()->create_category(); + $catdbrecord = $DB->get_record('course_categories', array('id' => $cat->id)); // Exercise SUT $this->testpage->set_category_by_id($cat->id); // Validate - $this->assertEquals($cat, $this->testpage->category); + $this->assertEquals($catdbrecord, $this->testpage->category); $this->assertSame(context_coursecat::instance($cat->id), $this->testpage->context); } public function test_set_nested_categories() { + global $DB; // Setup fixture $topcat = $this->getDataGenerator()->create_category(); + $topcatdbrecord = $DB->get_record('course_categories', array('id' => $topcat->id)); $subcat = $this->getDataGenerator()->create_category(array('parent'=>$topcat->id)); + $subcatdbrecord = $DB->get_record('course_categories', array('id' => $subcat->id)); // Exercise SUT $this->testpage->set_category_by_id($subcat->id); // Validate $categories = $this->testpage->categories; $this->assertEquals(2, count($categories)); - $this->assertEquals($topcat, array_pop($categories)); - $this->assertEquals($subcat, array_pop($categories)); + $this->assertEquals($topcatdbrecord, array_pop($categories)); + $this->assertEquals($subcatdbrecord, array_pop($categories)); } }