From 921e3a5303f3727b854bf7e0000a45f312529528 Mon Sep 17 00:00:00 2001
From: ADLMeganBohland
Error attempting to get AU data from DB. Check AU id.
"; + } + // Assiging the sessions to the aus $au = $retrieve_aus($auid); + // I bet an argument one string being array is in the au itself + + + // Tomorrow: no that isnt it. Something else is throwin the problem. // Now the AU will have properties and we want to assign the sessionid array to the 'sessions' property - $au->sessions = $sessionids; + $au->sessions = json_encode($sessionids); + // Update AU in table with new info. + + //echo au here nd check what sessons itr and if id mathces + + + + + // Save the AU back to the DB. + $success = $DB->update_record('cmi5launch_aus', $au); + - $newaus[] = $au; + + $newaus[] = $au; } + // AHA! They are whole damn aus // now save the new aus back to db - $save_aus($newaus); - } + // we dont need to sve twice!!! + // $save_aus($newaus); + // Save us is to make new aus we need to save them back to DB + // Now update to table. + //return $newauids; + + } /** * Heeelper func that assigns the aus made to the course(s) for testing purposes. @@ -458,6 +507,7 @@ function assign_aus_to_courses($courseids, $auids){ // Mooonday- there are no course helpers so just call the course, assign the auids // and then save ther course with DB calls + // Retreive the courses // Imust have copied below from the func above, it doesn't seem relevant $au_helpers = new au_helpers(); @@ -466,21 +516,117 @@ function assign_aus_to_courses($courseids, $auids){ //Array to holdd newly created AUs $newaus = array(); + + // if its an int + if (!is_array($courseids)){ + $courseids = array($courseids); + } // First populate the aus with the sessions foreach ($courseids as $courseid ){ // Get the course $record = $DB->get_record('cmi5launch_usercourse', array('id' => $courseid)); + // somewhere between thie au ids above and being encoded below its effin uop // Assigning the sessions to the aus - $record->aus == $auids; - + // Its like its not assigning it. + + // AHA What is auids here? + + $record->aus = json_encode($auids); + // Save the course back to the db. - $DB->update_record('cmi5launch_usercourse', $record); + $success = $DB->update_record('cmi5launch_usercourse', $record); } } +// 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; + } + + } + + + /* function get_file_get_contents() { diff --git a/cmi5PHP/tests/grade_helpersTest.php b/cmi5PHP/tests/grade_helpersTest.php index 6a8753c..2a808a3 100644 --- a/cmi5PHP/tests/grade_helpersTest.php +++ b/cmi5PHP/tests/grade_helpersTest.php @@ -2,7 +2,10 @@ 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; @@ -19,32 +22,12 @@ class grade_helpersTest extends TestCase { + // Use setupbefore and after class sparingly. In this case, we don't want to use it to connect tests, but rather to // 'prep' the test db with values the tests can run against. public static function setUpBeforeClass(): void { - global $DB, $cmi5launch, $cmi5launchid, $USER, $testcourseid, $testcourseausids, $testcoursesessionids, $cmi5launchsettings; - - // Make a fake cmi5 launch record. - $cmi5launchid = maketestcmi5launch(); - - $cmi5launchsettings = array("cmi5launchtenanttoken" => "Testtoken", "cmi5launchplayerurl" => "http://test/launch.php", "cmi5launchcustomacchp" => "http://testhomepage.com"); - - // Override global variable and function so that it returns test data. - $USER = new \stdClass(); - $USER->username = "testname"; - $USER->id = 10; - - // Make test course, AUs and sessions. - $testcourseid = maketestcourse($cmi5launchid); - $testcourseausids = maketestaus($testcourseid); - $testcoursesessionids = maketestsessions($testcourseid); - - // Assign the sessions to AUs. - assign_sessions_to_aus($testcourseausids, $testcoursesessionids); - - // Assign the AUs to the course. - assign_aus_to_courses($testcourseid, $testcourseausids); + } public static function tearDownAfterClass(): void @@ -52,21 +35,22 @@ public static function tearDownAfterClass(): void global $DB, $cmi5launch, $cmi5launchid, $USER, $testcourseid, $testcourseausids, $testcoursesessionids, $cmi5launchsettings; // Delete the test record. - deletetestcmi5launch($cmi5launchid); + // deletetestcmi5launch($cmi5launchid); // Delete the test course. - deletetestcmi5launch_usercourse($cmi5launchid); + // deletetestcmi5launch_usercourse($cmi5launchid); // Delete the test AUs. - deletetestcmi5launch_aus($testcourseausids); + // deletetestcmi5launch_aus($testcourseausids); // Delete the test sessions. - deletetestcmi5launch_sessions($testcoursesessionids); + // deletetestcmi5launch_sessions($testcoursesessionids); + // Restore overridden global variable. unset($GLOBALS['USER']); - unset($GLOBALS['DB']); + // unset($GLOBALS['DB']); unset($GLOBALS['cmi5launchsettings']); unset($GLOBALS['cmi5launch']); unset($GLOBALS['cmi5launchid']); @@ -78,6 +62,30 @@ public static function tearDownAfterClass(): void protected function setUp(): void { + global $DB, $cmi5launch, $cmi5launchid, $USER, $testcourseid, $testcourseausids, $testcoursesessionids, $cmi5launchsettings; + + // Make a fake cmi5 launch record. + $cmi5launchid = maketestcmi5launch(); + + $cmi5launchsettings = array("cmi5launchtenanttoken" => "Testtoken", "cmi5launchplayerurl" => "http://test/launch.php", "cmi5launchcustomacchp" => "http://testhomepage.com"); + + // Override global variable and function so that it returns test data. + $USER = new \stdClass(); + $USER->username = "testname"; + $USER->id = 10; + + // Make test course, AUs and sessions. + $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 @@ -360,7 +368,14 @@ public function testcmi5launch_check_user_grades_for_updates() { global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; + // what is cmi5launch here in test? + $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" @@ -369,32 +384,194 @@ public function testcmi5launch_check_user_grades_for_updates() // well then again it already is a lot of calls so maybe its fine // I dunno, my brain says its frisday + // Array to return + $returnvalue = array(0 => array( + "lmsid" => array( + "Title of AU" => 80, + "Title of AU2" => 100), + ), + 1 => array( + "overallgrade" => array( + "0" => 80, + "1" => 100), + ), + ); + // 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!!!!! + // 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) + ->willReturn($returnvalue); + // Bring in functions and classes. + $gradehelper = new grade_helpers; + + // Functions from other classes. + $checkusergrades = $mockedclass->get_cmi5launch_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. + $this->assertEquals($returnvalue[1], $result); + // 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 + * @return void + */ + public function testcmi5launch_check_user_grades_for_updates_no_grade() + { + global $cmi5launch, $USER, $DB, $testcourseid, $cmi5launchsettings; + + // 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; // Functions from other classes. - $updatesession = $gradehelper->get_cmi5launch_check_user_grades_for_updates(); + $checkusergrades = $gradehelper->get_cmi5launch_check_user_grades_for_updates(); - $result = $updatesession($USER); + $returnvalue = "No grades to update. No record for user found in this course."; + + $result = $checkusergrades($USER); + + // 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 + $this->assertIsArray($result); + + } + /* + * Test of the cmi5launch_highest_grade method. + * This one tests if something goes wrong, and throws an exception + * @return void + */ + 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]); - // Ok once called the function checks that the user course with - // cmi5launch->courseid and user->id exists - // If it doesn't returns false (this will be a separate test) - // if it does, continue... - // continuing on we retrieve it - // if usercourse is null (as oppossed to doesn't exit???) then they have net participaated in course yet and it return overall grade - // Except I found an error BECAUSE overall grade doesn't exist yet! - // So either it never fins null or and I need to nix that path, - // OR im lucky and need to declare overall elsewher - // wait, either way yhtis is lucky, how has this never thrown error? A usercourse cant be null right? Then it would have just been false. - // If yep, I think this whole branch is phony baloeny, not the return part, that is for EVERYONE, but the null part, there is no null + $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. + $mockedclass->expects($this->once()) + ->method('cmi5launch_update_au_for_user_grades') + ->with($auids, $USER) + ->willReturn(null); + + // Functions from other classes. + $checkusergrades = $mockedclass->get_cmi5launch_check_user_grades_for_updates(); - // Ok, moving on the usercoure->aus are decoded, so we will want to make our test usercourse have aus + // 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); + + } + + /* + * Test of the cmi5launch_update_au_for_user_grades method. + + * @return void + */ + public function testcmi5launch_update_au_for_user_grades() + { + 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]); + + + // The problem is that AUS needs to be an array of numbers and ita + // an actual au + $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(); + + // 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); + + + // Bring in functions and classes. + $gradehelper = new grade_helpers; + + // Functions from other classes. + $updateau = $mockedclass->get_cmi5launch_update_au_for_user_grades(); - // B + $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"); } } diff --git a/version.php b/version.php index e5b7f56..03d7656 100755 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024061115; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2024072517; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2015111000; // Requires Moodle 3.0 version. $plugin->cron = 0; // Period for cron to check this module (secs). diff --git a/view.php b/view.php index 7fde793..62c29d0 100755 --- a/view.php +++ b/view.php @@ -210,7 +210,7 @@ function mod_cmi5launch_launchexperience(registrationInfo) { $auscores = array(); // Query CMI5 player for updated registration info. -$registrationinfofromcmi5 = $getregistrationinfo($registrationid, $cmi5launch->id); +$registrationinfofromcmi5 = json_decode($getregistrationinfo($registrationid, $cmi5launch->id), true); // Take only info about AUs out of registrationinfofromcmi5. $ausfromcmi5 = array_chunk($registrationinfofromcmi5["metadata"]["moveOn"]["children"], 1, true); From 5e5de75a04412ab850c709087f9164a4c33e61fd Mon Sep 17 00:00:00 2001 From: ADLMeganBohlandError 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); + } + } From 109c0f7db6e3fcd24ea09e7c5bcc1400b53f7aa9 Mon Sep 17 00:00:00 2001 From: ADLMeganBohland
Error attempting to get session data from DB. Check session id.
"; - echo ""; - var_dump($sessionid); - echo ""; + // Restore default handlers. + restore_exception_handler(); + restore_error_handler(); - } else { + // Return value + return $newid; + } catch (\Throwable $e) { - $sessionitem = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + // Restore default handlers. + restore_exception_handler(); + restore_error_handler(); - $session = new session($sessionitem); + // If there is an error, return the error. + throw new nullException("Error in creating session. Report this error to system administrator: ". $e->getMessage()); } - - // Return new session object. - return $session; } -} + } diff --git a/cmi5PHP/tests/cmi5TestHelpers.php b/cmi5PHP/tests/cmi5TestHelpers.php index 69658ca..94a40bc 100644 --- a/cmi5PHP/tests/cmi5TestHelpers.php +++ b/cmi5PHP/tests/cmi5TestHelpers.php @@ -867,7 +867,7 @@ public function cmi5launch_get_retrieve_sessions_from_db() { * @param mixed $cmi5id - cmi5 instance id * @return */ - public function cmi5launch_update_sessions($sessionid, $cmi5id, $user) { + public function cmi5launch_update_sessions2($sessionid, $cmi5id, $user) { // Ok, lets make sure we are calling THIS one @@ -947,26 +947,63 @@ public function cmi5launch_retrieve_sessions_from_db($sessionid) { // Return new session object. return $session; } - } + // MAke a new progress class for overriding + // New class +class progress{ -// 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; + public function cmi5launch_get_retrieve_statements() { + return [$this, 'cmi5launch_retrieve_statements']; } -} +public function cmi5launch_retrieve_statements($registrationid, $session) { + + global $DB, $CFG, $cmi5launch, $USER; + // We need session objects to test the progress class + // Make a fake session object. + $sessionlrs = $session; + + // Change the session to have some new values from LRS. + $sessionlrs->isterminated = 1; + $sessionlrs->launchurl = "http://test.com"; + + return $sessionlrs; + + } + +} + // MAke a new cmi5 connectors class for overriding + // New class + class cmi5_connectors{ + public function cmi5launch_get_session_info() { + return [$this, 'cmi5launch_retrieve_session_info_from_player']; + } + public function cmi5launch_retrieve_session_info_from_player($sessionid, $id) { + global $DB, $CFG, $cmi5launch, $USER; + // We need session objects to test the progress class + // Make a fake session object. + $sessionids = maketestsessions(); + + // We just need one session to test this. + $sessionid = $sessionids[0]; + + // Get the session from DB with session id. + $sessioncmi5 = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + + // Change the session from cmi5 to have some new values. + $sessioncmi5->score = 100; + $sessioncmi5->iscompleted = 1; + $sessioncmi5->ispassed = 1; + $sessioncmi5->launchmethod = "ownWindow"; + // Change the session to have some new values from to match lrs values. + $sessioncmi5->isterminated = 1; + $sessioncmi5->launchurl = "http://test.com"; + + return json_encode($sessioncmi5); + } + + } ?> diff --git a/cmi5PHP/tests/session_helpersTest.php b/cmi5PHP/tests/session_helpersTest.php new file mode 100644 index 0000000..4fa601d --- /dev/null +++ b/cmi5PHP/tests/session_helpersTest.php @@ -0,0 +1,257 @@ + "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(); + $USER->username = "testname"; + $USER->id = 10; + + $testcourseid = maketestcourse($cmi5launchid); + + // We need session objects to test the progress class + // Make a fake session object. + $sessionids = maketestsessions(); + } + + protected function tearDown(): void + { + global $sessionids; + // Restore overridden global variable. + unset($GLOBALS['USER']); + unset($GLOBALS['cmi5launchsettings']); + + deletetestcmi5launch_sessions($sessionids); + } + + + /** + * Test of the cmi5launch_update_sessions with a pass condition. + * @return void + */ + public function testcmi5launch_update_sessions() + { + global $DB, $cmi5launch, $cmi5launchid, $sessionids, $USER; + + // We just need one session to test this. + $sessionid = $sessionids[0]; + + // Retrieve the session object. + // Get the session from DB with session id. + $session = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + + // So expected session should be the same as session with the other two changes. + $sessionexpected = $session; + $sessionexpected->score = 100; + $sessionexpected->iscompleted = 1; + $sessionexpected->ispassed = 1; + $sessionexpected->launchmethod = "ownWindow"; + $sessionexpected->isterminated = 1; + $sessionexpected->launchurl = "http://test.com"; + + // New session_helpers from mod_cmi5launch + $helpers = new \mod_cmi5launch\local\session_helpers(); + + + $progress = new \cmi5Test\progress(); + $cmi5 = new \cmi5Test\cmi5_connectors(); + + // Result of the function. + $helpers->cmi5launch_update_sessions($progress, $cmi5, $sessionid, $cmi5launchid, $USER); + + // So the func doesn't return anything, but we can check the session object in the db. + // Get the session from DB with session id. + $result = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + + // Result should be a session object. + $this->assertIsObject($result, "Result should be an object."); + + // Check that the result is the same as the expected session. + $this->assertEquals($sessionexpected, $result, "Result should be the same as the expected session."); + } + + + /** + * Test of the cmi5launch_update_sessions with an exception. + * @return void + */ + public function testcmi5launch_update_sessions_excep() + { + global $DB, $cmi5launch, $cmi5launchid, $sessionids, $USER; + + // We just need one session to test this. + $sessionid = $sessionids[0]; + + // Retrieve the session object. + // Get the session from DB with session id. + $session = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid)); + + $exceptionmessage = 'Error in updating session. Report this error to system administrator: Attempt to assign property "isterminated" on false'; + // So expected session should be the same as session with the other two changes. + $sessionexpected = $session; + $sessionexpected->score = 100; + $sessionexpected->iscompleted = 1; + $sessionexpected->ispassed = 1; + $sessionexpected->launchmethod = "ownWindow"; + $sessionexpected->isterminated = 1; + $sessionexpected->launchurl = "http://test.com"; + + // New session_helpers from mod_cmi5launch + $helpers = new \mod_cmi5launch\local\session_helpers(); + + $progress = new \cmi5Test\progress(); + $cmi5 = new \cmi5Test\cmi5_connectors(); + + // Wait, i bet this is being thrown in the cmi5 connectors error message func and so we need to catch + // the correct output not an exception + $output = "
Error attempting to get session data from DB. Check session id.";
+ // $this->assertStringStartsWith($output);
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(nullException::class);
+ // Pass null so that an exception is thrown.
+ // Result of the function.
+ $helpers->cmi5launch_update_sessions($progress, $cmi5, null, $cmi5launchid, $USER);
+
+
+ }
+
+
+ /**
+ * Test of the cmi5launch_create_session with a pass condition.
+ * @return void
+ */
+ public function testcmi5launch_create_session()
+ {
+ global $DB, $cmi5launch, $cmi5launchid, $sessionids, $USER;
+
+ // Fake values.
+ $sessionid = '100';
+ $launchurl = "http://test.com";
+ $launchmethod = "ownWindow";
+ $tenantname = $USER->username;
+
+ // New session_helpers from mod_cmi5launch
+ $helpers = new \mod_cmi5launch\local\session_helpers();
+
+ // Result of the function.
+ $resultid = $helpers->cmi5launch_create_session($sessionid, $launchurl, $launchmethod);
+
+ // Returns a new id.
+ $this->assertIsInt($resultid, "Result should be an int.");
+
+ // Now retrieve it back from the db and make sure it matches.
+ // So the func doesn't return anything, but we can check the session object in the db.
+ // Get the session from DB with session id.
+ $result = $DB->get_record('cmi5launch_sessions', array('id' => $resultid));
+
+ // Result should be a session object.
+ $this->assertIsObject($result, "Result should be an object.");
+
+ // Maybe we can just assert the newrecord fields that are different.
+ // Check results sessioid, launchurl, tenantname, launchmethod.
+
+ // Check that the result is the same as the expected session.
+ $this->assertEquals($sessionid, $result->sessionid, "Result should be the same as the expected session.");
+ $this->assertEquals($launchurl, $result->launchurl, "Result should be the same as the expected session.");
+ $this->assertEquals($tenantname, $result->tenantname, "Result should be the same as the expected session.");
+ $this->assertEquals($launchmethod, $result->launchmethod, "Result should be the same as the expected session.");
+ }
+
+
+ /**
+ * Test of the cmi5launch_create_session with a fail condition.
+ * Catches an exception.
+ * @return void
+ */
+ public function testcmi5launch_create_session_excep()
+ {
+ global $DB, $cmi5launch, $cmi5launchid, $sessionids, $USER;
+
+ // LEt's make user not have id?
+ $USER = null;
+ // Fake values.
+ $sessionid = 100;
+ $launchurl = "http://test.com";
+ $launchmethod = "ownWindow";
+
+ // New session_helpers from mod_cmi5launch
+ $helpers = new \mod_cmi5launch\local\session_helpers();
+
+ $exceptionmessage = 'Error in creating session. Report this error to system administrator: ';
+
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(nullException::class);
+
+ // Pass null so that an exception is thrown.
+
+ // Result of the function.
+
+ // Result of the function.
+ $resultid = $helpers->cmi5launch_create_session($sessionid, $launchurl, $launchmethod);
+
+ }
+
+
+
+}
diff --git a/session_report.php b/session_report.php
index be1d918..9050963 100644
--- a/session_report.php
+++ b/session_report.php
@@ -49,6 +49,9 @@
// External classes and functions.
$sessionhelper = new session_helpers;
$aushelpers = new au_helpers;
+// Instantiate progress and cmi5_connectors to pass.
+$progress = new \mod_cmi5launch\local\progress;
+$cmi5connectors = new \mod_cmi5launch\local\cmi5_connectors;
$updatesession = $sessionhelper->cmi5launch_get_update_session();
$getaus = $aushelpers->get_cmi5launch_retrieve_aus_from_db();
@@ -178,7 +181,7 @@
// There may be more than one session.
foreach ($sessions as $sessionid) {
- $session = $updatesession($sessionid, $cmi5launch->id, $user);
+ $session = $updatesession($progress, $cmi5, $sessionid, $cmi5launch->id, $user);
// Add score to array for AU.
$sessionscores[] = $session->score;
From a922e69120466f4b63654c4838d2eb25ea04de78 Mon Sep 17 00:00:00 2001
From: ADLMeganBohland Error attempting to get registration id querystring parameter." . implode("\n ", json_decode($session->progress) ) . "
");
diff --git a/classes/local/au_helpers.php b/classes/local/au_helpers.php
index 4ecdbff..259081a 100644
--- a/classes/local/au_helpers.php
+++ b/classes/local/au_helpers.php
@@ -155,6 +155,10 @@ public function cmi5launch_save_aus($auobjectarray)
//Check it's not null.
if ($auobjectarray == null) {
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
+
throw new nullException('Cannot save AU information. AU object array is: null', 0);
} else {
@@ -229,6 +233,9 @@ public function cmi5launch_save_aus($auobjectarray)
// Now use the found missing value to give feedback to user.
echo " One of the fields is incorrect. Check data for field '$missing'. " . $e->getMessage() . "\n";
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
}
}
diff --git a/classes/local/cmi5_connectors.php b/classes/local/cmi5_connectors.php
index 8a51360..b79b551 100755
--- a/classes/local/cmi5_connectors.php
+++ b/classes/local/cmi5_connectors.php
@@ -504,8 +504,11 @@ public function cmi5launch_send_request_to_cmi5_player_post($cmi5launch_stream_a
// Return response.
return $result;
- }catch(\Throwable $e) {
-
+ }catch(\Throwable $e) {
+
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
//
throw new playerException("communicating with player, sending or crafting a POST request: " . $e);
}
@@ -614,7 +617,7 @@ public function cmi5launch_connectors_error_message($resulttotest, $type) {
if ($resulttest === false ){
- $errormessage = $type . ". CMI5 Player is not communicating. Is it running?";
+ $errormessage = $type . " CMI5 Player is not communicating. Is it running?";
throw new playerException($errormessage);
}
diff --git a/classes/local/errorover.php b/classes/local/errorover.php
index 8fba574..1cc8679 100644
--- a/classes/local/errorover.php
+++ b/classes/local/errorover.php
@@ -15,9 +15,9 @@
// along with Moodle. If not, see " . implode("\n ", json_decode($session->progress) ) . "
");
+ // Array to hold info for table population.
+ $tabledata = array();
+
+ // Build table.
+ $table = new html_table();
+ $table->id = 'cmi5launch_auSessionTable';
+ $table->caption = get_string('modulenameplural', 'cmi5launch');
+ $table->head = array(
+ get_string('cmi5launchviewfirstlaunched', 'cmi5launch'),
+ get_string('cmi5launchviewlastlaunched', 'cmi5launch'),
+ get_string('cmi5launchviewprogress', 'cmi5launch'),
+ get_string('cmi5launchviewgradeheader', 'cmi5launch'),
+ );
+
+
+ // Retrieve session ids.
+ $sessionids = json_decode($au->sessions);
+
+ // Iterate through each session by id.
+ foreach ($sessionids as $key => $sessionid) {
+
+ // Get the session from DB with session id.
+ $session = $DB->get_record('cmi5launch_sessions', array('sessionid' => $sessionid));
- // Add score to table.
- $sessioninfo[] = $session->score;
- // Add score to array for AU.
- $sessionscores[] = $session->score;
+ // Array to hold data for table.
+ $sessioninfo = array();
- // Add to be fed to table.
- $tabledata[] = $sessioninfo;
+
+ if ($session->createdat != null) {
+
+ // Retrieve createdAt and format.
+ $date = new DateTime($session->createdat, new DateTimeZone('US/Eastern'));
+ $date->setTimezone(new DateTimeZone('America/New_York'));
+ // date_timezone_set($date, new DateTimeZone('America/New_York'));
+ $sessioninfo[] = $date->format('D d M Y H:i:s');
+ }
+
+ if ($session->lastrequesttime != null) {
+
+ // Retrieve lastRequestTime and format.
+ $date = new DateTime($session->lastrequesttime, new DateTimeZone('US/Eastern'));
+ $date->setTimezone(new DateTimeZone('America/New_York'));
+ $sessioninfo[] = $date->format('D d M Y H:i:s');
+ }
+ // Add progress to table.
+ $sessioninfo[] = ("" . implode("\n ", json_decode($session->progress)) . "
");
+
+ // Add score to table.
+ $sessioninfo[] = $session->score;
+ // Add score to array for AU.
+ $sessionscores[] = $session->score;
+
+ // Add to be fed to table.
+ $tabledata[] = $sessioninfo;
+ }
+ } catch (Exception $e) {
+
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
+
+ // Throw an exception.
+ throw new customException('loading session table on AUview page. Report this to system administrator: ' . $e->getMessage() . 'Check that session information is present in DB and session id is correct.' , 0);
}
// Write table.
@@ -188,17 +204,17 @@ function mod_cmi5launch_launchexperience(registration) {
// Update AU in table with new info.
$DB->update_record('cmi5launch_aus', $au);
-}
-// Build the new session link.
-$newsession = "true";
-// Create a string to pass the auid and new session info to next page (launch.php).
-$infofornextpage = $auid . "," . $newsession;
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
+}
+// Pass the auid and new session info to next page (launch.php).
// New attempt button.
echo "";
diff --git a/classes/local/errorover.php b/classes/local/errorover.php
index 1cc8679..5b2fcba 100644
--- a/classes/local/errorover.php
+++ b/classes/local/errorover.php
@@ -67,6 +67,24 @@ function progresslrsreq_warning($errno, $errstr, $errfile, $errline)
}
+/**
+ * An warning handler to use to post better warnings to users for troubleshooting.
+ * @param mixed $errno
+ * @param mixed $errstr
+ * @param mixed $errfile
+ * @param mixed $errline
+ * @throws \mod_cmi5launch\local\nullException
+ * @return never
+ */
+function custom_warningAU($errno, $errstr, $errfile, $errline)
+{
+ echo "Error loading session table on AUview page. Report this to system administrator:
$errstr at $errfile on $errline: Check that session information is present in DB and session id is correct.";
+
+ exit;
+
+}
+
+
/**
* An exception handler to use in AU cases when many different exceptions for data errors may be thrown.
* @param mixed $errno
@@ -219,3 +237,42 @@ public function customFunction() {
// $this->getTraceAsString();
}
}
+
+/**
+ * Define a custom exception class, this will make pour tests meaningful
+ * This is a catchall custom
+ * from php webpage: "Custom exception classes can allow you to write tests that prove your exceptions
+ * are meaningful. Usually testing exceptions, you either assert the message equals
+*something in which case you can't change the message format without refactoring,
+*or not make any assertions at all in which case you can get misleading messages
+*later down the line. Especially if your $e->getMessage is something complicated
+*like a var_dump'ed context array."
+ */
+class customException extends \Exception
+{
+ // Redefine the exception so message isn't optional
+ // I want an exception that takkkes what is missing and adds it to messsssage?
+ // Is this possivlbe?
+ public function __construct($message, $code = 0, Throwable $previous = null) {
+ // some code
+
+ // Ah maybe here is where I can differentiate them
+ $playermessage = "Caught error. Something went wrong " . $message;
+ // make sure everything is assigned properly
+ parent::__construct($playermessage, $code, $previous);
+
+ echo"$playermessage";
+ }
+
+
+ // custom string representation of object (what is returned with echo)
+ public function __toString(): string {
+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+ // maybe here?
+ }
+
+ public function customFunction() {
+ // echo " This error to string :";
+ // $this->getTraceAsString();
+ }
+}
diff --git a/cmi5PHP/tests/progressTest.php b/cmi5PHP/tests/progressTest.php
index 209ac39..b6a7bb8 100644
--- a/cmi5PHP/tests/progressTest.php
+++ b/cmi5PHP/tests/progressTest.php
@@ -79,11 +79,11 @@ protected function setUp(): void
protected function tearDown(): void
{
- global $sessionids;
+ global $sessionids, $testcourseid, $cmi5launchsettings;
// Restore overridden global variable.
unset($GLOBALS['USER']);
unset($GLOBALS['cmi5launchsettings']);
-
+ deletetestcmi5launch_usercourse($testcourseid);
deletetestcmi5launch_sessions($sessionids);
}
@@ -974,9 +974,6 @@ public function testcmi5launch_retrieve_statements()
{
global $CFG, $DB, $sessionids;
- // First create a fake session to pass to the function.
- $sessions = maketestsessions();
-
// Retrieve a sessionid, we'll just use the first one.
$sessionid = $sessionids[1];
@@ -1039,9 +1036,6 @@ public function testcmi5launch_retrieve_statements_excep_ext()
{
global $CFG, $DB, $sessionids;
- // First create a fake session to pass to the function.
- $sessions = maketestsessions();
-
// Retrieve a sessionid, we'll just use the first one.
$sessionid = $sessionids[1];
@@ -1103,9 +1097,6 @@ public function testcmi5launch_retrieve_statements_excep()
{
global $CFG, $DB, $sessionids;
- // First create a fake session to pass to the function.
- $sessions = maketestsessions();
-
// Retrieve a sessionid, we'll just use the first one.
$sessionid = $sessionids[1];
diff --git a/launch.php b/launch.php
index e00846b..2c13de1 100755
--- a/launch.php
+++ b/launch.php
@@ -56,7 +56,7 @@
$savesession = $sessionhelper->cmi5launch_get_create_session();
$cmi5launchretrieveurl = $connectors->cmi5launch_get_retrieve_url();
$retrieveaus = $auhelper->get_cmi5launch_retrieve_aus_from_db();
-
+/*
// Retrieve registration id and au index (from AUview.php).
$fromauview = required_param('launchform_registration', PARAM_TEXT);
@@ -65,7 +65,8 @@
// Retrieve AU OR session id.
$id = array_shift($idandstatus);
-
+*/
+$id = required_param('launchform_registration', PARAM_TEXT);
// Reload cmi5 instance.
$record = $DB->get_record('cmi5launch', array('id' => $cmi5launch->id));
From f6db1116abf1a46de8d077c104e5d12e43b67832 Mon Sep 17 00:00:00 2001
From: ADLMeganBohland
'. $errstr .' at '. $errfile .' on ' .$errline, 0);
+}
/**
* An exception handler to use in AU cases when many different exceptions for data errors may be thrown.
diff --git a/launch.php b/launch.php
index 2c13de1..9f9fa73 100755
--- a/launch.php
+++ b/launch.php
@@ -15,8 +15,8 @@
// along with Moodle. If not, see
'. $errstr .' at '. $errfile .' on ' .$errline, 0);
+
+}
/**
* An exception handler to use in AU cases when many different exceptions for data errors may be thrown.
* @param mixed $errno
diff --git a/classes/local/session_helpers.php b/classes/local/session_helpers.php
index 7ed3b8a..1bceeea 100644
--- a/classes/local/session_helpers.php
+++ b/classes/local/session_helpers.php
@@ -78,9 +78,22 @@ public function cmi5launch_update_sessions($progress, $cmi5, $sessionid, $cmi5la
$sessioninfo = json_decode($getsessioninfo($sessionid, $cmi5launchid), true);
// Update session.
foreach ($sessioninfo as $key => $value) {
+
+ // Is the problem key value is not matching due to caps?
// We don't want to overwrite ids.
// If the property exists and it's not id or sessionid, set it to lowercase and
// encode value if it is array. (DB needs properties in lowercase, but player returns camelcase).
+
+
+ // If it's an array, encode it so it can be saved to DB.
+ if (is_array($value)) {
+ $value = json_encode($value);
+ }
+
+ if (is_string($key)) {
+ $key = mb_convert_case($key, MB_CASE_LOWER, "UTF-8");
+ }
+
if (property_exists($session, $key) && $key != 'id' && $key != 'sessionid') {
// If it's an array, encode it so it can be saved to DB.
@@ -152,6 +165,13 @@ public function cmi5launch_create_session($sessionid, $launchurl, $launchmethod)
// Save record to table.
$newid = $DB->insert_record($table, $newrecord, true);
+ // Instantiate progress and cmi5_connectors class to pass.
+ $progress = new progress;
+ $cmi5 = new cmi5_connectors;
+
+ // Retrieve new info (if any) from CMI5 player and LRS on session.
+ $session = $this->cmi5launch_update_sessions($progress, $cmi5, $sessionid, $cmi5launch->id, $USER);
+
// Restore default handlers.
restore_exception_handler();
restore_error_handler();
diff --git a/view.php b/view.php
index f7479f9..9cc3c38 100755
--- a/view.php
+++ b/view.php
@@ -15,12 +15,14 @@
// along with Moodle. If not, see
";
-echo"Settings are: ";
-echo $playerurl . " ";
-echo "
";
-echo $playername;
-echo "
";
-echo $playerpass;
+
// If the settings are not set, then display the first form.
if(!$playerurl || !$playername || !$playerpass){