diff --git a/classes/local/au_helpers.php b/classes/local/au_helpers.php index 5911bce..4ecdbff 100644 --- a/classes/local/au_helpers.php +++ b/classes/local/au_helpers.php @@ -31,6 +31,7 @@ global $CFG; // Include the errorover (error override) funcs. require_once ($CFG->dirroot . '/mod/cmi5launch/classes/local/errorover.php'); +//require 'errorover.php'; defined('MOODLE_INTERNAL') || die(); @@ -166,7 +167,7 @@ public function cmi5launch_save_aus($auobjectarray) try { // Make a newrecord to save. $newrecord = new \stdClass(); - + // Assign the values to the new record. $newrecord->userid = $USER->id; $newrecord->attempt = $auobject->attempt; @@ -195,7 +196,6 @@ public function cmi5launch_save_aus($auobjectarray) $newrecord->satisfied = $auobject->satisfied; $newrecord->moodlecourseid = $cmi5launch->id; - // Save the record and get the new id. $newid = $DB->insert_record($table, $newrecord, true); diff --git a/classes/local/cmi5_connectors.php b/classes/local/cmi5_connectors.php index 1f3ab33..8a51360 100755 --- a/classes/local/cmi5_connectors.php +++ b/classes/local/cmi5_connectors.php @@ -27,7 +27,6 @@ use mod_cmi5launch\local\cmi5launch_helpers; // Include the errorover (error override) funcs. require_once ($CFG->dirroot . '/mod/cmi5launch/classes/local/errorover.php'); - class cmi5_connectors { public function cmi5launch_get_create_tenant() { diff --git a/classes/local/errorover.php b/classes/local/errorover.php index fc0075c..bf44700 100644 --- a/classes/local/errorover.php +++ b/classes/local/errorover.php @@ -80,19 +80,19 @@ function array_chunk_warning($errno, $errstr, $errfile, $errline) throw new nullException('Cannot parse array. Error: ' . $errstr, 0); // exit; } + /// Ok, this i a different error handler + function grade_warning($errno, $errstr, $errfile, $errline) + { + // echo"Error stirn --- $errstr"; + // echo"Error number --- $errno"; + //echo"Error errfile --- $errfile"; + // echo"Error errline --- $errline"; + // Maybe we can construct the new errors here. This would allow the error personalization? And keep main code clean + + throw new nullException('Error in checking user grades: ' . $errstr, 0); + // exit; + } - /// Ok, this i a different error handler - function grade_warning($errno, $errstr, $errfile, $errline) - { - // echo"Error stirn --- $errstr"; - // echo"Error number --- $errno"; -//echo"Error errfile --- $errfile"; - // echo"Error errline --- $errline"; - // Maybe we can construct the new errors here. This would allow the error personalization? And keep main code clean - - throw new nullException('Error in checking user grades: ' . $errstr, 0); - // exit; - } /** * Define a custom exception class, this will make pour tests meaningful diff --git a/classes/local/grade_helpers.php b/classes/local/grade_helpers.php index 4d7ef2e..a63bc37 100644 --- a/classes/local/grade_helpers.php +++ b/classes/local/grade_helpers.php @@ -26,8 +26,7 @@ defined('MOODLE_INTERNAL') || die(); use mod_cmi5launch\local\session_helpers; -use mod_cmi5launch\local\au_helpers; - +require_once ($CFG->dirroot . '/mod/cmi5launch/classes/local/errorover.php'); class grade_helpers { @@ -122,24 +121,25 @@ public function cmi5launch_highest_grade($scores) // Now apply intval. $highestgrade = intval($highestgrade); + + return $highestgrade; } + /** * Parses and retrieves AUs and their sessions from the returned info from CMI5 player and LRS and updates them. * @param array $user - the user whose grades are being updated. * @return array */ - public function cmi5launch_check_user_grades_for_updates($user) + public function cmi5launch_check_user_grades_for_updates($user, ) { global $cmi5launch, $USER, $DB; - // what is cmi5launch here in actual func? - - // Set error and exception handler to catch and override the default PHP error messages, to make messages more user friendly. - set_error_handler('mod_cmi5launch\local\grade_warning', E_WARNING); - set_exception_handler('mod_cmi5launch\local\exception_grade'); + // Set error and exception handler to catch and override the default PHP error messages, to make messages more user friendly. + set_error_handler('mod_cmi5launch\local\grade_warning', E_WARNING); + set_exception_handler('mod_cmi5launch\local\exception_grade'); // Check if record already exists. $exists = $DB->record_exists('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $user->id]); @@ -153,11 +153,10 @@ public function cmi5launch_check_user_grades_for_updates($user) $auids = json_decode($userscourse->aus); + // Bring in functions and classes. + $sessionhelper = new session_helpers; - - // Update the AUs - $returnedinfo = $this->cmi5launch_update_au_for_user_grades($auids, $user); - + $returnedinfo = $this->cmi5launch_update_au_for_user_grades($sessionhelper, $auids, $user); // Array to hold AU scores. $auscores = $returnedinfo[0]; $overallgrade = $returnedinfo[1]; @@ -165,7 +164,6 @@ public function cmi5launch_check_user_grades_for_updates($user) // Update course record. $userscourse->ausgrades = json_encode($auscores); $DB->update_record("cmi5launch_usercourse", $userscourse); - //echo" 1 branch"; // Restore default hadlers. restore_exception_handler(); restore_error_handler(); @@ -174,12 +172,11 @@ public function cmi5launch_check_user_grades_for_updates($user) } else { - // Should we return SOMEthing> $nograde = array(0 => 'No grades to update. No record for user found in this course.'); // Do nothing, there is no record for this user in this course. // Restore default hadlers. - restore_exception_handler(); - restore_error_handler(); + restore_exception_handler(); + restore_error_handler(); return $nograde; } @@ -199,118 +196,127 @@ public function cmi5launch_check_user_grades_for_updates($user) * @param mixed $auid * @return au|bool */ - public function cmi5launch_update_au_for_user_grades($auids, $user) + public function cmi5launch_update_au_for_user_grades($session_helpers, $auids, $user) { global $cmi5launch, $USER, $DB; - echo " HELLO I SHOULDN'T BE HERE?"; - $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); + // Set error and exception handler to catch and override the default PHP error messages, to make messages more user friendly. + set_error_handler('mod_cmi5launch\local\grade_warning', E_WARNING); + set_exception_handler('mod_cmi5launch\local\exception_grade'); + // Array to hold AU scores. $auscores = array(); $overallgrade = array(); + try { + // Bring in functions and classes. + $sessionhelper = $session_helpers; + // Functions from other classes. + $updatesession = $sessionhelper->cmi5launch_get_update_session(); - // Bring in functions and classes. - $sessionhelper = new session_helpers; + // Go through each Au, each Au will be responsible for updating its own session. + foreach ($auids as $key => $auid) { - // Functions from other classes. - $updatesession = $sessionhelper->cmi5launch_get_update_session(); + // Array to hold session scores for update. + $sessiongrades = array(); - // Go through each Au, each Au will be responsible for updating its own session. - foreach ($auids as $key => $auid) { - - - // Array to hold session scores for update. - $sessiongrades = array(); + // This uses the auid to pull the right record from the aus table. + $aurecord = $DB->get_record('cmi5launch_aus', ['id' => $auid]); - // This uses the auid to pull the right record from the aus table. - $aurecord = $DB->get_record('cmi5launch_aus', ['id' => $auid]); + // When it is null it is because the user has not launched the AU yet. + if (!$aurecord == null || false) { - // When it is null it is because the user has not launched the AU yet. - if (!$aurecord == null || false) { + // Check if there are sessions. + if (!$aurecord->sessions == null) { - // Check if there are sessions. - if (!$aurecord->sessions == null) { + // Retrieve session ids for this course. There may be more than one session. + $sessions = json_decode($aurecord->sessions, true); - // Retrieve session ids for this course. There may be more than one session. - $sessions = json_decode($aurecord->sessions, true); - - // Iterate through each session. - foreach ($sessions as $sessionid) { + // Iterate through each session. + foreach ($sessions as $sessionid) { - // Using current session id, retrieve session from DB. - $session = $DB->get_record('cmi5launch_sessions', ['sessionid' => $sessionid]); + // Using current session id, retrieve session from DB. + $session = $DB->get_record('cmi5launch_sessions', ['sessionid' => $sessionid]); - // the update session is call the ission - // we need to moick IT + // Retrieve new info (if any) from CMI5 player and LRS on session. + $session = $updatesession($sessionid, $cmi5launch->id, $user); - // Retrieve new info (if any) from CMI5 player and LRS on session. - $session = $updatesession($sessionid, $cmi5launch->id, $user); + // Now if the session is complete, passed, or terminated, we want to update the AU. + // These come in order, so the last one is the current status, so update on each one, + // overwrite as you go, and the last one if final. + if ($session->iscompleted == 1) { + // 0 is no 1 is yes, these are from players + $aurecord->completed = 1; + } + if ($session->ispassed == 1) { + // 0 is no 1 is yes, these are from players + $aurecord->passed = 1; + } + if ($session->isterminated == 1) { + // 0 is no 1 is yes, these are from players + $aurecord->terminated = 1; + } - // Now if the session is complete, passed, or terminated, we want to update the AU. - // These come in order, so the last one is the current status, so update on each one, - // overwrite as you go, and the last one if final. - if ($session->iscompleted == 1) { - // 0 is no 1 is yes, these are from players - $aurecord->completed = 1; - } - if ($session->ispassed == 1) { - // 0 is no 1 is yes, these are from players - $aurecord->passed = 1; - } - if ($session->isterminated == 1) { - // 0 is no 1 is yes, these are from players - $aurecord->terminated = 1; + // Add the session grade to array. + $sessiongrades[] = $session->score; } + // Save the session scores to AU, it is ok to overwrite. + $aurecord->scores = json_encode($sessiongrades, JSON_NUMERIC_CHECK); - // Add the session grade to array. - $sessiongrades[] = $session->score; - } - // Save the session scores to AU, it is ok to overwrite. - $aurecord->scores = json_encode($sessiongrades, JSON_NUMERIC_CHECK); - - // Determine gradetype and use it to save overall grade to AU. - $gradetype = $cmi5launchsettings["grademethod"]; - - switch ($gradetype) { - - // GRADE_AUS_CMI5 = 0. - // GRADE_HIGHEST_CMI5 = 1. - // GRADE_AVERAGE_CMI5 = 2. - // GRADE_SUM_CMI5 = 3. - - case 1: - $aurecord->grade = $this->cmi5launch_highest_grade($sessiongrades); - break; - case 2: - $aurecord->grade = $this->cmi5launch_average_grade($sessiongrades); - break; - default: - echo "Gradetype not found."; - } + // Determine gradetype and use it to save overall grade to AU. + $gradetype = $cmi5launchsettings["grademethod"]; + + switch ($gradetype) { - // Save AU scores to corresponding title. - $auscores[$aurecord->lmsid] = array($aurecord->title => $aurecord->scores); + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. - // Save an overall grade to array to be passed out to grade_update. - $overallgrade[] = $aurecord->grade; + case 1: + $aurecord->grade = $this->cmi5launch_highest_grade($sessiongrades); + break; + case 2: + $aurecord->grade = $this->cmi5launch_average_grade($sessiongrades); + break; + default: + echo("Gradetype not found."); + } - // Save Au title and their scores to AU. - // Save updates to DB. - $aurecord = $DB->update_record('cmi5launch_aus', $aurecord); + // Save AU scores to corresponding title. + $auscores[$aurecord->lmsid] = array($aurecord->title => $aurecord->scores); + // Save an overall grade \to be passed out to grade_update. + $overallgrade = $aurecord->grade; + + + // Save Au title and their scores to AU. + // Save updates to DB. + $aurecord = $DB->update_record('cmi5launch_aus', $aurecord); + + } } } - } - //Array to hold answer - $toreturn = array(0 => $auscores, 1 => $overallgrade); - // we need to return auscores and overallgrade. + // Array to hold answer. + $toreturn = array(0 => $auscores, 1 => $overallgrade); - return $toreturn; - } + // Restore default hadlers. + restore_exception_handler(); + restore_error_handler(); + return $toreturn; + } catch (\Throwable $e) { + + // Restore default handlers. + restore_exception_handler(); + restore_error_handler(); + + // If there is an error, return the error. + throw new nullException(" Error in updating or checking user grades. Report this error to system administrator: ". $e->getMessage()); + } + } } diff --git a/cmi5PHP/tests/cmi5TestHelpers.php b/cmi5PHP/tests/cmi5TestHelpers.php index 60acc02..c867dbc 100644 --- a/cmi5PHP/tests/cmi5TestHelpers.php +++ b/cmi5PHP/tests/cmi5TestHelpers.php @@ -5,7 +5,7 @@ use mod_cmi5launch\local\au; use mod_cmi5launch\local\au_helpers; use mod_cmi5launch\local\session; -use mod_cmi5launch\local\session_helpers; +//use mod_cmi5launch\local\session_helpers; use PHPUnit\Framework\TestCase; @@ -221,10 +221,10 @@ function maketestaus ($testcourseid) 'attempt' => $i, 'url' => 'url' . $i, 'type' => 'type' . $i, - 'lmsid' => 'lmsid' . $i, + 'lmsId' => 'lmsid' . $i, 'grade' => 'grade' . $i, 'scores' => 'scores' . $i, - 'title' => array(0 => array('text' => $i)), + 'title' => array(0 => array('text' => 'The title text ' . $i)), 'moveon' => 'moveon' . $i, 'auindex' => $i, 'parents' => 'parents' . $i, @@ -250,7 +250,12 @@ function maketestaus ($testcourseid) // maybe if we put the sessions here then we can skip the whole resaving thing $testcoursesessionids = maketestsessions(); $mockvalues['sessions'] = $testcoursesessionids; - $aus[] = new au($mockvalues); + + + $newau = new au($mockvalues); + + + $aus[] = $newau; } // Now save the fake aus to the test database @@ -259,7 +264,6 @@ function maketestaus ($testcourseid) - // Save AUs to test DB and save IDs. $newauids = $saveau($aus); @@ -455,7 +459,6 @@ function assign_sessions_to_aus($auids, $sessionids){ $check = $DB->record_exists( 'cmi5launch_aus', ['id' => $auid], '*', IGNORE_MISSING); - if (!$check) { // If check is negative, the record does not exist. Throw error. echo "

Error attempting to get AU data from DB. Check AU id.

"; @@ -475,6 +478,8 @@ function assign_sessions_to_aus($auids, $sessionids){ + // what is au record? + // Save the AU back to the DB. $success = $DB->update_record('cmi5launch_aus', $au); @@ -540,90 +545,7 @@ function assign_aus_to_courses($courseids, $auids){ } } -// New class -class session_helpers2 -{ - /** - * Creates a session record in DB. - * @param mixed $sessionid - the session id - * @param mixed $launchurl - the launch url - * @param mixed $launchmethod - the launch method - * @return void - */ - public function cmi5launch_create_sessio6n($sessionid, $launchurl, $launchmethod) { - - global $DB, $CFG, $cmi5launch, $USER; - - $table = "cmi5launch_sessions"; - - // Make a new record to save. - $newrecord = new \stdClass(); - // Because of many nested properties, needs to be done manually. - $newrecord->sessionid = $sessionid; - $newrecord->launchurl = $launchurl; - $newrecord->tenantname = $USER->username; - $newrecord->launchmethod = $launchmethod; - // I think here is where we eed to implement : moodlecourseid - $newrecord->moodlecourseid = $cmi5launch->id; - // And userid! - $newrecord->userid = $USER->id; - - // Save record to table. - $newid = $DB->insert_record($table, $newrecord, true); - - // Return value - return $newid; - - } - // So now all the test has to do is inject THIS which will return as we please - // We will inject the damn func! // inject this one! -function updatesessione($sessionid, $cmi5launchid, $user) -{ - global $DB, $cmi5launch, $USER; - - // Make new sessions, lets make five. - $sessions = array(); - $sessionids = array(); - - - $sessionids[] = $sessionid; - //$toaddtostring = strval($i); - // Add i to each value so the AUs are unique. - // Mock values to make sessions. - $mockvalues = array( - 'id' => $sessionid, - 'sessionid' => 'sessionid' . $sessionid, - 'userid' => 'userid' . $sessionid, - 'moodlecourseid' => 'moodlecourseid' . $sessionid, - 'registrationscoursesausid' => 'registrationscoursesausid' . $sessionid, - 'tenantname' => 'tenantname' . $sessionid, - 'createdat' => 'createdat' . $sessionid, - 'updatedat' => 'updatedat' . $sessionid, - 'code' => 'code' . $sessionid, - 'launchtokenid' => 'launchtokenid' . $sessionid, - 'lastrequesttime' => 'lastrequesttime' . $sessionid, - 'launchmode' => 'launchmode' . $sessionid, - 'masteryscore' => 'masteryscore' . $sessionid, - 'score' => 'score' . $sessionid, - 'islaunched' => 'islaunched' . $sessionid, - 'isinitialized' => 'isinitialized' . $sessionid, - 'duration' => 'duration' . $sessionid, - 'iscompleted' => 'iscompleted' . $sessionid, - 'ispassed' => 'ispassed' . $sessionid, - 'isfailed' => 'isfailed' . $sessionid, - 'isterminated' => 'isterminated' . $sessionid, - 'isabandoned' => 'isabandoned' . $sessionid, - 'progress' => 'progress' . $sessionid, - 'launchmethod' => 'launchmethod' . $sessionid, - 'launchurl' => 'launchurl' . $sessionid, - ); - $newsession = new session($mockvalues); - echo " Ive been calllled"; - return $newsession; - } - - } @@ -685,4 +607,128 @@ function cmi5launch_test_stream_and_send_excep($options, $url) throw new \Exception('test error'); } + // Ok lets make a new strea_helpers to override the other and enable testing + // New class +class session_helpers +{ + public function cmi5launch_get_create_session() { + return [$this, 'cmi5launch_create_session']; + } + + public function cmi5launch_get_update_session() { + return [$this, 'cmi5launch_update_sessions']; + } + + public function cmi5launch_get_retrieve_sessions_from_db() { + return [$this, 'cmi5launch_retrieve_sessions_from_db']; + } + + /** + * Gets updated session information from CMI5 player + * @param mixed $sessionid - the session id + * @param mixed $cmi5id - cmi5 instance id + * @return + */ + public function cmi5launch_update_sessions($sessionid, $cmi5id, $user) { + + + // Ok, lets make sure we are calling THIS one + // And not the other one + // echo "Calling from duplicate class!"; + $returnvalue = new \stdClass(); + $returnvalue->iscompleted = 1; + $returnvalue->ispassed = 1; + $returnvalue->isterminated = 1; + + $returnvalue->score = 80; + + // $returnvalue->score = 80; + return $returnvalue; + } + + /** + * Creates a session record in DB. + * @param mixed $sessionid - the session id + * @param mixed $launchurl - the launch url + * @param mixed $launchmethod - the launch method + * @return void + */ + public function cmi5launch_create_session($sessionid, $launchurl, $launchmethod) { + + global $DB, $CFG, $cmi5launch, $USER; + + $table = "cmi5launch_sessions"; + + // Make a new record to save. + $newrecord = new \stdClass(); + // Because of many nested properties, needs to be done manually. + $newrecord->sessionid = $sessionid; + $newrecord->launchurl = $launchurl; + $newrecord->tenantname = $USER->username; + $newrecord->launchmethod = $launchmethod; + // I think here is where we eed to implement : moodlecourseid + $newrecord->moodlecourseid = $cmi5launch->id; + // And userid! + $newrecord->userid = $USER->id; + + // Save record to table. + $newid = $DB->insert_record($table, $newrecord, true); + + // Return value + return $newid; + + } + + /** + * Retrieves session from DB + * @param mixed $sessionid - the session id + * @return session + */ + public function cmi5launch_retrieve_sessions_from_db($sessionid) { + + global $DB, $CFG; + + $check = $DB->record_exists('cmi5launch_sessions', ['sessionid' => $sessionid], '*', IGNORE_MISSING); + + // If check is negative, the record does not exist. Throw error. + if (!$check) { + + echo "

Error attempting to get session data from DB. Check session id.

"; + echo "
";
+            var_dump($sessionid);
+            echo "
"; + + } else { + + $sessionitem = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + + $session = new session($sessionitem); + + } + + // Return new session object. + return $session; + } + +} + +// To pass to the test and cause exception +class session_helpers2 +{ + /** + * Gets updated session information from CMI5 player and throw exception + * @param mixed $sessionid - the session id + * @param mixed $cmi5id - cmi5 instance id + * @return + */ + public function cmi5launch_update_sessions($sessionid, $cmi5id, $user) { + + // $returnvalue->score = 80; + return null; + } +} + + + + ?> diff --git a/cmi5PHP/tests/grade_helpersTest.php b/cmi5PHP/tests/grade_helpersTest.php index 2a808a3..a18304e 100644 --- a/cmi5PHP/tests/grade_helpersTest.php +++ b/cmi5PHP/tests/grade_helpersTest.php @@ -2,13 +2,9 @@ namespace cmi5Test; -use Exception; use mod_cmi5launch\local\grade_helpers; use mod_cmi5launch\local\nullException; -use mod_cmi5launch\local\fieldException; use PHPUnit\Framework\TestCase; -use mod_cmi5launch\local\cmi5_connectors; - require_once( "cmi5TestHelpers.php"); @@ -34,23 +30,10 @@ public static function tearDownAfterClass(): void { global $DB, $cmi5launch, $cmi5launchid, $USER, $testcourseid, $testcourseausids, $testcoursesessionids, $cmi5launchsettings; - // Delete the test record. - // deletetestcmi5launch($cmi5launchid); - - // Delete the test course. - // deletetestcmi5launch_usercourse($cmi5launchid); - - // Delete the test AUs. - // deletetestcmi5launch_aus($testcourseausids); - - // Delete the test sessions. - // deletetestcmi5launch_sessions($testcoursesessionids); - - + // Restore overridden global variable. unset($GLOBALS['USER']); - // unset($GLOBALS['DB']); unset($GLOBALS['cmi5launchsettings']); unset($GLOBALS['cmi5launch']); unset($GLOBALS['cmi5launchid']); @@ -67,7 +50,24 @@ protected function setUp(): void // Make a fake cmi5 launch record. $cmi5launchid = maketestcmi5launch(); - $cmi5launchsettings = array("cmi5launchtenanttoken" => "Testtoken", "cmi5launchplayerurl" => "http://test/launch.php", "cmi5launchcustomacchp" => "http://testhomepage.com"); + // Assign the new id as the cmi5launch id. + $cmi5launch->id = $cmi5launchid; + // Update db + $DB->update_record('cmi5launch', $cmi5launch); + // Gradetypes for ref + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. + $cmi5launchsettings = array( + "cmi5launchlrsendpoint" => "Test LRS point", + "cmi5launchlrslogin" => "Test LRS login", + "cmi5launchlrspass" => "Test LRS password", + "cmi5launchtenanttoken" => "Testtoken", + "cmi5launchplayerurl" => "http://test/launch.php", + "cmi5launchcustomacchp" => "http://testhomepage.com", + "grademethod" => 1 + ); // Override global variable and function so that it returns test data. $USER = new \stdClass(); @@ -75,22 +75,20 @@ protected function setUp(): void $USER->id = 10; // Make test course, AUs and sessions. - $testcourseid = maketestcourse($cmi5launchid); + $testcourseid = maketestcourse($cmi5launchid); $testcourseausids = maketestaus($testcourseid); $testcoursesessionids = maketestsessions(); // Assign the sessions to AUs. $newaus = assign_sessions_to_aus($testcourseausids, $testcoursesessionids); - //what are the testcourseauids here> - // Assign the AUs to the course. assign_aus_to_courses($testcourseid, $testcourseausids); - } + } protected function tearDown(): void { - + } @@ -106,10 +104,9 @@ public function testcmi5launch_average_grade_multiple() // Scores as an array. $scoresarray = array (1,2,3,4,5); - // Scores as a (json_encoded) string. - $scoresstring = json_encode($scoresarray); + // Scores as a (json_encoded) string. + $scoresstring = json_encode($scoresarray); - // So the average of either should be. $average = 3; @@ -133,6 +130,7 @@ public function testcmi5launch_average_grade_multiple() $this->assertIsInt($resultarray); } + /* * Test of the cmi5launch_average_grade method. * This takes scores and averages them. @@ -141,7 +139,6 @@ public function testcmi5launch_average_grade_multiple() */ public function testcmi5launch_average_grade_singular() { - // Scores as an array. $scoresarray = array (0 => 3); @@ -359,9 +356,8 @@ public function testcmi5launch_highest_grade_zero() } /* - * Test of the cmi5launch_highest_grade method. - * This takes scores and returns the highest one of them. - * // We need to test with scores being a 0 and string and int. + * Test of the cmi5launch_check_user_grades_for_updates method. + * Parses and retrieves AUs and their sessions from the returned info from CMI5 player and LRS and updates them. * @return void */ public function testcmi5launch_check_user_grades_for_updates() @@ -377,14 +373,8 @@ public function testcmi5launch_check_user_grades_for_updates() $auids = json_decode($userscourse->aus); - // So the systems under test does a lot, may need refactoring - // But we will need the testcourseid and userid to get the"usercourse" - // Ah the user course has aus in it and the function grabs them, then for each au grabs their session - // huhthese should be refactored into smaller functions. - // well then again it already is a lot of calls so maybe its fine - // I dunno, my brain says its frisday - // Array to return + // Array to return. $returnvalue = array(0 => array( "lmsid" => array( "Title of AU" => 80, @@ -397,20 +387,19 @@ public function testcmi5launch_check_user_grades_for_updates() ), ); - // so lets start by pretending to call finction under test - // I have to start somewhere // Mock a cmi5 connector object but only stub ONE method, as we want to test the others. $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\grade_helpers') ->onlyMethods(array('cmi5launch_update_au_for_user_grades')) ->getMock(); - - // Ok, the arrgs ar the same, the name is the same. What is YES! its not calling the mocked class!!!!! + $sessionhelper = new \mod_cmi5launch\local\session_helpers;; + // Mock returns json encoded data, as it would be from the player. $mockedclass->expects($this->once()) ->method('cmi5launch_update_au_for_user_grades') - ->with($auids, $USER) + ->with($sessionhelper, $auids, $USER) ->willReturn($returnvalue); + // Bring in functions and classes. $gradehelper = new grade_helpers; @@ -419,17 +408,16 @@ public function testcmi5launch_check_user_grades_for_updates() $result = $checkusergrades($USER); - // it should return only the overall grade, the other grades being for updating the records in DB. + // It should return only the overall grade, the other grades being for updating the records in DB. $this->assertEquals($returnvalue[1], $result); - // IT should be an array + // It should be an array. $this->assertIsArray($result); - } - /* - * Test of the cmi5launch_highest_grade method. - * This one tests if their are no rades for updates + /* + * Test of the cmi5launch_check_user_grades_for_updates method. + * This one tests if their are no grades for updates. * @return void */ public function testcmi5launch_check_user_grades_for_updates_no_grade() @@ -439,22 +427,7 @@ public function testcmi5launch_check_user_grades_for_updates_no_grade() // If we pass it the wrong user id then it cant find the usercourse and we can test that path. $USER->id = 100; $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); - // Retrieve the record. - // $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); - - // $auids = json_decode($userscourse->aus); - - // So the systems under test does a lot, may need refactoring - // But we will need the testcourseid and userid to get the"usercourse" - // Ah the user course has aus in it and the function grabs them, then for each au grabs their session - // huhthese should be refactored into smaller functions. - // well then again it already is a lot of calls so maybe its fine - // I dunno, my brain says its frisday - - // so lets start by pretending to call finction under test - // I have to start somewhere - // Mock a cmi5 connector object but only stub ONE method, as we want to test the others. - + // Bring in functions and classes. $gradehelper = new grade_helpers; @@ -465,14 +438,14 @@ public function testcmi5launch_check_user_grades_for_updates_no_grade() $result = $checkusergrades($USER); - // it should return only the overall grade, the other grades being for updating the records in DB. + // It should return only the overall grade, the other grades being for updating the records in DB. $this->assertEquals($returnvalue, $result[0]); - // IT should be an array + // It should be an array. $this->assertIsArray($result); } /* - * Test of the cmi5launch_highest_grade method. + * Test of the cmi5launch_check_user_grades_for_update. * This one tests if something goes wrong, and throws an exception * @return void */ @@ -481,99 +454,270 @@ public function testcmi5launch_check_user_grades_for_updates_excep() global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); - // Retrieve the record. - $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); + + // Retrieve the record. + $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); - $auids = json_decode($userscourse->aus); + $auids = json_decode($userscourse->aus); - // $auids = json_decode($userscourse->aus); - // so lets start by pretending to call finction under test - // I have to start somewhere // Mock a cmi5 connector object but only stub ONE method, as we want to test the others. $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\grade_helpers') ->onlyMethods(array('cmi5launch_update_au_for_user_grades')) ->getMock(); - - // If it returns null this should throw a null error exception. + $sessionhelper = new \mod_cmi5launch\local\session_helpers; $mockedclass->expects($this->once()) ->method('cmi5launch_update_au_for_user_grades') - ->with($auids, $USER) + ->with($sessionhelper, $auids, $USER) ->willReturn(null); // Functions from other classes. $checkusergrades = $mockedclass->get_cmi5launch_check_user_grades_for_updates(); - // Expected exceptions + // Expected exceptions. $expected = " Error in updating or checking user grades. Report this error to system administrator: Error in checking user grades: Trying to access array offset on null"; - - - // Expected exceptions and messages $result = $checkusergrades($USER); - // Because this exception is thrown by the error handler, not the SUT, test the output to ensure right exception was thrown. - $this->expectOutputString($expected); + // Because this exception is thrown by the error handler, not the SUT, test the output to ensure right exception was thrown. + $this->expectOutputString($expected); } - /* + /* * Test of the cmi5launch_update_au_for_user_grades method. - + * This one tests if the grades are returned highest. * @return void */ - public function testcmi5launch_update_au_for_user_grades() + public function testcmi5launch_update_au_for_user_grades_highest() { global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; - // global $session_helper; + $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); - // Retrieve the record. - $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); + + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. + $cmi5launchsettings["grademethod"] = 1; + + // Retrieve the record. + $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); - - // The problem is that AUS needs to be an array of numbers and ita - // an actual au + // Call the TEST version of session helpers to pass. + $sessionhelper = new \cmi5Test\session_helpers; + $auids = json_decode($userscourse->aus); - // So the systems under test does a lot, may need refactoring - // But we will need the testcourseid and userid to get the"usercourse" - // Ah the user course has aus in it and the function grabs them, then for each au grabs their session - // huhthese should be refactored into smaller functions. - // well then again it already is a lot of calls so maybe its fine - // I dunno, my brain says its frisday - - // Session to return to return - $returnvalue = new \stdClass(); - $returnvalue->iscompleted = 1; - $returnvalue->ispassed = 1; - $returnvalue->isterminated = 1; - $returnvalue->score = 80; - - // so lets start by pretending to call finction under test - // I have to start somewhere - // Mock a cmi5 connector object but only stub ONE method, as we want to test the others. - - $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\grade_helpers') - ->addMethods(array('cmi5launch_get_update_session')) - ->getMock(); + // Bring in functions and classes. + $gradehelper = new grade_helpers; - // Mock returns json encoded data, as it would be from the player. - $mockedclass->expects($this->once()) - ->method('cmi5launch_get_update_session'); - //->with($auids, $USER) - // ->willReturn($returnvalue); - + // Functions from other classes. + $updateau = $gradehelper->get_cmi5launch_update_au_for_user_grades(); + + $result = $updateau($sessionhelper, $auids, $USER); + // Result should be an array. + $this->assertIsArray($result); + + // And it is an array of two parts, one for the lmsid, and within it, the title and score of that title. + // And the second, the overall grade of ALL the aus (lmsids). + $this->assertArrayHasKey(0, $result); + // The lmsid and title will have different number endings but should all contain the same base string, + $lmsid = $result[0]; + $this->assertIsArray($lmsid); + + $this->assertStringStartsWith('lmsid', array_key_first($lmsid)); + + // Now finagle to get the title array + $title = $result[0][array_key_first($lmsid)]; + + // Shouild be an array where the title is key and the value is score + $this->assertIsArray($title); + $this->assertStringStartsWith('The title text', array_key_first($title)); + // And finally the value of the 'title' is a json string equalling all the session scores, in this case we + // made five and each was 80. + $scoresshouldbe = "[80,80,80,80,80]"; + $this->assertEquals($scoresshouldbe, $title[array_key_first($title)]); + + // And finally the overall grade which in this instance is the highest of all the scores, or just 80. + $this->assertArrayHasKey(1, $result); + $this->assertEquals(80, $result[1]); + } + + + /* + * Test of the cmi5launch_update_au_for_user_grades method. + * This one tests if the grades are returned averaged. + * @return void + */ + public function testcmi5launch_update_au_for_user_grades_average() + { + global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; + + $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); + + // Gradetype for reference. + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. + $cmi5launchsettings["grademethod"] = 2; + + // Retrieve the record. + $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); + + // Implement the duplicate of session helper to pass through. + $sessionhelper = new \cmi5Test\session_helpers; + + $auids = json_decode($userscourse->aus); + + // Bring in functions and classes. + $gradehelper = new grade_helpers; + + // Functions from other classes. + $updateau = $gradehelper->get_cmi5launch_update_au_for_user_grades(); + + $result = $updateau($sessionhelper, $auids, $USER); + + $this->assertIsArray($result); - // Bring in functions and classes. + // And it is an array of two parts, one for the lmsid, and within it, the title and score of that title + // and the second, the overall grade of ALL the aus (lmsids). + $this->assertArrayHasKey(0, $result); + // The lmsid and title will have different number endings but should all contain the same base string, + $lmsid = $result[0]; + $this->assertIsArray($lmsid); + + $this->assertStringStartsWith('lmsid', array_key_first($lmsid)); + + // Now finagle to get the title array. + $title = $result[0][array_key_first($lmsid)]; + + // Should be an array where the title is key and the value is score. + $this->assertIsArray($title); + $this->assertStringStartsWith('The title text', array_key_first($title)); + + // And finally the value of the 'title' is a json string equalling all the session scores, in this case we + // made five and each was 80. + $scoresshouldbe = "[80,80,80,80,80]"; + $this->assertEquals($scoresshouldbe, $title[array_key_first($title)]); + + // And finally the overall grade which in this instance is the average to all the scores, or just 80. + $this->assertArrayHasKey(1, $result); + + $this->assertEquals(80, $result[1]); + } + + + /* + * Test of the cmi5launch_update_au_for_user_grades method. + * Tests the function if there is a bad gradetype selected (this shouldn't ever happen). + * @return void + */ + public function testcmi5launch_update_au_for_user_grades_bad_gradetype() + { + global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; + + $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); + + // Gradetype for ref, passing in invalid value. + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. + $cmi5launchsettings["grademethod"] = 6; + + // Retrieve the record. + $userscourse = $DB->get_record('cmi5launch_usercourse', ['courseid' => $cmi5launch->courseid, 'userid' => $USER->id]); + + // Implement the duplicate of session helper to pass through function. + $sessionhelper = new \cmi5Test\session_helpers; + + $auids = json_decode($userscourse->aus); + + // Bring in functions and classes. $gradehelper = new grade_helpers; // Functions from other classes. - $updateau = $mockedclass->get_cmi5launch_update_au_for_user_grades(); + $updateau = $gradehelper->get_cmi5launch_update_au_for_user_grades(); + + $result = $updateau($sessionhelper, $auids, $USER); + + // There will be five of these, one for each au. + $this->expectOutputString("Gradetype not found.Gradetype not found.Gradetype not found.Gradetype not found.Gradetype not found."); + + $this->assertIsArray($result); + + // And it is an array of two parts, one for the lmsid, and within it, the title and score of that title + // and the second, the overall grade of ALL the aus (lmsids). + $this->assertArrayHasKey(0, $result); + // The lmsid and title will have different number endings but should all contain the same base string, + $lmsid = $result[0]; + $this->assertIsArray($lmsid); + + $this->assertStringStartsWith('lmsid', array_key_first($lmsid)); + + // Now finagle to get the title array + $title = $result[0][array_key_first($lmsid)]; + + // Shouild be an array where the title is key and the value is score. + $this->assertIsArray($title); + $this->assertStringStartsWith('The title text', array_key_first($title)); + + // And the value of the 'title' is a json string equalling all the session scores, in this case we + // made five and each was 80. + $scoresshouldbe = "[80,80,80,80,80]"; + $this->assertEquals($scoresshouldbe, $title[array_key_first($title)]); + + // And finally the overall grade in this instance will still be 80, because that is the saved value and hasnt been changed. + $this->assertArrayHasKey(1, $result); + + $this->assertEquals(80, $result[1]); + } + + + /* + * Test of the cmi5launch_update_au_for_user_grades method. + // Testing when exception is thrown + * @return void + */ + public function testcmi5launch_update_au_for_user_grades_excep() + { + global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; + + $cmi5launchsettings = cmi5launch_settings($cmi5launch->id); + + // Gradetype for reference. + // GRADE_AUS_CMI5 = 0. + // GRADE_HIGHEST_CMI5 = 1. + // GRADE_AVERAGE_CMI5 = 2. + // GRADE_SUM_CMI5 = 3. + $cmi5launchsettings["grademethod"] = 1; + + // Implement the duplicate of session helper to pass through function. + $sessionhelper = new \cmi5Test\session_helpers; + + // By passing the auid as a string the function should throw an exception. + $auids = "Throw an error"; + + // Bring in functions and classes. + $gradehelper = new grade_helpers; + + // Functions from other classes. + $updateau = $gradehelper->get_cmi5launch_update_au_for_user_grades(); + + // The expected is built bby the two messages knowing 'title' is an empty array. + $expected = "Error in updating or checking user grades. Report this error to system administrator: Error in checking user grades:"; + + // Catch the exception. + $this->expectException(nullException::class); + $this->expectExceptionMessage($expected); - $result = $updateau($auids, $USER); - // Because this exception is thrown by the error handler, not the SUT, test the output to ensure right exception was thrown. - $this->expectOutputString("test"); + + $result = $updateau($sessionhelper, $auids, $USER); + } + }