diff --git a/src/AICC.js b/src/AICC.js index 9d8f88c..6744d89 100644 --- a/src/AICC.js +++ b/src/AICC.js @@ -34,9 +34,9 @@ export default class AICC extends Scorm12API { if (!newChild) { if (this.stringMatches(CMIElement, 'cmi\\.evaluation\\.comments\\.\\d')) { - newChild = new CMIEvaluationCommentsObject(this); + newChild = new CMIEvaluationCommentsObject(); } else if (this.stringMatches(CMIElement, 'cmi\\.student_data\\.tries\\.\\d')) { - newChild = new CMITriesObject(this); + newChild = new CMITriesObject(); } } diff --git a/src/BaseAPI.js b/src/BaseAPI.js index 6d62db1..f922b10 100644 --- a/src/BaseAPI.js +++ b/src/BaseAPI.js @@ -152,6 +152,7 @@ export default class BaseAPI { returnValue = this.setCMIValue(CMIElement, value); } catch (e) { if (e instanceof ValidationError) { + this.lastErrorCode = e.errorCode; returnValue = api_constants.SCORM_FALSE; } else { this.throwSCORMError(this.#error_codes.GENERAL); @@ -160,7 +161,9 @@ export default class BaseAPI { this.processListeners(callbackName, CMIElement, value); } - if (returnValue === undefined) returnValue = api_constants.SCORM_FALSE; + if (returnValue === undefined) { + returnValue = api_constants.SCORM_FALSE; + } this.apiLog(callbackName, CMIElement, ': ' + value + ': result: ' + returnValue, @@ -382,7 +385,8 @@ export default class BaseAPI { * @abstract */ getLmsErrorMessageDetails(_errorNumber, _detail) { - throw new Error('The getLmsErrorMessageDetails method has not been implemented'); + throw new Error( + 'The getLmsErrorMessageDetails method has not been implemented'); } /** @@ -445,7 +449,7 @@ export default class BaseAPI { } else if (!this._checkObjectHasProperty(refObject, attribute)) { this.throwSCORMError(invalidErrorCode, invalidErrorMessage); } else { - if (this.stringMatches(CMIElement, '.correct_responses')) { + if (this.stringMatches(CMIElement, '\\.correct_responses\\.\\d')) { this.validateCorrectResponse(CMIElement, value); } @@ -471,12 +475,15 @@ export default class BaseAPI { if (item) { refObject = item; } else { - const newChild = this.getChildElement(CMIElement, value, foundFirstIndex); + const newChild = this.getChildElement(CMIElement, value, + foundFirstIndex); foundFirstIndex = true; if (!newChild) { this.throwSCORMError(invalidErrorCode, invalidErrorMessage); } else { + if (refObject.initialized) newChild.initialize(); + refObject.childArray.push(newChild); refObject = newChild; } diff --git a/src/Scorm12API.js b/src/Scorm12API.js index 425f664..a620f87 100644 --- a/src/Scorm12API.js +++ b/src/Scorm12API.js @@ -148,13 +148,13 @@ export default class Scorm12API extends BaseAPI { let newChild; if (this.stringMatches(CMIElement, 'cmi\\.objectives\\.\\d')) { - newChild = new CMIObjectivesObject(this); + newChild = new CMIObjectivesObject(); } else if (foundFirstIndex && this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d\\.correct_responses\\.\\d')) { - newChild = new CMIInteractionsCorrectResponsesObject(this); + newChild = new CMIInteractionsCorrectResponsesObject(); } else if (foundFirstIndex && this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d\\.objectives\\.\\d')) { - newChild = new CMIInteractionsObjectivesObject(this); + newChild = new CMIInteractionsObjectivesObject(); } else if (this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d')) { - newChild = new CMIInteractionsObject(this); + newChild = new CMIInteractionsObject(); } return newChild; diff --git a/src/Scorm2004API.js b/src/Scorm2004API.js index afd1102..32ebcac 100644 --- a/src/Scorm2004API.js +++ b/src/Scorm2004API.js @@ -3,8 +3,7 @@ import BaseAPI from './BaseAPI'; import { ADL, CMI, - CMICommentsFromLearnerObject, - CMICommentsFromLMSObject, + CMICommentsObject, CMIInteractionsCorrectResponsesObject, CMIInteractionsObject, CMIInteractionsObjectivesObject, @@ -128,9 +127,10 @@ export default class Scorm2004API extends BaseAPI { * * @param {string} CMIElement * @param {any} value + * @return {string} */ setCMIValue(CMIElement, value) { - this._commonSetCMIValue('SetValue', true, CMIElement, value); + return this._commonSetCMIValue('SetValue', true, CMIElement, value); } /** @@ -145,7 +145,7 @@ export default class Scorm2004API extends BaseAPI { let newChild; if (this.stringMatches(CMIElement, 'cmi\\.objectives\\.\\d')) { - newChild = new CMIObjectivesObject(this); + newChild = new CMIObjectivesObject(); } else if (foundFirstIndex && this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d\\.correct_responses\\.\\d')) { const parts = CMIElement.split('.'); const index = Number(parts[2]); @@ -181,16 +181,16 @@ export default class Scorm2004API extends BaseAPI { } } if (this.lastErrorCode === 0) { - newChild = new CMIInteractionsCorrectResponsesObject(this); + newChild = new CMIInteractionsCorrectResponsesObject(); } } else if (foundFirstIndex && this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d\\.objectives\\.\\d')) { - newChild = new CMIInteractionsObjectivesObject(this); + newChild = new CMIInteractionsObjectivesObject(); } else if (this.stringMatches(CMIElement, 'cmi\\.interactions\\.\\d')) { - newChild = new CMIInteractionsObject(this); + newChild = new CMIInteractionsObject(); } else if (this.stringMatches(CMIElement, 'cmi\\.comments_from_learner\\.\\d')) { - newChild = new CMICommentsFromLearnerObject(this); + newChild = new CMICommentsObject(); } else if (this.stringMatches(CMIElement, 'cmi\\.comments_from_lms\\.\\d')) { - newChild = new CMICommentsFromLMSObject(this); + newChild = new CMICommentsObject(true); } return newChild; diff --git a/src/cmi/scorm12_cmi.js b/src/cmi/scorm12_cmi.js index 142854f..cff7452 100644 --- a/src/cmi/scorm12_cmi.js +++ b/src/cmi/scorm12_cmi.js @@ -67,7 +67,6 @@ export function check12ValidRange( /** * Class representing the cmi object for SCORM 1.2 - * @extends BaseCMI */ export class CMI extends BaseCMI { #_children = ''; diff --git a/src/cmi/scorm2004_cmi.js b/src/cmi/scorm2004_cmi.js index 8db4e69..40d664b 100644 --- a/src/cmi/scorm2004_cmi.js +++ b/src/cmi/scorm2004_cmi.js @@ -94,14 +94,14 @@ export class CMI extends BaseCMI { constructor(initialized: boolean) { super(); - if (initialized) this.initialize(); - this.learner_preference = new CMILearnerPreference(); this.score = new Scorm2004CMIScore(); this.comments_from_learner = new CMICommentsFromLearner(); this.comments_from_lms = new CMICommentsFromLMS(); this.interactions = new CMIInteractions(); this.objectives = new CMIObjectives(); + + if (initialized) this.initialize(); } /** @@ -1150,7 +1150,7 @@ class Scorm2004CMIScore extends CMIScore { { score_children: constants.score_children, max: '', - invalidErrorCode: scorm2004_error_codes.INVALID_SET_VALUE, + invalidErrorCode: scorm2004_error_codes.READ_ONLY_ELEMENT, invalidTypeCode: scorm2004_error_codes.TYPE_MISMATCH, invalidRangeCode: scorm2004_error_codes.VALUE_OUT_OF_RANGE, decimalRegex: scorm2004_regex.CMIDecimal, @@ -1202,21 +1202,24 @@ class Scorm2004CMIScore extends CMIScore { } /** - * Class representing SCORM 2004's cmi.comments_from_learner.n object + * Class representing SCORM 2004's cmi.comments_from_learner.n and cmi.comments_from_lms.n object */ -export class CMICommentsFromLearnerObject extends BaseCMI { +export class CMICommentsObject extends BaseCMI { #comment = ''; #location = ''; #timestamp = ''; + #readOnlyAfterInit; /** - * Constructor for cmi.comments_from_learner.n + * Constructor for cmi.comments_from_learner.n and cmi.comments_from_lms.n + * @param {boolean} readOnlyAfterInit */ - constructor() { + constructor(readOnlyAfterInit = false) { super(); this.#comment = ''; this.#location = ''; this.#timestamp = ''; + this.#readOnlyAfterInit = readOnlyAfterInit; } /** @@ -1232,8 +1235,12 @@ export class CMICommentsFromLearnerObject extends BaseCMI { * @param {string} comment */ set comment(comment) { - if (check2004ValidFormat(comment, regex.CMILangString4000, true)) { - this.#comment = comment; + if (this.initialized && this.#readOnlyAfterInit) { + throwReadOnlyError(); + } else { + if (check2004ValidFormat(comment, regex.CMILangString4000, true)) { + this.#comment = comment; + } } } @@ -1250,8 +1257,12 @@ export class CMICommentsFromLearnerObject extends BaseCMI { * @param {string} location */ set location(location) { - if (check2004ValidFormat(location, regex.CMIString250)) { - this.#location = location; + if (this.initialized && this.#readOnlyAfterInit) { + throwReadOnlyError(); + } else { + if (check2004ValidFormat(location, regex.CMIString250)) { + this.#location = location; + } } } @@ -1268,8 +1279,12 @@ export class CMICommentsFromLearnerObject extends BaseCMI { * @param {string} timestamp */ set timestamp(timestamp) { - if (check2004ValidFormat(timestamp, regex.CMITime)) { - this.#timestamp = timestamp; + if (this.initialized && this.#readOnlyAfterInit) { + throwReadOnlyError(); + } else { + if (check2004ValidFormat(timestamp, regex.CMITime)) { + this.#timestamp = timestamp; + } } } @@ -1295,80 +1310,6 @@ export class CMICommentsFromLearnerObject extends BaseCMI { } } -/** - * Class representing SCORM 2004's cmi.comments_from_lms.n object - */ -export class CMICommentsFromLMSObject extends CMICommentsFromLearnerObject { - /** - * Constructor for cmi.comments_from_lms.n - */ - constructor() { - super(); - } - - /** - * Getter for #comment - * @return {string} - */ - get comment() { - return super.comment; - } - - /** - * Setter for #comment. Can only be called before initialization. - * @param {string} comment - */ - set comment(comment) { - !this.initialized ? super.comment = comment : throwReadOnlyError(); - } - - /** - * Getter for #location - * @return {string} - */ - get location() { - return super.location; - } - - /** - * Setter for #location. Can only be called before initialization. - * @param {string} location - */ - set location(location) { - !this.initialized ? super.location = location : throwReadOnlyError(); - } - - /** - * Getter for #timestamp - * @return {string} - */ - get timestamp() { - return super.timestamp; - } - - /** - * Setter for #timestamp. Can only be called before initialization. - * @param {string} timestamp - */ - set timestamp(timestamp) { - !this.initialized ? super.timestamp = timestamp : throwReadOnlyError(); - } - - /** - * toJSON for cmi.comments_from_lms.n - * @return { - * { - * comment: string, - * location: string, - * timestamp: string - * } - * } - */ - toJSON() { - return super.toJSON(); - } -} - /** * Class representing SCORM 2004's cmi.interactions.n.objectives.n object */ diff --git a/src/exceptions.js b/src/exceptions.js index 981426b..c1dc089 100644 --- a/src/exceptions.js +++ b/src/exceptions.js @@ -15,6 +15,14 @@ export class ValidationError extends Error { #errorCode; + /** + * Getter for #errorCode + * @return {number} + */ + get errorCode() { + return this.#errorCode; + } + /** * Trying to override the default Error message * @return {string} diff --git a/test/AICC.spec.js b/test/AICC.spec.js new file mode 100644 index 0000000..eda20e0 --- /dev/null +++ b/test/AICC.spec.js @@ -0,0 +1,249 @@ +import {expect} from 'chai'; +import {describe, it} from 'mocha'; +import * as h from './api_helpers'; +import {scorm12_error_codes} from '../src/constants/error_codes'; +import AICC from '../src/AICC'; + +const api = () => { + const API = new AICC(); + API.apiLogLevel = 1; + return API; +}; +const apiInitialized = () => { + const API = api(); + API.lmsInitialize(); + return API; +}; + +describe('AICC API Tests', () => { + describe('setCMIValue()', () => { + describe('Invalid Sets - Should Always Fail', () => { + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi._version', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi._children', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.core._children', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.core.score._children', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.objectives._children', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.objectives._count', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions._children', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions._count', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions.0.objectives._count', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions.0.correct_responses._count', + expectedError: scorm12_error_codes.INVALID_SET_VALUE, + }); + }); + + describe('Invalid Sets - Should Fail After Initialization', () => { + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.launch_data', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.student_id', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.student_name', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.credit', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.entry', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.total_time', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.core.lesson_mode', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.student_data.mastery_score', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.student_data.max_time_allowed', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.student_data.time_limit_action', + expectedError: scorm12_error_codes.READ_ONLY_ELEMENT, + }); + }); + }); + + describe('LMSGetValue()', () => { + describe('Invalid Properties - Should Always Fail', () => { + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.close', + expectedError: scorm12_error_codes.GENERAL, + errorThrown: false, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.exit', + expectedError: scorm12_error_codes.GENERAL, + errorThrown: false, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.entry', + expectedError: scorm12_error_codes.GENERAL, + errorThrown: false, + }); + }); + + describe('Write-Only Properties - Should Always Fail', () => { + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.exit', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.session_time', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.id', + initializeFirst: true, + initializationValue: 'AAA', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.time', + initializeFirst: true, + initializationValue: '12:59:59', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.type', + initializeFirst: true, + initializationValue: 'true-false', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.weighting', + initializeFirst: true, + initializationValue: '0', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.student_response', + initializeFirst: true, + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.result', + initializeFirst: true, + initializationValue: 'correct', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.latency', + initializeFirst: true, + initializationValue: '01:59:59.99', + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.correct_responses.0.pattern', + initializeFirst: true, + expectedError: scorm12_error_codes.WRITE_ONLY_ELEMENT, + }); + }); + }); + + describe('LMSSetValue()', () => { + describe('Uninitialized - Should Fail', () => { + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.objectives.0.id', + expectedError: scorm12_error_codes.STORE_BEFORE_INIT, + }); + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.interactions.0.id', + expectedError: scorm12_error_codes.STORE_BEFORE_INIT, + }); + }); + + describe('Initialized - Should Succeed', () => { + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.objectives.0.id', + valueToTest: 'AAA', + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.id', + valueToTest: 'AAA', + }); + }); + }); +}); diff --git a/test/Scorm2004API.spec.js b/test/Scorm2004API.spec.js new file mode 100644 index 0000000..98c7b04 --- /dev/null +++ b/test/Scorm2004API.spec.js @@ -0,0 +1,290 @@ +import {expect} from 'chai'; +import {describe, it} from 'mocha'; +import * as h from './api_helpers'; +import {scorm2004_error_codes} from '../src/constants/error_codes'; +import Scorm2004API from '../src/Scorm2004API'; +import {scorm2004_values} from '../src/constants/field_values'; + +const api = () => { + const API = new Scorm2004API(); + API.apiLogLevel = 1; + return API; +}; +const apiInitialized = () => { + const API = api(true); + API.lmsInitialize(); + return API; +}; + +describe('SCORM 2004 API Tests', () => { + describe('setCMIValue()', () => { + describe('Invalid Sets - Should Always Fail', () => { + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi._version', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.comments_from_learner._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.comments_from_learner._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.comments_from_lms._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.comments_from_lms._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions.0.objectives._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.interactions.0.correct_responses._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.learner_preference._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.objectives._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.objectives._count', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.objectives.0.score._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: api(), + fieldName: 'cmi.score._children', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + }); + + describe('Invalid Sets - Should Fail After Initialization', () => { + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.completion_threshold', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.credit', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.entry', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.launch_data', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.learner_id', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.learner_name', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.max_time_allowed', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.mode', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.scaled_passing_score', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.time_limit_action', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.total_time', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.comment', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.location', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkSetCMIValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.timestamp', + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + }); + }); + + describe('GetValue()', () => { + describe('Invalid Properties - Should Always Fail', () => { + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.close', + expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL, + errorThrown: false, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.exit', + expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL, + errorThrown: false, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.core.entry', + expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL, + errorThrown: false, + }); + }); + + describe('Write-Only Properties - Should Always Fail', () => { + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.exit', + expectedError: scorm2004_error_codes.WRITE_ONLY_ELEMENT, + }); + h.checkLMSGetValue({ + api: apiInitialized(), + fieldName: 'cmi.session_time', + expectedError: scorm2004_error_codes.WRITE_ONLY_ELEMENT, + }); + }); + }); + + describe('SetValue()', () => { + describe('Uninitialized - Should Fail', () => { + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.objectives.0.id', + expectedError: scorm2004_error_codes.STORE_BEFORE_INIT, + }); + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.interactions.0.id', + expectedError: scorm2004_error_codes.STORE_BEFORE_INIT, + }); + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.comments_from_learner.0.comment', + expectedError: scorm2004_error_codes.STORE_BEFORE_INIT, + }); + h.checkLMSSetValue({ + api: api(), + fieldName: 'cmi.comments_from_lms.0.comment', + expectedError: scorm2004_error_codes.STORE_BEFORE_INIT, + }); + }); + + describe('Initialized - Should Succeed', () => { + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.objectives.0.id', + valueToTest: 'AAA', + errorThrown: false, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.interactions.0.id', + valueToTest: 'AAA', + errorThrown: false, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_learner.0.comment', + valueToTest: 'comment', + errorThrown: false, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_learner.0.location', + valueToTest: 'location', + errorThrown: false, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_learner.0.timestamp', + valueToTest: scorm2004_values.validTimestamps[0], + errorThrown: false, + }); + }); + + describe('Initialized - Should Fail', () => { + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.comment', + valueToTest: 'comment', + errorThrown: false, + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.location', + valueToTest: 'location', + errorThrown: false, + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + h.checkLMSSetValue({ + api: apiInitialized(), + fieldName: 'cmi.comments_from_lms.0.timestamp', + valueToTest: scorm2004_values.validTimestamps[0], + errorThrown: false, + expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT, + }); + }); + }); +}); diff --git a/test/api_helpers.js b/test/api_helpers.js index 4c009e9..e8fcc3a 100644 --- a/test/api_helpers.js +++ b/test/api_helpers.js @@ -12,12 +12,22 @@ export const checkLMSSetValue = ( describe(`Field: ${fieldName}`, () => { const status = expectedError > 0 ? 'fail to' : 'successfully'; it(`Should ${status} set value for ${fieldName}`, () => { - if (errorThrown) { - expect(() => api.setValue(fieldName, valueToTest)). - to.throw(String(expectedError)); + if (expectedError > 0) { + if (errorThrown) { + expect(() => api.lmsSetValue(fieldName, valueToTest)). + to.throw(String(expectedError)); + } else { + api.lmsSetValue(fieldName, valueToTest); + expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); + } } else { - api.setValue(fieldName, valueToTest); - expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); + if (errorThrown) { + expect(() => api.lmsSetValue(fieldName, valueToTest)). + to.not.throw(); + } else { + api.lmsSetValue(fieldName, valueToTest); + expect(String(api.lmsGetLastError())).to.equal(String(0)); + } } }); }); @@ -76,7 +86,12 @@ export const checkSetCMIValue = ( expect(String(api.lmsGetLastError())).to.equal(String(expectedError)); } } else { - expect(() => api.setCMIValue(fieldName, valueToTest)).to.not.throw(); + if (errorThrown) { + expect(() => api.setCMIValue(fieldName, valueToTest)).to.not.throw(); + } else { + api.setCMIValue(fieldName, valueToTest); + expect(String(api.lmsGetLastError())).to.equal(String(0)); + } } }); }); diff --git a/test/cmi/scorm2004_cmi.spec.js b/test/cmi/scorm2004_cmi.spec.js index 33bea3f..4f7878a 100644 --- a/test/cmi/scorm2004_cmi.spec.js +++ b/test/cmi/scorm2004_cmi.spec.js @@ -4,7 +4,7 @@ import {scorm2004_constants} from '../../src/constants/api_constants'; import { ADL, CMI, - CMICommentsFromLearnerObject, + CMICommentsObject, CMICommentsFromLMSObject, CMIInteractionsCorrectResponsesObject, CMIInteractionsObject, CMIInteractionsObjectivesObject, @@ -219,7 +219,7 @@ describe('SCORM 2004 CMI Tests', () => { cmi: cmi(), fieldName: 'cmi.score._children', expectedValue: scorm2004_constants.score_children, - expectedError: invalid_set, + expectedError: read_only, }); h.checkValidValues({ cmi: cmi(), @@ -535,7 +535,7 @@ describe('SCORM 2004 CMI Tests', () => { cmi: cmi(), fieldName: 'cmi.score._children', expectedValue: scorm2004_constants.score_children, - expectedError: invalid_set, + expectedError: read_only, }); h.checkValidValues({ cmi: cmi(), @@ -639,9 +639,9 @@ describe('SCORM 2004 CMI Tests', () => { }); }); - describe('CMICommentsFromLearnerObject Tests', () => { + describe('CMICommentsObject Tests', () => { const comments = () => { - return new CMICommentsFromLearnerObject(); + return new CMICommentsObject(); }; /** @@ -683,10 +683,10 @@ describe('SCORM 2004 CMI Tests', () => { describe('CMICommentsFromLMSObject Tests', () => { const comments = () => { - return new CMICommentsFromLMSObject(); + return new CMICommentsObject(true); }; const commentsInitialized = () => { - const cmi = new CMICommentsFromLMSObject(); + const cmi = new CMICommentsObject(true); cmi.initialize(); return cmi; }; @@ -915,7 +915,7 @@ describe('SCORM 2004 CMI Tests', () => { cmi: objective(), fieldName: 'cmi.score._children', expectedValue: scorm2004_constants.score_children, - expectedError: invalid_set, + expectedError: read_only, }); h.checkValidValues({ cmi: objective(),