Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/simpletest/testcompletionlib.php
Go to the documentation of this file.
00001 <?php
00002 if (!defined('MOODLE_INTERNAL')) {
00003     die('Direct access to this script is forbidden.');
00004 }
00005 require_once($CFG->libdir.'/completionlib.php');
00006 
00007 global $DB;
00008 Mock::generate(get_class($DB), 'mock_database');
00009 Mock::generate('moodle_transaction', 'mock_transaction');
00010 
00011 Mock::generatePartial('completion_info','completion_cutdown',
00012     array('delete_all_state','get_tracked_users','update_state',
00013         'internal_get_grade_state','is_enabled','get_data','internal_get_state','internal_set_data'));
00014 Mock::generatePartial('completion_info','completion_cutdown2',
00015     array('is_enabled','get_data','internal_get_state','internal_set_data'));
00016 Mock::generatePartial('completion_info','completion_cutdown3',
00017     array('internal_get_grade_state'));
00018 
00019 class fake_recordset implements Iterator {
00020     var $closed;
00021     var $values,$index;
00022 
00023     function fake_recordset($values) {
00024         $this->values=$values;
00025         $this->index=0;
00026     }
00027 
00028     function current() {
00029         return $this->values[$this->index];
00030     }
00031 
00032     function key() {
00033         return $this->values[$this->index];
00034     }
00035 
00036     function next() {
00037         $this->index++;
00038     }
00039 
00040     function rewind() {
00041         $this->index=0;
00042     }
00043 
00044     function valid() {
00045         return count($this->values) > $this->index;
00046     }
00047 
00048     function close() {
00049         $this->closed=true;
00050     }
00051 
00052     function was_closed() {
00053         return $this->closed;
00054     }
00055 }
00056 
00061 class TimeModifiedExpectation extends SimpleExpectation {
00062     private $otherfields;
00063 
00067     function TimeModifiedExpectation($otherfields) {
00068         $this->otherfields=$otherfields;
00069     }
00070 
00071     function test($thing) {
00072         $thingfields=(array)$thing;
00073         foreach($this->otherfields as $key=>$value) {
00074             if(!array_key_exists($key,$thingfields)) {
00075                 return false;
00076             }
00077             if($thingfields[$key]!=$value) {
00078                 return false;
00079             }
00080         }
00081 
00082         $timedifference=time()-$thing->timemodified;
00083         return ($timedifference < 2 && $timedifference>=0);
00084     }
00085 
00086     function testMessage($thing) {
00087         return "Object does not match fields/time requirement";
00088     }
00089 }
00090 
00091 class completionlib_test extends UnitTestCaseUsingDatabase {
00092 
00093     public static $includecoverage = array('lib/completionlib.php');
00094     var $realdb,$realcfg,$realsession,$realuser;
00095 
00096     function setUp() {
00097         global $DB,$CFG,$SESSION,$USER;
00098         $this->realdb=$DB;
00099         $this->realcfg=$CFG;
00100         $this->realsession=$SESSION;
00101         $this->prevuser=$USER;
00102         $DB=new mock_database();
00103         $CFG=clone($this->realcfg);
00104         $CFG->prefix='test_';
00105         $CFG->enablecompletion=COMPLETION_ENABLED;
00106         $SESSION=new stdClass();
00107         $USER=(object)array('id'=>314159);
00108     }
00109 
00110     function tearDown() {
00111         global $DB,$CFG,$SESSION,$USER;
00112         $DB=$this->realdb;
00113         $CFG=$this->realcfg;
00114         $SESSION=$this->realsession;
00115         $USER=$this->prevuser;
00116     }
00117 
00118     function test_is_enabled() {
00119         global $CFG;
00120 
00121         // Config alone
00122         $CFG->enablecompletion=COMPLETION_DISABLED;
00123         $this->assertEqual(COMPLETION_DISABLED,completion_info::is_enabled_for_site());
00124         $CFG->enablecompletion=COMPLETION_ENABLED;
00125         $this->assertEqual(COMPLETION_ENABLED,completion_info::is_enabled_for_site());
00126 
00127         // Course
00128         //$course=new stdClass;
00129         $course=(object)array('id'=>13);
00130         $c=new completion_info($course);
00131         $course->enablecompletion=COMPLETION_DISABLED;
00132         $this->assertEqual(COMPLETION_DISABLED,$c->is_enabled());
00133         $course->enablecompletion=COMPLETION_ENABLED;
00134         $this->assertEqual(COMPLETION_ENABLED,$c->is_enabled());
00135         $CFG->enablecompletion=COMPLETION_DISABLED;
00136         $this->assertEqual(COMPLETION_DISABLED,$c->is_enabled());
00137 
00138         // Course and CM
00139         $cm=new stdClass;
00140         $cm->completion=COMPLETION_TRACKING_MANUAL;
00141         $this->assertEqual(COMPLETION_DISABLED,$c->is_enabled($cm));
00142         $CFG->enablecompletion=COMPLETION_ENABLED;
00143         $course->enablecompletion=COMPLETION_DISABLED;
00144         $this->assertEqual(COMPLETION_DISABLED,$c->is_enabled($cm));
00145         $course->enablecompletion=COMPLETION_ENABLED;
00146         $this->assertEqual(COMPLETION_TRACKING_MANUAL,$c->is_enabled($cm));
00147         $cm->completion=COMPLETION_TRACKING_NONE;
00148         $this->assertEqual(COMPLETION_TRACKING_NONE,$c->is_enabled($cm));
00149         $cm->completion=COMPLETION_TRACKING_AUTOMATIC;
00150         $this->assertEqual(COMPLETION_TRACKING_AUTOMATIC,$c->is_enabled($cm));
00151     }
00152 
00153     function test_update_state() {
00154         $c=new completion_cutdown2();
00155         $c->__construct((object)array('id'=>42));
00156         $cm=(object)array('id'=>13,'course'=>42);
00157 
00158         // Not enabled, should do nothing
00159         $c->expectAt(0,'is_enabled',array($cm));
00160         $c->setReturnValueAt(0,'is_enabled',false);
00161         $c->update_state($cm);
00162 
00163         // Enabled, but current state is same as possible result, do nothing
00164         $current=(object)array('completionstate'=>COMPLETION_COMPLETE);
00165         $c->expectAt(1,'is_enabled',array($cm));
00166         $c->setReturnValueAt(1,'is_enabled',true);
00167 
00168         $c->expectAt(0,'get_data',array($cm,false,0));
00169         $c->setReturnValueAt(0,'get_data',$current);
00170         $c->update_state($cm,COMPLETION_COMPLETE);
00171 
00172         // Enabled, but current state is a specific one and new state is just
00173         // omplete, so do nothing
00174         $current->completionstate=COMPLETION_COMPLETE_PASS;
00175         $c->expectAt(2,'is_enabled',array($cm));
00176         $c->setReturnValueAt(2,'is_enabled',true);
00177         $c->expectAt(1,'get_data',array($cm,false,0));
00178         $c->setReturnValueAt(1,'get_data',$current);
00179         $c->update_state($cm,COMPLETION_COMPLETE);
00180 
00181         // Manual, change state (no change)
00182         $cm->completion=COMPLETION_TRACKING_MANUAL;
00183         $current->completionstate=COMPLETION_COMPLETE;
00184         $c->expectAt(3,'is_enabled',array($cm));
00185         $c->setReturnValueAt(3,'is_enabled',true);
00186         $c->expectAt(2,'get_data',array($cm,false,0));
00187         $c->setReturnValueAt(2,'get_data',$current);
00188         $c->update_state($cm,COMPLETION_COMPLETE);
00189 
00190         // Manual, change state (change)
00191         $c->expectAt(4,'is_enabled',array($cm));
00192         $c->setReturnValueAt(4,'is_enabled',true);
00193         $c->expectAt(3,'get_data',array($cm,false,0));
00194         $c->setReturnValueAt(3,'get_data',$current);
00195         $c->expectAt(0,'internal_set_data',array($cm,
00196             new TimeModifiedExpectation(array('completionstate'=>COMPLETION_INCOMPLETE))));
00197         $c->update_state($cm,COMPLETION_INCOMPLETE);
00198 
00199         // Auto, change state
00200         $cm->completion=COMPLETION_TRACKING_AUTOMATIC;
00201         $c->expectAt(5,'is_enabled',array($cm));
00202         $c->setReturnValueAt(5,'is_enabled',true);
00203         $c->expectAt(4,'get_data',array($cm,false,0));
00204         $c->setReturnValueAt(4,'get_data',$current);
00205         $c->expectAt(0,'internal_get_state',array($cm,0,$current));
00206         $c->setReturnValueAt(0,'internal_get_state',COMPLETION_COMPLETE_PASS);
00207         $c->expectAt(1,'internal_set_data',array($cm,
00208             new TimeModifiedExpectation(array('completionstate'=>COMPLETION_COMPLETE_PASS))));
00209         $c->update_state($cm,COMPLETION_COMPLETE_PASS);
00210 
00211         $c->tally();
00212     }
00213 
00214     function test_internal_get_state() {
00215         global $DB;
00216 
00217         $c=new completion_cutdown3();
00218         $c->__construct((object)array('id'=>42));
00219         $cm=(object)array('id'=>13,'course'=>42,'completiongradeitemnumber'=>null);
00220 
00221         // If view is required, but they haven't viewed it yet
00222         $cm->completionview=COMPLETION_VIEW_REQUIRED;
00223         $current=(object)array('viewed'=>COMPLETION_NOT_VIEWED);
00224         $this->assertEqual(COMPLETION_INCOMPLETE,$c->internal_get_state($cm,123,$current));
00225 
00226         // OK set view not required
00227         $cm->completionview=COMPLETION_VIEW_NOT_REQUIRED;
00228 
00229         // Test not getting module name
00230         $cm->modname='label';
00231         $this->assertEqual(COMPLETION_COMPLETE,$c->internal_get_state($cm,123,$current));
00232 
00233         // Test getting module name
00234         $cm->module=13;
00235         unset($cm->modname);
00236         $DB->expectOnce('get_field',array('modules','name',array('id'=>13)));
00237         $DB->setReturnValue('get_field','label');
00238         $this->assertEqual(COMPLETION_COMPLETE,$c->internal_get_state($cm,123,$current));
00239 
00240         // Note: This function is not fully tested (including kind of the main
00241         // part) because:
00242         // * the grade_item/grade_grade calls are static and can't be mocked
00243         // * the plugin_supports call is static and can't be mocked
00244 
00245         $DB->tally();
00246         $c->tally();
00247     }
00248 
00249     function test_set_module_viewed() {
00250         $c=new completion_cutdown();
00251         $c->__construct((object)array('id'=>42));
00252         $cm=(object)array('id'=>13,'course'=>42);
00253 
00254         // Not tracking completion, should do nothing
00255         $cm->completionview=COMPLETION_VIEW_NOT_REQUIRED;
00256         $c->set_module_viewed($cm);
00257 
00258         // Tracking completion but completion is disabled, should do nothing
00259         $cm->completionview=COMPLETION_VIEW_REQUIRED;
00260         $c->expectAt(0,'is_enabled',array($cm));
00261         $c->setReturnValueAt(0,'is_enabled',false);
00262         $c->set_module_viewed($cm);
00263 
00264         // Now it's enabled, we expect it to get data. If data already has
00265         // viewed, still do nothing
00266         $c->expectAt(1,'is_enabled',array($cm));
00267         $c->setReturnValueAt(1,'is_enabled',true);
00268         $c->expectAt(0,'get_data',array($cm,0));
00269         $hasviewed=(object)array('viewed'=>COMPLETION_VIEWED);
00270         $c->setReturnValueAt(0,'get_data',$hasviewed);
00271         $c->set_module_viewed($cm);
00272 
00273         // OK finally one that hasn't been viewed, now it should set it viewed
00274         // and update state
00275         $c->expectAt(2,'is_enabled',array($cm));
00276         $c->setReturnValueAt(2,'is_enabled',true);
00277         $notviewed=(object)array('viewed'=>COMPLETION_NOT_VIEWED);
00278         $c->expectAt(1,'get_data',array($cm,1337));
00279         $c->setReturnValueAt(1,'get_data',$notviewed);
00280         $c->expectOnce('internal_set_data',array($cm,$hasviewed));
00281         $c->expectOnce('update_state',array($cm,COMPLETION_COMPLETE,1337));
00282         $c->set_module_viewed($cm,1337);
00283 
00284         $c->tally();
00285     }
00286 
00287     function test_count_user_data() {
00288         global $DB;
00289         $course=(object)array('id'=>13);
00290         $cm=(object)array('id'=>42);
00291         $DB->setReturnValue('get_field_sql',666);
00292         $DB->expectOnce('get_field_sql',array(new IgnoreWhitespaceExpectation("SELECT
00293     COUNT(1)
00294 FROM
00295     {course_modules_completion}
00296 WHERE
00297     coursemoduleid=? AND completionstate<>0"),array(42)));
00298         $c=new completion_info($course);
00299         $this->assertEqual(666,$c->count_user_data($cm));
00300 
00301         $DB->tally();
00302     }
00303 
00304     function test_delete_all_state() {
00305         global $DB,$SESSION;
00306         $course=(object)array('id'=>13);
00307         $cm=(object)array('id'=>42,'course'=>13);
00308         $c=new completion_info($course);
00309         // Check it works ok without data in session
00310         $DB->expectAt(0,'delete_records',
00311             array('course_modules_completion',array('coursemoduleid'=>42)));
00312         $c->delete_all_state($cm);
00313 
00314         // Build up a session to check it deletes the right bits from it
00315         // (and not other bits)
00316         $SESSION->completioncache=array();
00317         $SESSION->completioncache[13]=array();
00318         $SESSION->completioncache[13][42]='foo';
00319         $SESSION->completioncache[13][43]='foo';
00320         $SESSION->completioncache[14]=array();
00321         $SESSION->completioncache[14][42]='foo';
00322         $DB->expectAt(1,'delete_records',
00323             array('course_modules_completion',array('coursemoduleid'=>42)));
00324         $c->delete_all_state($cm);
00325         $this->assertEqual(array(13=>array(43=>'foo'),14=>array(42=>'foo')),
00326             $SESSION->completioncache);
00327 
00328         $DB->tally();
00329     }
00330 
00331     function test_reset_all_state() {
00332         global $DB;
00333         $c=new completion_cutdown();
00334         $c->__construct((object)array('id'=>42));
00335 
00336         $cm=(object)array('id'=>13,'course'=>42,
00337             'completion'=>COMPLETION_TRACKING_AUTOMATIC);
00338 
00339         $DB->setReturnValue('get_recordset',new fake_recordset(array(
00340             (object)array('id'=>1,'userid'=>100),
00341             (object)array('id'=>2,'userid'=>101),
00342         )));
00343         $DB->expectOnce('get_recordset',array('course_modules_completion',
00344             array('coursemoduleid'=>13),'','userid'));
00345         $c->expectOnce('delete_all_state',array($cm));
00346         $c->expectOnce('get_tracked_users',array());
00347         $c->setReturnValue('get_tracked_users',array(
00348             (object)array('id'=>100,'firstname'=>'Woot','lastname'=>'Plugh'),
00349             (object)array('id'=>201,'firstname'=>'Vroom','lastname'=>'Xyzzy'),
00350             ));
00351 
00352         $c->expectAt(0,'update_state',array($cm,COMPLETION_UNKNOWN,100));
00353         $c->expectAt(1,'update_state',array($cm,COMPLETION_UNKNOWN,101));
00354         $c->expectAt(2,'update_state',array($cm,COMPLETION_UNKNOWN,201));
00355 
00356         $c->reset_all_state($cm);
00357 
00358         $DB->tally();
00359         $c->tally();
00360     }
00361 
00362     function test_get_data() {
00363         global $DB,$SESSION;
00364 
00365         $c=new completion_info((object)array('id'=>42));
00366         $cm=(object)array('id'=>13,'course'=>42);
00367 
00368         // 1. Not current user, record exists
00369         $sillyrecord=(object)array('frog'=>'kermit');
00370         $DB->expectAt(0,'get_record',array('course_modules_completion',
00371             array('coursemoduleid'=>13,'userid'=>123)));
00372         $DB->setReturnValueAt(0,'get_record',$sillyrecord);
00373         $result=$c->get_data($cm,false,123);
00374         $this->assertEqual($sillyrecord,$result);
00375         $this->assertTrue(empty($SESSION->completioncache));
00376 
00377         // 2. Not current user, default record, wholecourse (ignored)
00378         $DB->expectAt(1,'get_record',array('course_modules_completion',
00379             array('coursemoduleid'=>13,'userid'=>123)));
00380         $DB->setReturnValueAt(1,'get_record',false);
00381         $result=$c->get_data($cm,true,123);
00382         $this->assertEqual((object)array(
00383             'id'=>'0','coursemoduleid'=>13,'userid'=>123,'completionstate'=>0,
00384             'viewed'=>0,'timemodified'=>0),$result);
00385         $this->assertTrue(empty($SESSION->completioncache));
00386 
00387         // 3. Current user, single record, not from cache
00388         $DB->expectAt(2,'get_record',array('course_modules_completion',
00389             array('coursemoduleid'=>13,'userid'=>314159)));
00390         $DB->setReturnValueAt(2,'get_record',$sillyrecord);
00391         $result=$c->get_data($cm);
00392         $this->assertEqual($sillyrecord,$result);
00393         $this->assertEqual($sillyrecord,$SESSION->completioncache[42][13]);
00394         // When checking time(), allow for second overlaps
00395         $this->assertTrue(time()-$SESSION->completioncache[42]['updated']<2);
00396 
00397         // 4. Current user, 'whole course', but from cache
00398         $result=$c->get_data($cm,true);
00399         $this->assertEqual($sillyrecord,$result);
00400 
00401         // 5. Current user, single record, cache expired
00402         $SESSION->completioncache[42]['updated']=37; // Quite a long time ago
00403         $now=time();
00404         $SESSION->completioncache[17]['updated']=$now;
00405         $SESSION->completioncache[39]['updated']=72; // Also a long time ago
00406         $DB->expectAt(3,'get_record',array('course_modules_completion',
00407             array('coursemoduleid'=>13,'userid'=>314159)));
00408         $DB->setReturnValueAt(3,'get_record',$sillyrecord);
00409         $result=$c->get_data($cm,false);
00410         $this->assertEqual($sillyrecord,$result);
00411         // Check that updated value is right, then fudge it to make next compare
00412         // work
00413         $this->assertTrue(time()-$SESSION->completioncache[42]['updated']<2);
00414         $SESSION->completioncache[42]['updated']=$now;
00415         // Check things got expired from cache
00416         $this->assertEqual(array(42=>array(13=>$sillyrecord,'updated'=>$now),
00417             17=>array('updated'=>$now)),$SESSION->completioncache);
00418 
00419         // 6. Current user, 'whole course' and record not in cache
00420         unset($SESSION->completioncache);
00421 
00422         // Scenario: Completion data exists for one CMid
00423         $basicrecord=(object)array('coursemoduleid'=>13);
00424         $DB->setReturnValueAt(0,'get_records_sql',array(
00425             1=>$basicrecord
00426         ));
00427         $DB->expectAt(0,'get_records_sql',array(new IgnoreWhitespaceExpectation("
00428 SELECT
00429     cmc.*
00430 FROM
00431     {course_modules} cm
00432     INNER JOIN {course_modules_completion} cmc ON cmc.coursemoduleid=cm.id
00433 WHERE
00434     cm.course=? AND cmc.userid=?"),array(42,314159)));
00435 
00436         // There are two CMids in total, the one we had data for and another one
00437         $modinfo->cms=array((object)array('id'=>13),(object)array('id'=>14));
00438         $result=$c->get_data($cm,true,0,$modinfo);
00439 
00440         // Check result
00441         $this->assertEqual($basicrecord,$result);
00442 
00443         // Check the cache contents
00444         $this->assertTrue(time()-$SESSION->completioncache[42]['updated']<2);
00445         $SESSION->completioncache[42]['updated']=$now;
00446         $this->assertEqual(array(42=>array(13=>$basicrecord,14=>(object)array(
00447             'id'=>'0','coursemoduleid'=>14,'userid'=>314159,'completionstate'=>0,
00448             'viewed'=>0,'timemodified'=>0),'updated'=>$now)),$SESSION->completioncache);
00449 
00450         $DB->tally();
00451     }
00452 
00453     function test_internal_set_data() {
00454         global $DB,$SESSION;
00455 
00456         $cm = (object)array('course' => 42,'id' => 13);
00457         $c = new completion_info((object)array('id' => 42));
00458 
00459         // 1) Test with new data
00460         $data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
00461         $DB->setReturnValueAt(0, 'start_delegated_transaction', new mock_transaction());
00462         $DB->setReturnValueAt(0, 'insert_record', 4);
00463         $DB->expectAt(0, 'get_field', array('course_modules_completion', 'id',
00464                 array('coursemoduleid' => 99, 'userid' => 314159)));
00465         $DB->expectAt(0, 'insert_record', array('course_modules_completion', $data));
00466         $c->internal_set_data($cm, $data);
00467         $this->assertEqual(4, $data->id);
00468         $this->assertEqual(array(42 => array(13 => $data)), $SESSION->completioncache);
00469 
00470         // 2) Test with existing data and for different user (not cached)
00471         unset($SESSION->completioncache);
00472         $d2 = (object)array('id' => 7, 'userid' => 17, 'coursemoduleid' => 66);
00473         $DB->setReturnValueAt(1, 'start_delegated_transaction', new mock_transaction());
00474         $DB->expectAt(0,'update_record', array('course_modules_completion', $d2));
00475         $c->internal_set_data($cm, $d2);
00476         $this->assertFalse(isset($SESSION->completioncache));
00477 
00478         // 3) Test where it THINKS the data is new (from cache) but actually
00479         // in the database it has been set since
00480         // 1) Test with new data
00481         $data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
00482         $DB->setReturnValueAt(2, 'start_delegated_transaction', new mock_transaction());
00483         $DB->setReturnValueAt(1, 'get_field', 13);
00484         $DB->expectAt(1, 'get_field', array('course_modules_completion', 'id',
00485                 array('coursemoduleid' => 99, 'userid' => 314159)));
00486         $d3 = (object)array('id' => 13, 'userid' => 314159, 'coursemoduleid' => 99);
00487         $DB->expectAt(1,'update_record', array('course_modules_completion', $d3));
00488         $c->internal_set_data($cm, $data);
00489 
00490         $DB->tally();
00491     }
00492 
00493     function test_get_activities() {
00494         global $DB;
00495 
00496         $c=new completion_info((object)array('id'=>42));
00497 
00498         // Try with no activities
00499         $DB->expectAt(0,'get_records_select',array('course_modules',
00500               'course=42 AND completion<>'.COMPLETION_TRACKING_NONE));
00501         $DB->setReturnValueAt(0,'get_records_select',array());
00502         $result=$c->get_activities();
00503         $this->assertEqual(array(),$result);
00504 
00505         // Try with an activity (need to fake up modinfo for it as well)
00506         $DB->expectAt(1,'get_records_select',array('course_modules',
00507               'course=42 AND completion<>'.COMPLETION_TRACKING_NONE));
00508         $DB->setReturnValueAt(1,'get_records_select',array(
00509             13=>(object)array('id'=>13)
00510         ));
00511         $modinfo=new stdClass;
00512         $modinfo->sections=array(array(1,2,3),array(12,13,14));
00513         $modinfo->cms[13]=(object)array('modname'=>'frog','name'=>'kermit');
00514         $result=$c->get_activities($modinfo);
00515         $this->assertEqual(array(13=>(object)array('id'=>13,'modname'=>'frog','name'=>'kermit')),$result);
00516 
00517         $DB->tally();
00518     }
00519 
00520     // get_tracked_users() cannot easily be tested because it uses
00521     // get_role_users, so skipping that
00522 
00523     function test_get_progress_all() {
00524         global $DB;
00525 
00526         $c=new completion_cutdown();
00527         $c->__construct((object)array('id'=>42));
00528 
00529         // 1) Basic usage
00530         $c->expectAt(0,'get_tracked_users',array(false, array(), 0, '', '', '', null));
00531         $c->setReturnValueAt(0,'get_tracked_users',array(
00532             (object)array('id'=>100,'firstname'=>'Woot','lastname'=>'Plugh'),
00533             (object)array('id'=>201,'firstname'=>'Vroom','lastname'=>'Xyzzy'),
00534             ));
00535         $DB->expectAt(0,'get_in_or_equal',array(array(100,201)));
00536         $DB->setReturnValueAt(0,'get_in_or_equal',array(' IN (100,201)',array()));
00537         $DB->expectAt(0,'get_recordset_sql',array(new IgnoreWhitespaceExpectation("
00538 SELECT
00539     cmc.*
00540 FROM
00541     {course_modules} cm
00542     INNER JOIN {course_modules_completion} cmc ON cm.id=cmc.coursemoduleid
00543 WHERE
00544     cm.course=? AND cmc.userid IN (100,201)"),array(42)));
00545         $progress1=(object)array('userid'=>100,'coursemoduleid'=>13);
00546         $progress2=(object)array('userid'=>201,'coursemoduleid'=>14);
00547         $DB->setReturnValueAt(0,'get_recordset_sql',new fake_recordset(array(
00548             $progress1,$progress2
00549         )));
00550         $this->assertEqual(array(
00551 
00552                 100 => (object)array('id'=>100,'firstname'=>'Woot','lastname'=>'Plugh',
00553                     'progress'=>array(13=>$progress1)),
00554                 201 => (object)array('id'=>201,'firstname'=>'Vroom','lastname'=>'Xyzzy',
00555                     'progress'=>array(14=>$progress2)),
00556             ),$c->get_progress_all(false));
00557 
00558         // 2) With more than 1,000 results
00559         $c->expectAt(1,'get_tracked_users',array(true, 3, 0, '', '', '', null));
00560 
00561         $tracked=array();
00562         $ids=array();
00563         $progress=array();
00564         for($i=100;$i<2000;$i++) {
00565             $tracked[]=(object)array('id'=>$i,'firstname'=>'frog','lastname'=>$i);
00566             $ids[]=$i;
00567             $progress[]=(object)array('userid'=>$i,'coursemoduleid'=>13);
00568             $progress[]=(object)array('userid'=>$i,'coursemoduleid'=>14);
00569         }
00570         $c->setReturnValueAt(1,'get_tracked_users',$tracked);
00571 
00572         $DB->expectAt(1,'get_in_or_equal',array(array_slice($ids,0,1000)));
00573         $DB->setReturnValueAt(1,'get_in_or_equal',array(' IN whatever',array()));
00574         $DB->expectAt(1,'get_recordset_sql',array(new IgnoreWhitespaceExpectation("
00575 SELECT
00576     cmc.*
00577 FROM
00578     {course_modules} cm
00579     INNER JOIN {course_modules_completion} cmc ON cm.id=cmc.coursemoduleid
00580 WHERE
00581     cm.course=? AND cmc.userid IN whatever"),array(42)));
00582         $DB->setReturnValueAt(1,'get_recordset_sql',new fake_recordset(array_slice($progress,0,1000)));
00583         $DB->expectAt(2,'get_in_or_equal',array(array_slice($ids,1000)));
00584         $DB->setReturnValueAt(2,'get_in_or_equal',array(' IN whatever2',array()));
00585         $DB->expectAt(2,'get_recordset_sql',array(new IgnoreWhitespaceExpectation("
00586 SELECT
00587     cmc.*
00588 FROM
00589     {course_modules} cm
00590     INNER JOIN {course_modules_completion} cmc ON cm.id=cmc.coursemoduleid
00591 WHERE
00592     cm.course=? AND cmc.userid IN whatever2"),array(42)));
00593         $DB->setReturnValueAt(2,'get_recordset_sql',new fake_recordset(array_slice($progress,1000)));
00594         $result=$c->get_progress_all(true,3);
00595         $resultok=true;
00596         $resultok = $resultok && ($ids==array_keys($result));
00597 
00598         foreach($result as $userid => $data) {
00599             $resultok = $resultok && $data->firstname=='frog';
00600             $resultok = $resultok && $data->lastname==$userid;
00601             $resultok = $resultok && $data->id==$userid;
00602             $cms=$data->progress;
00603             $resultok= $resultok && (array(13,14)==array_keys($cms));
00604             $resultok= $resultok && ((object)array('userid'=>$userid,'coursemoduleid'=>13)==$cms[13]);
00605             $resultok= $resultok && ((object)array('userid'=>$userid,'coursemoduleid'=>14)==$cms[14]);
00606         }
00607         $this->assertTrue($resultok);
00608 
00609         $DB->tally();
00610         $c->tally();
00611     }
00612 
00613     function test_inform_grade_changed() {
00614         $c=new completion_cutdown();
00615         $c->__construct((object)array('id'=>42));
00616 
00617         $cm=(object)array('course'=>42,'id'=>13,'completion'=>0,'completiongradeitemnumber'=>null);
00618         $item=(object)array('itemnumber'=>3);
00619         $grade=(object)array('userid'=>31337);
00620 
00621         // Not enabled (should do nothing)
00622         $c->setReturnValueAt(0,'is_enabled',false);
00623         $c->expectAt(0,'is_enabled',array($cm));
00624         $c->inform_grade_changed($cm,$item,$grade,false);
00625 
00626         // Enabled but still no grade completion required, should still do nothing
00627         $c->setReturnValueAt(1,'is_enabled',true);
00628         $c->expectAt(1,'is_enabled',array($cm));
00629         $c->inform_grade_changed($cm,$item,$grade,false);
00630 
00631         // Enabled and completion required but item number is wrong, does nothing
00632         $cm->completiongradeitemnumber=7;
00633         $c->setReturnValueAt(2,'is_enabled',true);
00634         $c->expectAt(2,'is_enabled',array($cm));
00635         $c->inform_grade_changed($cm,$item,$grade,false);
00636 
00637         // Enabled and completion required and item number right. It is supposed
00638         // to call update_state with the new potential state being obtained from
00639         // internal_get_grade_state.
00640         $cm->completiongradeitemnumber=3;
00641         $c->setReturnValueAt(3,'is_enabled',true);
00642         $c->expectAt(3,'is_enabled',array($cm));
00643         $c->expectAt(0,'internal_get_grade_state',array($item,$grade));
00644         $c->setReturnValueAt(0,'internal_get_grade_state',COMPLETION_COMPLETE_PASS);
00645         $c->expectAt(0,'update_state',array($cm,COMPLETION_COMPLETE_PASS,31337));
00646         $c->inform_grade_changed($cm,$item,$grade,false);
00647 
00648         // Same as above but marked deleted. It is supposed to call update_state
00649         // with new potential state being COMPLETION_INCOMPLETE
00650         $c->setReturnValueAt(4,'is_enabled',false);
00651         $c->expectAt(4,'is_enabled',array($cm));
00652         $c->expectAt(1,'update_state',array($cm,COMPLETION_INCOMPLETE,31337));
00653         $c->inform_grade_changed($cm,$item,$grade,false);
00654 
00655         $c->tally();
00656     }
00657 
00658     function test_internal_get_grade_state() {
00659         $item=new stdClass;
00660         $grade=new stdClass;
00661 
00662         $item->gradepass=4;
00663         $item->hidden=0;
00664         $grade->rawgrade=4.0;
00665         $grade->finalgrade=null;
00666 
00667         // Grade has pass mark and is not hidden, user passes
00668         $this->assertEqual(
00669             COMPLETION_COMPLETE_PASS,
00670             completion_info::internal_get_grade_state($item,$grade));
00671 
00672         // Same but user fails
00673         $grade->rawgrade=3.9;
00674         $this->assertEqual(
00675             COMPLETION_COMPLETE_FAIL,
00676             completion_info::internal_get_grade_state($item,$grade));
00677 
00678         // User fails on raw grade but passes on final
00679         $grade->finalgrade=4.0;
00680         $this->assertEqual(
00681             COMPLETION_COMPLETE_PASS,
00682             completion_info::internal_get_grade_state($item,$grade));
00683 
00684         // Item is hidden
00685         $item->hidden=1;
00686         $this->assertEqual(
00687             COMPLETION_COMPLETE,
00688             completion_info::internal_get_grade_state($item,$grade));
00689 
00690         // Item isn't hidden but has no pass mark
00691         $item->hidden=0;
00692         $item->gradepass=0;
00693         $this->assertEqual(
00694             COMPLETION_COMPLETE,
00695             completion_info::internal_get_grade_state($item,$grade));
00696     }
00697 }
00698 
 All Data Structures Namespaces Files Functions Variables Enumerations