diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..7004f47
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,11 @@
+{
+ "github.copilot.enable": {
+
+ "*": true,
+ "plaintext": false,
+ "markdown": false,
+ "scminput": false
+ },
+ "github.copilot.advanced": {},
+ "files.eol": "\n"
+}
\ No newline at end of file
diff --git a/AUview.php b/AUview.php
index 13318ea..c91f43d 100755
--- a/AUview.php
+++ b/AUview.php
@@ -154,14 +154,13 @@ function mod_cmi5launch_launchexperience(registration) {
// Array to hold data for table.
$sessioninfo = array();
-
// Retrieve createdAt and format.
$date = new DateTime($session->createdat, new DateTimeZone('US/Eastern'));
$date->setTimezone(new DateTimeZone('America/New_York'));
$sessioninfo[] = $date->format('D d M Y H:i:s');
// Retrieve lastRequestTime and format.
- $date = new DateTime($session->updatedat, new DateTimeZone('US/Eastern'));
+ $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');
diff --git a/classes/local/au.php b/classes/local/au.php
old mode 100755
new mode 100644
index 55e2d4d..b3eb7fe
--- a/classes/local/au.php
+++ b/classes/local/au.php
@@ -21,6 +21,9 @@
*/
namespace mod_cmi5launch\local;
+// Include the errorover (error override) funcs.
+require_once ($CFG->dirroot . '/mod/cmi5launch/classes/local/errorover.php');
+
class au {
// Lowercase values are for saving to DB.
@@ -34,6 +37,13 @@ class au {
// Constructs AUs. Is fed array and where array key matches property, sets the property.
public function __construct($statement) {
+ // What can go wrong here? It could be that a statement is null
+ // or that the statement is not an array or not an object.
+ if (is_null($statement) || (!is_array($statement) && !is_object($statement) )) {
+
+ throw new nullException('Statement to build AU is null or not an array/object.', 0);
+ }
+ // If it is an array, create the object.
foreach ($statement as $key => $value) {
$this->$key = ($value);
diff --git a/classes/local/au_helpers.php b/classes/local/au_helpers.php
old mode 100755
new mode 100644
index 5785ad5..5fad354
--- a/classes/local/au_helpers.php
+++ b/classes/local/au_helpers.php
@@ -24,6 +24,12 @@
namespace mod_cmi5launch\local;
use mod_cmi5launch\local\au;
+use mod_cmi5launch\local\errorover;
+
+global $CFG;
+// Include the errorover (error override) funcs.
+require_once ($CFG->dirroot . '/mod/cmi5launch/classes/local/errorover.php');
+
defined('MOODLE_INTERNAL') || die();
class au_helpers {
@@ -46,38 +52,67 @@ public function get_cmi5launch_retrieve_aus_from_db() {
* @return array
*/
public function cmi5launch_retrieve_aus($returnedinfo) {
+
+ $resultchunked = "";
+
+
+ // Use our own more specific error handler, to give better info tto user.
+ set_error_handler('mod_cmi5launch\local\array_chunk_warning', E_WARNING);
+
// The results come back as nested array under more then just AUs.
- // We only want the info pertaining to the AU.
- $resultchunked = array_chunk($returnedinfo["metadata"]["aus"], 1, );
+ // We only want the info pertaining to the AU. However, if the wrong info is passed array_chunk will through an exception.
+ try {
+ $resultchunked = array_chunk($returnedinfo["metadata"]["aus"], 1, );
+ }
+ catch (\Exception $e) {
+
+ echo "Cannot retrieve AUs. Error found when trying to parse them from course creation: " .
+ "Please check the connection to player or course format and try again. \n"
+ . $e->getMessage() . "\n";
+
+ //exit;
+ }
+ // Restore the error handler.
+ restore_error_handler();
+
return $resultchunked;
}
+
/**
* So it should be fed an array of statements that then assigns the values to
* several aus, and then returns them as au objects.
* @param mixed $austatements
* @return array
*/
- public function cmi5launch_create_aus($austatements) {
-
+ public function cmi5launch_create_aus($austatements)
+ {
// Needs to return our new AU objects.
$newaus = array();
- foreach ($austatements as $int => $info) {
+ // We should not be able to get here but what if null is pulled from record and passed in?
+ // So in case it is given null.
+ if ($austatements == null) {
+
+ throw new nullException('Cannot retrieve AU information. AU statements from DB are: ' . $austatements, 0);
- // The aus come back decoded from DB nestled in an array.
- // So they are the first key, which is '0'.
- $statement = $info[0];
+ } else {
+ foreach ($austatements as $int => $info) {
- $au = new au($statement);
+ // The aus come back decoded from DB nestled in an array.
+ // So they are the first key, which is '0'.
+ $statement = $info[0];
- // Assign the newly created au to the return array.
- $newaus[] = $au;
- }
+ $au = new au($statement);
+
+ // Assign the newly created au to the return array.
+ $newaus[] = $au;
+ }
- // Return our new list of AU.
- return $newaus;
+ // Return our new list of AU.
+ return $newaus;
+ }
}
/**
@@ -89,50 +124,105 @@ public function cmi5launch_save_aus($auobjectarray) {
// Add userid to the record.
global $DB, $USER, $cmi5launch;
$table = "cmi5launch_aus";
-
+
// An array to hold the created ids.
$auids = array();
- // For each AU in array build a new record and save it.
- // Because of so many nested variables this needs to be done manually.
- foreach ($auobjectarray as $auobject) {
-
- // Make a newrecord to save.
- $newrecord = new \stdClass();
-
- $newrecord->userid = $USER->id;
- $newrecord->attempt = $auobject->attempt;
- $newrecord->auid = $auobject->id;
- $newrecord->launchmethod = $auobject->launchMethod;
- $newrecord->lmsid = json_decode(json_encode($auobject->lmsId, true) );
- $newrecord->url = $auobject->url;
- $newrecord->type = $auobject->type;
- $title = json_decode(json_encode($auobject->title), true);
- $newrecord->title = $title[0]['text'];
- $newrecord->moveon = $auobject->moveOn;
- $newrecord->auindex = $auobject->auIndex;
- $newrecord->parents = json_encode($auobject->parents, true);
- $newrecord->objectives = json_encode($auobject->objectives);
- $desc = json_decode(json_encode($auobject->description), true);
- $newrecord->description = $desc[0]['text'];
- $newrecord->activitytype = $auobject->activityType;
- $newrecord->masteryscore = $auobject->masteryscore;
- $newrecord->completed = $auobject->completed;
- $newrecord->passed = $auobject->passed;
- $newrecord->inprogress = $auobject->inprogress;
- $newrecord->noattempt = $auobject->noattempt;
- $newrecord->satisfied = $auobject->satisfied;
- // And HERE we can add the moodlecourseid.
- $newrecord->moodlecourseid = $cmi5launch->id;
-
- // Save the record and get the new id.
- $newid = $DB->insert_record($table, $newrecord, true);
- // Save new id to list to pass back.
- $auids[] = $newid;
- }
+ // Variables for error over and exception handling.
+ // Array of all items in new record, this will be useful for troubleshooting.
+ $newrecorditems = array('id', 'attempt', 'auid', 'launchmethod', 'lmsid', 'url', 'type', 'title', 'moveon', 'auindex', 'parents', 'objectives', 'description', 'activitytype', 'masteryscore', 'completed', 'passed', 'inprogress', 'noattempt', 'satisfied', 'moodlecourseid');
+ $currentrecord = 1;
+ $newid = "";
+ $newrecord = "";
+
+ // 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\sifting_data_warning', E_WARNING);
+ set_exception_handler('mod_cmi5launch\local\exception_au');
+
+ //Check it's not null.
+ if ($auobjectarray == null) {
- return $auids;
+ throw new nullException('Cannot save AU information. AU object array is: null' , 0);
+
+ } else {
+ // For each AU in array build a new record and save it.
+ // Because of so many nested variables this needs to be done manually.
+ foreach ($auobjectarray as $auobject) {
+
+ // A try statement to catch any errors that may be thrown.
+ try {
+ // Make a newrecord to save.
+ $newrecord = new \stdClass();
+
+ // Assign the values to the new record.
+ $newrecord->userid = $USER->id;
+ $newrecord->attempt = $auobject->attempt;
+ $newrecord->auid = $auobject->id;
+ $newrecord->launchmethod = $auobject->launchMethod;
+ $newrecord->lmsid = json_decode(json_encode($auobject->lmsId, true));
+ $newrecord->url = $auobject->url;
+ $newrecord->type = $auobject->type;
+ $title = json_decode(json_encode($auobject->title), true);
+ $newrecord->title = $title[0]['text'];
+ $newrecord->moveon = $auobject->moveOn;
+ $newrecord->auindex = $auobject->auIndex;
+ $newrecord->parents = json_encode($auobject->parents, true);
+ $newrecord->objectives = json_encode($auobject->objectives);
+ $desc = json_decode(json_encode($auobject->description), true);
+ $newrecord->description = $desc[0]['text'];
+ $newrecord->activitytype = $auobject->activityType;
+ $newrecord->masteryscore = $auobject->masteryscore;
+ $newrecord->completed = $auobject->completed;
+ $newrecord->passed = $auobject->passed;
+ $newrecord->inprogress = $auobject->inprogress;
+ $newrecord->noattempt = $auobject->noattempt;
+ $newrecord->satisfied = $auobject->satisfied;
+ $newrecord->moodlecourseid = $cmi5launch->id;
+
+ // Save the record and get the new id.
+ $newid = $DB->insert_record($table, $newrecord, true);
+
+ // Save new id to list to pass back.
+ $auids[] = $newid;
+
+ // This is for troubleshooting, so we know where the error is.
+ $currentrecord++;
+
+ // The set exception handler catches exceptionas that SLIP by,
+ // so maybe DONT make it throwable and catch type errror
+ } catch (\Throwable $e) {
+
+
+ echo "Cannot save to DB. Stopped at record with ID number " . ($currentrecord) . ".";
+
+ // This is the tricky part, we need to find out which field is missing. But because the error is thrown ON the field, we need to do some
+ // manuevering to find out which field is missing.
+ // Typecast to array to grab the list item.
+ $items = (array) $newrecord;
+
+ // Get the last ley of array
+ $lastkey = array_key_last($items);
+
+ // Heres thhe tricky part, the lastkey here is somewhere in the array we earlier made and the NEXT one would be the one that threw the error.
+ // So now we can grab the key after the last one.
+ $key = array_search($lastkey, $newrecorditems) + 1;
+
+ // Ok, NOW the missin element is key in newrecorditems.
+ $missing = $newrecorditems[$key];
+
+ // 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();
+
+ return $auids;
+ }
}
+
/**
* Retrieves AU info from DB, converts to AU object, and returns it.
@@ -145,22 +235,24 @@ public function cmi5launch_retrieve_aus_from_db($auid) {
$check = $DB->record_exists( 'cmi5launch_aus', ['id' => $auid], '*', IGNORE_MISSING);
- // If check is negative, the record does not exist. It should so throw error.
+
+ // If check is negative, the record does not exist. It should also throw error.
// Moodle will throw the error, but we want to pass this message back ot user.
if (!$check) {
- echo "Error attempting to get AU data from DB. Check AU id. AU id is: " . $auid ."
";
+ throw new nullException("Error attempting to get AU data from DB. Check AU id. AU id is: " . $auid ."
", 0);
- return false;
} else {
$auitem = $DB->get_record('cmi5launch_aus', array('id' => $auid));
$au = new au($auitem);
+
+ // Return our new list of AU.
+ return $au;
}
- // Return our new list of AU.
- return $au;
+
}
}
diff --git a/classes/local/cmi5_connectors.php b/classes/local/cmi5_connectors.php
index 439576c..1f3ab33 100755
--- a/classes/local/cmi5_connectors.php
+++ b/classes/local/cmi5_connectors.php
@@ -25,6 +25,8 @@
defined('MOODLE_INTERNAL') || die();
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 {
@@ -60,6 +62,10 @@ public function cmi5launch_get_send_request_to_cmi5_player_get() {
}
+ public function cmi5launch_get_connectors_error_message() {
+ return [$this, 'cmi5launch_connectors_error_message'];
+ }
+
/**
* Function to create a course.
* @param mixed $id - tenant id in Moodle.
@@ -81,20 +87,37 @@ public function cmi5launch_create_course($id, $tenanttoken, $filename) {
$databody = $filename->get_content();
+ // So this one has some troubleshooting built in already, but we probably need to throw an exception to stop function or moodle will freak
+
// Sends the stream to the specified URL.
$result = $this->cmi5launch_send_request_to_cmi5_player_post('cmi5launch_stream_and_send',$databody, $url, $filetype, $tenanttoken);
- // Check result and display message if not 200.
- $resulttest = $this->cmi5launch_connectors_error_message($result, "creating the course");
-
- if ($resulttest == true) {
- // Return an array with course info.
- return $result;
- } else {
- return false;
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ // Check result and display message if not 200.
+ $resulttest = $this->cmi5launch_connectors_error_message($result, "creating the course");
+
+ // echo "Is it resulting?";
+ if ($resulttest == true) {
+ // Return an array with course info.
+ return $result;
+ // I think this is the problem, it is coming back and throwing another error! I thought it would stop... do I need a kill in the error message hander?
+ // Its throwing BOB??? The third path is executing, THATS the problem!
+ // either way though, shouldn't the error funtion have ITS own test? like,
+ // what we need to test here is is resulttrue is true or not
+ } else {
+ // This should never be false, it should throw an exception if it is, so we can just return the result
+ // But catch all else that miht go wrong
+ throw new playerException("creating the course.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+ throw new playerException("creating the course" . $e);
}
+
}
+
/**
* Function to create a tenant.
* @param $urltosend - URL retrieved from user in URL textbox.
@@ -108,11 +131,9 @@ public function cmi5launch_create_tenant($newtenantname) {
$settings = cmi5launch_settings($cmi5launchid);
- //$actor = $USER->username;
$username = $settings['cmi5launchbasicname'];
$playerurl = $settings['cmi5launchplayerurl'];
$password = $settings['cmi5launchbasepass'];
- global $CFG;
// Build URL for launch URL request.
$url = $playerurl . "/api/v1/tenant";
@@ -130,19 +151,27 @@ public function cmi5launch_create_tenant($newtenantname) {
// Sends the stream to the specified URL.
$result = $this->cmi5launch_send_request_to_cmi5_player_post('cmi5launch_stream_and_send', $data, $url, $filetype, $username, $password);
+
// Check result and display message if not 200.
$resulttest = $this->cmi5launch_connectors_error_message($result, "creating the tenant");
-
- if ($resulttest == true) {
-
- // Decode returned response into array.
- $returnedinfo = json_decode($result, true);
-
- // Return an array with tenant name and info.
- return $returnedinfo;
- } else {
- return false;
- };
+ // why is it coming back null and shouldnt we go to else the?
+
+
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ if ($resulttest == true) {
+
+ return $result;
+ } else {
+
+ throw new playerException("creating the tenant.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+
+ throw new playerException("Uncaught error creating the tenant" . $e);
+ }
+
}
/**
@@ -169,13 +198,21 @@ public function cmi5launch_retrieve_registration_with_get($registration, $id) {
// Check result and display message if not 200.
$resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving the registration");
-
- if ($resulttest == true) {
-
- return $result;
- } else {
- return false;
+
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ if ($resulttest == true) {
+ return $result;
+ } else {
+
+ throw new playerException("retrieving the registration information.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+
+ throw new playerException("Uncaught error retrieving the registration information." . $e);
}
+
}
/**
@@ -223,19 +260,26 @@ public function cmi5launch_retrieve_registration_with_post($courseid, $id) {
// Check result and display message if not 200.
$resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving the registration");
- // Catch errors.
- if ($resulttest == true) {
-
- $registrationinfo = json_decode($result, true);
-
- // The returned 'registration info' is a large json object.
- // Code is the registration id we want.
- $registration = $registrationinfo["code"];
-
- return $registration;
- } else {
- return false;
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ if ($resulttest == true) {
+
+ $registrationinfo = json_decode($result, true);
+
+ // The returned 'registration info' is a large json object.
+ // Code is the registration id we want.
+ $registration = $registrationinfo["code"];
+
+ return $registration;
+ } else {
+ throw new playerException("retrieving the registration information.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+
+ throw new playerException("Uncaught error retrieving the registration information." . $e);
}
+
}
/**
@@ -260,7 +304,6 @@ public function cmi5launch_retrieve_token($audience, $tenantid) {
$username = $settings['cmi5launchbasicname'];
$playerurl = $settings['cmi5launchplayerurl'];
$password = $settings['cmi5launchbasepass'];
- global $CFG;
// Build URL for launch URL request.
$url = $playerurl . "/api/v1/auth";
@@ -279,15 +322,23 @@ public function cmi5launch_retrieve_token($audience, $tenantid) {
$result = $this->cmi5launch_send_request_to_cmi5_player_post('cmi5launch_stream_and_send', $data, $url, $filetype, $username, $password);
// Check result and display message if not 200.
- $resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving the token");
+ $resulttest = $this->cmi5launch_connectors_error_message($result, 'retrieving the tenant token.');
- if ($resulttest == true) {
- $resultDecoded = json_decode($result, true);
- $token = $resultDecoded['token'];
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ if ($resulttest == true) {
- return $token;
- } else {
- return false;
+ $resultDecoded = json_decode($result, true);
+ $token = $resultDecoded['token'];
+
+ return $token;
+
+ } else {
+ throw new playerException("retrieving the tenant token.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+ throw new playerException("Uncaught error retrieving the tenant token." . $e);
}
}
@@ -340,18 +391,24 @@ public function cmi5launch_retrieve_url($id, $auindex) {
$result = $this->cmi5launch_send_request_to_cmi5_player_post('cmi5launch_stream_and_send', $data, $url, $filetype, $token);
// Check result and display message if not 200.
- $resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving launch url");
+ $resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving the launch url from player.");
- // Catch errors.
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
if ($resulttest == true) {
-
// Only return the URL.
$urldecoded = json_decode($result, true);
return $urldecoded;
} else {
- return false;
+ throw new playerException("retrieving the launch url from player.");
}
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+ throw new playerException("Uncaught error retrieving the launch url from player." . $e);
+ }
+
+
}
/**
@@ -364,72 +421,96 @@ public function cmi5launch_retrieve_url($id, $auindex) {
*/
public function cmi5launch_send_request_to_cmi5_player_post($cmi5launch_stream_and_send, $databody, $url, $filetype, ...$tokenorpassword) {
- // Assign passed in function to variable.
- $stream = $cmi5launch_stream_and_send;
- // Determine content type to be used in header.
- // It is also the same as accepted type.
- $contenttype = $filetype;
- if ($contenttype == "zip") {
- $contenttype = "application/zip\r\n";
- } else if ("json") {
- $contenttype = "application/json\r\n";
- }
-
- // If number of args is greater than one it is for retrieving tenant info and args are username and password.
- if (count($tokenorpassword) == 2 ) {
+ // 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\sifting_data_warning', E_WARNING);
+ set_exception_handler('mod_cmi5launch\local\exception_au');
+
+ try {
+
+ // I rhink this whole thing should be try catch cause there are several things that cango w
+ // Assign passed in function to variable.
+ $stream = $cmi5launch_stream_and_send;
+ // Determine content type to be used in header.
+ // It is also the same as accepted type.
+ $contenttype = $filetype;
+ if ($contenttype == "zip") {
+ $contenttype = "application/zip\r\n";
+ } else if ("json") {
+ $contenttype = "application/json\r\n";
+ }
+
+ // If number of args is greater than one it is for retrieving tenant info and args are username and password.
+ if (count($tokenorpassword) == 2) {
+
+ $username = $tokenorpassword[0];
+ $password = $tokenorpassword[1];
+
+
+ // Use key 'http' even if you send the request to https://...
+ // There can be multiple headers but as an array under the ONE header.
+ // Content(body) must be JSON encoded here, as that is what CMI5 player accepts.
+ $options = array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'header' => array(
+ 'Authorization: Basic ' . base64_encode("$username:$password"),
+ "Content-Type: " . $contenttype .
+ "Accept: " . $contenttype
+ ),
+ 'content' => ($databody),
+ ),
+ );
+
+ //By calling the function this way, it enables encapsulation of the function and allows for testing.
+ //It is an extra step, but necessary for required PHP Unit testing.
+ $result = call_user_func($stream, $options, $url);
+
+
+ // Else the args are what we need for posting a course.
+ } else {
+
+ // First arg will be token.
+ $token = $tokenorpassword[0];
+
+ // Use key 'http' even if you send the request to https://...
+ // There can be multiple headers but as an array under the ONE header
+ // content(body) must be JSON encoded here, as that is what CMI5 player accepts
+ // JSON_UNESCAPED_SLASHES used so http addresses are displayed correctly.
+ $options = array(
+ 'http' => array(
+ 'method' => 'POST',
+ 'ignore_errors' => true,
+ 'header' => array(
+ "Authorization: Bearer " . $token,
+ "Content-Type: " . $contenttype .
+ "Accept: " . $contenttype
+ ),
+ 'content' => ($databody),
+ ),
+ );
+
+
+ //By calling the function this way, it enables encapsulation of the function and allows for testing.
+ //It is an extra step, but necessary for required PHP Unit testing.
+ $result = call_user_func($stream, $options, $url);
+
+ // Ok, calling it throuw the third party isn't workin, what if we mock call_user_func instead and have an eror thrown there
+ }
+
+
+ // Restore default hadlers.
+ restore_exception_handler();
+ restore_error_handler();
+
+ // Return response.
+ return $result;
- $username = $tokenorpassword[0];
- $password = $tokenorpassword[1];
+ }catch(\Throwable $e) {
+ //
+ throw new playerException("communicating with player, sending or crafting a POST request: " . $e);
+ }
- // Use key 'http' even if you send the request to https://...
- // There can be multiple headers but as an array under the ONE header.
- // Content(body) must be JSON encoded here, as that is what CMI5 player accepts.
- $options = array(
- 'http' => array(
- 'method' => 'POST',
- 'header' => array('Authorization: Basic '. base64_encode("$username:$password"),
- "Content-Type: " .$contenttype .
- "Accept: " . $contenttype),
- 'content' => ($databody),
- ),
- );
-
- //By calling the function this way, it enables encapsulation of the function and allows for testing.
- //It is an extra step, but necessary for required PHP Unit testing.
- $result = call_user_func($stream, $options, $url);
-
-
- // Else the args are what we need for posting a course.
- } else {
-
- // First arg will be token.
- $token = $tokenorpassword[0];
-
- // Use key 'http' even if you send the request to https://...
- // There can be multiple headers but as an array under the ONE header
- // content(body) must be JSON encoded here, as that is what CMI5 player accepts
- // JSON_UNESCAPED_SLASHES used so http addresses are displayed correctly.
- $options = array(
- 'http' => array(
- 'method' => 'POST',
- 'ignore_errors' => true,
- 'header' => array("Authorization: Bearer ". $token,
- "Content-Type: " .$contenttype .
- "Accept: " . $contenttype),
- 'content' => ($databody),
- ),
- );
-
-
- //By calling the function this way, it enables encapsulation of the function and allows for testing.
- //It is an extra step, but necessary for required PHP Unit testing.
- $result = call_user_func($stream, $options, $url);
-
- }
-
- // Return response.
- return $result;
}
/**
@@ -455,21 +536,18 @@ public function cmi5launch_send_request_to_cmi5_player_get($cmi5launch_stream_an
),
);
- //$helper = new cmi5launch_helpers;
- // $stream = cmi5launch_stream_and_send();
- // Sends the stream to the specified URL and stores results.
- // The false is use_include_path, which we dont want in this case, we want to go to the url.
- //$launchresponse = cmi5launch_stream_and_send( $options, $url );
-
+ try {
//By calling the function this way, it enables encapsulation of the function and allows for testing.
//It is an extra step, but necessary for required PHP Unit testing.
$result = call_user_func($stream, $options, $url);
-
-
- $sessiondecoded = json_decode($result, true);
- // Return response.
- return $sessiondecoded;
+ // Return response.
+ return $result;
+
+ } catch (\Throwable $e) {
+ // echo" are we here?";
+ throw new playerException("communicating with player, sending or crafting a GET request: " . $e);
+ }
}
/**
@@ -494,13 +572,21 @@ public function cmi5launch_retrieve_session_info_from_player($sessionid, $id) {
$result = $this->cmi5launch_send_request_to_cmi5_player_get('cmi5launch_stream_and_send', $token, $url);
// Check result and display message if not 200.
- $resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving session info");
+ $resulttest = $this->cmi5launch_connectors_error_message($result, "retrieving the session information.");
- if ($resulttest == true) {
+ // Now this will never return false, it will throw an exception if it fails, so we can just return the result
+ try {
+ if ($resulttest == true) {
- return $result;
- } else {
- return false;
+ return $result;
+
+ } else {
+ throw new playerException("retrieving the session information.");
+ }
+ }// catch all else that might go wrong
+ catch (\Throwable $e){
+
+ throw new playerException("Uncaught error retrieving the session information." . $e);
}
}
@@ -513,8 +599,9 @@ public function cmi5launch_retrieve_session_info_from_player($sessionid, $id) {
* @param string $type - The type missing to be added to the error message.
* @return bool
*/
- public static function cmi5launch_connectors_error_message($resulttotest, $type) {
-
+ public function cmi5launch_connectors_error_message($resulttotest, $type) {
+
+
// Decode result because if it is not 200 then something went wrong
// If it's a string, decode it.
if (is_string($resulttotest)) {
@@ -527,26 +614,24 @@ public static function cmi5launch_connectors_error_message($resulttotest, $type)
// Player cannot return an error if not runnin,
if ($resulttest === false ){
- echo "
";
-
- echo "Something went wrong " . $type . ". CMI5 Player is not communicating. Is it running?";
-
- echo "
";
+
+ $errormessage = $type . ". CMI5 Player is not communicating. Is it running?";
- return false;
+ throw new playerException($errormessage);
}
else if( array_key_exists("statusCode", $resulttest) && $resulttest["statusCode"] != 200) {
- echo "
";
+
+ $errormessage = $type . " CMI5 Player returned " . $resulttest["statusCode"] . " error. With message '"
+ . $resulttest["message"] . "'." ;
- echo "Something went wrong " . $type . ". CMI5 Player returned " . $resulttest["statusCode"] . " error. With message '"
- . $resulttest["message"] . "'." ;
- echo "
";
-
- return false;
+ // echo"whatt is error messae before throwing::: " . $errormessage;
+ // echo" what is error messae: " . $errormessage;"";
+ throw new playerException($errormessage);
+
} else {
-
- // No errors, continue.
+ // No errors, continue.
+
return true;
}
}
diff --git a/classes/local/course.php b/classes/local/course.php
old mode 100755
new mode 100644
diff --git a/classes/local/errorover.php b/classes/local/errorover.php
new file mode 100644
index 0000000..5e60a27
--- /dev/null
+++ b/classes/local/errorover.php
@@ -0,0 +1,199 @@
+.
+
+/**
+ * Lets see if this works. making an ovrride error class, or several
+ *
+ * @copyright 2023 Megan Bohland
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_cmi5launch\local;
+
+/**
+ * An exception handler to use in AU cases when many different exceptions for data errors may be thrown.
+ * @param mixed $errno
+ * @param mixed $errstr
+ * @param mixed $errfile
+ * @param mixed $errline
+ * @throws \mod_cmi5launch\local\nullException
+ * @return never
+ */
+function exception_au(\Throwable $exception)
+{
+ // echo"Error stirn --- $errstr";
+ // echo"Error number --- $errno";
+ echo " EHAT?";
+ // Maybe we can construct the new errors here. This would allow the error personalization? And keep main code clean
+
+ throw new fieldException('Error OVER: ' . $exception->getMessage(), 0);
+ // exit;
+}
+ function array_chunk_warning($errno, $errstr, $errfile, $errline)
+ {
+ // echo"Error stirn --- $errstr";
+ // echo"Error number --- $errno";
+
+ // Maybe we can construct the new errors here. This would allow the error personalization? And keep main code clean
+
+ throw new nullException('Cannot parse array. Error: ' . $errstr, 0);
+ // exit;
+ }
+
+ /// Ok, this i a different error handler
+ function sifting_data_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 fieldException('Error: ' . $errstr, 0);
+ // exit;
+ }
+
+/**
+ * Define a custom exception class, this will make pour tests meaningful
+ * 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 nullException extends \Exception
+{
+ // Redefine the exception so message isn't optional
+ public function __construct($message, $code = 0, Throwable $previous = null) {
+ // some code
+
+ // make sure everything is assigned properly
+ parent::__construct($message, $code, $previous);
+ }
+
+ // custom string representation of object (what is returned with echo)
+ public function __toString(): string {
+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+ }
+
+ public function customFunction() {
+ echo "A custom function for this type of exception\n";
+ }
+}
+/**
+ * Define a custom exception class, this will make pour tests meaningful
+ * 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 missingException 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
+
+ // make sure everything is assigned properly
+ parent::__construct($message, $code, $previous);
+ }
+
+
+ // 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();
+ }
+}
+/**
+ * Define a custom exception class, this will make pour tests meaningful
+ * 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 fieldException 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
+
+ // make sure everything is assigned properly
+ parent::__construct($message, $code, $previous);
+ }
+
+
+ // 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();
+ }
+}
+/**
+ * Define a custom exception class, this will make pour tests meaningful
+ * 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 playerException 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 = "Player communication error. Something went wrong " . $message;
+ // make sure everything is assigned properly
+ parent::__construct($playermessage, $code, $previous);
+ }
+
+
+ // 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();
+ }
+}
+
+// If all my exceptions are the same, just diff names, are they necessary? Do any of my try/catches really differentiate?
\ No newline at end of file
diff --git a/classes/local/grade_helpers.php b/classes/local/grade_helpers.php
old mode 100755
new mode 100644
index 818fc57..fe78c85
--- a/classes/local/grade_helpers.php
+++ b/classes/local/grade_helpers.php
@@ -202,10 +202,10 @@ public function cmi5launch_check_user_grades_for_updates($user) {
switch ($gradetype) {
- // MOD_CMI5LAUNCH_AUS_GRADE = 0.
- // MOD_CMI5LAUNCH_GRADE_HIGHEST = 1.
- // MOD_CMI5LAUNCH_GRADE_AVERAGE = 2.
- // MOD_CMI5LAUNCH_GRADE_SUM = 3.
+ // 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);
diff --git a/classes/local/progress.php b/classes/local/progress.php
old mode 100755
new mode 100644
diff --git a/classes/local/session.php b/classes/local/session.php
old mode 100755
new mode 100644
index 58fefb7..283c2ee
--- a/classes/local/session.php
+++ b/classes/local/session.php
@@ -44,7 +44,6 @@ public function __construct($statement) {
foreach ($statement as $key => $value) {
-
$this->$key = ($value);
}
diff --git a/classes/local/session_helpers.php b/classes/local/session_helpers.php
old mode 100755
new mode 100644
diff --git a/cmi5PHP/tests/auTest.php b/cmi5PHP/tests/auTest.php
old mode 100755
new mode 100644
index 3292a92..7d36302
--- a/cmi5PHP/tests/auTest.php
+++ b/cmi5PHP/tests/auTest.php
@@ -1,6 +1,7 @@
auProperties = array(
+ $this->auproperties = array(
'id',
'attempt',
'url',
@@ -54,10 +55,10 @@ protected function setUp(): void
'userid'
);
- $this->emptyStatement = array();
+ $this->emptystatement = array();
- // Perhaps a good test would be to test the constructor with a statement that has all the properties set.
- $this->mockStatementValues = array(
+ // A good test would be to test the constructor with a statement that has all the properties set.
+ $this->mockstatementvalues = array(
'id' => 'id',
'attempt' => 'attempt',
'url' => 'url',
@@ -105,16 +106,15 @@ protected function tearDown(): void
*/
public function testInstantiationWithEmpty()
{
- $obj = new au($this->emptyStatement);
+ // Make an AU object with no values.
+ $obj = new au($this->emptystatement);
- // Is an AU object?
+ // Assert its an AU object.
$this->assertInstanceOf(au::class, $obj);
- //It is saying AU is not transversable
- //Implementing traversable in AU is breaking the code,
- //Make sure the AU object does not have any 'extra' properties, only the amount passed in
- $expectedAmount = count($this->auProperties);
- //could typecasting the object as an array help? dirty fix
+ // It is saying AU is not transversable. Implementing traversable in AU is breaking the code, typecast the object as array for dirty fix.
+ // Make sure the AU object does not have any 'extra' properties, only the amount passed in
+ $expectedAmount = count($this->auproperties);
$auArray = (array) $obj;
$this->assertCount($expectedAmount, $auArray, "AU has $expectedAmount properties");
@@ -124,7 +124,6 @@ public function testInstantiationWithEmpty()
$this->assertArrayHasKey($property, $auArray, "$property exists");
$this->assertNull($value, "$property empty");
}
-
}
/**
@@ -132,19 +131,16 @@ public function testInstantiationWithEmpty()
* Should instantiate an AU object with values.
* @return void
*/
-
public function testInstantiationWithValues()
{
- $obj = new au($this->mockStatementValues);
+ $obj = new au($this->mockstatementvalues);
- // Is an AU object?
+ // Assert it's an AU object?
$this->assertInstanceOf(au::class, $obj);
-
- //It is saying AU is not transversable
- //Implementing traversable in AU is breaking the code,
- //Make sure the AU object does not have any 'extra' properties, only the amount passed in
- $expectedAmount = count($this->auProperties);
- //could typecasting the object as an array help? dirty fix
+
+ // It is saying AU is not transversable. Implementing traversable in AU is breaking the code, typecast the object as array for dirty fix.
+ // Make sure the AU object does not have any 'extra' properties, only the amount passed in
+ $expectedAmount = count($this->auproperties);
$auArray = (array) $obj;
$this->assertCount($expectedAmount, $auArray, "AU has $expectedAmount properties");
@@ -155,4 +151,41 @@ public function testInstantiationWithValues()
$this->assertEquals($property, $value, "$value does not equal $property");
}
}
+
+ /**
+ * Test of AU constructor class exceptions. This one tests if statement is null.
+ * @return void
+ */
+ public function testInstantiation_except_null()
+ {
+ // Null statement to send and trigger exception.
+ $nullstatement = null;
+
+ // Expected message
+ // Catch the exception.
+ $this->expectException(nullException::class);
+ $this->expectExceptionMessage("Statement to build AU is null or not an array/object." );
+
+ $obj = new au($nullstatement);
+
+ }
+
+ /**
+ * Test of AU constructor class exceptions. This one tests if statement passed in is not an array.
+ * @return void
+ */
+ public function testInstantiation_except_nonarray()
+ {
+ // Null statement to send and trigger exception.
+ $nullstatement = "string";
+
+ // Catch the exception.
+ $this->expectException(nullException::class);
+ $this->expectExceptionMessage("Statement to build AU is null or not an array/object." );
+
+ $obj = new au($nullstatement);
+
+ }
+
+
}
\ No newline at end of file
diff --git a/cmi5PHP/tests/ausHelpersTest.php b/cmi5PHP/tests/ausHelpersTest.php
old mode 100755
new mode 100644
index 9e3bdd7..3d4584e
--- a/cmi5PHP/tests/ausHelpersTest.php
+++ b/cmi5PHP/tests/ausHelpersTest.php
@@ -1,6 +1,8 @@
auProperties = array(
- 'id',
- 'attempt',
- 'url',
- 'type',
- 'lmsid',
- 'grade',
- 'scores',
- 'title',
- 'moveon',
- 'auindex',
- 'parents',
- 'objectives',
- 'description',
- 'activitytype',
- 'launchmethod',
- 'masteryscore',
- 'satisfied',
- 'launchurl',
- 'sessions',
- 'progress',
- 'noattempt',
- 'completed',
- 'passed',
- 'inprogress',
- );
-
- $this->emptyStatement = array();
- // Based on created AU in program, but with some values removed.
+ // Based on created AU in program.
$this->mockStatement2 = array(
"id" => "https://exampleau",
"attempt" => NULL,
@@ -63,9 +36,68 @@ protected function setUp(): void
"title" => array( 0 => array(
"lang" => "en-US",
"text" => "Example AU")
+ ),
+ "parents" => array(),
+ "objectives" => NULL,
+ "description" => array( 0 => array(
+ "lang" => "en-US",
+ "text" => "Example AU lesson description")
),
- "moveOn"=> NULL,
- "auIndex" => NULL,
+ 'satisfied' => NULL,
+ 'sessions' => NULL,
+ 'progress' => NULL,
+ 'noattempt' => NULL,
+ 'completed' => NULL,
+ 'passed' => NULL,
+ 'inprogress' => NULL,
+ 'launchMethod' => "AnyWindow",
+ 'lmsId' => "https://exampleau/ranomnum/au0",
+ 'moveOn' => "CompletedOrPassed",
+ 'auIndex' => 0,
+ 'activityType' => NULL,
+ 'masteryScore' => NULL
+ );
+
+ // Based on created AU in program, but with some values changed.
+ // For instance title is an empty array
+ $this->mockStatementExcept = array(
+ "id" => "https://exampleau",
+ "attempt" => NULL,
+ "url" => "example.html?pages=1&complete=launch",
+ "type" => "au example",
+ "grade" => NULL,
+ "scores" => NULL,
+ "title" => array()
+ ,
+ "parents" => array(),
+ "objectives" => NULL,
+ "description" => array( 0 => array(
+ "lang" => "en-US",
+ "text" => "Example AU lesson description")
+ ),
+ 'satisfied' => NULL,
+ 'sessions' => NULL,
+ 'progress' => NULL,
+ 'noattempt' => NULL,
+ 'completed' => NULL,
+ 'passed' => NULL,
+ 'inprogress' => NULL,
+ 'launchMethod' => "AnyWindow",
+ 'lmsId' => "https://exampleau/ranomnum/au0",
+ 'auIndex' => 0,
+ 'activityType' => NULL,
+ 'masteryScore' => NULL
+ );
+ // Based on created AU in program, but with some values changed. Here title is a string.
+ $this->mockStatementExcept2 = array(
+ "id" => "https://exampleau",
+ "attempt" => NULL,
+ "url" => "example.html?pages=1&complete=launch",
+ "type" => "au example",
+ "lmsid" => NULL,
+ "grade" => NULL,
+ "scores" => NULL,
+ "title" => array( "title "),
"parents" => array(),
"objectives" => NULL,
"description" => array( 0 => array(
@@ -76,7 +108,6 @@ protected function setUp(): void
'launchmethod' => NULL,
'masteryscore' => NULL,
'satisfied' => NULL,
- 'launchurl' => NULL,
'sessions' => NULL,
'progress' => NULL,
'noattempt' => NULL,
@@ -91,7 +122,7 @@ protected function setUp(): void
'masteryScore' => NULL
);
// Perhaps a good test would be to test the constructor with a statement that has all the properties set.
- $this->mockStatementValues = array(
+ $this->mockstatementvalues = array(
'id' => 'id',
'attempt' => 'attempt',
'url' => 'url',
@@ -117,7 +148,6 @@ protected function setUp(): void
'passed' => 'passed',
'inprogress' => 'inprogress',
);
-
}
protected function tearDown(): void
@@ -126,14 +156,11 @@ protected function tearDown(): void
}
- // Retrieve Aus parses and returns AUs from large statements from the CMI5 player
- // So to test, maybe make a statement and ensure the test value is returned?
- // Arbitrarily pick a word and put in right place? See if it is returned?
+ // Retrieve Aus parses and returns AUs from large statements from the CMI5 player.
+ // So to test, we will make a statement and ensure the test value is returned.
public function testcmi5launch_retrieve_aus()
{
- //It's not just returning it, it's splitting it into chuncks~!
-
- //Fake values to return
+ // Fake values to return.
$mockStatement = array(
"createdAt" => "2023-06-26T18:36:15.000Z",
"id"=> 000,
@@ -186,9 +213,10 @@ public function testcmi5launch_retrieve_aus()
)
);
- //This is the value that should be returned, basically, an array holding all the aus separately
- $shouldBeReturned = array (
- //First au, nestled in array
+ // This is the value that should be returned, basically, an array holding all the aus separately.
+ $shouldbereturned = array (
+
+ //First au, nestled in array.
0 => array (
0 => array (
"activityType" => null,
@@ -212,7 +240,7 @@ public function testcmi5launch_retrieve_aus()
"url" => "index.html?pages=1&complete=launch",
)
),
- //second au nestled in array
+ // Second au nestled in array.
1 => array (
0 => array (
"activityType" => null,
@@ -236,59 +264,150 @@ public function testcmi5launch_retrieve_aus()
"url"=> "index.html?pages=2&complete=launch"
),
)
-
);
$helper = new au_helpers();
- //So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
+
+ // So now with this fake 'statement', lets ensure it pulls the correct value which is "correct retrieval".
$retrieved = $helper->cmi5launch_retrieve_aus($mockStatement);
-
// It should retrieve the mock aus
- $this->assertEquals($shouldBeReturned, $retrieved, "Expected retrieved statement to be equal to mock statement");
- //This is being flaged as risky?
- //Is there a different way to test this?
- //Maybe we 'expect' two properties since 2 aus were passed in?
- //I mean we aren't testing 'chunked?' so....?
+ $this->assertEquals($shouldbereturned, $retrieved, "Expected retrieved statement to be equal to mock statement");
- //It DOES return as array
+ // It returns as array.
$this->assertIsArray($retrieved, "Expected retrieved statement to be an array");
- //And it returns two in array? Since we passed in two?
+ // And it returns two in array?
$this->assertCount(2, $retrieved, "Expected retrieved statement to have two aus");
- //TODO MB
- //Those seem to pass, so take away line 206?
}
- //Test function that is fed an array of statments and returns an array of aus onjects
+ //Lets try testing so it throws excrption if thhe array doesn't have the right keys
+
+ // We cannot test 'caught' exception because it is thrown by the overriden error handler, not the SUT.
+ // To test the exception we need to test the right output (from the exception) is generated,
+ public function testcmi5launch_retrieve_aus_exception()
+ {
+ // Note this is an incorrect statement, cut off before 'aus'.
+ $mockStatement = array(
+ "createdAt" => "2023-06-26T18:36:15.000Z",
+ "id"=> 000,
+ "lmsId"=> "https://example",
+ "metadata" => array(
+ ));
+
+ // This is the expected output message.
+ $expectedMessage = "Cannot retrieve AUs. Error found when trying to parse them from course creation: " .
+ "Please check the connection to player or course format and try again. \n"
+ . 'Cannot parse array. Error: Undefined array key "aus"' . "\n";
+ $helper = new au_helpers();
+
+ // Call function under test.
+ $retrieved = $helper->cmi5launch_retrieve_aus($mockStatement);
+
+ // If the right message is displayed the try/catch wworked!
+ $this->expectOutputString($expectedMessage);
+ }
+
+
+ // Test function that is fed an array of statments and returns an array of aus objects.
public function testcmi5launch_create_aus()
{
- // Should be enough to pass the mock statement values here, make an array of them first
- $testStatements = array();
+ // Should be enough to pass the mock statement values here, make an array of them first.
+ $teststatements = array();
- //Lets create 4 aus statement
+ //Lets create 4 aus statement.
for ($i = 0; $i < 4; $i++) {
- $testStatements[$i][] = $this->mockStatementValues;
+ $teststatements[$i][] = $this->mockstatementvalues;
}
$helper = new au_helpers();
- //So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
- $auList = $helper->cmi5launch_create_aus($testStatements);
+ // So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
+ $auList = $helper->cmi5launch_create_aus($teststatements);
- //There should be a total of 4 Aus in this array
+ // There should be a total of 4 Aus in this array.
$this->assertCount(4, $auList, "Expected retrieved statement to have four aus");
- //And they should all be au objects
+ // And they should all be au objects.
foreach ($auList as $au) {
$this->assertInstanceOf(au::class, $au, "Expected retrieved statement to be an array of aus");
}
}
- //This one is going to be tricky, it saves to a DB! I know test php can have TEST DBs, but is that setup here?
- //And how to freaking test THAT?
- //Well, actually we don't need to test it goes to the DB, THAT was the job of the person who invented insert_record
- //We just need tothat it saves the correct values and CALLS insert_record
- //Technically this function returns ids, so we can make a stub which just returns ids
- //This will test it is called without messing with the DB
- public function testcmi5launch_save_aus()
+ // Test function creat aus null exception.
+ public function testcmi5launch_create_aus_exception()
+ {
+
+ // If we pass a null value in, it should throw an exception immedietely
+ $teststatements = null;
+
+ $this->expectException(nullException::class);
+ $this->expectExceptionMessage('Cannot retrieve AU information. AU statements from DB are: ' . null);
+
+ $helper = new au_helpers();
+
+ // Pass null to SUT.
+ $helper->cmi5launch_create_aus($teststatements);
+ }
+
+
+
+ // test saving aus with exceptions.
+ public function testcmi5launch_save_aus_exceptions()
+ {
+ // Make a global variable to hold the id's to pretend to be cmi5launch instance id.
+ global $cmi5launch;
+
+ $cmi5launch = new \stdClass();
+ $cmi5launch->id = 1;
+
+ // The func should return auids created by the DB when AU's were saved in array format.
+ $helper = new au_helpers();
+
+
+ // Pass in a statement with something wrong. This one has a null title.
+ $testAus[0][] = $this->mockStatementExcept;
+
+ // Because this exception is thrown by the error handler, not the SUT, test the output to ensure right exception was thrown.
+ $expected = "Cannot save to DB. Stopped at record with ID number " . 1 . "."
+ . " One of the fields is incorrect. Check data for field 'title'. Error: Undefined array key 0\n";
+
+ // Call function under test.
+ $returnedAUids = $helper->cmi5launch_save_aus($helper->cmi5launch_create_aus($testAus));
+ // If the right message is displayed the try/catch wworked!
+ $this->expectOutputString($expected);
+ }
+
+
+ // Test saving aus with exceptions, a different exception.
+ public function testcmi5launch_save_aus_exceptions_2()
+ {
+ // Make a global variable to hold the id's to pretend to be cmi5launch instance id.
+ global $cmi5launch;
+
+ $cmi5launch = new \stdClass();
+ $cmi5launch->id = 1;
+
+ // The func should return auids created by the DB when AU's were saved in array format.
+ $helper = new au_helpers();
+
+ // This first statement is correct. We want to test that it gets the SECOND statement number,
+ $testAus[0][] = $this->mockStatement2;
+ // This one has 'title' as string instead of array.
+ $testAus[1][] = $this->mockStatementExcept2;
+
+ // The expected is built by the two messages knowing 'title' is a string.
+ $expected = "Cannot save to DB. Stopped at record with ID number " . 2 . "."
+ . " One of the fields is incorrect. Check data for field 'title'. Cannot access offset of type string on string\n";
+
+ // Call the function to throw the exception.
+ $returnedAUids = $helper->cmi5launch_save_aus($helper->cmi5launch_create_aus($testAus));
+
+ // 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 saving aus with exceptions, a (null) exception.
+ public function testcmi5launch_save_aus_exceptions_test_null()
{
// Make a global variable to hold the id's to pretend to be cmi5launch instance id.
@@ -296,7 +415,33 @@ public function testcmi5launch_save_aus()
$cmi5launch = new \stdClass();
$cmi5launch->id = 1;
- // $cmi5launch->id = 1;
+
+ $helper = new au_helpers();
+
+ // A test statement with a null value.
+ $testAus = null;
+
+ // Catch the exception.
+ $this->expectException(nullException::class);
+ $this->expectExceptionMessage('Cannot save AU information. AU object array is: null' . null);
+
+ // The expected is built bby the two messages knowing 'title' is an empty array.
+ $expected = "Cannot save to DB. Stopped at record with ID number " . 1 . "."
+ . " One of the fields is incorrect. Check data for field 'title'. Error: Undefined array key 0\n";
+ //So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
+ $returnedAUids = $helper->cmi5launch_save_aus($testAus);
+
+ }
+
+ // Test saving aus, this function returns ids, so we can make a stub which just returns ids.
+ // This will test it is called without messing with the DB.
+ public function testcmi5launch_save_aus()
+ {
+ // Make a global variable to hold the id's to pretend to be cmi5launch instance id.
+ global $cmi5launch, $auidForTest;
+
+ $cmi5launch = new \stdClass();
+ $cmi5launch->id = 1;
// The func should return auids created by the DB when AU's were saved in array format.
$helper = new au_helpers();
@@ -304,8 +449,6 @@ public function testcmi5launch_save_aus()
//Lets create 4 aus statement
for ($i = 0; $i < 3; $i++) {
$testAus[$i][] = $this->mockStatement2;
- // $testAus[$i][] = ($this->$cmi5launch);
- // $testAus = array_merge($testAus, $cmi5launch);
}
//So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
@@ -316,46 +459,63 @@ public function testcmi5launch_save_aus()
// The array should have the same count of ids as AU's passed in
$this->assertCount(3, $returnedAUids, "Expected retrieved statement to have three aus");
+
// Now iterate through the returned array and ensure ids were passed back, numeric ids
foreach ($returnedAUids as $auId) {
- // what is id?
- // echo"auId: $auId";
$this->assertIsNumeric($auId, "Expected array to have numeric values");
}
- global $auidForTest;
- //Save to use in next test?
- $auidForTest = $returnedAUids;
- //Do I need to test fail?
+ // Is this not savin?
+ // echo "Returned AU ids: " . var_dump($returnedAUids) . "\n";
- }
-
+ $auidForTest = $returnedAUids;
+ }
+ // Test retrieving an AU from the DB with a correct value.
public function testcmi5launch_retrieve_aus_from_db()
{
- // Access the global array of ids from above test
+ // ok, what if we saved ere the retrieved
+ // Access the global array of ids from above test
global $auidForTest;
// global $auidForTest;
$helper = new au_helpers();
+ // Save new aus to db to pull.
+ //Lets create 4 aus statement
+ for ($i = 0; $i < 3; $i++) {
+ $testAus[$i][] = $this->mockStatement2;
+ }
+
+ //So now with this fake 'statement', lets ensure it pulls the correct value which is "correct Retrieval"
+ $returnedAUids = $helper->cmi5launch_save_aus($helper->cmi5launch_create_aus($testAus));
+
+ //and what is here?
+ // echo"au id for test: " . var_dump($auidForTest) . "\n";
// It takes singular ids, so we will iterate through them
- foreach ($auidForTest as $auId) {
+ foreach ($returnedAUids as $auId) {
$returnedAu = $helper->cmi5launch_retrieve_aus_from_db($auId);
// And the return should be an au object
$this->assertInstanceOf(au::class, $returnedAu, "Expected retrieved object to be an au object");
}
+ }
+
- // And if it fails it should fail gracefully
+ // Test retrieving an AU from the DB with a null value and thrown exception.
+ public function testcmi5launch_retrieve_aus_from_db_null_exception()
+ {
+ $helper = new au_helpers();
+
+ // And if it fails it should fail gracefully, throwin the correct exception.
$badid = 0;
+
+ // Catch the exception.
+ $this->expectException(nullException::class);
+ $this->expectExceptionMessage("Error attempting to get AU data from DB. Check AU id. AU id is: " . $badid ."" . null);
+
$returnedAu = $helper->cmi5launch_retrieve_aus_from_db($badid);
-
- // And the return should be a false value
- $this->assertNotTrue($returnedAu, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString("Error attempting to get AU data from DB. Check AU id. AU id is: " . $badid . "
");
}
}
\ No newline at end of file
diff --git a/cmi5PHP/tests/cmi5TestHelpers.php b/cmi5PHP/tests/cmi5TestHelpers.php
old mode 100755
new mode 100644
index db477f5..5db6485
--- a/cmi5PHP/tests/cmi5TestHelpers.php
+++ b/cmi5PHP/tests/cmi5TestHelpers.php
@@ -532,5 +532,11 @@ function cmi5launch_test_stream_and_send_fail($options, $url)
// Lets pass in the 'return' value as the option.
return $errormessage;
}
+ // should I have it throw an error? would that work, or would that take the erorr out of SUT?
+ // So now all the test has to do is inject THIS which will return as we please
+ function cmi5launch_test_stream_and_send_excep($options, $url)
+ {
+ throw new \Exception('test error');
+ }
?>
diff --git a/cmi5PHP/tests/cmi5_connectorsTest.php b/cmi5PHP/tests/cmi5_connectorsTest.php
index e0d28d3..0028976 100755
--- a/cmi5PHP/tests/cmi5_connectorsTest.php
+++ b/cmi5PHP/tests/cmi5_connectorsTest.php
@@ -5,6 +5,8 @@
use PHPUnit\Framework\TestCase;
use mod_cmi5launch\local\cmi5_connectors;
use mod_cmi5launch\test\cmi5TestHelpers;
+use mod_cmi5launch\local\playerException;
+
require_once( "cmi5TestHelpers.php");
/**
@@ -33,7 +35,7 @@ public static function setUpBeforeClass(): void
{
global $DB, $cmi5launch, $cmi5launchid;
- // Mke a fake cmi5 launch record.
+ // Make a fake cmi5 launch record.
$cmi5launchid = maketestcmi5launch();
}
@@ -51,7 +53,8 @@ protected function setUp(): void
{
global $DB, $cmi5launch, $cmi5launchid, $USER, $testcourseid, $cmi5launchsettings;
- $cmi5launchsettings = array("cmi5launchtenanttoken" => "Testtoken", "cmi5launchplayerurl" => "http://test/launch.php", "cmi5launchcustomacchp" => "http://testhomepage.com");
+ $cmi5launchsettings = array("cmi5launchtenanttoken" => "Testtoken", "cmi5launchplayerurl" => "http://test/launch.php", "cmi5launchcustomacchp" => "http://testhomepage.com",
+ "cmi5launchbasicname" => 'testname', "cmi5launchbasepass" => "testpassword");
// Override global variable and function so that it returns test data.
@@ -129,9 +132,8 @@ public function testcmi5launch_create_course_fail_with_message()
// Function that will be called in function under test.
$testfunction = 'cmi5launch_stream_and_send';
- // Message we expect to be output.
- $expectedstring= "
Something went wrong creating the course. CMI5 Player returned 404 error. With message 'testmessage'.
";
- // Arguments to be passed to the method under test.
+
+ // Arguments to be passed to the method under test.
$id = 0;
$tenanttoken = "testtoken";
// Error message for stubbed method to return.
@@ -143,7 +145,10 @@ public function get_content() {
return "testfilecontents";
}
};
-
+ $test = false;
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong creating the course. CMI5 Player returned 404 error. With message 'testmessage'." ;
+
// Mock a cmi5 connector object but only stub ONE method, as we want to test the other methods.
// Create a mock of the send_request class as we don't actually want
// to create a new course in the player.
@@ -158,16 +163,77 @@ public function get_content() {
->with($testfunction, 'testfilecontents', 'http://test/launch.php/api/v1/course', 'zip', 'testtoken')
->willReturn($errormessage);
- // Call the method under test.
- $returnedresult =$csc->cmi5launch_create_course($id, $tenanttoken, $filename);
+ //
- // Result should be debug echo string and false.
- $this->assertNotTrue($returnedresult, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
+ // 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
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ // Call the method under test.
+ $returnedresult = $csc->cmi5launch_create_course($id, $tenanttoken, $filename);
+
}
+ /**
+ * Test of the cmi5launch_create_course method with a failed response from the player.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_create_course_fail_with_exception()
+ {
+
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+ // Arguments to be passed to the method under test.
+ $id = 0;
+ $tenanttoken = "testtoken";
+ // Error message for stubbed method to return.
+ $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
+
+ //If we make filename an object with it's own get_content method, we can stub it out.
+ $filename = new class {
+ public function get_content() {
+ return "testfilecontents";
+ }
+ };
+ $test = false;
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong creating the course." ;
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the other methods.
+ // Create a mock of the send_request class as we don't actually want
+ // to create a new course in the player.
+ $csc = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post', 'cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ // We will have the mock return a fake message as if the player had a problem with request.
+ // This should enable us to test the method under failing conditions. We do expect create_course to only call this once.
+ $csc->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_post')
+ ->with($testfunction, 'testfilecontents', 'http://test/launch.php/api/v1/course', 'zip', 'testtoken')
+ ->willReturn($errormessage);
+
+ // The string just needs to be returned as is. We do expect create_tenant to only call this once.
+ $csc->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, 'creating the course') // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
+ // IRL it returns something that needs to be json decoded, so lets pass somethin that is encoded>
+ ->willReturn(false);
+
+ //
+
+ // 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
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ // Call the method under test.
+ $returnedresult = $csc->cmi5launch_create_course($id, $tenanttoken, $filename);
+
+ }
/**
* Test of the cmi5launch_create_tenant method with a successful response from the player.
* @return void
@@ -179,21 +245,14 @@ public function testcmi5launch_create_tenant_pass()
$testfunction = 'cmi5launch_stream_and_send';
// Arguments to be passed to the method under test.
- $urltosend = "playerwebaddress";
- $username = "testname";
- $password = "testpassword";
- $newtenantname = "testtenantname";
- $data = array ('code' => 'testtenantname');
+ $newtenantname = "newtenantname";
+ $data = array ('code' => 'newtenantname');
// Encode data as it will be encoded when sent to player
$data = json_encode($data);
-
- // This is the expected return value.
- $returnvalue = array(
- "code" => "testtenantname",
- "id" => 9
- );
-
-
+
+ // Message for stubbed method to return.
+ $returnvalue = json_encode(array("statusCode" => "200", "code" => "newtenantname","id" => "9" ) );
+
// Mock a cmi5 connector object but only stub ONE method, as we want to test the other methods.
// Create a mock of the send_request class as we don't actually want
// to create a new tenant.
@@ -205,24 +264,24 @@ public function testcmi5launch_create_tenant_pass()
// The string just needs to be returned as is. We do expect create_tenant to only call this once.
$csc->expects($this->once())
->method('cmi5launch_send_request_to_cmi5_player_post')
- ->with($testfunction, $data, 'playerwebaddress','json', 'testname', 'testpassword') // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
+ ->with($testfunction, $data, 'http://test/launch.php/api/v1/tenant','json', 'testname', 'testpassword') // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
// IRL it returns something that needs to be json decoded, so lets pass somethin that is encoded>
- ->willReturn('{
- "code": "testtenantname",
- "id": 9
- }'
- );
+ ->willReturn($returnvalue);
+
//Call the method under test.
- $result =$csc->cmi5launch_create_tenant($urltosend, $username, $password, $newtenantname);
+ $result =$csc->cmi5launch_create_tenant( $newtenantname);
+
// And the return should be a string (the original method returns what the player sends back json-decoded or FALSE)
- $this->assertIsArray($result);
+ $this->assertIsString($result);
$this->assertEquals( $returnvalue, $result);
+
}
+
/**
- * Test of the cmi5launch_create_tenant method with a error response from the player.
+ * Test of the cmi5launch_create_tenant method with a failed response from the player. Should trigger an exception.
* @return void
*/
public function testcmi5launch_create_tenant_fail()
@@ -232,44 +291,103 @@ public function testcmi5launch_create_tenant_fail()
$testfunction = 'cmi5launch_stream_and_send';
// Arguments to be passed to the method under test.
- $urltosend = "playerwebaddress";
- $username = "testname";
- $password = "testpassword";
- $newtenantname = "testtenantname";
- $data = array ('code' => 'testtenantname');
+
+ $newtenantname = "newtenantname";
+ $data = array ('code' => 'newtenantname');
// Encode data as it will be encoded when sent to player
$data = json_encode($data);
- // The expected error message to be output.
- $expectedstring= "
Something went wrong creating the tenant. CMI5 Player returned 404 error. With message 'testmessage'.
";
+
+ // Message for stubbed method to return.
+ $errormessage = array("statusCode" => "400", "message" => "website not found","id" => "9" );
+
- // Error message for stubbed method to return.
- $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
-
- // Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the other methods.
// Create a mock of the send_request class as we don't actually want
- // to create a new course in the player.
+ // to create a new tenant.
$csc = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post'))
->getMock();
-
- // We will have the mock return a fake message as if the player had a problem with request.
- // This will enable us to test the method under failing conditions. We do expect create_tenant to only call this once.
+ // We will have the mock return a basic string, as it's not under test.
+ // The string just needs to be returned as is. We do expect create_tenant to only call this once.
$csc->expects($this->once())
->method('cmi5launch_send_request_to_cmi5_player_post')
- ->with($testfunction, $data, 'playerwebaddress', 'json', 'testname', 'testpassword')
+ ->with($testfunction, $data, 'http://test/launch.php/api/v1/tenant','json', 'testname', 'testpassword') // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
+ // IRL it returns something that needs to be json decoded, so lets pass somethin that is encoded>
->willReturn($errormessage);
- //Call the method under test.
- $result =$csc->cmi5launch_create_tenant($urltosend, $username, $password, $newtenantname);
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the registration information. CMI5 Player returned 400 error. With message 'website not found'." ;
+
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- // And it should output this error message
- $this->expectOutputString($expectedstring);
+ // the correct output not an exception
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result =$csc->cmi5launch_create_tenant( $newtenantname);
+
}
+
+ /**
+ * Test of the cmi5launch_create_tenant method with a failed response from the player. Should trigger an exception.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_create_tenant_fail_2()
+ {
+
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+
+ // Arguments to be passed to the method under test.
+
+ $newtenantname = "newtenantname";
+ $data = array ('code' => 'newtenantname');
+ // Encode data as it will be encoded when sent to player
+ $data = json_encode($data);
+
+
+ // Message for stubbed method to return.
+ $errormessage = array("statusCode" => "400", "message" => "website not found","id" => "9" );
+
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the other methods.
+ // Create a mock of the send_request class as we don't actually want
+ // to create a new tenant.
+ $csc = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post','cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ // We will have the mock return a basic string, as it's not under test.
+ // The string just needs to be returned as is. We do expect create_tenant to only call this once.
+ $csc->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_post')
+ ->with($testfunction, $data, 'http://test/launch.php/api/v1/tenant','json', 'testname', 'testpassword') // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
+ // IRL it returns something that needs to be json decoded, so lets pass somethin that is encoded>
+ ->willReturn($errormessage);
+ // We will have the mock return a basic string, as it's not under test.
+ // The string just needs to be returned as is. We do expect create_tenant to only call this once.
+ $csc->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, "creating the tenant") // for tomorrow, is thi failing because with only evaluates strings? Like do we need to string the array out>
+ // IRL it returns something that needs to be json decoded, so lets pass somethin that is encoded>
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong creating the tenant." ;
+
+
+ // the correct output not an exception
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result =$csc->cmi5launch_create_tenant( $newtenantname);
+
+ }
/**
* * Test the retrieve_registration method with a successful response from the player.
* @return void
@@ -327,7 +445,7 @@ public function testcmi5launch_retrieve_registration_with_get_fail()
$errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
// The expected error message to be output.
- $expectedstring= "
Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'.
";
+ // $expectedstring= "
Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'.
";
// The arguments to be passed to the method under test.
$id = 0;
@@ -350,13 +468,68 @@ public function testcmi5launch_retrieve_registration_with_get_fail()
->with($testfunction, "Testtoken", $urltosend)
->willReturn($errormessage);
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'" ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_registration_with_get($registration, $id);
+
+ }
+
+ /**
+ * * Test the retrieve_registration method with a failed response from the player.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_retrieve_registration_with_get_fail_2()
+ {
+ // Error message for stubbed method to return.
+ $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
+
+ // The expected error message to be output.
+ // $expectedstring= "
Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'.
";
+
+ // The arguments to be passed to the method under test.
+ $id = 0;
+ $registration = "testregistration";
+
+ // This is the url the stubbed method shopuld receive.
+ $urltosend = "http://test/launch.php/api/v1/registration/testregistration";
+
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
+ $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_get', 'cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_get')
+ ->with($testfunction, "Testtoken", $urltosend)
+ ->willReturn($errormessage);
+
+
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, "retrieving the registration")
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the registration information." ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
//Call the method under test.
$result = $mockedclass->cmi5launch_retrieve_registration_with_get($registration, $id);
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
}
/**
@@ -416,17 +589,72 @@ public function testcmi5launch_retrieve_registration_with_post_pass()
}
/**
- * * Test the retrieve_registration_with_post method with a failed response from the player.
+ * * Test the retrieve_registration_with_post method with a failed response from the player. Should throw exception.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
* @return void
*/
- public function testcmi5launch_retrieve_registration_with_post_fail()
+ public function testcmi5launch_retrieve_registration_with_post_fail_2()
{
// Error message for stubbed method to return.
$errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
+ // The arguments to be passed to the method under test.
+ $id = 0;
+ $courseid = 1;
+ $filetype = "json";
- // The expected error message to be output.
- $expectedstring= "
Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'.
";
+ // The data to be passed to the mocked method.
+ $data = array(
+ "courseId" => $courseid,
+ "actor" => array(
+ "account" => array (
+ "homePage" => "http://testhomepage.com",
+ "name" => "testname"
+ ),
+ ),
+ );
+
+ // This is the url the stubbed method shopuld receive.
+ $urltosend = "http://test/launch.php/api/v1/registration";
+
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
+ $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post', 'cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_post')
+ ->with($testfunction, json_encode($data), $urltosend, $filetype, "Testtoken")
+ ->willReturn($errormessage);
+
+
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, "retrieving the registration")
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the registration information." ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_registration_with_post($courseid, $id);
+ }
+ /**
+ * * Test the retrieve_registration_with_post method with a failed response from the player. Should throw exception.
+ * @return void
+ */
+ public function testcmi5launch_retrieve_registration_with_post_fail()
+ {
+ // Error message for stubbed method to return.
+ $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
// The arguments to be passed to the method under test.
$id = 0;
$courseid = 1;
@@ -460,15 +688,17 @@ public function testcmi5launch_retrieve_registration_with_post_fail()
->with($testfunction, json_encode($data), $urltosend, $filetype, "Testtoken")
->willReturn($errormessage);
- //Call the method under test.
- $result = $mockedclass->cmi5launch_retrieve_registration_with_post($courseid, $id);
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the registration. CMI5 Player returned 404 error. With message 'testmessage'" ;
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
- }
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_registration_with_post($courseid, $id);
+ }
/**
* * Test the retrieve_token method with a successful response from the player.
@@ -476,14 +706,19 @@ public function testcmi5launch_retrieve_registration_with_post_fail()
*/
public function testcmi5launch_retrieve_token_pass()
{
+ global $CFG, $cmi5launchid;
+
+ $settings = cmi5launch_settings($cmi5launchid);
// Arguments to be passed to the method under test.
- $url = "http://test/launch.php";
- $username = "testname";
+ //$url = "http://test/launch.php";
+ // $username = "testname";
$filetype = "json";
- $password = "testpassword";
+ //$password = "testpassword";
$audience = "testaudience";
$tenantid = 0;
-
+ $username = $settings['cmi5launchbasicname'];
+ $url = $settings['cmi5launchplayerurl'] . "/api/v1/auth";
+ $password = $settings['cmi5launchbasepass'];
// The data to be passed to the mocked method.
$data = array(
"tenantId" => $tenantid,
@@ -491,9 +726,10 @@ public function testcmi5launch_retrieve_token_pass()
);
// The player returns a json string.
- $returnvalue = '{
- "token": "testtoken"
- }';
+ $returnvalue = "testtoken";
+
+ $playervalue = array("statusCode" => "200", "token" => "testtoken","message" => "testmessage" );
+
// Function that will be called in function under test.
$testfunction = 'cmi5launch_stream_and_send';
@@ -505,10 +741,10 @@ public function testcmi5launch_retrieve_token_pass()
$mockedclass->expects($this->once())
->method('cmi5launch_send_request_to_cmi5_player_post')
->with($testfunction, json_encode($data), $url, $filetype, $username, $password)
- ->willReturn($returnvalue);
+ ->willReturn(json_encode($playervalue));
//Call the method under test.
- $result = $mockedclass->cmi5launch_retrieve_token($url, $username, $password, $audience, $tenantid);
+ $result = $mockedclass->cmi5launch_retrieve_token($audience, $tenantid);
// And the return should be a string (the original method returns what the player sends back or FALSE.
$this->assertIsString($result);
@@ -521,18 +757,21 @@ public function testcmi5launch_retrieve_token_pass()
*/
public function testcmi5launch_retrieve_token_fail()
{
+ global $CFG, $cmi5launchid;
+ $settings = cmi5launch_settings($cmi5launchid);
+
// Error message for stubbed method to return.
$errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
- // The expected error message to be output.
- $expectedstring= "
Something went wrong retrieving the token. CMI5 Player returned 404 error. With message 'testmessage'.
";
-
// Arguments to be passed to the method under test.
- $url = "http://test/launch.php";
- $username = "testname";
- $password = "testpassword";
+ $url = $settings['cmi5launchplayerurl'] . '/api/v1/auth';
+
$audience = "testaudience";
$tenantid = 0;
+
+ //$actor = $USER->username;
+ $username = $settings['cmi5launchbasicname'];
+ $password = $settings['cmi5launchbasepass'];
// The data to be passed to the mocked method.
$filetype = "json";
@@ -555,13 +794,80 @@ public function testcmi5launch_retrieve_token_fail()
->with($testfunction, json_encode($data), $url, $filetype, $username, $password)
->willReturn($errormessage);
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the tenant token. CMI5 Player returned 404 error. With message 'testmessage'" ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_token($audience, $tenantid);
+
+ }
+
+ /**
+ * * Test the retrieve_token method with a failed response from the player.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_retrieve_token_fail_2()
+ {
+ global $CFG, $cmi5launchid;
+ $settings = cmi5launch_settings($cmi5launchid);
+
+ // Error message for stubbed method to return.
+ $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
+
+ // Arguments to be passed to the method under test.
+ $url = $settings['cmi5launchplayerurl'] . '/api/v1/auth';
+
+ $audience = "testaudience";
+ $tenantid = 0;
+
+ //$actor = $USER->username;
+ $username = $settings['cmi5launchbasicname'];
+ $password = $settings['cmi5launchbasepass'];
+
+ // The data to be passed to the mocked method.
+ $filetype = "json";
+ $data = array(
+ "tenantId" => $tenantid,
+ "audience" => $audience,
+ );
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
+ $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors' )
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post', 'cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_post')
+ ->with($testfunction, json_encode($data), $url, $filetype, $username, $password)
+ ->willReturn($errormessage);
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, 'retrieving the tenant token.')
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the tenant token." ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+
//Call the method under test.
- $result = $mockedclass->cmi5launch_retrieve_token($url, $username, $password, $audience, $tenantid);
+ $result = $mockedclass->cmi5launch_retrieve_token($audience, $tenantid);
- // Result should be debug echo string and false.
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- // And it should output this error message.
- $this->expectOutputString($expectedstring);
}
/**
@@ -683,13 +989,93 @@ public function testcmi5launch_retrieve_url_fail()
->with($testfunction, json_encode($data), $urltosend, $filetype, "Testtoken")
->willReturn($errormessage);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the launch url from player. CMI5 Player returned 404 error. With message 'testmessage'" ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
//Call the method under test.
$result = $mockedclass->cmi5launch_retrieve_url($id, $auindex);
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
+
+ }
+
+ /**
+ * * Test the retrieve_url (launchurl) method with a failed response from the player.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_retrieve_url_fail_2()
+ {
+ global $cmi5launchid;
+
+ // Error message for stubbed method to return.
+ $errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
+
+ // The id to be passed to method under test.
+ $id = $cmi5launchid;
+ $auindex = 1;
+ $filetype = "json";
+
+ //Retrieve settings like the method under test will.
+ $settings = cmi5launch_settings($id);
+ $playerurl = $settings['cmi5launchplayerurl'];
+
+ $returnurl = "https://testmoodle.com";
+ $registrationid = "testregistrationid";
+
+ // The data to be passed to the mocked method.
+ $data = array(
+ 'actor' => array(
+ 'account' => array(
+ "homePage" => "http://testhomepage.com",
+ "name" => "testname",
+ ),
+ ),
+ 'returnUrl' => $returnurl,
+ 'reg' => $registrationid,
+ );
+
+ // This is the url the stubbed method shopuld receive.
+ $urltosend = $playerurl . "/api/v1/course/" . "1" ."/launch-url/" . $auindex;
+
+ // Function that will be called in function under test.
+ $testfunction = 'cmi5launch_stream_and_send';
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the other.
+ // Create a mock of the send_request class as we don't actually want
+ // to create a new course in the player.
+ $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_post', 'cmi5launch_connectors_error_message'))
+ ->getMock();
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_post')
+ ->with($testfunction, json_encode($data), $urltosend, $filetype, "Testtoken")
+ ->willReturn($errormessage);
+
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, 'retrieving the launch url from player.')
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the launch url from player." ;
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_url($id, $auindex);
+
+
}
/**
@@ -728,17 +1114,80 @@ public function testcmi5launch_send_request_to_cmi5_player_post_with_one_arg()
//The arguments to pass in, in this case one, a pretend token.
$token = "testtoken";
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Error communicating with player, sending a POST request." ;
+
+ // Expected exceptions and messages
+ // $this->expectExceptionMessage($exceptionmessage);
+ // $this->expectException(playerException::class);
+
// Class for function under test.
$helper = new cmi5_connectors;
// Call the method under test.
$test = $helper->cmi5launch_send_request_to_cmi5_player_post($testfunction, $data, $url, $filetype, $token);
+ // If the right message is displayed the try/catch wworked!
+ $this->expectOutputString($exceptionmessage);
+
+ }
+
+ /**
+ * Test the send_request_to_cmi5_player_post method with one arg.
+ * Test the thrown exception.
+ * @return void
+ */
+ public function testcmi5launch_send_request_to_cmi5_player_post_with_one_arg_fail()
+ {
+ // We send the TEST function to the function under test now!
+ $testfunction = 'cmi5Test\cmi5launch_test_stream_and_send_excep';
+ // Which returns the 'options' parameter passed to it.
+ // The player returns a string under normal circumstances.
+ $returnvalue = json_encode(array(
+ "statusCode" => 200,
+ "Response" => "Successful Post",
+ ));
+
+ // The data to be passed to the mocked method.
+ $data = array(
+ 'actor' => array(
+ 'account' => array(
+ "homePage" => "http://testhomepage.com",
+ "name" => "testname",
+ ),
+ ),
+ 'returnUrl' => 'returnurl',
+ 'reg' => 'registrationid',
+ );
+
+ // Fake arguments to pass in.
+ $filetype = "json";
+ $url = "http://test/url.com";
+
+
+ //The arguments to pass in, in this case one, a pretend token.
+ $token = "testtoken";
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong communicating with player, sending or crafting a POST request: " ;
+
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ // Class for function under test.
+ $helper = new cmi5_connectors;
+ // Call the method under test.
+ // Note: by not sending an actual function, this will cause an exception and allow testing of try/catch and error override.
+ $test = $helper->cmi5launch_send_request_to_cmi5_player_post('testfunction', $data, $url, $filetype, $token);
+
// And the return should be a string.
$this->assertIsString($test);
// And it should be the same as the return value.
$this->assertEquals($test, $returnvalue);
}
+
/**
* * Test the send_request_to_cmi5_player_post method with two args.
* This is what is used to retrieve info like tenant info.
@@ -789,12 +1238,67 @@ public function testcmi5launch_send_request_to_cmi5_player_post_with_two_args()
$this->assertEquals($test, $returnvalue);
}
+
+ /**
+ * * Test the send_request_to_cmi5_player_post method with two args.
+ * This is what is used to retrieve info like tenant info.
+ * @return void
+ */
+ public function testcmi5launch_send_request_to_cmi5_player_post_with_two_args_fail()
+ {
+
+ // We send the TEST function to the function under test now!
+ $testfunction = 'cmi5Test\cmi5launch_test_stream_and_send_pass';
+
+ // The player returns a string under normal circumstances.
+ $returnvalue = json_encode(array(
+ "statusCode" => 200,
+ "Response" => "Successful Post",
+ ));
+
+ // The data to be passed to the mocked method.
+ $data = array(
+ 'actor' => array(
+ 'account' => array(
+ "homePage" => "http://testhomepage.com",
+ "name" => "testname",
+ ),
+ ),
+ 'returnUrl' => 'returnurl',
+ 'reg' => 'registrationid',
+ );
+
+ // Fake arguments to pass in.
+ $filetype = "json";
+ $url = "http://test/url.com";
+ $contenttype = "application/json\r\n";
+
+ //The arguments to pass in, in this case one, a pretend username and password.
+ $username = "testname";
+ $password = "testpassword";
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong communicating with player, sending or crafting a POST request: " ;
+
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ // Class for function under test.
+ $helper = new cmi5_connectors;
+ $test = $helper->cmi5launch_send_request_to_cmi5_player_post('testfunction', $data, $url, $filetype, $username, $password);
+
+
+ }
+
+
/**
* * Test the send_request_to_cmi5_player_get
* This is what is used to retrieve info like tenant info.
* @return void
*/
- public function testcmi5launch_send_request_to_cmi5_player_post_with_get_pass()
+ public function testcmi5launch_send_request_to_cmi5_player_with_get_pass()
{
// We send the TEST function to the function under test now!
@@ -816,7 +1320,7 @@ public function testcmi5launch_send_request_to_cmi5_player_post_with_get_pass()
$test = $helper->cmi5launch_send_request_to_cmi5_player_get($testfunction, $token, $url);
// And the return should be an array.
- $this->assertIsArray($test);
+ $this->assertIsString($test);
// And it should be the same as the return value.
$this->assertEquals($test, json_decode($returnvalue, true) );
@@ -828,10 +1332,10 @@ public function testcmi5launch_send_request_to_cmi5_player_post_with_get_pass()
* This is meant to fail, we want it to act as if the player is unreachable
* @return void
*/
- public function testcmi5launch_send_request_to_cmi5_player_post_with_get_fail()
+ public function testcmi5launch_send_request_to_cmi5_player_with_get_fail()
{
// We send the TEST function to the function under test now!
- $testfunction = 'cmi5Test\cmi5launch_test_stream_and_send_fail';
+ $testfunction = 'cmi5Test\cmi5launch_test_stream_and_send_excep';
// Error message for stubbed method to return.
@@ -852,32 +1356,32 @@ public function testcmi5launch_send_request_to_cmi5_player_post_with_get_fail()
"Accept: application/json\r\n"),
),
);
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong communicating with player, sending or crafting a GET request: " ;
- // What if we run the entire class mocked except the one under test?
- // would it run in the riht namespace?
- // AKA OUR test namepspace
- // Mock a cmi5 connector object but only stub ONE method, as we want to test the other.
-
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
// This is the SUT?
$helper = new cmi5_connectors;
- $post = $helper->cmi5launch_get_send_request_to_cmi5_player_get();
+ $get = $helper->cmi5launch_get_send_request_to_cmi5_player_get();
//$test = $mockedclass->cmi5launch_send_request_to_cmi5_player_get($token, $url);
- $test = $post($testfunction, $token, $url);
+ $test = $get($testfunction, $token, $url);
- // And the return should be an array since the method under test returns player message decoded.
- $this->assertIsArray($test);
- // And it should be the same as the return value.
- $this->assertEquals($test, $errormessage);
+
}
+
+
/**
* * Test the retrieve_session method with a successful response from the player.
* @return void
*/
- public function testcmi5launch_session_info_from_player_pass()
+ public function testcmi5launch_retrieve_session_info_from_player_pass()
{
global $cmi5launchid;
@@ -894,11 +1398,11 @@ public function testcmi5launch_session_info_from_player_pass()
$urltosend = $playerurl . "/api/v1/session/" . $sessionid;
// The player returns a string, but the mocked method returns an array.
- $returnvalue = array(
+ $returnvalue = json_encode(array(
"statusCode" => 200,
"launchMethod" => "AnyWindow",
"url" => "http://testlaunchurl"
- );
+ ));
// We send the TEST function to the function under test now!
$testfunction = 'cmi5launch_stream_and_send';
@@ -913,7 +1417,7 @@ public function testcmi5launch_session_info_from_player_pass()
$mockedclass->expects($this->once())
->method('cmi5launch_send_request_to_cmi5_player_get')
->with($testfunction, $token, $urltosend)
- ->willReturn(json_encode($returnvalue));
+ ->willReturn(($returnvalue));
//Call the method under test.
@@ -921,14 +1425,69 @@ public function testcmi5launch_session_info_from_player_pass()
// And the return should be an array (the original method returns what the player sends back json-decoded or FALSE)
$this->assertIsString($result);
- $this->assertEquals($result, json_encode($returnvalue));
+ $this->assertEquals($result,($returnvalue));
}
/**
* * Test the retrieve_session (launchurl) method with a failed response from the player.
* @return void
*/
- public function testcmi5launch_session_info_from_player_fail()
+ public function testcmi5launch_retrieve_session_info_from_player_fail()
+ {
+ global $cmi5launchid;
+
+ // Error message for stubbed method to return.
+ $errormessage = json_encode(
+ array("statusCode" => "404",
+ "error" => "Not Found",
+ "message" => "testmessage" ));
+
+
+ // The id to be passed to method under test.
+ $id = $cmi5launchid;
+
+ //Retrieve settings like the method under test will.
+ $settings = cmi5launch_settings($id);
+ $playerurl = $settings['cmi5launchplayerurl'];
+ $sessionid = "testsessionid";
+ $token = $settings['cmi5launchtenanttoken'];
+ // This is the url the stubbed method shopuld receive.
+ $urltosend = $playerurl . "/api/v1/session/" . $sessionid;
+
+ // We send the TEST function to the function under test now!
+ $testfunction = 'cmi5launch_stream_and_send';
+
+
+ // Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
+ $mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_get'))
+ ->getMock();
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_send_request_to_cmi5_player_get')
+ ->with($testfunction, $token, $urltosend)
+ ->willReturn($errormessage);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the session information. CMI5 Player returned 404 error. With message 'testmessage'." ;
+
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_session_info_from_player($sessionid, $id);
+
+ }
+
+ /**
+ * * Test the retrieve_session (launchurl) method with a failed response from the player.
+ * This one tests if resulttest is false. This path shouldnt be able to be reached but is here to test the failsafe.
+ * @return void
+ */
+ public function testcmi5launch_retrieve_session_info_from_player_fail_excep()
{
global $cmi5launchid;
@@ -936,7 +1495,7 @@ public function testcmi5launch_session_info_from_player_fail()
$errormessage = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
// The expected error message to be output.
- $expectedstring= "
Something went wrong retrieving session info. CMI5 Player returned 404 error. With message 'testmessage'.
";
+ $expectedstring= "
Something went wrong retrieving session information. CMI5 Player returned 404 error. With message 'testmessage'.
";
// The id to be passed to method under test.
$id = $cmi5launchid;
@@ -948,28 +1507,39 @@ public function testcmi5launch_session_info_from_player_fail()
$token = $settings['cmi5launchtenanttoken'];
// This is the url the stubbed method shopuld receive.
$urltosend = $playerurl . "/api/v1/session/" . $sessionid;
- // We send the TEST function to the function under test now!
- $testfunction = 'cmi5launch_stream_and_send';
+
+ // We send the TEST function to the function under test now!
+ $testfunction = 'cmi5launch_stream_and_send';
// Mock a cmi5 connector object but only stub ONE method, as we want to test the others.
$mockedclass = $this->getMockBuilder('mod_cmi5launch\local\cmi5_connectors')
- ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_get'))
+ ->onlyMethods(array('cmi5launch_send_request_to_cmi5_player_get', 'cmi5launch_connectors_error_message'))
->getMock();
// Mock returns json encoded data, as it would be from the player.
$mockedclass->expects($this->once())
->method('cmi5launch_send_request_to_cmi5_player_get')
->with($testfunction, $token, $urltosend)
- ->willReturn(json_encode($errormessage));
+ ->willReturn(($errormessage));
+
+ // Mock returns json encoded data, as it would be from the player.
+ $mockedclass->expects($this->once())
+ ->method('cmi5launch_connectors_error_message')
+ ->with($errormessage, 'retrieving the session information.')
+ ->willReturn(false);
+
+ // Expected exceptions
+ $exceptionmessage = "Player communication error. Something went wrong retrieving the session information." ;
- //Call the method under test.
- $result = $mockedclass->cmi5launch_retrieve_session_info_from_player($sessionid, $id);
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
+
+ //Call the method under test.
+ $result = $mockedclass->cmi5launch_retrieve_session_info_from_player($sessionid, $id);
+
}
/**
@@ -984,16 +1554,22 @@ public function testcmi5launch_connectors_error_message_path_one()
$response = false;
$type = "retreiving 'item'";
+ $helper = new cmi5_connectors;
+ $error = $helper->cmi5launch_get_connectors_error_message();
+
+
// The expected error message to be output.
- $errormessage ="
Something went wrong " . $type . ". CMI5 Player is not communicating. Is it running?
";
+ $exceptionmessage ="Something went wrong " . $type . ". CMI5 Player is not communicating. Is it running?";
+
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
// Call the method under test.
- $result = cmi5_connectors::cmi5launch_connectors_error_message($response, $type);
+ $result = $error($response, $type);
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($errormessage);
+
}
/**
@@ -1009,15 +1585,19 @@ public function testcmi5launch_connectors_error_message_path_two()
$response = array("statusCode" => "404", "error" => "Not Found","message" => "testmessage" );
// The expected error message to be output.
- $expectedstring ="
Something went wrong " . $type . ". CMI5 Player returned " . $response['statusCode'] . " error. With message '" . $response['message'] . "'.
";
+ $exceptionmessage="Something went wrong " . $type . " CMI5 Player returned " . $response['statusCode'] . " error. With message '" . $response['message'] . "'.";
+
+ $helper = new cmi5_connectors;
+ $error = $helper->cmi5launch_get_connectors_error_message();
+
+
+ // Expected exceptions and messages
+ $this->expectExceptionMessage($exceptionmessage);
+ $this->expectException(playerException::class);
// Call the method under test.
- $result = cmi5_connectors::cmi5launch_connectors_error_message($response, $type);
-
- // Result should be debug echo string and false
- $this->assertNotTrue($result, "Expected retrieved object to be false");
- //And it should output this error message
- $this->expectOutputString($expectedstring);
+ $result = $error($response, $type);
+
}
/**
@@ -1036,8 +1616,11 @@ public function testcmi5launch_connectors_error_message_path_three()
"Response" => "Successful Post",
));
+ $helper = new cmi5_connectors;
+ $error = $helper->cmi5launch_get_connectors_error_message();
+
// Call the method under test.
- $result = cmi5_connectors::cmi5launch_connectors_error_message($response, $type);
+ $result = $error($response, $type);
// Result should be debug echo string and false
$this->assertTrue($result, "Expected retrieved object to be true");
diff --git a/cmi5PHP/tests/errorOverTest.php b/cmi5PHP/tests/errorOverTest.php
new file mode 100644
index 0000000..38d4c7c
--- /dev/null
+++ b/cmi5PHP/tests/errorOverTest.php
@@ -0,0 +1,36 @@
+expectException(nullException::class);
+
+ //can we just call it?
+ // is this necessary? errorover::array_chunk_warning(E_WARNING, "This is a test error", "testfile.php", 1);
+
+
+ }
+}
\ No newline at end of file
diff --git a/db/install.php b/db/install.php
index 83d5b22..a66fb03 100755
--- a/db/install.php
+++ b/db/install.php
@@ -25,7 +25,7 @@
require_once(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
-//require_login($course, false, $cm);
+
/**
* Post installation procedure
diff --git a/grade.php b/grade.php
old mode 100755
new mode 100644
diff --git a/lib.php b/lib.php
index 8fb9c67..af2db5e 100755
--- a/lib.php
+++ b/lib.php
@@ -610,6 +610,8 @@ function cmi5launch_process_new_package($cmi5launch) {
$record->courseid = $returnedinfo["id"];
+ // TEST
+ $test = "";
// Create url for sending to when requesting launch url for course.
$playerurl = $settings['cmi5launchplayerurl'];
@@ -617,7 +619,8 @@ function cmi5launch_process_new_package($cmi5launch) {
$url = $playerurl . "/api/v1/" . $record->courseid . "/launch-url/";
$record->launchurl = $url;
- // Retrieve AUs and save to table.
+
+
$aus = ($retrieveaus($returnedinfo));
$record->aus = (json_encode($aus));
@@ -1098,10 +1101,10 @@ function cmi5launch_grade_item_update($cmi5launch, $grades = null) {
// Calculate grade based on grade type, and update rawgrade (a param of grade item).
switch($gradetype){
- // 'MOD_CMI5LAUNCH_AUS_GRADE' = '0'.
- // 'MOD_CMI5LAUNCH_GRADE_HIGHEST' = '1'.
- // 'MOD_CMI5LAUNCH_GRADE_AVERAGE', = '2'.
- // 'MOD_CMI5LAUNCH_GRADE_SUM', = '3'.
+ // 'GRADE_AUS_CMI5' = '0'.
+ // 'GRADE_HIGHEST_CMI5' = '1'.
+ // 'GRADE_AVERAGE_CMI5', = '2'.
+ // 'GRADE_SUM_CMI5', = '3'.
case 1:
foreach ($grades as $key => $grade) {
diff --git a/locallib.php b/locallib.php
index 30c3ae0..3ee2f5c 100755
--- a/locallib.php
+++ b/locallib.php
@@ -33,7 +33,7 @@
use mod_cmi5launch\local\cmi5_connectors;
// Grade stuff.
-define('MOD_CMI5LAUNCH_AUS_GRADE', '0');
+define('MOD_CMI5LAUNCH_GRADE_AUS', '0');
define('MOD_CMI5LAUNCH_GRADE_HIGHEST', '1');
define('MOD_CMI5LAUNCH_GRADE_AVERAGE', '2');
define('MOD_CMI5LAUNCH_GRADE_SUM', '3');
@@ -43,13 +43,13 @@
define('MOD_CMI5LAUNCH_FIRST_ATTEMPT', '2');
define('MOD_CMI5LAUNCH_LAST_ATTEMPT', '3');
-define('MOD_CMI5LAUNCH_FORCEATTEMPT_NO', 0);
-define('MOD_CMI5LAUNCH_FORCEATTEMPT_ONCOMPLETE', 1);
-define('MOD_CMI5LAUNCH_FORCEATTEMPT_ALWAYS', 2);
+define('CMI5_FORCEATTEMPT_NO', 0);
+define('CMI5_FORCEATTEMPT_ONCOMPLETE', 1);
+define('CMI5_FORCEATTEMPT_ALWAYS', 2);
-define('MOD_CMI5LAUNCH_UPDATE_NEVER', '0');
-define('MOD_CMI5LAUNCH_UPDATE_EVERYDAY', '2');
-define('MOD_CMI5LAUNCH_UPDATE_EVERYTIME', '3');
+define('CMI5_UPDATE_NEVER', '0');
+define('CMI5_UPDATE_EVERYDAY', '2');
+define('CMI5_UPDATE_EVERYTIME', '3');
diff --git a/report.php b/report.php
old mode 100755
new mode 100644
index fc768cc..7681097
--- a/report.php
+++ b/report.php
@@ -280,10 +280,10 @@ function mod_cmi5launch_open_report(inforfornextpage) {
// This is just to display, it calculates here so it doesn't effect the base array stored for AU.
switch($gradetype){
- // MOD_CMI5LAUNCH_AUS_GRADE' = '0'.
- // MOD_CMI5LAUNCH_GRADE_HIGHEST' = '1'.
- // MOD_CMI5LAUNCH_GRADE_AVERAGE', = '2'.
- // MOD_CMI5LAUNCH_GRADE_SUM', = '3'.
+ // GRADE_AUS_CMI5' = '0'.
+ // GRADE_HIGHEST_CMI5' = '1'.
+ // GRADE_AVERAGE_CMI5', = '2'.
+ // GRADE_SUM_CMI5', = '3'.
case 1:
$userscore = strval($highestgrade($augrades));
break;
diff --git a/session_report.php b/session_report.php
old mode 100755
new mode 100644
index 738afdd..be1d918
--- a/session_report.php
+++ b/session_report.php
@@ -229,10 +229,10 @@
switch ($gradetype) {
- // 'MOD_CMI5LAUNCH_AUS_GRADE' = '0').
- // 'MOD_CMI5LAUNCH_GRADE_HIGHEST' = '1'.
- // 'MOD_CMI5LAUNCH_GRADE_AVERAGE', = '2'.
- // 'MOD_CMI5LAUNCH_GRADE_SUM', = '3'.
+ // 'GRADE_AUS_CMI5' = '0').
+ // 'GRADE_HIGHEST_CMI5' = '1'.
+ // 'GRADE_AVERAGE_CMI5', = '2'.
+ // 'GRADE_SUM_CMI5', = '3'.
case 1:
$grade = "Highest";
diff --git a/view.php b/view.php
index ce7855c..7fde793 100755
--- a/view.php
+++ b/view.php
@@ -156,6 +156,8 @@ function mod_cmi5launch_launchexperience(registrationInfo) {
// Retrieve AU ids for this user/course.
$aus = json_decode($record->aus);
+ // We should not even be able to et here if these are false on record
+
$auids = $saveaus($createaus($aus));
$userscourse->aus = (json_encode($auids));