Merge branch 'master' into issue/283

This commit is contained in:
Jonathan Putney
2021-05-27 11:02:44 -04:00
committed by GitHub
18 changed files with 1608 additions and 882 deletions

View File

@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Mocha Unit Tests" type="mocha-javascript-test-runner">
<node-interpreter>project</node-interpreter>
<node-options />
<mocha-package>$PROJECT_DIR$/node_modules/mocha</mocha-package>
<working-directory>$PROJECT_DIR$</working-directory>
<pass-parent-env>true</pass-parent-env>
<ui>bdd</ui>
<extra-mocha-options>--watch --require @babel/register</extra-mocha-options>
<test-kind>PATTERN</test-kind>
<test-pattern>test/**/*.spec.js</test-pattern>
<method v="2" />
</configuration>
</component>

12
.run/compile.run.xml Normal file
View File

@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="compile" type="js.build_tools.npm" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="compile" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>

818
dist/scorm-again.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,46 +1,46 @@
{ {
"name": "scorm-again", "name": "scorm-again",
"version": "1.5.4", "version": "1.6.0",
"description": "A modern SCORM JavaScript run-time library for AICC, SCORM 1.2, and SCORM 2004", "description": "A modern SCORM JavaScript run-time library for AICC, SCORM 1.2, and SCORM 2004",
"main": "dist/scorm-again.min.js", "main": "dist/scorm-again.min.js",
"directories": { "directories": {
"test": "test" "test": "test"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.13.14", "@babel/cli": "^7.14.3",
"@babel/core": "^7.13.15", "@babel/core": "^7.14.3",
"@babel/node": "^7.13.13", "@babel/node": "^7.14.2",
"@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-proposal-optional-chaining": "^7.13.12", "@babel/plugin-proposal-optional-chaining": "^7.14.2",
"@babel/plugin-proposal-private-methods": "^7.13.0", "@babel/plugin-proposal-private-methods": "^7.13.0",
"@babel/preset-env": "^7.13.15", "@babel/preset-env": "^7.14.2",
"@babel/preset-flow": "^7.13.13", "@babel/preset-flow": "^7.13.13",
"@babel/register": "^7.13.14", "@babel/register": "^7.13.16",
"@types/chai": "^4.2.16", "@types/chai": "^4.2.18",
"@types/mocha": "^8.2.2", "@types/mocha": "^8.2.2",
"babel-eslint": "^11.0.0-beta.2", "babel-eslint": "^11.0.0-beta.2",
"babelify": "^10.0.0", "babelify": "^10.0.0",
"browserify": "^17.0.0", "browserify": "^17.0.0",
"chai": "^4.3.4", "chai": "^4.3.4",
"eslint": "^7.24.0", "eslint": "^7.27.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.23.3",
"fetch-pretender": "^1.5.0", "fetch-pretender": "^1.5.0",
"grunt": "^1.3.0", "grunt": "^1.4.1",
"grunt-browserify": "^6.0.0", "grunt-browserify": "^6.0.0",
"grunt-cli": "^1.4.2", "grunt-cli": "^1.4.3",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "^1.1.0",
"grunt-mocha-test": "^0.13.3", "grunt-mocha-test": "^0.13.3",
"jsdoc": "^3.6.6", "jsdoc": "^3.6.7",
"jsdoc-babel": "^0.5.0", "jsdoc-babel": "^0.5.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"minifyify": "^7.3.5", "minifyify": "^7.3.5",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"mocha": "^8.3.2", "mocha": "^8.4.0",
"mocha-junit-reporter": "^2.0.0", "mocha-junit-reporter": "^2.0.0",
"mochawesome": "^6.2.1", "mochawesome": "^6.2.1",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"sinon": "^10.0.0" "sinon": "^11.1.1"
}, },
"scripts": { "scripts": {
"test": "./node_modules/.bin/mocha --require @babel/register --bdd --recursive --reporter list", "test": "./node_modules/.bin/mocha --require @babel/register --bdd --recursive --reporter list",

View File

@@ -28,6 +28,7 @@ export default class BaseAPI {
logLevel: global_constants.LOG_LEVEL_ERROR, logLevel: global_constants.LOG_LEVEL_ERROR,
selfReportSessionTime: false, selfReportSessionTime: false,
alwaysSendTotalTime: false, alwaysSendTotalTime: false,
strict_errors: true,
responseHandler: function(xhr) { responseHandler: function(xhr) {
let result; let result;
if (typeof xhr !== 'undefined') { if (typeof xhr !== 'undefined') {
@@ -185,7 +186,21 @@ export default class BaseAPI {
this.#error_codes.RETRIEVE_BEFORE_INIT, this.#error_codes.RETRIEVE_BEFORE_INIT,
this.#error_codes.RETRIEVE_AFTER_TERM)) { this.#error_codes.RETRIEVE_AFTER_TERM)) {
if (checkTerminated) this.lastErrorCode = 0; if (checkTerminated) this.lastErrorCode = 0;
returnValue = this.getCMIValue(CMIElement); try {
returnValue = this.getCMIValue(CMIElement);
} catch (e) {
if (e instanceof ValidationError) {
this.lastErrorCode = e.errorCode;
returnValue = global_constants.SCORM_FALSE;
} else {
if (e.message) {
console.error(e.message);
} else {
console.error(e);
}
this.throwSCORMError(this.#error_codes.GENERAL);
}
}
this.processListeners(callbackName, CMIElement); this.processListeners(callbackName, CMIElement);
} }

View File

@@ -202,7 +202,7 @@ export default class Scorm12API extends BaseAPI {
* Returns the message that corresponds to errorNumber. * Returns the message that corresponds to errorNumber.
* *
* @param {*} errorNumber * @param {*} errorNumber
* @param {boolean }detail * @param {boolean} detail
* @return {string} * @return {string}
*/ */
getLmsErrorMessageDetails(errorNumber, detail) { getLmsErrorMessageDetails(errorNumber, detail) {
@@ -278,8 +278,7 @@ export default class Scorm12API extends BaseAPI {
if (this.settings.mastery_override && if (this.settings.mastery_override &&
this.cmi.student_data.mastery_score !== '' && this.cmi.student_data.mastery_score !== '' &&
this.cmi.core.score.raw !== '') { this.cmi.core.score.raw !== '') {
if (parseFloat(this.cmi.core.score.raw) >= if (parseFloat(this.cmi.core.score.raw) >= parseFloat(this.cmi.student_data.mastery_score)) {
parseFloat(this.cmi.student_data.mastery_score)) {
this.cmi.core.lesson_status = 'passed'; this.cmi.core.lesson_status = 'passed';
} else { } else {
this.cmi.core.lesson_status = 'failed'; this.cmi.core.lesson_status = 'failed';
@@ -287,8 +286,7 @@ export default class Scorm12API extends BaseAPI {
} }
} }
} else if (this.cmi.core.lesson_mode === 'browse') { } else if (this.cmi.core.lesson_mode === 'browse') {
if ((this.startingData?.cmi?.core?.lesson_status || '') === '' && if ((this.startingData?.cmi?.core?.lesson_status || '') === '' && originalStatus === 'not attempted') {
originalStatus === 'not attempted') {
this.cmi.core.lesson_status = 'browsed'; this.cmi.core.lesson_status = 'browsed';
} }
} }
@@ -298,13 +296,11 @@ export default class Scorm12API extends BaseAPI {
this.settings.alwaysSendTotalTime); this.settings.alwaysSendTotalTime);
if (this.apiLogLevel === global_constants.LOG_LEVEL_DEBUG) { if (this.apiLogLevel === global_constants.LOG_LEVEL_DEBUG) {
console.debug('Commit (terminated: ' + console.debug('Commit (terminated: ' + (terminateCommit ? 'yes' : 'no') + '): ');
(terminateCommit ? 'yes' : 'no') + '): ');
console.debug(commitObject); console.debug(commitObject);
} }
if (this.settings.lmsCommitUrl) { if (this.settings.lmsCommitUrl) {
return this.processHttpRequest(this.settings.lmsCommitUrl, commitObject, return this.processHttpRequest(this.settings.lmsCommitUrl, commitObject, terminateCommit);
terminateCommit);
} else { } else {
return global_constants.SCORM_TRUE; return global_constants.SCORM_TRUE;
} }

View File

@@ -1,16 +1,40 @@
import * as Scorm12CMI from './scorm12_cmi'; import * as Scorm12CMI from './scorm12_cmi';
import {BaseCMI, CMIArray, CMIScore} from './common'; import {BaseCMI, checkValidFormat, CMIArray, CMIScore} from './common';
import APIConstants from '../constants/api_constants'; import APIConstants from '../constants/api_constants';
import Regex from '../constants/regex'; import Regex from '../constants/regex';
import ErrorCodes from '../constants/error_codes'; import ErrorCodes from '../constants/error_codes';
import { import {AICCValidationError} from '../exceptions';
check12ValidFormat,
throwReadOnlyError,
} from './scorm12_cmi';
const aicc_constants = APIConstants.aicc; const aicc_constants = APIConstants.aicc;
const aicc_regex = Regex.aicc; const aicc_regex = Regex.aicc;
const scorm12_error_codes = ErrorCodes.scorm12; const aicc_error_codes = ErrorCodes.scorm12;
/**
* Helper method for throwing Read Only error
*/
function throwReadOnlyError() {
throw new AICCValidationError(aicc_error_codes.READ_ONLY_ELEMENT);
}
/**
* Helper method, no reason to have to pass the same error codes every time
* @param {*} value
* @param {string} regexPattern
* @param {boolean} allowEmptyString
* @return {boolean}
*/
function checkAICCValidFormat(
value: String,
regexPattern: String,
allowEmptyString?: boolean) {
return checkValidFormat(
value,
regexPattern,
aicc_error_codes.TYPE_MISMATCH,
AICCValidationError,
allowEmptyString
);
}
/** /**
* CMI Class for AICC * CMI Class for AICC
@@ -126,8 +150,11 @@ class CMIEvaluationComments extends CMIArray {
* Constructor for AICC Evaluation Comments object * Constructor for AICC Evaluation Comments object
*/ */
constructor() { constructor() {
super(aicc_constants.comments_children, super({
scorm12_error_codes.INVALID_SET_VALUE); children: aicc_constants.comments_children,
errorCode: aicc_error_codes.INVALID_SET_VALUE,
errorClass: AICCValidationError,
});
} }
} }
@@ -142,7 +169,8 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
super(aicc_constants.student_preference_children); super(aicc_constants.student_preference_children);
this.windows = new CMIArray({ this.windows = new CMIArray({
errorCode: scorm12_error_codes.INVALID_SET_VALUE, errorCode: aicc_error_codes.INVALID_SET_VALUE,
errorClass: AICCValidationError,
children: '', children: '',
}); });
} }
@@ -174,7 +202,7 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
* @param {string} lesson_type * @param {string} lesson_type
*/ */
set lesson_type(lesson_type: string) { set lesson_type(lesson_type: string) {
if (check12ValidFormat(lesson_type, aicc_regex.CMIString256)) { if (checkAICCValidFormat(lesson_type, aicc_regex.CMIString256)) {
this.#lesson_type = lesson_type; this.#lesson_type = lesson_type;
} }
} }
@@ -192,7 +220,7 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
* @param {string} text_color * @param {string} text_color
*/ */
set text_color(text_color: string) { set text_color(text_color: string) {
if (check12ValidFormat(text_color, aicc_regex.CMIString256)) { if (checkAICCValidFormat(text_color, aicc_regex.CMIString256)) {
this.#text_color = text_color; this.#text_color = text_color;
} }
} }
@@ -210,7 +238,7 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
* @param {string} text_location * @param {string} text_location
*/ */
set text_location(text_location: string) { set text_location(text_location: string) {
if (check12ValidFormat(text_location, aicc_regex.CMIString256)) { if (checkAICCValidFormat(text_location, aicc_regex.CMIString256)) {
this.#text_location = text_location; this.#text_location = text_location;
} }
} }
@@ -228,7 +256,7 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
* @param {string} text_size * @param {string} text_size
*/ */
set text_size(text_size: string) { set text_size(text_size: string) {
if (check12ValidFormat(text_size, aicc_regex.CMIString256)) { if (checkAICCValidFormat(text_size, aicc_regex.CMIString256)) {
this.#text_size = text_size; this.#text_size = text_size;
} }
} }
@@ -246,7 +274,7 @@ class AICCStudentPreferences extends Scorm12CMI.CMIStudentPreference {
* @param {string} video * @param {string} video
*/ */
set video(video: string) { set video(video: string) {
if (check12ValidFormat(video, aicc_regex.CMIString256)) { if (checkAICCValidFormat(video, aicc_regex.CMIString256)) {
this.#video = video; this.#video = video;
} }
} }
@@ -374,6 +402,14 @@ export class CMIStudentDemographics extends BaseCMI {
#telephone = ''; #telephone = '';
#years_experience = ''; #years_experience = '';
/**
* Getter for _children
* @return {string}
*/
get _children() {
return this.#_children;
}
/** /**
* Getter for city * Getter for city
* @return {string} * @return {string}
@@ -671,7 +707,7 @@ export class CMIPaths extends CMIArray {
* Constructor for inline Paths Array class * Constructor for inline Paths Array class
*/ */
constructor() { constructor() {
super(aicc_constants.paths_children); super({children: aicc_constants.paths_children});
} }
} }
@@ -706,7 +742,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} location_id * @param {string} location_id
*/ */
set location_id(location_id) { set location_id(location_id) {
if (check12ValidFormat(location_id, aicc_regex.CMIString256)) { if (checkAICCValidFormat(location_id, aicc_regex.CMIString256)) {
this.#location_id = location_id; this.#location_id = location_id;
} }
} }
@@ -724,7 +760,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} date * @param {string} date
*/ */
set date(date) { set date(date) {
if (check12ValidFormat(date, aicc_regex.CMIString256)) { if (checkAICCValidFormat(date, aicc_regex.CMIString256)) {
this.#date = date; this.#date = date;
} }
} }
@@ -742,7 +778,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} time * @param {string} time
*/ */
set time(time) { set time(time) {
if (check12ValidFormat(time, aicc_regex.CMITime)) { if (checkAICCValidFormat(time, aicc_regex.CMITime)) {
this.#time = time; this.#time = time;
} }
} }
@@ -760,7 +796,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} status * @param {string} status
*/ */
set status(status) { set status(status) {
if (check12ValidFormat(status, aicc_regex.CMIStatus2)) { if (checkAICCValidFormat(status, aicc_regex.CMIStatus2)) {
this.#status = status; this.#status = status;
} }
} }
@@ -778,7 +814,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} why_left * @param {string} why_left
*/ */
set why_left(why_left) { set why_left(why_left) {
if (check12ValidFormat(why_left, aicc_regex.CMIString256)) { if (checkAICCValidFormat(why_left, aicc_regex.CMIString256)) {
this.#why_left = why_left; this.#why_left = why_left;
} }
} }
@@ -796,7 +832,7 @@ export class CMIPathsObject extends BaseCMI {
* @param {string} time_in_element * @param {string} time_in_element
*/ */
set time_in_element(time_in_element) { set time_in_element(time_in_element) {
if (check12ValidFormat(time_in_element, aicc_regex.CMITime)) { if (checkAICCValidFormat(time_in_element, aicc_regex.CMITime)) {
this.#time_in_element = time_in_element; this.#time_in_element = time_in_element;
} }
} }
@@ -837,7 +873,7 @@ export class CMITries extends CMIArray {
* Constructor for inline Tries Array class * Constructor for inline Tries Array class
*/ */
constructor() { constructor() {
super(aicc_constants.tries_children); super({children: aicc_constants.tries_children});
} }
} }
@@ -855,9 +891,10 @@ export class CMITriesObject extends BaseCMI {
{ {
score_children: aicc_constants.score_children, score_children: aicc_constants.score_children,
score_range: aicc_regex.score_range, score_range: aicc_regex.score_range,
invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE, invalidErrorCode: aicc_error_codes.INVALID_SET_VALUE,
invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH, invalidTypeCode: aicc_error_codes.TYPE_MISMATCH,
invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE, invalidRangeCode: aicc_error_codes.VALUE_OUT_OF_RANGE,
errorClass: AICCValidationError,
}); });
} }
@@ -885,7 +922,7 @@ export class CMITriesObject extends BaseCMI {
* @param {string} status * @param {string} status
*/ */
set status(status) { set status(status) {
if (check12ValidFormat(status, aicc_regex.CMIStatus2)) { if (checkAICCValidFormat(status, aicc_regex.CMIStatus2)) {
this.#status = status; this.#status = status;
} }
} }
@@ -903,7 +940,7 @@ export class CMITriesObject extends BaseCMI {
* @param {string} time * @param {string} time
*/ */
set time(time) { set time(time) {
if (check12ValidFormat(time, aicc_regex.CMITime)) { if (checkAICCValidFormat(time, aicc_regex.CMITime)) {
this.#time = time; this.#time = time;
} }
} }
@@ -938,7 +975,7 @@ export class CMIAttemptRecords extends CMIArray {
* Constructor for inline Tries Array class * Constructor for inline Tries Array class
*/ */
constructor() { constructor() {
super(aicc_constants.attempt_records_children); super({children: aicc_constants.attempt_records_children});
} }
} }
@@ -956,9 +993,10 @@ export class CMIAttemptRecordsObject extends BaseCMI {
{ {
score_children: aicc_constants.score_children, score_children: aicc_constants.score_children,
score_range: aicc_regex.score_range, score_range: aicc_regex.score_range,
invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE, invalidErrorCode: aicc_error_codes.INVALID_SET_VALUE,
invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH, invalidTypeCode: aicc_error_codes.TYPE_MISMATCH,
invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE, invalidRangeCode: aicc_error_codes.VALUE_OUT_OF_RANGE,
errorClass: AICCValidationError,
}); });
} }
@@ -985,7 +1023,7 @@ export class CMIAttemptRecordsObject extends BaseCMI {
* @param {string} lesson_status * @param {string} lesson_status
*/ */
set lesson_status(lesson_status) { set lesson_status(lesson_status) {
if (check12ValidFormat(lesson_status, aicc_regex.CMIStatus2)) { if (checkAICCValidFormat(lesson_status, aicc_regex.CMIStatus2)) {
this.#lesson_status = lesson_status; this.#lesson_status = lesson_status;
} }
} }
@@ -1039,7 +1077,7 @@ export class CMIEvaluationCommentsObject extends BaseCMI {
* @param {string} content * @param {string} content
*/ */
set content(content) { set content(content) {
if (check12ValidFormat(content, aicc_regex.CMIString256)) { if (checkAICCValidFormat(content, aicc_regex.CMIString256)) {
this.#content = content; this.#content = content;
} }
} }
@@ -1057,7 +1095,7 @@ export class CMIEvaluationCommentsObject extends BaseCMI {
* @param {string} location * @param {string} location
*/ */
set location(location) { set location(location) {
if (check12ValidFormat(location, aicc_regex.CMIString256)) { if (checkAICCValidFormat(location, aicc_regex.CMIString256)) {
this.#location = location; this.#location = location;
} }
} }
@@ -1075,7 +1113,7 @@ export class CMIEvaluationCommentsObject extends BaseCMI {
* @param {string} time * @param {string} time
*/ */
set time(time) { set time(time) {
if (check12ValidFormat(time, aicc_regex.CMITime)) { if (checkAICCValidFormat(time, aicc_regex.CMITime)) {
this.#time = time; this.#time = time;
} }
} }

View File

@@ -1,7 +1,6 @@
// @flow // @flow
import APIConstants from '../constants/api_constants'; import APIConstants from '../constants/api_constants';
import ErrorCodes from '../constants/error_codes'; import ErrorCodes from '../constants/error_codes';
import {ValidationError} from '../exceptions';
import Regex from '../constants/regex'; import Regex from '../constants/regex';
const scorm12_constants = APIConstants.scorm12; const scorm12_constants = APIConstants.scorm12;
@@ -14,6 +13,7 @@ const scorm12_error_codes = ErrorCodes.scorm12;
* @param {string} value * @param {string} value
* @param {string} regexPattern * @param {string} regexPattern
* @param {number} errorCode * @param {number} errorCode
* @param {class} errorClass
* @param {boolean} allowEmptyString * @param {boolean} allowEmptyString
* @return {boolean} * @return {boolean}
*/ */
@@ -21,6 +21,7 @@ export function checkValidFormat(
value: String, value: String,
regexPattern: String, regexPattern: String,
errorCode: number, errorCode: number,
errorClass: function,
allowEmptyString?: boolean) { allowEmptyString?: boolean) {
const formatRegex = new RegExp(regexPattern); const formatRegex = new RegExp(regexPattern);
const matches = value.match(formatRegex); const matches = value.match(formatRegex);
@@ -28,7 +29,7 @@ export function checkValidFormat(
return true; return true;
} }
if (value === undefined || !matches || matches[0] === '') { if (value === undefined || !matches || matches[0] === '') {
throw new ValidationError(errorCode); throw new errorClass.prototype.constructor(errorCode);
} }
return true; return true;
} }
@@ -39,20 +40,24 @@ export function checkValidFormat(
* @param {*} value * @param {*} value
* @param {string} rangePattern * @param {string} rangePattern
* @param {number} errorCode * @param {number} errorCode
* @param {class} errorClass
* @return {boolean} * @return {boolean}
*/ */
export function checkValidRange( export function checkValidRange(
value: any, rangePattern: String, errorCode: number) { value: any,
rangePattern: String,
errorCode: number,
errorClass: function) {
const ranges = rangePattern.split('#'); const ranges = rangePattern.split('#');
value = value * 1.0; value = value * 1.0;
if (value >= ranges[0]) { if (value >= ranges[0]) {
if ((ranges[1] === '*') || (value <= ranges[1])) { if ((ranges[1] === '*') || (value <= ranges[1])) {
return true; return true;
} else { } else {
throw new ValidationError(errorCode); throw new errorClass.prototype.constructor(errorCode);
} }
} else { } else {
throw new ValidationError(errorCode); throw new errorClass.prototype.constructor(errorCode);
} }
} }
@@ -118,6 +123,7 @@ export class CMIScore extends BaseCMI {
* @param {number} invalidTypeCode * @param {number} invalidTypeCode
* @param {number} invalidRangeCode * @param {number} invalidRangeCode
* @param {string} decimalRegex * @param {string} decimalRegex
* @param {class} errorClass
*/ */
constructor( constructor(
{ {
@@ -128,6 +134,7 @@ export class CMIScore extends BaseCMI {
invalidTypeCode, invalidTypeCode,
invalidRangeCode, invalidRangeCode,
decimalRegex, decimalRegex,
errorClass,
}) { }) {
super(); super();
@@ -143,6 +150,7 @@ export class CMIScore extends BaseCMI {
scorm12_error_codes.VALUE_OUT_OF_RANGE; scorm12_error_codes.VALUE_OUT_OF_RANGE;
this.#_decimal_regex = decimalRegex || this.#_decimal_regex = decimalRegex ||
scorm12_regex.CMIDecimal; scorm12_regex.CMIDecimal;
this.#_error_class = errorClass;
} }
#_children; #_children;
@@ -151,6 +159,7 @@ export class CMIScore extends BaseCMI {
#_invalid_type_code; #_invalid_type_code;
#_invalid_range_code; #_invalid_range_code;
#_decimal_regex; #_decimal_regex;
#_error_class;
#raw = ''; #raw = '';
#min = ''; #min = '';
#max; #max;
@@ -170,7 +179,7 @@ export class CMIScore extends BaseCMI {
* @private * @private
*/ */
set _children(_children) { set _children(_children) {
throw new ValidationError(this.#_invalid_error_code); throw new this.#_error_class.prototype.constructor(this.#_invalid_error_code);
} }
/** /**
@@ -186,11 +195,9 @@ export class CMIScore extends BaseCMI {
* @param {string} raw * @param {string} raw
*/ */
set raw(raw) { set raw(raw) {
if (checkValidFormat(raw, this.#_decimal_regex, if (checkValidFormat(raw, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
this.#_invalid_type_code) &&
(!this.#_score_range || (!this.#_score_range ||
checkValidRange(raw, this.#_score_range, checkValidRange(raw, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
this.#_invalid_range_code))) {
this.#raw = raw; this.#raw = raw;
} }
} }
@@ -208,11 +215,9 @@ export class CMIScore extends BaseCMI {
* @param {string} min * @param {string} min
*/ */
set min(min) { set min(min) {
if (checkValidFormat(min, this.#_decimal_regex, if (checkValidFormat(min, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
this.#_invalid_type_code) &&
(!this.#_score_range || (!this.#_score_range ||
checkValidRange(min, this.#_score_range, checkValidRange(min, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
this.#_invalid_range_code))) {
this.#min = min; this.#min = min;
} }
} }
@@ -230,11 +235,9 @@ export class CMIScore extends BaseCMI {
* @param {string} max * @param {string} max
*/ */
set max(max) { set max(max) {
if (checkValidFormat(max, this.#_decimal_regex, if (checkValidFormat(max, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
this.#_invalid_type_code) &&
(!this.#_score_range || (!this.#_score_range ||
checkValidRange(max, this.#_score_range, checkValidRange(max, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
this.#_invalid_range_code))) {
this.#max = max; this.#max = max;
} }
} }
@@ -263,15 +266,18 @@ export class CMIArray extends BaseCMI {
* Constructor cmi *.n arrays * Constructor cmi *.n arrays
* @param {string} children * @param {string} children
* @param {number} errorCode * @param {number} errorCode
* @param {class} errorClass
*/ */
constructor({children, errorCode}) { constructor({children, errorCode, errorClass}) {
super(); super();
this.#_children = children; this.#_children = children;
this.#errorCode = errorCode; this.#errorCode = errorCode;
this.#errorClass = errorClass;
this.childArray = []; this.childArray = [];
} }
#errorCode; #errorCode;
#errorClass;
#_children; #_children;
/** /**
@@ -287,7 +293,7 @@ export class CMIArray extends BaseCMI {
* @param {string} _children * @param {string} _children
*/ */
set _children(_children) { set _children(_children) {
throw new ValidationError(this.#errorCode); throw new this.#errorClass.prototype.constructor(this.#errorCode);
} }
/** /**
@@ -303,7 +309,7 @@ export class CMIArray extends BaseCMI {
* @param {number} _count * @param {number} _count
*/ */
set _count(_count) { set _count(_count) {
throw new ValidationError(this.#errorCode); throw new this.#errorClass.prototype.constructor(this.#errorCode);
} }
/** /**

View File

@@ -9,7 +9,7 @@ import {
import APIConstants from '../constants/api_constants'; import APIConstants from '../constants/api_constants';
import ErrorCodes from '../constants/error_codes'; import ErrorCodes from '../constants/error_codes';
import Regex from '../constants/regex'; import Regex from '../constants/regex';
import {ValidationError} from '../exceptions'; import {Scorm12ValidationError} from '../exceptions';
import * as Utilities from '../utilities'; import * as Utilities from '../utilities';
import * as Util from '../utilities'; import * as Util from '../utilities';
@@ -21,21 +21,21 @@ const scorm12_error_codes = ErrorCodes.scorm12;
* Helper method for throwing Read Only error * Helper method for throwing Read Only error
*/ */
export function throwReadOnlyError() { export function throwReadOnlyError() {
throw new ValidationError(scorm12_error_codes.READ_ONLY_ELEMENT); throw new Scorm12ValidationError(scorm12_error_codes.READ_ONLY_ELEMENT);
} }
/** /**
* Helper method for throwing Write Only error * Helper method for throwing Write Only error
*/ */
export function throwWriteOnlyError() { export function throwWriteOnlyError() {
throw new ValidationError(scorm12_error_codes.WRITE_ONLY_ELEMENT); throw new Scorm12ValidationError(scorm12_error_codes.WRITE_ONLY_ELEMENT);
} }
/** /**
* Helper method for throwing Invalid Set error * Helper method for throwing Invalid Set error
*/ */
function throwInvalidValueError() { function throwInvalidValueError() {
throw new ValidationError(scorm12_error_codes.INVALID_SET_VALUE); throw new Scorm12ValidationError(scorm12_error_codes.INVALID_SET_VALUE);
} }
/** /**
@@ -49,8 +49,13 @@ export function check12ValidFormat(
value: String, value: String,
regexPattern: String, regexPattern: String,
allowEmptyString?: boolean) { allowEmptyString?: boolean) {
return checkValidFormat(value, regexPattern, return checkValidFormat(
scorm12_error_codes.TYPE_MISMATCH, allowEmptyString); value,
regexPattern,
scorm12_error_codes.TYPE_MISMATCH,
Scorm12ValidationError,
allowEmptyString
);
} }
/** /**
@@ -64,8 +69,13 @@ export function check12ValidRange(
value: any, value: any,
rangePattern: String, rangePattern: String,
allowEmptyString?: boolean) { allowEmptyString?: boolean) {
return checkValidRange(value, rangePattern, return checkValidRange(
scorm12_error_codes.VALUE_OUT_OF_RANGE, allowEmptyString); value,
rangePattern,
scorm12_error_codes.VALUE_OUT_OF_RANGE,
Scorm12ValidationError,
allowEmptyString
);
} }
/** /**
@@ -277,6 +287,7 @@ class CMICore extends BaseCMI {
invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE, invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE,
invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH, invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH,
invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE, invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE,
errorClass: Scorm12ValidationError,
}); });
} }
@@ -583,6 +594,7 @@ class CMIObjectives extends CMIArray {
super({ super({
children: scorm12_constants.objectives_children, children: scorm12_constants.objectives_children,
errorCode: scorm12_error_codes.INVALID_SET_VALUE, errorCode: scorm12_error_codes.INVALID_SET_VALUE,
errorClass: Scorm12ValidationError,
}); });
} }
} }
@@ -858,6 +870,7 @@ class CMIInteractions extends CMIArray {
super({ super({
children: scorm12_constants.interactions_children, children: scorm12_constants.interactions_children,
errorCode: scorm12_error_codes.INVALID_SET_VALUE, errorCode: scorm12_error_codes.INVALID_SET_VALUE,
errorClass: Scorm12ValidationError,
}); });
} }
} }
@@ -875,10 +888,12 @@ export class CMIInteractionsObject extends BaseCMI {
this.objectives = new CMIArray({ this.objectives = new CMIArray({
errorCode: scorm12_error_codes.INVALID_SET_VALUE, errorCode: scorm12_error_codes.INVALID_SET_VALUE,
errorClass: Scorm12ValidationError,
children: scorm12_constants.objectives_children, children: scorm12_constants.objectives_children,
}); });
this.correct_responses = new CMIArray({ this.correct_responses = new CMIArray({
errorCode: scorm12_error_codes.INVALID_SET_VALUE, errorCode: scorm12_error_codes.INVALID_SET_VALUE,
errorClass: Scorm12ValidationError,
children: scorm12_constants.correct_responses_children, children: scorm12_constants.correct_responses_children,
}); });
} }
@@ -1082,6 +1097,7 @@ export class CMIObjectivesObject extends BaseCMI {
invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE, invalidErrorCode: scorm12_error_codes.INVALID_SET_VALUE,
invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH, invalidTypeCode: scorm12_error_codes.TYPE_MISMATCH,
invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE, invalidRangeCode: scorm12_error_codes.VALUE_OUT_OF_RANGE,
errorClass: Scorm12ValidationError,
}); });
} }

View File

@@ -10,7 +10,7 @@ import APIConstants from '../constants/api_constants';
import Regex from '../constants/regex'; import Regex from '../constants/regex';
import ErrorCodes from '../constants/error_codes'; import ErrorCodes from '../constants/error_codes';
import Responses from '../constants/response_constants'; import Responses from '../constants/response_constants';
import {ValidationError} from '../exceptions'; import {Scorm2004ValidationError} from '../exceptions';
import * as Util from '../utilities'; import * as Util from '../utilities';
const scorm2004_constants = APIConstants.scorm2004; const scorm2004_constants = APIConstants.scorm2004;
@@ -23,21 +23,35 @@ const scorm2004_regex = Regex.scorm2004;
* Helper method for throwing Read Only error * Helper method for throwing Read Only error
*/ */
function throwReadOnlyError() { function throwReadOnlyError() {
throw new ValidationError(scorm2004_error_codes.READ_ONLY_ELEMENT); throw new Scorm2004ValidationError(scorm2004_error_codes.READ_ONLY_ELEMENT);
} }
/** /**
* Helper method for throwing Write Only error * Helper method for throwing Write Only error
*/ */
function throwWriteOnlyError() { function throwWriteOnlyError() {
throw new ValidationError(scorm2004_error_codes.WRITE_ONLY_ELEMENT); throw new Scorm2004ValidationError(scorm2004_error_codes.WRITE_ONLY_ELEMENT);
} }
/** /**
* Helper method for throwing Type Mismatch error * Helper method for throwing Type Mismatch error
*/ */
function throwTypeMismatchError() { function throwTypeMismatchError() {
throw new ValidationError(scorm2004_error_codes.TYPE_MISMATCH); throw new Scorm2004ValidationError(scorm2004_error_codes.TYPE_MISMATCH);
}
/**
* Helper method for throwing Dependency Not Established error
*/
function throwDependencyNotEstablishedError() {
throw new Scorm2004ValidationError(scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
}
/**
* Helper method for throwing Dependency Not Established error
*/
function throwGeneralSetError() {
throw new Scorm2004ValidationError(scorm2004_error_codes.GENERAL_SET_FAILURE);
} }
/** /**
@@ -51,8 +65,13 @@ function check2004ValidFormat(
value: String, value: String,
regexPattern: String, regexPattern: String,
allowEmptyString?: boolean) { allowEmptyString?: boolean) {
return checkValidFormat(value, regexPattern, return checkValidFormat(
scorm2004_error_codes.TYPE_MISMATCH, allowEmptyString); value,
regexPattern,
scorm2004_error_codes.TYPE_MISMATCH,
Scorm2004ValidationError,
allowEmptyString,
);
} }
/** /**
@@ -62,8 +81,12 @@ function check2004ValidFormat(
* @return {boolean} * @return {boolean}
*/ */
function check2004ValidRange(value: any, rangePattern: String) { function check2004ValidRange(value: any, rangePattern: String) {
return checkValidRange(value, rangePattern, return checkValidRange(
scorm2004_error_codes.VALUE_OUT_OF_RANGE); value,
rangePattern,
scorm2004_error_codes.VALUE_OUT_OF_RANGE,
Scorm2004ValidationError,
);
} }
/** /**
@@ -189,8 +212,8 @@ export class CMI extends BaseCMI {
*/ */
set completion_threshold(completion_threshold) { set completion_threshold(completion_threshold) {
!this.initialized ? !this.initialized ?
this.#completion_threshold = completion_threshold : this.#completion_threshold = completion_threshold :
throwReadOnlyError(); throwReadOnlyError();
} }
/** /**
@@ -289,8 +312,8 @@ export class CMI extends BaseCMI {
*/ */
set learner_name(learner_name) { set learner_name(learner_name) {
!this.initialized ? !this.initialized ?
this.#learner_name = learner_name : this.#learner_name = learner_name :
throwReadOnlyError(); throwReadOnlyError();
} }
/** /**
@@ -325,8 +348,8 @@ export class CMI extends BaseCMI {
*/ */
set max_time_allowed(max_time_allowed) { set max_time_allowed(max_time_allowed) {
!this.initialized ? !this.initialized ?
this.#max_time_allowed = max_time_allowed : this.#max_time_allowed = max_time_allowed :
throwReadOnlyError(); throwReadOnlyError();
} }
/** /**
@@ -359,7 +382,7 @@ export class CMI extends BaseCMI {
*/ */
set progress_measure(progress_measure) { set progress_measure(progress_measure) {
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) && if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) { check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) {
this.#progress_measure = progress_measure; this.#progress_measure = progress_measure;
} }
} }
@@ -378,8 +401,8 @@ export class CMI extends BaseCMI {
*/ */
set scaled_passing_score(scaled_passing_score) { set scaled_passing_score(scaled_passing_score) {
!this.initialized ? !this.initialized ?
this.#scaled_passing_score = scaled_passing_score : this.#scaled_passing_score = scaled_passing_score :
throwReadOnlyError(); throwReadOnlyError();
} }
/** /**
@@ -451,8 +474,8 @@ export class CMI extends BaseCMI {
*/ */
set time_limit_action(time_limit_action) { set time_limit_action(time_limit_action) {
!this.initialized ? !this.initialized ?
this.#time_limit_action = time_limit_action : this.#time_limit_action = time_limit_action :
throwReadOnlyError(); throwReadOnlyError();
} }
/** /**
@@ -604,7 +627,7 @@ class CMILearnerPreference extends BaseCMI {
*/ */
set audio_level(audio_level) { set audio_level(audio_level) {
if (check2004ValidFormat(audio_level, scorm2004_regex.CMIDecimal) && if (check2004ValidFormat(audio_level, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(audio_level, scorm2004_regex.audio_range)) { check2004ValidRange(audio_level, scorm2004_regex.audio_range)) {
this.#audio_level = audio_level; this.#audio_level = audio_level;
} }
} }
@@ -641,7 +664,7 @@ class CMILearnerPreference extends BaseCMI {
*/ */
set delivery_speed(delivery_speed) { set delivery_speed(delivery_speed) {
if (check2004ValidFormat(delivery_speed, scorm2004_regex.CMIDecimal) && if (check2004ValidFormat(delivery_speed, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(delivery_speed, scorm2004_regex.speed_range)) { check2004ValidRange(delivery_speed, scorm2004_regex.speed_range)) {
this.#delivery_speed = delivery_speed; this.#delivery_speed = delivery_speed;
} }
} }
@@ -660,7 +683,7 @@ class CMILearnerPreference extends BaseCMI {
*/ */
set audio_captioning(audio_captioning) { set audio_captioning(audio_captioning) {
if (check2004ValidFormat(audio_captioning, scorm2004_regex.CMISInteger) && if (check2004ValidFormat(audio_captioning, scorm2004_regex.CMISInteger) &&
check2004ValidRange(audio_captioning, scorm2004_regex.text_range)) { check2004ValidRange(audio_captioning, scorm2004_regex.text_range)) {
this.#audio_captioning = audio_captioning; this.#audio_captioning = audio_captioning;
} }
} }
@@ -701,6 +724,7 @@ class CMIInteractions extends CMIArray {
super({ super({
children: scorm2004_constants.interactions_children, children: scorm2004_constants.interactions_children,
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
}); });
} }
} }
@@ -716,6 +740,7 @@ class CMIObjectives extends CMIArray {
super({ super({
children: scorm2004_constants.objectives_children, children: scorm2004_constants.objectives_children,
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
}); });
} }
} }
@@ -731,6 +756,7 @@ class CMICommentsFromLMS extends CMIArray {
super({ super({
children: scorm2004_constants.comments_children, children: scorm2004_constants.comments_children,
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
}); });
} }
} }
@@ -746,6 +772,7 @@ class CMICommentsFromLearner extends CMIArray {
super({ super({
children: scorm2004_constants.comments_children, children: scorm2004_constants.comments_children,
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
}); });
} }
} }
@@ -771,10 +798,12 @@ export class CMIInteractionsObject extends BaseCMI {
this.objectives = new CMIArray({ this.objectives = new CMIArray({
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
children: scorm2004_constants.objectives_children, children: scorm2004_constants.objectives_children,
}); });
this.correct_responses = new CMIArray({ this.correct_responses = new CMIArray({
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
errorClass: Scorm2004ValidationError,
children: scorm2004_constants.correct_responses_children, children: scorm2004_constants.correct_responses_children,
}); });
} }
@@ -820,8 +849,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set type(type) { set type(type) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(type, scorm2004_regex.CMIType)) { if (check2004ValidFormat(type, scorm2004_regex.CMIType)) {
this.#type = type; this.#type = type;
@@ -843,8 +871,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set timestamp(timestamp) { set timestamp(timestamp) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) { if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) {
this.#timestamp = timestamp; this.#timestamp = timestamp;
@@ -866,8 +893,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set weighting(weighting) { set weighting(weighting) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) { if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) {
this.#weighting = weighting; this.#weighting = weighting;
@@ -890,8 +916,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set learner_response(learner_response) { set learner_response(learner_response) {
if (this.initialized && (this.#type === '' || this.#id === '')) { if (this.initialized && (this.#type === '' || this.#id === '')) {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
let nodes = []; let nodes = [];
const response_type = learner_responses[this.type]; const response_type = learner_responses[this.type];
@@ -933,12 +958,12 @@ export class CMIInteractionsObject extends BaseCMI {
} }
} }
} else { } else {
throw new ValidationError(scorm2004_error_codes.GENERAL_SET_FAILURE); throwGeneralSetError();
} }
this.#learner_response = learner_response; this.#learner_response = learner_response;
} else { } else {
throw new ValidationError(scorm2004_error_codes.TYPE_MISMATCH); throwTypeMismatchError();
} }
} }
} }
@@ -975,8 +1000,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set latency(latency) { set latency(latency) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) { if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) {
this.#latency = latency; this.#latency = latency;
@@ -998,8 +1022,7 @@ export class CMIInteractionsObject extends BaseCMI {
*/ */
set description(description) { set description(description) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250, if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) { true)) {
@@ -1104,8 +1127,7 @@ export class CMIObjectivesObject extends BaseCMI {
*/ */
set success_status(success_status) { set success_status(success_status) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) { if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) {
this.#success_status = success_status; this.#success_status = success_status;
@@ -1127,8 +1149,7 @@ export class CMIObjectivesObject extends BaseCMI {
*/ */
set completion_status(completion_status) { set completion_status(completion_status) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) { if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) {
this.#completion_status = completion_status; this.#completion_status = completion_status;
@@ -1150,12 +1171,11 @@ export class CMIObjectivesObject extends BaseCMI {
*/ */
set progress_measure(progress_measure) { set progress_measure(progress_measure) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) && if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(progress_measure, check2004ValidRange(progress_measure,
scorm2004_regex.progress_range)) { scorm2004_regex.progress_range)) {
this.#progress_measure = progress_measure; this.#progress_measure = progress_measure;
} }
} }
@@ -1175,8 +1195,7 @@ export class CMIObjectivesObject extends BaseCMI {
*/ */
set description(description) { set description(description) {
if (this.initialized && this.#id === '') { if (this.initialized && this.#id === '') {
throw new ValidationError( throwDependencyNotEstablishedError();
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250, if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) { true)) {
@@ -1232,6 +1251,7 @@ class Scorm2004CMIScore extends CMIScore {
invalidTypeCode: scorm2004_error_codes.TYPE_MISMATCH, invalidTypeCode: scorm2004_error_codes.TYPE_MISMATCH,
invalidRangeCode: scorm2004_error_codes.VALUE_OUT_OF_RANGE, invalidRangeCode: scorm2004_error_codes.VALUE_OUT_OF_RANGE,
decimalRegex: scorm2004_regex.CMIDecimal, decimalRegex: scorm2004_regex.CMIDecimal,
errorClass: Scorm2004ValidationError,
}); });
} }
@@ -1249,7 +1269,7 @@ class Scorm2004CMIScore extends CMIScore {
*/ */
set scaled(scaled) { set scaled(scaled) {
if (check2004ValidFormat(scaled, scorm2004_regex.CMIDecimal) && if (check2004ValidFormat(scaled, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(scaled, scorm2004_regex.scaled_range)) { check2004ValidRange(scaled, scorm2004_regex.scaled_range)) {
this.#scaled = scaled; this.#scaled = scaled;
} }
} }

View File

@@ -66,6 +66,14 @@ const scorm12 = {
basicMessage: 'Incorrect Data Type', basicMessage: 'Incorrect Data Type',
detailMessage: 'LMSSetValue was called with a value that is not consistent with the data format of the supplied data model element.', detailMessage: 'LMSSetValue was called with a value that is not consistent with the data format of the supplied data model element.',
}, },
'407': {
basicMessage: 'Element Value Out Of Range',
detailMessage: 'The numeric value supplied to a LMSSetValue call is outside of the numeric range allowed for the supplied data model element.',
},
'408': {
basicMessage: 'Data Model Dependency Not Established',
detailMessage: 'Some data model elements cannot be set until another data model element was set. This error condition indicates that the prerequisite element was not set before the dependent element.',
},
}, },
}; };

View File

@@ -1,19 +1,31 @@
// @flow // @flow
import APIConstants from './constants/api_constants';
const scorm12_errors = APIConstants.scorm12.error_descriptions;
const aicc_errors = APIConstants.aicc.error_descriptions;
const scorm2004_errors = APIConstants.scorm2004.error_descriptions;
/** /**
* Data Validation Exception * Base Validation Exception
*/ */
export class ValidationError extends Error { export class ValidationError extends Error {
/** /**
* Constructor to take in an error message and code * Constructor to take in an error message and code
* @param {number} errorCode * @param {number} errorCode
* @param {string} errorMessage
* @param {string} detailedMessage
*/ */
constructor(errorCode: number) { constructor(errorCode: number, errorMessage: String, detailedMessage: String) {
super(errorCode); super(errorMessage);
this.#errorCode = errorCode; this.#errorCode = errorCode;
this.#errorMessage = errorMessage;
this.#detailedMessage = detailedMessage;
} }
#errorCode; #errorCode;
#errorMessage;
#detailedMessage;
/** /**
* Getter for #errorCode * Getter for #errorCode
@@ -24,10 +36,69 @@ export class ValidationError extends Error {
} }
/** /**
* Trying to override the default Error message * Getter for #errorMessage
* @return {string} * @return {string}
*/ */
get message() { get errorMessage() {
return this.#errorCode + ''; return this.#errorMessage;
}
/**
* Getter for #detailedMessage
* @return {string}
*/
get detailedMessage() {
return this.#detailedMessage;
}
}
/**
* SCORM 1.2 Validation Error
*/
export class Scorm12ValidationError extends ValidationError {
/**
* Constructor to take in an error code
* @param {number} errorCode
*/
constructor(errorCode: number) {
if ({}.hasOwnProperty.call(scorm12_errors, String(errorCode))) {
super(errorCode, scorm12_errors[String(errorCode)].basicMessage, scorm12_errors[String(errorCode)].detailMessage);
} else {
super(101, scorm12_errors['101'].basicMessage, scorm12_errors['101'].detailMessage);
}
}
}
/**
* AICC Validation Error
*/
export class AICCValidationError extends ValidationError {
/**
* Constructor to take in an error code
* @param {number} errorCode
*/
constructor(errorCode: number) {
if ({}.hasOwnProperty.call(aicc_errors, String(errorCode))) {
super(errorCode, aicc_errors[String(errorCode)].basicMessage, aicc_errors[String(errorCode)].detailMessage);
} else {
super(101, aicc_errors['101'].basicMessage, aicc_errors['101'].detailMessage);
}
}
}
/**
* SCORM 2004 Validation Error
*/
export class Scorm2004ValidationError extends ValidationError {
/**
* Constructor to take in an error code
* @param {number} errorCode
*/
constructor(errorCode: number) {
if ({}.hasOwnProperty.call(scorm2004_errors, String(errorCode))) {
super(errorCode, scorm2004_errors[String(errorCode)].basicMessage, scorm2004_errors[String(errorCode)].detailMessage);
} else {
super(101, scorm2004_errors['101'].basicMessage, scorm2004_errors['101'].detailMessage);
}
} }
} }

View File

@@ -45,7 +45,7 @@ export const checkLMSSetValue = (
if (expectedError > 0) { if (expectedError > 0) {
if (errorThrown) { if (errorThrown) {
expect(() => api.lmsSetValue(fieldName, valueToTest)). expect(() => api.lmsSetValue(fieldName, valueToTest)).
to.throw(String(expectedError)); to.throw().with.property('errorCode', expectedError);
} else { } else {
api.lmsSetValue(fieldName, valueToTest); api.lmsSetValue(fieldName, valueToTest);
expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); expect(String(api.lmsGetLastError())).to.equal(String(expectedError));
@@ -71,7 +71,7 @@ export const checkLMSGetValue = (
initializeFirst = false, initializeFirst = false,
initializationValue = '', initializationValue = '',
expectedError = 0, expectedError = 0,
errorThrown = true, errorThrown = false,
}) => { }) => {
describe(`Field: ${fieldName}`, () => { describe(`Field: ${fieldName}`, () => {
const status = expectedError > 0 ? 'fail to' : 'successfully'; const status = expectedError > 0 ? 'fail to' : 'successfully';
@@ -84,7 +84,7 @@ export const checkLMSGetValue = (
if (expectedError > 0) { if (expectedError > 0) {
if (errorThrown) { if (errorThrown) {
expect(() => api.lmsGetValue(fieldName)). expect(() => api.lmsGetValue(fieldName)).
to.throw(String(expectedError)); to.throw().with.property('errorCode', expectedError);
} else { } else {
api.lmsGetValue(fieldName); api.lmsGetValue(fieldName);
expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); expect(String(api.lmsGetLastError())).to.equal(String(expectedError));
@@ -110,7 +110,7 @@ export const checkSetCMIValue = (
if (expectedError > 0) { if (expectedError > 0) {
if (errorThrown) { if (errorThrown) {
expect(() => api.setCMIValue(fieldName, valueToTest)). expect(() => api.setCMIValue(fieldName, valueToTest)).
to.throw(String(expectedError)); to.throw().with.property('errorCode', expectedError);
} else { } else {
api.setCMIValue(fieldName, valueToTest); api.setCMIValue(fieldName, valueToTest);
expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); expect(String(api.lmsGetLastError())).to.equal(String(expectedError));

View File

@@ -23,7 +23,7 @@ export const checkFieldConstraintSize = (
it(`Should fail to write more than ${limit} characters to ${fieldName}`, it(`Should fail to write more than ${limit} characters to ${fieldName}`,
() => { () => {
expect(() => eval(`${fieldName} = 'x'.repeat(${limit + 1})`)). expect(() => eval(`${fieldName} = 'x'.repeat(${limit + 1})`)).
to.throw(expectedError + ''); to.throw().with.property('errorCode', expectedError);
}); });
}); });
}; };
@@ -42,7 +42,7 @@ export const checkReadOnly = (
it(`Should fail to write to ${fieldName}`, () => { it(`Should fail to write to ${fieldName}`, () => {
expect(() => eval(`${fieldName} = 'xxx'`)). expect(() => eval(`${fieldName} = 'xxx'`)).
to.throw(expectedError + ''); to.throw().with.property('errorCode', expectedError);
}); });
}); });
}; };
@@ -89,7 +89,7 @@ export const checkWriteOnly = (
describe(`Field: ${fieldName}`, () => { describe(`Field: ${fieldName}`, () => {
it(`Should fail to read from ${fieldName}`, () => { it(`Should fail to read from ${fieldName}`, () => {
expect(() => eval(`${fieldName}`)). expect(() => eval(`${fieldName}`)).
to.throw(expectedError + ''); to.throw().with.property('errorCode', expectedError);
}); });
it(`Should successfully write to ${fieldName}`, () => { it(`Should successfully write to ${fieldName}`, () => {

View File

@@ -1,16 +1,71 @@
import {describe, it} from 'mocha'; import {describe, it} from 'mocha';
import {expect} from 'chai'; import {expect} from 'chai';
import {ValidationError} from '../src/exceptions'; import {ValidationError, AICCValidationError, Scorm12ValidationError, Scorm2004ValidationError} from '../src/exceptions';
import APIConstants from '../src/constants/api_constants';
const scorm12_errors = APIConstants.scorm12.error_descriptions;
const aicc_errors = APIConstants.aicc.error_descriptions;
const scorm2004_errors = APIConstants.scorm2004.error_descriptions;
const checkValidationMessage = (
{
errorClass,
errorCodes,
error_messages,
}
) => {
describe(`ValidationError: ${typeof errorClass}`, () => {
it(`${typeof errorClass} should return general errorCode number when not recognized`, () => {
expect(
new errorClass.prototype.constructor(53).errorCode,
).to.equal(101);
});
it(`${typeof errorClass} should return general message when not recognized`, () => {
expect(
new errorClass.prototype.constructor(53).message,
).to.equal(error_messages['101'].basicMessage);
});
for (let i = 0; i < errorCodes.length; i++) {
const errorCode = errorCodes[i];
it(`${typeof errorClass} should return proper errorCode number when recognized`, () => {
expect(
new errorClass.prototype.constructor(errorCode).errorCode,
).to.equal(errorCode);
});
it(`${typeof errorClass} should return proper ${errorCode} message`, () => {
expect(
new errorClass.prototype.constructor(errorCode).message,
).to.equal(error_messages[String(errorCode)].basicMessage);
});
}
});
};
describe('Exception Tests', () => { describe('Exception Tests', () => {
it('ValidationException should return message string', () => { it('ValidationException should return message string', () => {
expect( expect(
new ValidationError(0).message, new ValidationError(0, 'Error Message').message,
).to.equal('0'); ).to.equal('Error Message');
}); });
it('ValidationException should return errorCode number', () => { it('ValidationException should return errorCode number', () => {
expect( expect(
new ValidationError(0).errorCode, new ValidationError(0, 'Error Message').errorCode,
).to.equal(0); ).to.equal(0);
}); });
checkValidationMessage({
errorClass: AICCValidationError,
errorCodes: [101, 201, 202, 203, 301, 401, 402, 403, 404, 405, 407, 408],
error_messages: aicc_errors,
});
checkValidationMessage({
errorClass: Scorm12ValidationError,
errorCodes: [101, 201, 202, 203, 301, 401, 402, 403, 404, 405, 407, 408],
error_messages: scorm12_errors,
});
checkValidationMessage({
errorClass: Scorm2004ValidationError,
errorCodes: [0, 101, 102, 103, 104, 111, 112, 113, 122, 123, 132, 133, 142, 143, 201, 301, 351, 391, 401, 402, 403, 404, 405, 406, 407, 408],
error_messages: scorm2004_errors,
});
}); });

1087
yarn.lock

File diff suppressed because it is too large Load Diff