moodle/lib/simpletest/testconditionlib.php

378 lines
15 KiB
PHP

<?php
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.');
}
require_once($CFG->dirroot . '/lib/conditionlib.php');
class conditionlib_test extends UnitTestCaseUsingDatabase {
public static $includecoverage = array('lib/conditionlib.php');
public $conditionlib_tables = array(
'lib' => array(
'context', 'capabilities', 'role',
'role_capabilities', 'role_assignments',
'course_categories', 'course',
'modules',
'course_sections', 'course_modules',
'course_modules_availability',
'course_modules_completion',
'grade_items', 'grade_grades'),
'mod/resource' => array(
'resource'));
public $oldcfg;
public function setUp() {
global $CFG;
parent::setUp();
$this->oldcfg=clone $CFG;
$CFG->enableavailability=true;
$CFG->enablecompletion=true;
$this->switch_to_test_db(); // All operations until end of test method will happen in test DB
foreach ($this->conditionlib_tables as $dir => $tables) {
$this->create_test_tables($tables, $dir); // Create tables
}
$this->fill_records(); // Add common stuff needed by various test methods
}
/**
* Method called after each test method. Doesn't do anything extraordinary except restore the global $DB to the real one.
*/
public function tearDown() {
global $CFG;
$CFG->enableavailability=$this->oldcfg->enableavailability;
$CFG->enablecompletion=$this->oldcfg->enablecompletion;
parent::tearDown(); // All the test tables created in setUp will be dropped by this
}
private function fill_records() {
global $DB;
// We need the resource modules record available
$DB->insert_record('modules', (object)array('name' => 'resource'));
// We (get_fast_modinfo) need some capabilities present
$DB->insert_record('capabilities', (object)array('name' => 'moodle/course:viewhiddenactivities',
'contextlevel' => CONTEXT_COURSE));
}
function test_constructor() {
global $DB,$CFG;
$cm=new stdClass;
// Test records
$id=$DB->insert_record('course_modules',(object)array(
'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,'course'=>64));
// no ID
try {
$test=new condition_info($cm);
$this->fail();
} catch(coding_exception $e) {
}
// no other data
$cm->id=$id;
$test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
$this->assertEqual(
(object)array('id'=>$id,'showavailability'=>1,
'availablefrom'=>17,'availableuntil'=>398,'course'=>64,
'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
$test->get_full_course_module());
// just the course_modules stuff; check it doesn't request that from db
$cm->showavailability=0;
$cm->availablefrom=2;
$cm->availableuntil=74;
$cm->course=38;
$test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE);
$this->assertEqual(
(object)array('id'=>$id,'showavailability'=>0,
'availablefrom'=>2,'availableuntil'=>74,'course'=>38,
'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
$test->get_full_course_module());
// Now let's add some actual grade/completion conditions
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'sourcecmid'=>42,
'requiredcompletion'=>2
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'sourcecmid'=>666,
'requiredcompletion'=>1
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'gradeitemid'=>37,
'grademin'=>5.5
));
$cm=(object)array('id'=>$id);
$test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
$fullcm=$test->get_full_course_module();
$this->assertEqual(array(42=>2,666=>1),$fullcm->conditionscompletion);
$this->assertEqual(array(37=>(object)array('min'=>5.5,'max'=>null,'name'=>'!missing')),
$fullcm->conditionsgrade);
}
private function make_course() {
global $DB;
$categoryid=$DB->insert_record('course_categories',(object)array('name'=>'conditionlibtest'));
return $DB->insert_record('course',(object)array(
'fullname'=>'Condition test','shortname'=>'CT1',
'category'=>$categoryid,'enablecompletion'=>1));
}
private function make_course_module($courseid,$params=array()) {
global $DB;
static $moduleid=0;
if(!$moduleid) {
$moduleid=$DB->get_field('modules','id',array('name'=>'resource'));
}
$rid=$DB->insert_record('resource',(object)array('course'=>$courseid,
'name'=>'xxx','alltext'=>'','popup'=>''));
$settings=(object)array(
'course'=>$courseid,'module'=>$moduleid,'instance'=>$rid);
foreach($params as $name=>$value) {
$settings->{$name}=$value;
}
return $DB->insert_record('course_modules',$settings);
}
private function make_section($courseid,$cmids,$sectionnum=0) {
global $DB;
$DB->insert_record('course_sections',(object)array(
'course'=>$courseid,'sequence'=>implode(',',$cmids),'section'=>$sectionnum));
}
function test_modinfo() {
global $DB;
// Let's make a course
$courseid=$this->make_course();
// Now let's make a couple modules on that course
$cmid1=$this->make_course_module($courseid,array(
'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,
'completion'=>COMPLETION_TRACKING_MANUAL));
$cmid2=$this->make_course_module($courseid,array(
'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
$this->make_section($courseid,array($cmid1,$cmid2));
// Add a fake grade item
$gradeitemid=$DB->insert_record('grade_items',(object)array(
'courseid'=>$courseid,'itemname'=>'frog'));
// One of the modules has grade and completion conditions, other doesn't
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$cmid2,
'sourcecmid'=>$cmid1,
'requiredcompletion'=>1
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$cmid2,
'gradeitemid'=>$gradeitemid,
'grademin'=>5.5
));
// Okay sweet, now get modinfo
$modinfo=get_fast_modinfo($DB->get_record('course',array('id'=>$courseid)));
// Test basic data
$this->assertEqual(1,$modinfo->cms[$cmid1]->showavailability);
$this->assertEqual(17,$modinfo->cms[$cmid1]->availablefrom);
$this->assertEqual(398,$modinfo->cms[$cmid1]->availableuntil);
$this->assertEqual(0,$modinfo->cms[$cmid2]->showavailability);
$this->assertEqual(0,$modinfo->cms[$cmid2]->availablefrom);
$this->assertEqual(0,$modinfo->cms[$cmid2]->availableuntil);
// Test condition arrays
$this->assertEqual(array(),$modinfo->cms[$cmid1]->conditionscompletion);
$this->assertEqual(array(),$modinfo->cms[$cmid1]->conditionsgrade);
$this->assertEqual(array($cmid1=>1),
$modinfo->cms[$cmid2]->conditionscompletion);
$this->assertEqual(array($gradeitemid=>(object)array('min'=>5.5,'max'=>null,'name'=>'frog')),
$modinfo->cms[$cmid2]->conditionsgrade);
}
function test_add_and_remove() {
global $DB;
// Make course and module
$courseid=$this->make_course();
$cmid=$this->make_course_module($courseid,array(
'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
$this->make_section($courseid,array($cmid));
// Check it has no conditions
$test1=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test1->get_full_course_module();
$this->assertEqual(array(),$cm->conditionscompletion);
$this->assertEqual(array(),$cm->conditionsgrade);
// Add conditions of each type
$test1->add_completion_condition(13,3);
$this->assertEqual(array(13=>3),$cm->conditionscompletion);
$test1->add_grade_condition(666,0.4,null,true);
$this->assertEqual(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
$cm->conditionsgrade);
// Check they were really added in db
$test2=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test2->get_full_course_module();
$this->assertEqual(array(13=>3),$cm->conditionscompletion);
$this->assertEqual(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
$cm->conditionsgrade);
// Wipe conditions
$test2->wipe_conditions();
$this->assertEqual(array(),$cm->conditionscompletion);
$this->assertEqual(array(),$cm->conditionsgrade);
// Check they were really wiped
$test3=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test3->get_full_course_module();
$this->assertEqual(array(),$cm->conditionscompletion);
$this->assertEqual(array(),$cm->conditionsgrade);
}
function test_is_available() {
global $DB,$USER;
$courseid=$this->make_course();
// No conditions
$cmid=$this->make_course_module($courseid);
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertTrue($ci->is_available($text,false,0));
$this->assertEqual('',$text);
// Time (from)
$time=time()+100;
$cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertFalse($ci->is_available($text));
$this->assert(new PatternExpectation(
'/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/'),$text);
$time=time()-100;
$cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertTrue($ci->is_available($text));
$this->assertEqual('',$text);
$this->assert(new PatternExpectation(
'/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/'),$ci->get_full_information());
// Time (until)
$cmid=$this->make_course_module($courseid,array('availableuntil'=>time()-100));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertFalse($ci->is_available($text));
$this->assertEqual('',$text);
// Completion
$oldid=$cmid;
$cmid=$this->make_course_module($courseid);
$this->make_section($courseid,array($oldid,$cmid));
$oldcm=$DB->get_record('course_modules',array('id'=>$oldid));
$oldcm->completion=COMPLETION_TRACKING_MANUAL;
$DB->update_record('course_modules',$oldcm);
$ci=new condition_info((object)array('id'=>$cmid),CONDITION_MISSING_EVERYTHING);
$ci->add_completion_condition($oldid,COMPLETION_COMPLETE);
$this->assertFalse($ci->is_available($text,false));
$this->assertEqual(get_string('requires_completion_1','condition','xxx'),$text);
$completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
$completion->update_state($oldcm,COMPLETION_COMPLETE);
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
$this->assertFalse($ci->is_available($text,false,$USER->id+1));
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
$completion->update_state($oldcm,COMPLETION_INCOMPLETE);
$this->assertFalse($ci->is_available($text));
$ci->wipe_conditions();
$ci->add_completion_condition($oldid,COMPLETION_INCOMPLETE);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
$this->assertTrue($ci->is_available($text,false,$USER->id+1));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text,true));
// Grade
$ci->wipe_conditions();
// Add a fake grade item
$gradeitemid=$DB->insert_record('grade_items',(object)array(
'courseid'=>$courseid,'itemname'=>'frog'));
// Add a condition on a value existing...
$ci->add_grade_condition($gradeitemid,null,null,true);
$this->assertFalse($ci->is_available($text));
$this->assertEqual(get_string('requires_grade_any','condition','frog'),$text);
// Fake it existing
$DB->insert_record('grade_grades',(object)array(
'itemid'=>$gradeitemid,'userid'=>$USER->id,'finalgrade'=>3.78));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text,true));
// Now require that user gets more than 3.78001
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3.78001,null,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEqual(get_string('requires_grade_min','condition','frog'),$text);
// ...just on 3.78...
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3.78,null,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...less than 3.78
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,null,3.78,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEqual(get_string('requires_grade_max','condition','frog'),$text);
// ...less than 3.78001
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,null,3.78001,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that includes it
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3,4,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that doesn't include it
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,4,5,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEqual(get_string('requires_grade_range','condition','frog'),$text);
}
}