diff --git a/lib/tests/completionlib_test.php b/lib/tests/completionlib_test.php index 75de3067cac..6267d18caab 100644 --- a/lib/tests/completionlib_test.php +++ b/lib/tests/completionlib_test.php @@ -132,23 +132,24 @@ class core_completionlib_testcase extends advanced_testcase { $mockbuilder->setMethods(array('is_enabled', 'get_data', 'internal_get_state', 'internal_set_data', 'user_can_override_completion')); $mockbuilder->setConstructorArgs(array((object)array('id' => 42))); - $c = $mockbuilder->getMock(); $cm = (object)array('id'=>13, 'course'=>42); // Not enabled, should do nothing. - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(false)); $c->update_state($cm); // Enabled, but current state is same as possible result, do nothing. + $c = $mockbuilder->getMock(); $current = (object)array('completionstate' => COMPLETION_COMPLETE, 'overrideby' => null); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 0) ->will($this->returnValue($current)); @@ -156,36 +157,39 @@ class core_completionlib_testcase extends advanced_testcase { // Enabled, but current state is a specific one and new state is just // complete, so do nothing. + $c = $mockbuilder->getMock(); $current->completionstate = COMPLETION_COMPLETE_PASS; - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 0) ->will($this->returnValue($current)); $c->update_state($cm, COMPLETION_COMPLETE); // Manual, change state (no change). + $c = $mockbuilder->getMock(); $cm = (object)array('id'=>13, 'course'=>42, 'completion'=>COMPLETION_TRACKING_MANUAL); $current->completionstate=COMPLETION_COMPLETE; - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 0) ->will($this->returnValue($current)); $c->update_state($cm, COMPLETION_COMPLETE); // Manual, change state (change). - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 0) ->will($this->returnValue($current)); @@ -194,23 +198,24 @@ class core_completionlib_testcase extends advanced_testcase { $changed->completionstate = COMPLETION_INCOMPLETE; $comparewith = new phpunit_constraint_object_is_equal_with_exceptions($changed); $comparewith->add_exception('timemodified', 'assertGreaterThanOrEqual'); - $c->expects($this->at(2)) + $c->expects($this->once()) ->method('internal_set_data') ->with($cm, $comparewith); $c->update_state($cm, COMPLETION_INCOMPLETE); // Auto, change state. + $c = $mockbuilder->getMock(); $cm = (object)array('id'=>13, 'course'=>42, 'completion'=>COMPLETION_TRACKING_AUTOMATIC); $current = (object)array('completionstate' => COMPLETION_COMPLETE, 'overrideby' => null); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 0) ->will($this->returnValue($current)); - $c->expects($this->at(2)) + $c->expects($this->once()) ->method('internal_get_state') ->will($this->returnValue(COMPLETION_COMPLETE_PASS)); $changed = clone($current); @@ -218,54 +223,61 @@ class core_completionlib_testcase extends advanced_testcase { $changed->completionstate = COMPLETION_COMPLETE_PASS; $comparewith = new phpunit_constraint_object_is_equal_with_exceptions($changed); $comparewith->add_exception('timemodified', 'assertGreaterThanOrEqual'); - $c->expects($this->at(3)) + $c->expects($this->once()) ->method('internal_set_data') ->with($cm, $comparewith); $c->update_state($cm, COMPLETION_COMPLETE_PASS); // Manual tracking, change state by overriding it manually. + $c = $mockbuilder->getMock(); $cm = (object)array('id' => 13, 'course' => 42, 'completion' => COMPLETION_TRACKING_MANUAL); - $current = (object)array('completionstate' => COMPLETION_INCOMPLETE, 'overrideby' => null); - $c->expects($this->at(0)) + $current1 = (object)array('completionstate' => COMPLETION_INCOMPLETE, 'overrideby' => null); + $current2 = (object)array('completionstate' => COMPLETION_COMPLETE, 'overrideby' => null); + $c->expects($this->exactly(2)) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) // Pretend the user has the required capability for overriding completion statuses. + $c->expects($this->exactly(1)) // Pretend the user has the required capability for overriding completion statuses. ->method('user_can_override_completion') ->will($this->returnValue(true)); - $c->expects($this->at(2)) + $c->expects($this->exactly(2)) ->method('get_data') ->with($cm, false, 100) - ->will($this->returnValue($current)); - $changed = clone($current); - $changed->timemodified = time(); - $changed->completionstate = COMPLETION_COMPLETE; - $changed->overrideby = 314159; - $comparewith = new phpunit_constraint_object_is_equal_with_exceptions($changed); - $comparewith->add_exception('timemodified', 'assertGreaterThanOrEqual'); - $c->expects($this->at(3)) + ->willReturnOnConsecutiveCalls($current1, $current2); + $changed1 = clone($current1); + $changed1->timemodified = time(); + $changed1->completionstate = COMPLETION_COMPLETE; + $changed1->overrideby = 314159; + $comparewith1 = new phpunit_constraint_object_is_equal_with_exceptions($changed1); + $comparewith1->add_exception('timemodified', 'assertGreaterThanOrEqual'); + $changed2 = clone($current2); + $changed2->timemodified = time(); + $changed2->overrideby = null; + $changed2->completionstate = COMPLETION_INCOMPLETE; + $comparewith2 = new phpunit_constraint_object_is_equal_with_exceptions($changed2); + $comparewith2->add_exception('timemodified', 'assertGreaterThanOrEqual'); + $c->expects($this->exactly(2)) ->method('internal_set_data') - ->with($cm, $comparewith); + ->withConsecutive( + array($cm, $comparewith1), + array($cm, $comparewith2) + ); $c->update_state($cm, COMPLETION_COMPLETE, 100, true); // And confirm that the status can be changed back to incomplete without an override. $c->update_state($cm, COMPLETION_INCOMPLETE, 100); - $c->expects($this->at(0)) - ->method('get_data') - ->with($cm, false, 100) - ->will($this->returnValue($current)); - $c->get_data($cm, false, 100); // Auto, change state via override, incomplete to complete. + $c = $mockbuilder->getMock(); $cm = (object)array('id' => 13, 'course' => 42, 'completion' => COMPLETION_TRACKING_AUTOMATIC); $current = (object)array('completionstate' => COMPLETION_INCOMPLETE, 'overrideby' => null); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) // Pretend the user has the required capability for overriding completion statuses. + $c->expects($this->once()) // Pretend the user has the required capability for overriding completion statuses. ->method('user_can_override_completion') ->will($this->returnValue(true)); - $c->expects($this->at(2)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 100) ->will($this->returnValue($current)); @@ -275,36 +287,23 @@ class core_completionlib_testcase extends advanced_testcase { $changed->overrideby = 314159; $comparewith = new phpunit_constraint_object_is_equal_with_exceptions($changed); $comparewith->add_exception('timemodified', 'assertGreaterThanOrEqual'); - $c->expects($this->at(3)) + $c->expects($this->once()) ->method('internal_set_data') ->with($cm, $comparewith); $c->update_state($cm, COMPLETION_COMPLETE, 100, true); - $c->expects($this->at(0)) - ->method('get_data') - ->with($cm, false, 100) - ->will($this->returnValue($changed)); - $c->get_data($cm, false, 100); - - // Now confirm that the status cannot be changed back to incomplete without an override. - // I.e. test that automatic completion won't trigger a change back to COMPLETION_INCOMPLETE when overridden. - $c->update_state($cm, COMPLETION_INCOMPLETE, 100); - $c->expects($this->at(0)) - ->method('get_data') - ->with($cm, false, 100) - ->will($this->returnValue($changed)); - $c->get_data($cm, false, 100); // Now confirm the status can be changed back from complete to incomplete using an override. + $c = $mockbuilder->getMock(); $cm = (object)array('id' => 13, 'course' => 42, 'completion' => COMPLETION_TRACKING_AUTOMATIC); $current = (object)array('completionstate' => COMPLETION_COMPLETE, 'overrideby' => 2); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) // Pretend the user has the required capability for overriding completion statuses. + $c->expects($this->Once()) // Pretend the user has the required capability for overriding completion statuses. ->method('user_can_override_completion') ->will($this->returnValue(true)); - $c->expects($this->at(2)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 100) ->will($this->returnValue($current)); @@ -314,15 +313,10 @@ class core_completionlib_testcase extends advanced_testcase { $changed->overrideby = 314159; $comparewith = new phpunit_constraint_object_is_equal_with_exceptions($changed); $comparewith->add_exception('timemodified', 'assertGreaterThanOrEqual'); - $c->expects($this->at(3)) + $c->expects($this->once()) ->method('internal_set_data') ->with($cm, $comparewith); $c->update_state($cm, COMPLETION_INCOMPLETE, 100, true); - $c->expects($this->at(0)) - ->method('get_data') - ->with($cm, false, 100) - ->will($this->returnValue($changed)); - $c->get_data($cm, false, 100); } /** @@ -461,16 +455,17 @@ class core_completionlib_testcase extends advanced_testcase { $mockbuilder = $this->getMockBuilder('completion_info'); $mockbuilder->setMethods(array('is_enabled', 'get_data', 'internal_set_data', 'update_state')); $mockbuilder->setConstructorArgs(array((object)array('id' => 42))); - $c = $mockbuilder->getMock(); $cm = (object)array('id'=>13, 'course'=>42); // Not tracking completion, should do nothing. + $c = $mockbuilder->getMock(); $cm->completionview = COMPLETION_VIEW_NOT_REQUIRED; $c->set_module_viewed($cm); // Tracking completion but completion is disabled, should do nothing. + $c = $mockbuilder->getMock(); $cm->completionview = COMPLETION_VIEW_REQUIRED; - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(false)); @@ -478,11 +473,12 @@ class core_completionlib_testcase extends advanced_testcase { // Now it's enabled, we expect it to get data. If data already has // viewed, still do nothing. - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, 0) ->will($this->returnValue((object)array('viewed'=>COMPLETION_VIEWED))); @@ -490,18 +486,19 @@ class core_completionlib_testcase extends advanced_testcase { // OK finally one that hasn't been viewed, now it should set it viewed // and update state. - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_data') ->with($cm, false, 1337) ->will($this->returnValue((object)array('viewed'=>COMPLETION_NOT_VIEWED))); - $c->expects($this->at(2)) + $c->expects($this->once()) ->method('internal_set_data') ->with($cm, (object)array('viewed'=>COMPLETION_VIEWED)); - $c->expects($this->at(3)) + $c->expects($this->once()) ->method('update_state') ->with($cm, COMPLETION_COMPLETE, 1337); $c->set_module_viewed($cm, 1337); @@ -515,7 +512,7 @@ class core_completionlib_testcase extends advanced_testcase { $cm = (object)array('id'=>42); /** @var $DB PHPUnit_Framework_MockObject_MockObject */ - $DB->expects($this->at(0)) + $DB->expects($this->once()) ->method('get_field_sql') ->will($this->returnValue(666)); @@ -533,7 +530,7 @@ class core_completionlib_testcase extends advanced_testcase { // Check it works ok without data in session. /** @var $DB PHPUnit_Framework_MockObject_MockObject */ - $DB->expects($this->at(0)) + $DB->expects($this->once()) ->method('delete_records') ->with('course_modules_completion', array('coursemoduleid'=>42)) ->will($this->returnValue(true)); @@ -552,30 +549,28 @@ class core_completionlib_testcase extends advanced_testcase { $cm = (object)array('id'=>13, 'course'=>42, 'completion'=>COMPLETION_TRACKING_AUTOMATIC); /** @var $DB PHPUnit_Framework_MockObject_MockObject */ - $DB->expects($this->at(0)) + $DB->expects($this->once()) ->method('get_recordset') ->will($this->returnValue( new core_completionlib_fake_recordset(array((object)array('id'=>1, 'userid'=>100), (object)array('id'=>2, 'userid'=>101))))); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('delete_all_state') ->with($cm); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('get_tracked_users') ->will($this->returnValue(array( (object)array('id'=>100, 'firstname'=>'Woot', 'lastname'=>'Plugh'), (object)array('id'=>201, 'firstname'=>'Vroom', 'lastname'=>'Xyzzy')))); - $c->expects($this->at(2)) + $c->expects($this->exactly(3)) ->method('update_state') - ->with($cm, COMPLETION_UNKNOWN, 100); - $c->expects($this->at(3)) - ->method('update_state') - ->with($cm, COMPLETION_UNKNOWN, 101); - $c->expects($this->at(4)) - ->method('update_state') - ->with($cm, COMPLETION_UNKNOWN, 201); + ->withConsecutive( + array($cm, COMPLETION_UNKNOWN, 100), + array($cm, COMPLETION_UNKNOWN, 101), + array($cm, COMPLETION_UNKNOWN, 201) + ); $c->reset_all_state($cm); } @@ -756,7 +751,7 @@ class core_completionlib_testcase extends advanced_testcase { $c->internal_set_data($cm, $data); } - public function test_get_progress_all() { + public function test_get_progress_all_few() { global $DB; $this->mock_setup(); @@ -765,20 +760,20 @@ class core_completionlib_testcase extends advanced_testcase { $mockbuilder->setConstructorArgs(array((object)array('id' => 42))); $c = $mockbuilder->getMock(); - // 1) Basic usage. - $c->expects($this->at(0)) + // With few results. + $c->expects($this->once()) ->method('get_tracked_users') ->with(false, array(), 0, '', '', '', null) ->will($this->returnValue(array( (object)array('id'=>100, 'firstname'=>'Woot', 'lastname'=>'Plugh'), (object)array('id'=>201, 'firstname'=>'Vroom', 'lastname'=>'Xyzzy')))); - $DB->expects($this->at(0)) + $DB->expects($this->once()) ->method('get_in_or_equal') ->with(array(100, 201)) ->will($this->returnValue(array(' IN (100, 201)', array()))); $progress1 = (object)array('userid'=>100, 'coursemoduleid'=>13); $progress2 = (object)array('userid'=>201, 'coursemoduleid'=>14); - $DB->expects($this->at(1)) + $DB->expects($this->once()) ->method('get_recordset_sql') ->will($this->returnValue(new core_completionlib_fake_recordset(array($progress1, $progress2)))); @@ -788,36 +783,45 @@ class core_completionlib_testcase extends advanced_testcase { 201 => (object)array('id'=>201, 'firstname'=>'Vroom', 'lastname'=>'Xyzzy', 'progress'=>array(14=>$progress2)), ), $c->get_progress_all(false)); + } + + public function test_get_progress_all_lots() { + global $DB; + $this->mock_setup(); + + $mockbuilder = $this->getMockBuilder('completion_info'); + $mockbuilder->setMethods(array('get_tracked_users')); + $mockbuilder->setConstructorArgs(array((object)array('id' => 42))); + $c = $mockbuilder->getMock(); - // 2) With more than 1, 000 results. $tracked = array(); $ids = array(); $progress = array(); + // With more than 1000 results. for ($i = 100; $i<2000; $i++) { $tracked[] = (object)array('id'=>$i, 'firstname'=>'frog', 'lastname'=>$i); $ids[] = $i; $progress[] = (object)array('userid'=>$i, 'coursemoduleid'=>13); $progress[] = (object)array('userid'=>$i, 'coursemoduleid'=>14); } - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('get_tracked_users') ->with(true, 3, 0, '', '', '', null) ->will($this->returnValue($tracked)); - $DB->expects($this->at(0)) + $DB->expects($this->exactly(2)) ->method('get_in_or_equal') - ->with(array_slice($ids, 0, 1000)) - ->will($this->returnValue(array(' IN whatever', array()))); - $DB->expects($this->at(1)) + ->withConsecutive( + array(array_slice($ids, 0, 1000)), + array(array_slice($ids, 1000)) + ) + ->willReturnOnConsecutiveCalls( + array(' IN whatever', array()), + array(' IN whatever2', array())); + $DB->expects($this->exactly(2)) ->method('get_recordset_sql') - ->will($this->returnValue(new core_completionlib_fake_recordset(array_slice($progress, 0, 1000)))); - - $DB->expects($this->at(2)) - ->method('get_in_or_equal') - ->with(array_slice($ids, 1000)) - ->will($this->returnValue(array(' IN whatever2', array()))); - $DB->expects($this->at(3)) - ->method('get_recordset_sql') - ->will($this->returnValue(new core_completionlib_fake_recordset(array_slice($progress, 1000)))); + ->willReturnOnConsecutiveCalls( + new core_completionlib_fake_recordset(array_slice($progress, 0, 1000)), + new core_completionlib_fake_recordset(array_slice($progress, 1000))); $result = $c->get_progress_all(true, 3); $resultok = true; @@ -833,6 +837,7 @@ class core_completionlib_testcase extends advanced_testcase { $resultok = $resultok && ((object)array('userid'=>$userid, 'coursemoduleid'=>14) == $cms[14]); } $this->assertTrue($resultok); + $this->assertCount(count($tracked), $result); } public function test_inform_grade_changed() { @@ -841,29 +846,31 @@ class core_completionlib_testcase extends advanced_testcase { $mockbuilder = $this->getMockBuilder('completion_info'); $mockbuilder->setMethods(array('is_enabled', 'update_state')); $mockbuilder->setConstructorArgs(array((object)array('id' => 42))); - $c = $mockbuilder->getMock(); $cm = (object)array('course'=>42, 'id'=>13, 'completion'=>0, 'completiongradeitemnumber'=>null); $item = (object)array('itemnumber'=>3, 'gradepass'=>1, 'hidden'=>0); $grade = (object)array('userid'=>31337, 'finalgrade'=>0, 'rawgrade'=>0); // Not enabled (should do nothing). - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(false)); $c->inform_grade_changed($cm, $item, $grade, false); // Enabled but still no grade completion required, should still do nothing. - $c->expects($this->at(0)) + $c = $mockbuilder->getMock(); + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); $c->inform_grade_changed($cm, $item, $grade, false); // Enabled and completion required but item number is wrong, does nothing. + $c = $mockbuilder->getMock(); $cm = (object)array('course'=>42, 'id'=>13, 'completion'=>0, 'completiongradeitemnumber'=>7); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); @@ -872,13 +879,14 @@ class core_completionlib_testcase extends advanced_testcase { // Enabled and completion required and item number right. It is supposed // to call update_state with the new potential state being obtained from // internal_get_grade_state. + $c = $mockbuilder->getMock(); $cm = (object)array('course'=>42, 'id'=>13, 'completion'=>0, 'completiongradeitemnumber'=>3); $grade = (object)array('userid'=>31337, 'finalgrade'=>1, 'rawgrade'=>0); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('update_state') ->with($cm, COMPLETION_COMPLETE_PASS, 31337) ->will($this->returnValue(true)); @@ -886,13 +894,14 @@ class core_completionlib_testcase extends advanced_testcase { // Same as above but marked deleted. It is supposed to call update_state // with new potential state being COMPLETION_INCOMPLETE. + $c = $mockbuilder->getMock(); $cm = (object)array('course'=>42, 'id'=>13, 'completion'=>0, 'completiongradeitemnumber'=>3); $grade = (object)array('userid'=>31337, 'finalgrade'=>1, 'rawgrade'=>0); - $c->expects($this->at(0)) + $c->expects($this->once()) ->method('is_enabled') ->with($cm) ->will($this->returnValue(true)); - $c->expects($this->at(1)) + $c->expects($this->once()) ->method('update_state') ->with($cm, COMPLETION_INCOMPLETE, 31337) ->will($this->returnValue(true));