diff --git a/src/Scorm12API.js b/src/Scorm12API.js index cb2c2e0..7576485 100644 --- a/src/Scorm12API.js +++ b/src/Scorm12API.js @@ -10,7 +10,7 @@ import { import * as Utilities from './utilities'; import {scorm12_constants} from './constants/api_constants'; import {scorm12_error_codes} from './constants/error_codes'; -import {scorm12_regex} from './regex'; +import {scorm12_regex} from './constants/regex'; const constants = scorm12_constants; diff --git a/src/Scorm2004API.js b/src/Scorm2004API.js index 7f48040..a8cc63f 100644 --- a/src/Scorm2004API.js +++ b/src/Scorm2004API.js @@ -15,7 +15,7 @@ import {scorm2004_constants} from './constants/api_constants'; import {scorm2004_error_codes} from './constants/error_codes'; import {correct_responses} from './constants/response_constants'; import {valid_languages} from './constants/language_constants'; -import {scorm2004_regex} from './regex'; +import {scorm2004_regex} from './constants/regex'; const constants = scorm2004_constants; diff --git a/src/cmi/aicc_cmi.js b/src/cmi/aicc_cmi.js index 36d78a6..0e5c5f9 100644 --- a/src/cmi/aicc_cmi.js +++ b/src/cmi/aicc_cmi.js @@ -1,7 +1,7 @@ import * as Scorm12CMI from './scorm12_cmi'; import {BaseCMI, CMIArray, CMIScore} from './common'; import {aicc_constants} from '../constants/api_constants'; -import {aicc_regex} from '../regex'; +import {aicc_regex} from '../constants/regex'; import {scorm12_error_codes} from '../constants/error_codes'; import { check12ValidFormat, diff --git a/src/cmi/common.js b/src/cmi/common.js index 1a462a8..b83b62b 100644 --- a/src/cmi/common.js +++ b/src/cmi/common.js @@ -2,7 +2,7 @@ import {scorm12_constants} from '../constants/api_constants'; import {scorm12_error_codes} from '../constants/error_codes'; import {ValidationError} from '../exceptions'; -import {scorm12_regex} from '../regex'; +import {scorm12_regex} from '../constants/regex'; /** * Check if the value matches the proper format. If not, throw proper error code. @@ -10,12 +10,20 @@ import {scorm12_regex} from '../regex'; * @param {string} value * @param {string} regexPattern * @param {number} errorCode + * @param {boolean} allowEmptyString * @return {boolean} */ export function checkValidFormat( - value: String, regexPattern: String, errorCode: number) { + value: String, + regexPattern: String, + errorCode: number, + allowEmptyString?: boolean) { const formatRegex = new RegExp(regexPattern); - if (!value || !value.match(formatRegex)) { + const matches = value.match(formatRegex); + if (allowEmptyString && value === '') { + return true; + } + if (value === undefined || !matches || matches[0] === '') { throw new ValidationError(errorCode); } return true; @@ -97,7 +105,7 @@ export class CMIScore extends BaseCMI { score_children : scorm12_constants.score_children; this.#_score_range = !score_range ? false : scorm12_regex.score_range; - this.#max = max ? max : '100'; + this.#max = (max || max === '') ? max : '100'; this.#_invalid_error_code = invalidErrorCode ? invalidErrorCode : scorm12_error_codes.INVALID_SET_VALUE; diff --git a/src/cmi/scorm12_cmi.js b/src/cmi/scorm12_cmi.js index 2941bef..e063efb 100644 --- a/src/cmi/scorm12_cmi.js +++ b/src/cmi/scorm12_cmi.js @@ -8,7 +8,7 @@ import { } from './common'; import {scorm12_constants} from '../constants/api_constants'; import {scorm12_error_codes} from '../constants/error_codes'; -import {scorm12_regex} from '../regex'; +import {scorm12_regex} from '../constants/regex'; import {ValidationError} from '../exceptions'; const constants = scorm12_constants; diff --git a/src/cmi/scorm2004_cmi.js b/src/cmi/scorm2004_cmi.js index 814114e..8db4e69 100644 --- a/src/cmi/scorm2004_cmi.js +++ b/src/cmi/scorm2004_cmi.js @@ -7,7 +7,7 @@ import { CMIScore, } from './common'; import {scorm2004_constants} from '../constants/api_constants'; -import {scorm2004_regex} from '../regex'; +import {scorm2004_regex} from '../constants/regex'; import {scorm2004_error_codes} from '../constants/error_codes'; import {learner_responses} from '../constants/response_constants'; import {ValidationError} from '../exceptions'; @@ -40,11 +40,15 @@ function throwTypeMismatchError() { * 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 check2004ValidFormat(value: String, regexPattern: String) { +function check2004ValidFormat( + value: String, + regexPattern: String, + allowEmptyString?: boolean) { return checkValidFormat(value, regexPattern, - scorm2004_error_codes.TYPE_MISMATCH); + scorm2004_error_codes.TYPE_MISMATCH, allowEmptyString); } /** @@ -943,7 +947,7 @@ export class CMIInteractionsObject extends BaseCMI { * @param {string} description */ set description(description) { - if (check2004ValidFormat(description, regex.CMILangString250)) { + if (check2004ValidFormat(description, regex.CMILangString250, true)) { this.#description = description; } } @@ -1098,7 +1102,7 @@ export class CMIObjectivesObject extends BaseCMI { * @param {string} description */ set description(description) { - if (check2004ValidFormat(description, regex.CMILangString250)) { + if (check2004ValidFormat(description, regex.CMILangString250, true)) { this.#description = description; } } @@ -1112,7 +1116,8 @@ export class CMIObjectivesObject extends BaseCMI { * success_status: string, * completion_status: string, * progress_measure: string, - * description: string + * description: string, + * score: Scorm2004CMIScore * } * } */ @@ -1124,6 +1129,7 @@ export class CMIObjectivesObject extends BaseCMI { 'completion_status': this.completion_status, 'progress_measure': this.progress_measure, 'description': this.description, + 'score': this.score, }; delete this.jsonString; return result; @@ -1186,9 +1192,9 @@ class Scorm2004CMIScore extends CMIScore { this.jsonString = true; const result = { 'scaled': this.scaled, - 'raw': this.raw, - 'min': this.min, - 'max': this.max, + 'raw': super.raw, + 'min': super.min, + 'max': super.max, }; delete this.jsonString; return result; @@ -1208,6 +1214,9 @@ export class CMICommentsFromLearnerObject extends BaseCMI { */ constructor() { super(); + this.#comment = ''; + this.#location = ''; + this.#timestamp = ''; } /** @@ -1223,7 +1232,7 @@ export class CMICommentsFromLearnerObject extends BaseCMI { * @param {string} comment */ set comment(comment) { - if (check2004ValidFormat(comment, regex.CMILangString4000)) { + if (check2004ValidFormat(comment, regex.CMILangString4000, true)) { this.#comment = comment; } } @@ -1263,6 +1272,27 @@ export class CMICommentsFromLearnerObject extends BaseCMI { this.#timestamp = timestamp; } } + + /** + * toJSON for cmi.comments_from_learner.n object + * @return { + * { + * comment: string, + * location: string, + * timestamp: string + * } + * } + */ + toJSON() { + this.jsonString = true; + const result = { + 'comment': this.comment, + 'location': this.location, + 'timestamp': this.timestamp, + }; + delete this.jsonString; + return result; + } } /** @@ -1276,12 +1306,28 @@ export class CMICommentsFromLMSObject extends CMICommentsFromLearnerObject { 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 ? this.comment = comment : throwReadOnlyError(); + !this.initialized ? super.comment = comment : throwReadOnlyError(); + } + + /** + * Getter for #location + * @return {string} + */ + get location() { + return super.location; } /** @@ -1289,7 +1335,15 @@ export class CMICommentsFromLMSObject extends CMICommentsFromLearnerObject { * @param {string} location */ set location(location) { - !this.initialized ? this.location = location : throwReadOnlyError(); + !this.initialized ? super.location = location : throwReadOnlyError(); + } + + /** + * Getter for #timestamp + * @return {string} + */ + get timestamp() { + return super.timestamp; } /** @@ -1297,7 +1351,21 @@ export class CMICommentsFromLMSObject extends CMICommentsFromLearnerObject { * @param {string} timestamp */ set timestamp(timestamp) { - !this.initialized ? this.timestamp = timestamp : throwReadOnlyError(); + !this.initialized ? super.timestamp = timestamp : throwReadOnlyError(); + } + + /** + * toJSON for cmi.comments_from_lms.n + * @return { + * { + * comment: string, + * location: string, + * timestamp: string + * } + * } + */ + toJSON() { + return super.toJSON(); } } @@ -1331,6 +1399,23 @@ export class CMIInteractionsObjectivesObject extends BaseCMI { this.#id = id; } } + + /** + * toJSON for cmi.interactions.n.objectives.n + * @return { + * { + * id: string + * } + * } + */ + toJSON() { + this.jsonString = true; + const result = { + 'id': this.id, + }; + delete this.jsonString; + return result; + } } /** @@ -1363,6 +1448,23 @@ export class CMIInteractionsCorrectResponsesObject extends BaseCMI { this.#pattern = pattern; } } + + /** + * toJSON cmi.interactions.n.correct_responses.n object + * @return { + * { + * pattern: string + * } + * } + */ + toJSON() { + this.jsonString = true; + const result = { + 'pattern': this.pattern, + }; + delete this.jsonString; + return result; + } } /** diff --git a/src/constants/field_values.js b/src/constants/field_values.js new file mode 100644 index 0000000..e34a6fd --- /dev/null +++ b/src/constants/field_values.js @@ -0,0 +1,334 @@ +const common_values = { + validResult: [ + 'correct', + 'wrong', + 'unanticipated', + 'neutral', + ], + invalidResult: [ + '-10000', + '10000', + 'invalid', + ], + + valid0To1Range: [ + '0.0', + '0.25', + '0.5', + '1.0', + ], + invalid0To1Range: [ + '-1', + '-0.1', + '1.1', + '.25', + ], + + valid0To100Range: [ + '1', + '50', + '100', + ], + invalid0To100Range: [ + 'invalid', + 'a100', + '-1', + ], + + validScaledRange: [ + '1', + '0.5', + '0', + '-0.5', + '-1', + ], + invalidScaledRange: [ + '-101', + '25.1', + '50.5', + '75', + '100', + ], + + validIntegerScaledRange: [ + '1', + '0', + '-1', + ], + invalidIntegerScaledRange: [ + '-101', + '-0.5', + '0.5', + '25.1', + '50.5', + '75', + '100', + ], +}; + +export const scorm12_values = { + ...common_values, ...{ + validLessonStatus: [ + 'passed', + 'completed', + 'failed', + 'incomplete', + 'browsed', + ], + invalidLessonStatus: [ + 'Passed', + 'P', + 'F', + 'p', + 'true', + 'false', + 'complete', + ], + + validExit: [ + 'time-out', + 'suspend', + 'logout', + ], + invalidExit: [ + 'close', + 'exit', + 'crash', + ], + + validType: [ + 'true-false', + 'choice', + 'fill-in', + 'matching', + 'performance', + 'sequencing', + 'likert', + 'numeric', + ], + invalidType: [ + 'correct', + 'wrong', + 'logout', + ], + + validSpeedRange: [ + '1', + '50', + '100', + '-1', + '-50', + '-100', + ], + invalidSpeedRange: [ + 'invalid', + 'a100', + '-101', + '101', + '-100000', + '100000', + ], + + validScoreRange: [ + '1', + '50.25', + '100', + ], + invalidScoreRange: [ + 'invalid', + 'a100', + '-1', + '101', + '-100000', + '100000', + ], + invalid0To100Range: [ + 'invalid', + 'a100', + '-2', + ], + + validTime: [ + '10:06:57', + '23:59:59', + '00:00:00', + ], + invalidTime: [ + '47:59:59', + '00:00:01.56', + '06:5:13', + '23:59:59.123', + 'P1DT23H59M59S', + ], + + validTimestamp: [ + '10:06:57', + '00:00:01.56', + '23:59:59', + '47:59:59', + ], + invalidTimestamp: [ + '06:5:13', + '23:59:59.123', + 'P1DT23H59M59S', + ], + }, +}; + +export const scorm2004_values = { + ...common_values, ...{ + // valid field values + validTimestamps: [ + '2019-06-25', + '2019-06-25T23:59', + '2019-06-25T23:59:59.99', + '1970-01-01', + ], + invalidTimestamps: [ + '2019-06-25T', + '2019-06-25T23:59:59.999', + '2019-06-25T25:59:59.99', + '2019-13-31', + '1969-12-31', + '-00:00:30', + '0:50:30', + '23:00:30.', + ], + + validCStatus: [ + 'completed', + 'incomplete', + 'not attempted', + 'unknown', + ], + invalidCStatus: [ + 'complete', + 'passed', + 'failed', + ], + + validSStatus: [ + 'passed', + 'failed', + 'unknown', + ], + invalidSStatus: [ + 'complete', + 'incomplete', + 'P', + 'f', + ], + + validExit: [ + 'time-out', + 'suspend', + 'logout', + 'normal', + ], + invalidExit: [ + 'close', + 'exit', + 'crash', + ], + + validType: [ + 'true-false', + 'choice', + 'fill-in', + 'long-fill-in', + 'matching', + 'performance', + 'sequencing', + 'likert', + 'numeric', + 'other', + ], + invalidType: [ + 'correct', + 'wrong', + 'logout', + ], + + validScoreRange: [ + '1', + '50', + '100', + '-10000', + '-1', + '10000', + ], + invalidScoreRange: [ + 'invalid', + 'a100', + '-100000', + '100000', + ], + + validISO8601Durations: [ + 'P1Y34DT23H45M15S', + 'PT1M45S', + 'P0S', + 'PT75M', + ], + invalidISO8601Durations: [ + '00:08:45', + '-P1H', + '1y45D', + '0', + ], + + validComment: [ + '{lang=en-98} learner comment', + '{lang=eng-98-9} learner comment', + '{lang=eng-98-9fhgj}' + 'x'.repeat(4000), + 'learner comment', + 'learner comment}', + '{lang=i-xx}', + '{lang=i}', + '', + ], + invalidComment: [ + '{lang=i-}', + '{lang=i-x}', + '{lang=eng-98-9fhgj}{ learner comment', + '{learner comment', + '{lang=eng-98-9fhgj}' + 'x'.repeat(4001), + '{lang=eng-98-9fhgj}{' + 'x'.repeat(3999), + ], + + validDescription: [ + '{lang=en-98} learner comment', + '{lang=eng-98-9} learner comment', + '{lang=eng-98-9fhgj}' + 'x'.repeat(250), + 'learner comment', + 'learner comment}', + '{lang=i-xx}', + '{lang=i}', + '', + ], + invalidDescription: [ + '{lang=i-}', + '{lang=i-x}', + '{lang=eng-98-9fhgj}{ learner comment', + '{learner comment', + '{lang=eng-98-9fhgj}' + 'x'.repeat(251), + '{lang=eng-98-9fhgj}{' + 'x'.repeat(249), + ], + + validNavRequest: [ + 'previous', + 'continue', + 'exit', + 'exitAll', + 'abandon', + 'abandonAll', + 'suspendAll', + ], + invalidNavRequest: [ + 'close', + 'quit', + 'next', + 'before', + ], + }, +}; diff --git a/src/regex.js b/src/constants/regex.js similarity index 71% rename from src/regex.js rename to src/constants/regex.js index 350ba41..3a0e7ed 100644 --- a/src/regex.js +++ b/src/constants/regex.js @@ -1,5 +1,7 @@ // @flow +import {scorm12_values, scorm2004_values} from './field_values'; + export const scorm12_regex = { CMIString256: '^.{0,255}$', CMIString4096: '^.{0,4096}$', @@ -13,11 +15,11 @@ export const scorm12_regex = { CMIIndex: '[._](\\d+).', // Vocabulary Data Type Definition - CMIStatus: '^(passed|completed|failed|incomplete|browsed)$', - CMIStatus2: '^(passed|completed|failed|incomplete|browsed|not attempted)$', - CMIExit: '^(time-out|suspend|logout|)$', - CMIType: '^(true-false|choice|fill-in|matching|performance|sequencing|likert|numeric)$', - CMIResult: '^(correct|wrong|unanticipated|neutral|([0-9]{0,3})?(\\.[0-9]*)?)$', // eslint-disable-line + CMIStatus: '^(' + scorm12_values.validLessonStatus.join('|') + ')$', + CMIStatus2: '^(' + scorm12_values.validLessonStatus.join('|') + '|not attempted)$', + CMIExit: '^(' + scorm12_values.validExit.join('|') + '|)$', + CMIType: '^(' + scorm12_values.validType.join('|') + ')$', + CMIResult: '^(' + scorm12_values.validResult.join('|') + '|([0-9]{0,3})?(\\.[0-9]*)?)$', // eslint-disable-line NAVEvent: '^(previous|continue)$', // Data ranges @@ -41,10 +43,10 @@ export const scorm2004_regex = { CMIString4000: '^[\\u0000-\\uFFFF]{0,4000}$', CMIString64000: '^[\\u0000-\\uFFFF]{0,64000}$', CMILang: '^([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?$|^$', // eslint-disable-line - CMILangString250: '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250}$)?', // eslint-disable-line + CMILangString250: '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?((?!\{.*$).{0,250}$)?$', // eslint-disable-line CMILangcr: '^((\{lang=([a-zA-Z]{2,3}|i|x)?(\-[a-zA-Z0-9\-]{2,8})?\}))(.*?)$', // eslint-disable-line CMILangString250cr: '^((\{lang=([a-zA-Z]{2,3}|i|x)?(\-[a-zA-Z0-9\-]{2,8})?\})?(.{0,250})?)?$', // eslint-disable-line - CMILangString4000: '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,4000}$)?', // eslint-disable-line + CMILangString4000: '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?((?!\{.*$).{0,4000}$)?$', // eslint-disable-line CMITime: '^(19[7-9]{1}[0-9]{1}|20[0-2]{1}[0-9]{1}|203[0-8]{1})((-(0[1-9]{1}|1[0-2]{1}))((-(0[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1}))(T([0-1]{1}[0-9]{1}|2[0-3]{1})((:[0-5]{1}[0-9]{1})((:[0-5]{1}[0-9]{1})((\\.[0-9]{1,2})((Z|([+|-]([0-1]{1}[0-9]{1}|2[0-3]{1})))(:[0-5]{1}[0-9]{1})?)?)?)?)?)?)?)?$', CMITimespan: '^P(?:([.,\\d]+)Y)?(?:([.,\\d]+)M)?(?:([.,\\d]+)W)?(?:([.,\\d]+)D)?(?:T?(?:([.,\\d]+)H)?(?:([.,\\d]+)M)?(?:([.,\\d]+)S)?)?$', CMIInteger: '^\\d+$', @@ -58,12 +60,12 @@ export const scorm2004_regex = { CMIIndexStore: '.N(\\d+).', // Vocabulary Data Type Definition - CMICStatus: '^(completed|incomplete|not attempted|unknown)$', - CMISStatus: '^(passed|failed|unknown)$', - CMIExit: '^(time-out|suspend|logout|normal|)$', - CMIType: '^(true-false|choice|(long-)?fill-in|matching|performance|sequencing|likert|numeric|other)$', - CMIResult: '^(correct|incorrect|unanticipated|neutral|-?([0-9]{1,4})(\\.[0-9]{1,18})?)$', - NAVEvent: '^(previous|continue|exit|exitAll|abandon|abandonAll|suspendAll|\{target=\\S{0,200}[a-zA-Z0-9]\}choice|jump)$', // eslint-disable-line + CMICStatus: '^(' + scorm2004_values.validCStatus.join('|') + ')$', + CMISStatus: '^(' + scorm2004_values.validSStatus.join('|') + ')$', + CMIExit: '^(' + scorm2004_values.validExit.join('|') + ')$', + CMIType: '^(' + scorm2004_values.validType.join('|') + ')$', + CMIResult: '^(' + scorm2004_values.validResult.join('|') + '|-?([0-9]{1,4})(\\.[0-9]{1,18})?)$', + NAVEvent: '^(' + scorm2004_values.validNavRequest.join('|') + '|\{target=\\S{0,200}[a-zA-Z0-9]\}choice|jump)$', // eslint-disable-line NAVBoolean: '^(unknown|true|false$)', NAVTarget: '^(previous|continue|choice.{target=\\S{0,200}[a-zA-Z0-9]})$', diff --git a/src/constants/response_constants.js b/src/constants/response_constants.js index 9980ae5..33d0cad 100644 --- a/src/constants/response_constants.js +++ b/src/constants/response_constants.js @@ -1,5 +1,5 @@ // @flow -import {scorm2004_regex} from '../regex'; +import {scorm2004_regex} from './regex'; export const learner_responses = { 'true-false': { diff --git a/test/cmi/aicc_cmi.spec.js b/test/cmi/aicc_cmi.spec.js index cdb8b6f..51fa461 100644 --- a/test/cmi/aicc_cmi.spec.js +++ b/test/cmi/aicc_cmi.spec.js @@ -12,6 +12,7 @@ import { CMIObjectivesObject, } from '../../src/cmi/scorm12_cmi'; import {expect} from 'chai'; +import {scorm12_values} from '../../src/constants/field_values'; const invalid_set = scorm12_error_codes.INVALID_SET_VALUE; const type_mismatch = scorm12_error_codes.TYPE_MISMATCH; @@ -94,22 +95,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.lesson_status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', - ], - invalidValues: [ - 'Passed', - 'P', - 'F', - 'p', - 'true', - 'false', - 'complete', - ], + validValues: scorm12_values.validLessonStatus, + invalidValues: scorm12_values.invalidLessonStatus, }); h.checkReadAndWrite({ cmi: cmi(), @@ -132,14 +119,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.exit', - validValues: [ - 'time-out', - 'suspend', - 'logout', - ], invalidValues: [ - 'complete', - 'exit', - ], + validValues: scorm12_values.validExit, + invalidValues: scorm12_values.invalidExit, }); h.checkWriteOnly({ @@ -151,17 +132,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.session_time', - validValues: [ - '10:06:57', - '00:00:01.56', - '23:59:59', - '47:59:59', - ], - invalidValues: [ - '06:5:13', - '23:59:59.123', - 'P1DT23H59M59S', - ], + validValues: scorm12_values.validTimestamp, + invalidValues: scorm12_values.invalidTimestamp, }); /** @@ -177,47 +149,20 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); /** @@ -273,26 +218,10 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.audio', - validValues: [ - '1', + validValues: scorm12_values.valid0To100Range.concat([ '-1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.audio', - validValues: [], - invalidValues: [ - '101', - '5000000', - '-500', - ], + ]), + invalidValues: scorm12_values.invalid0To100Range, }); h.checkFieldConstraintSize({ cmi: cmi(), @@ -303,48 +232,14 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.speed', - validValues: [ - '1', - '-100', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.speed', - validValues: [], - invalidValues: [ - '101', - '-101', - '5000000', - '-500', - ], + validValues: scorm12_values.validSpeedRange, + invalidValues: scorm12_values.invalidSpeedRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.text', - validValues: [ - '1', - '-1', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.text', - validValues: [], - invalidValues: [ - '2', - '-2', - ], + validValues: scorm12_values.validIntegerScaledRange, + invalidValues: scorm12_values.invalidIntegerScaledRange, }); /** @@ -443,22 +338,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.lesson_status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', - ], - invalidValues: [ - 'Passed', - 'P', - 'F', - 'p', - 'true', - 'false', - 'complete', - ], + validValues: scorm12_values.validLessonStatus, + invalidValues: scorm12_values.invalidLessonStatus, }); h.checkReadOnly({ cmi: cmi(), @@ -484,14 +365,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.exit', - validValues: [ - 'time-out', - 'suspend', - 'logout', - ], invalidValues: [ - 'complete', - 'exit', - ], + validValues: scorm12_values.validExit, + invalidValues: scorm12_values.invalidExit, }); h.checkWriteOnly({ cmi: cmi(), @@ -502,17 +377,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.session_time', - validValues: [ - '10:06:57', - '00:00:01.56', - '23:59:59', - '47:59:59', - ], - invalidValues: [ - '06:5:13', - '23:59:59.123', - 'P1DT23H59M59S', - ], + validValues: scorm12_values.validTimestamp, + invalidValues: scorm12_values.invalidTimestamp, }); /** @@ -527,47 +393,20 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); /** @@ -627,26 +466,10 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.audio', - validValues: [ - '1', + validValues: scorm12_values.valid0To100Range.concat([ '-1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.audio', - validValues: [], - invalidValues: [ - '101', - '5000000', - '-500', - ], + ]), + invalidValues: scorm12_values.invalid0To100Range, }); h.checkFieldConstraintSize({ cmi: cmi(), @@ -657,48 +480,14 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.speed', - validValues: [ - '1', - '-100', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.speed', - validValues: [], - invalidValues: [ - '101', - '-101', - '5000000', - '-500', - ], + validValues: scorm12_values.validSpeedRange, + invalidValues: scorm12_values.invalidSpeedRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.text', - validValues: [ - '1', - '-1', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.text', - validValues: [], - invalidValues: [ - '2', - '-2', - ], + validValues: scorm12_values.validIntegerScaledRange, + invalidValues: scorm12_values.invalidIntegerScaledRange, }); /** @@ -756,21 +545,10 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: triesObject(), fieldName: 'cmi.status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', + validValues: scorm12_values.validLessonStatus.concat([ 'not attempted', - ], - invalidValues: [ - 'P', - 'f', - 'complete', - 'started', - 'in progress', - ], + ]), + invalidValues: scorm12_values.invalidLessonStatus, }); h.checkReadAndWrite({ cmi: triesObject(), @@ -781,16 +559,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: triesObject(), fieldName: 'cmi.time', - validValues: [ - '15:00:30', - '00:50:30', - '23:00:30', - ], - invalidValues: [ - '-00:00:30', - '0:50:30', - '23:00:30.', - ], + validValues: scorm12_values.validTime, + invalidValues: scorm12_values.invalidTime, }); /** @@ -805,47 +575,20 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: triesObject(), fieldName: 'cmi.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: triesObject(), fieldName: 'cmi.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: triesObject(), fieldName: 'cmi.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); it('should export JSON', () => { @@ -888,16 +631,8 @@ describe('AICC CMI Tests', () => { h.checkValidValues({ cmi: evaluationComment(), fieldName: 'cmi.time', - validValues: [ - '15:00:30', - '00:50:30', - '23:00:30', - ], - invalidValues: [ - '-00:00:30', - '0:50:30', - '23:00:30.', - ], + validValues: scorm12_values.validTime, + invalidValues: scorm12_values.invalidTime, }); it('should export JSON', () => { diff --git a/test/cmi/scorm12_cmi.spec.js b/test/cmi/scorm12_cmi.spec.js index e7d42ed..45c1167 100644 --- a/test/cmi/scorm12_cmi.spec.js +++ b/test/cmi/scorm12_cmi.spec.js @@ -10,6 +10,7 @@ import { CMIObjectivesObject, } from '../../src/cmi/scorm12_cmi'; import * as h from '../helpers'; +import {scorm12_values} from '../../src/constants/field_values'; const invalid_set = scorm12_error_codes.INVALID_SET_VALUE; const type_mismatch = scorm12_error_codes.TYPE_MISMATCH; @@ -93,22 +94,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.lesson_status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', - ], - invalidValues: [ - 'Passed', - 'P', - 'F', - 'p', - 'true', - 'false', - 'complete', - ], + validValues: scorm12_values.validLessonStatus, + invalidValues: scorm12_values.invalidLessonStatus, }); h.checkReadAndWrite({ cmi: cmi(), @@ -131,14 +118,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.exit', - validValues: [ - 'time-out', - 'suspend', - 'logout', - ], invalidValues: [ - 'complete', - 'exit', - ], + validValues: scorm12_values.validExit, + invalidValues: scorm12_values.invalidExit, }); h.checkWriteOnly({ cmi: cmi(), @@ -149,17 +130,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.session_time', - validValues: [ - '10:06:57', - '00:00:01.56', - '23:59:59', - '47:59:59', - ], - invalidValues: [ - '06:5:13', - '23:59:59.123', - 'P1DT23H59M59S', - ], + validValues: scorm12_values.validHHMMSS, + invalidValues: scorm12_values.invalidHHMMSS, }); /** @@ -178,17 +150,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkRead({ cmi: cmi(), @@ -197,17 +160,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkRead({ cmi: cmi(), @@ -217,17 +171,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); /** @@ -284,19 +229,10 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.audio', - validValues: [ - '1', + validValues: scorm12_values.valid0To100Range.concat([ '-1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - '101', - '5000000', - '-500', - ], + ]), + invalidValues: scorm12_values.invalid0To100Range, }); h.checkFieldConstraintSize({ cmi: cmi(), @@ -311,20 +247,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.speed', - validValues: [ - '1', - '-100', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - '101', - '-101', - '5000000', - '-500', - ], + validValues: scorm12_values.validSpeedRange, + invalidValues: scorm12_values.invalidSpeedRange, }); h.checkRead({ cmi: cmi(), @@ -333,23 +257,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.text', - validValues: [ - '1', - '-1', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.text', - validValues: [], - invalidValues: [ - '2', - '-2', - ], + validValues: scorm12_values.validIntegerScaledRange, + invalidValues: scorm12_values.invalidIntegerScaledRange, }); /** @@ -451,22 +360,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.lesson_status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', - ], - invalidValues: [ - 'Passed', - 'P', - 'F', - 'p', - 'true', - 'false', - 'complete', - ], + validValues: scorm12_values.validLessonStatus, + invalidValues: scorm12_values.invalidLessonStatus, }); h.checkReadOnly({ cmi: cmi(), @@ -492,14 +387,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.exit', - validValues: [ - 'time-out', - 'suspend', - 'logout', - ], invalidValues: [ - 'complete', - 'exit', - ], + validValues: scorm12_values.validExit, + invalidValues: scorm12_values.invalidExit, }); h.checkWriteOnly({ cmi: cmi(), @@ -510,17 +399,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.session_time', - validValues: [ - '10:06:57', - '00:00:01.56', - '23:59:59', - '47:59:59', - ], - invalidValues: [ - '06:5:13', - '23:59:59.123', - 'P1DT23H59M59S', - ], + validValues: scorm12_values.validHHMMSS, + invalidValues: scorm12_values.invalidHHMMSS, }); /** @@ -535,47 +415,20 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.core.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); /** @@ -631,26 +484,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.audio', - validValues: [ - '1', - '-1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.audio', - validValues: [], - invalidValues: [ - '101', - '5000000', - '-500', - ], + validValues: scorm12_values.valid0To100Range.concat(['-1']), + invalidValues: scorm12_values.invalid0To100Range, }); h.checkFieldConstraintSize({ cmi: cmi(), @@ -661,48 +496,14 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.speed', - validValues: [ - '1', - '-100', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.speed', - validValues: [], - invalidValues: [ - '101', - '-101', - '5000000', - '-500', - ], + validValues: scorm12_values.validSpeedRange, + invalidValues: scorm12_values.invalidSpeedRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.student_preference.text', - validValues: [ - '1', - '-1', - ], - invalidValues: [ - 'invalid', - 'a100', - ], - }); - h.checkValidValues({ - cmi: cmi(), - fieldName: 'cmi.student_preference.text', - validValues: [], - invalidValues: [ - '2', - '-2', - ], + validValues: scorm12_values.validIntegerScaledRange, + invalidValues: scorm12_values.invalidIntegerScaledRange, }); /** @@ -727,7 +528,10 @@ describe('SCORM 1.2 CMI Tests', () => { cmiObj.interactions.childArray.push(new CMIInteractionsObject()); expect( JSON.stringify(cmiObj), - ).to.equal('{"suspend_data":"","launch_data":"","comments":"","comments_from_lms":"","core":{"student_id":"","student_name":"","lesson_location":"","credit":"","lesson_status":"","entry":"","total_time":"","lesson_mode":"normal","exit":"","session_time":"00:00:00","score":{"raw":"","min":"","max":"100"}},"objectives":{"0":{"id":"","status":"","score":{"raw":"","min":"","max":"100"}}},"student_data":{"mastery_score":"","max_time_allowed":"","time_limit_action":""},"student_preference":{"audio":"","language":"","speed":"","text":""},"interactions":{"0":{"id":"","time":"","type":"","weighting":"","student_response":"","result":"","latency":"","objectives":{},"correct_responses":{}}}}'); + ). + to. + equal( + '{"suspend_data":"","launch_data":"","comments":"","comments_from_lms":"","core":{"student_id":"","student_name":"","lesson_location":"","credit":"","lesson_status":"","entry":"","total_time":"","lesson_mode":"normal","exit":"","session_time":"00:00:00","score":{"raw":"","min":"","max":"100"}},"objectives":{"0":{"id":"","status":"","score":{"raw":"","min":"","max":"100"}}},"student_data":{"mastery_score":"","max_time_allowed":"","time_limit_action":""},"student_preference":{"audio":"","language":"","speed":"","text":""},"interactions":{"0":{"id":"","time":"","type":"","weighting":"","student_response":"","result":"","latency":"","objectives":{},"correct_responses":{}}}}'); }); }); @@ -763,16 +567,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: interaction(), fieldName: 'cmi.time', - validValues: [ - '15:00:30', - '00:50:30', - '23:00:30', - ], - invalidValues: [ - '-00:00:30', - '0:50:30', - '23:00:30.', - ], + validValues: scorm12_values.validTime, + invalidValues: scorm12_values.invalidTime, }); h.checkWriteOnly({ cmi: interaction(), @@ -783,21 +579,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: interaction(), fieldName: 'cmi.type', - validValues: [ - 'true-false', - 'choice', - 'fill-in', - 'matching', - 'performance', - 'sequencing', - 'likert', - 'numeric', - ], - invalidValues: [ - 'correct', - 'wrong', - 'logout', - ], + validValues: scorm12_values.validType, + invalidValues: scorm12_values.invalidType, }); h.checkReadOnly({ cmi: interaction(), @@ -820,17 +603,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: interaction(), fieldName: 'cmi.weighting', - validValues: [ - '-100', - '-1', - '1', - '100', - ], - invalidValues: [ - '-101', - '101', - 'invalid', - ], + validValues: scorm12_values.validSpeedRange, + invalidValues: scorm12_values.invalidSpeedRange, }); h.checkWriteOnly({ cmi: interaction(), @@ -846,20 +620,12 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: interaction(), fieldName: 'cmi.result', - validValues: [ - 'correct', - 'wrong', - 'unanticipated', - 'neutral', + validValues: scorm12_values.validResult.concat([ '1', '999', '999.99999', - ], - invalidValues: [ - '-1', - '10000', - 'invalid', - ], + ]), + invalidValues: scorm12_values.invalidResult, }); h.checkWriteOnly({ cmi: interaction(), @@ -870,26 +636,21 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: interaction(), fieldName: 'cmi.latency', - validValues: [ - '10:06:57', - '00:00:01.56', - '23:59:59', - '47:59:59', - ], - invalidValues: [ - '06:5:13', - '23:59:59.123', - 'P1DT23H59M59S', - ], + validValues: scorm12_values.validTimestamp, + invalidValues: scorm12_values.invalidTimestamp, }); it('should export JSON', () => { const cmi = interaction(); cmi.objectives.childArray.push(new CMIInteractionsObjectivesObject()); - cmi.correct_responses.childArray.push(new CMIInteractionsCorrectResponsesObject()); + cmi.correct_responses.childArray.push( + new CMIInteractionsCorrectResponsesObject()); expect( JSON.stringify(cmi), - ).to.equal('{"id":"","time":"","type":"","weighting":"","student_response":"","result":"","latency":"","objectives":{"0":{"id":""}},"correct_responses":{"0":{"pattern":""}}}'); + ). + to. + equal( + '{"id":"","time":"","type":"","weighting":"","student_response":"","result":"","latency":"","objectives":{"0":{"id":""}},"correct_responses":{"0":{"pattern":""}}}'); }); }); @@ -955,21 +716,10 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: objective(), fieldName: 'cmi.status', - validValues: [ - 'passed', - 'completed', - 'failed', - 'incomplete', - 'browsed', + validValues: scorm12_values.validLessonStatus.concat([ 'not attempted', - ], - invalidValues: [ - 'P', - 'f', - 'complete', - 'started', - 'in progress', - ], + ]), + invalidValues: scorm12_values.invalidLessonStatus, }); /** @@ -988,17 +738,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: objective(), fieldName: 'cmi.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkRead({ cmi: objective(), @@ -1007,17 +748,8 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: objective(), fieldName: 'cmi.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); h.checkRead({ cmi: objective(), @@ -1027,24 +759,18 @@ describe('SCORM 1.2 CMI Tests', () => { h.checkValidValues({ cmi: objective(), fieldName: 'cmi.score.max', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - '-1', - '101', - ], + validValues: scorm12_values.validScoreRange, + invalidValues: scorm12_values.invalidScoreRange, }); it('should export JSON', () => { const cmi = objective(); expect( JSON.stringify(cmi), - ).to.equal('{"id":"","status":"","score":{"raw":"","min":"","max":"100"}}'); + ). + to. + equal( + '{"id":"","status":"","score":{"raw":"","min":"","max":"100"}}'); }); }); }); diff --git a/test/cmi/scorm2004_cmi.spec.js b/test/cmi/scorm2004_cmi.spec.js index f3a54a3..e445df5 100644 --- a/test/cmi/scorm2004_cmi.spec.js +++ b/test/cmi/scorm2004_cmi.spec.js @@ -1,8 +1,19 @@ -import {describe} from 'mocha'; +import {describe, it} from 'mocha'; import {scorm2004_error_codes} from '../../src/constants/error_codes'; import {scorm2004_constants} from '../../src/constants/api_constants'; -import {CMI} from '../../src/cmi/scorm2004_cmi'; +import { + ADL, + CMI, + CMICommentsFromLearnerObject, + CMICommentsFromLMSObject, CMIInteractionsCorrectResponsesObject, + CMIInteractionsObject, + CMIInteractionsObjectivesObject, + CMIObjectivesObject, +} from '../../src/cmi/scorm2004_cmi'; import * as h from '../helpers'; +import {expect} from 'chai'; +import {scorm2004_values} from '../../src/constants/field_values'; +import {valid_languages} from '../../src/constants/language_constants'; const read_only = scorm2004_error_codes.READ_ONLY_ELEMENT; const write_only = scorm2004_error_codes.WRITE_ONLY_ELEMENT; @@ -35,17 +46,8 @@ describe('SCORM 2004 CMI Tests', () => { cmi: cmi(), fieldName: 'cmi.completion_status', expectedError: type_mismatch, - validValues: [ - 'completed', - 'incomplete', - 'not attempted', - 'unknown', - ], - invalidValues: [ - 'complete', - 'passed', - 'failed', - ], + validValues: scorm2004_values.validCStatus, + invalidValues: scorm2004_values.invalidCStatus, }); h.checkReadAndWrite({ cmi: cmi(), @@ -69,17 +71,8 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.exit', - validValues: [ - 'time-out', - 'suspend', - 'logout', - 'normal', - ], - invalidValues: [ - 'close', - 'exit', - 'crash', - ], + validValues: scorm2004_values.validExit, + invalidValues: scorm2004_values.invalidExit, }); h.checkReadAndWrite({ cmi: cmi(), @@ -115,18 +108,8 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.progress_measure', - validValues: [ - '0.0', - '0.25', - '0.5', - '1.0', - ], - invalidValues: [ - '-1', - '-0.1', - '1.1', - '.25', - ], + validValues: scorm2004_values.valid0To1Range, + invalidValues: scorm2004_values.invalid0To1Range, }); h.checkReadAndWrite({ cmi: cmi(), @@ -141,18 +124,8 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.session_time', - validValues: [ - 'P1Y34DT23H45M15S', - 'PT1M45S', - 'P0S', - 'PT75M', - ], - invalidValues: [ - '00:08:45', - '-P1H', - '1y45D', - '0', - ], + validValues: scorm2004_values.validISO8601Durations, + invalidValues: scorm2004_values.invalidISO8601Durations, }); h.checkRead({ cmi: cmi(), @@ -162,17 +135,8 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.success_status', - validValues: [ - 'passed', - 'failed', - 'unknown', - ], - invalidValues: [ - 'complete', - 'incomplete', - 'P', - 'f', - ], + validValues: scorm2004_values.validSStatus, + invalidValues: scorm2004_values.invalidSStatus, }); h.checkFieldConstraintSize({ cmi: cmi(), @@ -191,22 +155,6 @@ describe('SCORM 2004 CMI Tests', () => { expectedValue: '0', }); - /** - * cmi.interactions Properties - */ - h.checkReadOnly({ - cmi: cmi(), - fieldName: 'cmi.interactions._children', - expectedValue: scorm2004_constants.interactions_children, - expectedError: read_only, - }); - h.checkReadOnly({ - cmi: cmi(), - fieldName: 'cmi.interactions._count', - expectedValue: 0, - expectedError: read_only, - }); - /** * cmi.learner_preference Properties */ @@ -219,16 +167,8 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.learner_preference.audio_level', - validValues: [ - '1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - '-1', - ], + validValues: scorm2004_values.valid0To100Range, + invalidValues: scorm2004_values.invalid0To100Range, }); h.checkValidValues({ cmi: cmi(), @@ -247,29 +187,14 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.learner_preference.delivery_speed', - validValues: [ - '1', - '50', - '100', - ], - invalidValues: [ - 'invalid', - 'a100', - ], + validValues: scorm2004_values.valid0To100Range, + invalidValues: scorm2004_values.invalid0To100Range, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.learner_preference.audio_captioning', - validValues: [ - '1', - '-1', - ], - invalidValues: [ - 'invalid', - 'a100', - '2', - '-2', - ], + validValues: scorm2004_values.validIntegerScaledRange, + invalidValues: scorm2004_values.invalidIntegerScaledRange, }); /** @@ -300,66 +225,806 @@ describe('SCORM 2004 CMI Tests', () => { h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.score.scaled', - validValues: [ - '1', - '0.5', - '0', - '-0.5', - '-1', - ], - invalidValues: [ - '-101', - '25.1', - '50.5', - '75', - '100', - ], + validValues: scorm2004_values.validScaledRange, + invalidValues: scorm2004_values.invalidScaledRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.score.raw', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - 'a100', - 'invalid', - ], + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.score.min', - validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', - ], - invalidValues: [ - 'a100', - 'invalid', - ], + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, }); h.checkValidValues({ cmi: cmi(), fieldName: 'cmi.score.max', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + + /** + * cmi.comments_from_learner Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_learner._children', + expectedValue: scorm2004_constants.comments_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_learner._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.comments_from_lms Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_lms._children', + expectedValue: scorm2004_constants.comments_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_lms._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.interactions Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.interactions._children', + expectedValue: scorm2004_constants.interactions_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.interactions._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.objectives Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._children', + expectedValue: scorm2004_constants.objectives_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._count', + expectedValue: 0, + expectedError: read_only, + }); + + it('should export JSON', () => { + const cmiObj = cmi(); + cmiObj.objectives.childArray.push(new CMIObjectivesObject()); + cmiObj.interactions.childArray.push(new CMIInteractionsObject()); + expect( + JSON.stringify(cmiObj), + ). + to. + equal( + '{"comments_from_learner":{},"comments_from_lms":{},"completion_status":"unknown","completion_threshold":"","credit":"credit","entry":"","exit":"","interactions":{"0":{"id":"","type":"","objectives":{},"timestamp":"","weighting":"","learner_response":"","result":"","latency":"","description":"","correct_responses":{}}},"launch_data":"","learner_id":"","learner_name":"","learner_preference":{"audio_level":"1","language":"","delivery_speed":"1","audio_captioning":"0"},"location":"","max_time_allowed":"","mode":"normal","objectives":{"0":{"id":"","success_status":"unknown","completion_status":"unknown","progress_measure":"","description":"","score":{"scaled":"","raw":"","min":"","max":""}}},"progress_measure":"","scaled_passing_score":"","score":{"scaled":"","raw":"","min":"","max":""},"session_time":"PT0H0M0S","success_status":"unknown","suspend_data":"","time_limit_action":"continue,no message","total_time":"0"}'); + }); + }); + + describe('Post-Initialize Tests', () => { + const cmi = () => { + const cmiObj = new CMI(); + cmiObj.initialize(); + return cmiObj; + }; + + /** + * Base CMI Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi._version', + expectedValue: '1.0', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi._children', + expectedValue: scorm2004_constants.cmi_children, + expectedError: read_only, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.completion_status', + expectedError: type_mismatch, + validValues: scorm2004_values.validCStatus, + invalidValues: scorm2004_values.invalidCStatus, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.completion_threshold', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.credit', + expectedValue: 'credit', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.entry', + expectedError: read_only, + }); + h.checkWriteOnly({ + cmi: cmi(), + fieldName: 'cmi.exit', + expectedError: write_only, + valueToTest: 'time-out', + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.exit', + validValues: scorm2004_values.validExit, + invalidValues: scorm2004_values.invalidExit, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.launch_data', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.learner_id', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.learner_name', + expectedError: read_only, + }); + h.checkFieldConstraintSize({ + cmi: cmi(), + fieldName: 'cmi.location', + limit: 1000, + expectedError: type_mismatch, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.max_time_allowed', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.mode', + expectedValue: 'normal', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.max_time_allowed', + expectedError: read_only, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.progress_measure', + validValues: scorm2004_values.valid0To1Range, + invalidValues: scorm2004_values.invalid0To1Range, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.scaled_passing_score', + expectedError: read_only, + }); + h.checkWriteOnly({ + cmi: cmi(), + fieldName: 'cmi.session_time', + valueToTest: 'P0S', + expectedError: write_only, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.session_time', + validValues: scorm2004_values.validISO8601Durations, + invalidValues: scorm2004_values.invalidISO8601Durations, + }); + h.checkRead({ + cmi: cmi(), + fieldName: 'cmi.success_status', + expectedValue: 'unknown', + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.success_status', + validValues: scorm2004_values.validSStatus, + invalidValues: scorm2004_values.invalidSStatus, + }); + h.checkFieldConstraintSize({ + cmi: cmi(), + fieldName: 'cmi.suspend_data', + limit: 64000, + expectedError: type_mismatch, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.time_limit_action', + expectedValue: 'continue,no message', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.total_time', + expectedValue: '0', + expectedError: read_only, + }); + + /** + * cmi.learner_preference Properties + */ + h.checkInvalidSet({ + cmi: cmi(), + fieldName: 'cmi.learner_preference._children', + expectedValue: scorm2004_constants.student_preference_children, + expectedError: read_only, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.learner_preference.audio_level', + validValues: scorm2004_values.valid0To100Range, + invalidValues: scorm2004_values.invalid0To100Range, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.learner_preference.language', validValues: [ - '0', - '25.1', - '50.5', - '75', - '100', + 'en', + 'fr', + 'ru', + 'es', ], invalidValues: [ - 'a100', 'invalid', + 'a100', ], }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.learner_preference.delivery_speed', + validValues: scorm2004_values.valid0To100Range, + invalidValues: scorm2004_values.invalid0To100Range, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.learner_preference.audio_captioning', + validValues: scorm2004_values.validIntegerScaledRange, + invalidValues: scorm2004_values.invalidIntegerScaledRange, + }); + + /** + * cmi.objectives Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._children', + expectedValue: scorm2004_constants.objectives_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.score Properties + */ + h.checkInvalidSet({ + cmi: cmi(), + fieldName: 'cmi.score._children', + expectedValue: scorm2004_constants.score_children, + expectedError: invalid_set, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.score.scaled', + validValues: scorm2004_values.validScaledRange, + invalidValues: scorm2004_values.invalidScaledRange, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.score.raw', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.score.min', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + h.checkValidValues({ + cmi: cmi(), + fieldName: 'cmi.score.max', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + + /** + * cmi.comments_from_learner Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_learner._children', + expectedValue: scorm2004_constants.comments_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_learner._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.comments_from_lms Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_lms._children', + expectedValue: scorm2004_constants.comments_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.comments_from_lms._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.interactions Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.interactions._children', + expectedValue: scorm2004_constants.interactions_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.interactions._count', + expectedValue: 0, + expectedError: read_only, + }); + + /** + * cmi.objectives Properties + */ + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._children', + expectedValue: scorm2004_constants.objectives_children, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: cmi(), + fieldName: 'cmi.objectives._count', + expectedValue: 0, + expectedError: read_only, + }); + + it('should export JSON', () => { + const cmiObj = cmi(); + cmiObj.objectives.childArray.push(new CMIObjectivesObject()); + cmiObj.interactions.childArray.push(new CMIInteractionsObject()); + expect( + JSON.stringify(cmiObj), + ). + to. + equal( + '{"comments_from_learner":{},"comments_from_lms":{},"completion_status":"unknown","completion_threshold":"","credit":"credit","entry":"","exit":"","interactions":{"0":{"id":"","type":"","objectives":{},"timestamp":"","weighting":"","learner_response":"","result":"","latency":"","description":"","correct_responses":{}}},"launch_data":"","learner_id":"","learner_name":"","learner_preference":{"audio_level":"1","language":"","delivery_speed":"1","audio_captioning":"0"},"location":"","max_time_allowed":"","mode":"normal","objectives":{"0":{"id":"","success_status":"unknown","completion_status":"unknown","progress_measure":"","description":"","score":{"scaled":"","raw":"","min":"","max":""}}},"progress_measure":"","scaled_passing_score":"","score":{"scaled":"","raw":"","min":"","max":""},"session_time":"PT0H0M0S","success_status":"unknown","suspend_data":"","time_limit_action":"continue,no message","total_time":"0"}'); + }); + }); + + describe('CMICommentsFromLearnerObject Tests', () => { + const comments = () => { + return new CMICommentsFromLearnerObject(); + }; + + /** + * cmi.comments_from_learner.n object + */ + h.checkValidValues({ + cmi: comments(), + fieldName: 'cmi.comment', + validValues: scorm2004_values.validComment, + invalidValues: scorm2004_values.invalidComment, + }); + + h.checkFieldConstraintSize({ + cmi: comments(), + fieldName: 'cmi.location', + expectedError: type_mismatch, + limit: 250, + }); + + h.checkReadAndWrite({ + cmi: comments(), + fieldName: 'cmi.timestamp', + valueToTest: '2019-06-25T02:30:00', + }); + h.checkValidValues({ + cmi: comments(), + fieldName: 'cmi.timestamp', + validValues: scorm2004_values.validTimestamps, + invalidValues: scorm2004_values.invalidTimestamps, + }); + + it('should export JSON', () => { + const cmi = comments(); + expect( + JSON.stringify(cmi), + ).to.equal('{"comment":"","location":"","timestamp":""}'); + }); + }); + + describe('CMICommentsFromLMSObject Tests', () => { + const comments = () => { + return new CMICommentsFromLMSObject(); + }; + const commentsInitialized = () => { + const cmi = new CMICommentsFromLMSObject(); + cmi.initialize(); + return cmi; + }; + + /** + * cmi.comments_from_lms.n object + */ + h.checkValidValues({ + cmi: comments(), + fieldName: 'cmi.comment', + validValues: scorm2004_values.validComment, + invalidValues: scorm2004_values.invalidComment, + }); + + h.checkFieldConstraintSize({ + cmi: comments(), + fieldName: 'cmi.location', + expectedError: type_mismatch, + limit: 250, + }); + + h.checkReadAndWrite({ + cmi: comments(), + fieldName: 'cmi.timestamp', + valueToTest: scorm2004_values.validTimestamps[0], + }); + h.checkValidValues({ + cmi: comments(), + fieldName: 'cmi.timestamp', + validValues: scorm2004_values.validTimestamps, + invalidValues: scorm2004_values.invalidTimestamps, + }); + + h.checkReadOnly({ + cmi: commentsInitialized(), + fieldName: 'cmi.comment', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: commentsInitialized(), + fieldName: 'cmi.location', + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: commentsInitialized(), + fieldName: 'cmi.timestamp', + expectedError: read_only, + }); + + it('should export JSON', () => { + const cmi = comments(); + expect( + JSON.stringify(cmi), + ).to.equal('{"comment":"","location":"","timestamp":""}'); + }); + }); + + describe('CMIInteractionsObject Tests', () => { + const interaction = () => { + return new CMIInteractionsObject(); + }; + const interactionInitialized = () => { + const cmi = new CMIInteractionsObject(); + cmi.initialize(); + return cmi; + }; + + /** + * cmi.interactions.n object + */ + h.checkReadAndWrite({ + cmi: interaction(), + fieldName: 'cmi.id', + }); + h.checkReadAndWrite({ + cmi: interactionInitialized(), + fieldName: 'cmi.id', + }); + + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.timestamp', + validValues: scorm2004_values.validTimestamps, + invalidValues: scorm2004_values.invalidTimestamps, + }); + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.type', + validValues: scorm2004_values.validType, + invalidValues: scorm2004_values.invalidType, + }); + h.checkReadOnly({ + cmi: interaction(), + fieldName: 'cmi.objectives._count', + expectedValue: 0, + expectedError: read_only, + }); + h.checkReadOnly({ + cmi: interaction(), + fieldName: 'cmi.correct_responses._count', + expectedValue: 0, + expectedError: read_only, + }); + h.checkWrite({ + cmi: interaction(), + fieldName: 'cmi.weighting', + valueToTest: '0', + }); + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.weighting', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + + /** + * TODO: Learner Response depends on first setting Type, so need to build out lots of test cases + */ + + h.checkRead({ + cmi: interaction(), + fieldName: 'cmi.result', + }); + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.result', + validValues: scorm2004_values.validResult.concat([ + '1', + '999', + '999.99999', + ]), + invalidValues: scorm2004_values.invalidResult, + }); + h.checkRead({ + cmi: interaction(), + fieldName: 'cmi.latency', + }); + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.latency', + validValues: scorm2004_values.validISO8601Durations, + invalidValues: scorm2004_values.invalidISO8601Durations, + }); + + h.checkValidValues({ + cmi: interaction(), + fieldName: 'cmi.description', + validValues: scorm2004_values.validDescription, + invalidValues: scorm2004_values.invalidDescription, + }); + + it('should export JSON', () => { + const cmi = interaction(); + cmi.objectives.childArray.push(new CMIInteractionsObjectivesObject()); + cmi.correct_responses.childArray.push( + new CMIInteractionsCorrectResponsesObject()); + expect( + JSON.stringify(cmi), + ). + to. + equal( + '{"id":"","type":"","objectives":{"0":{"id":""}},"timestamp":"","weighting":"","learner_response":"","result":"","latency":"","description":"","correct_responses":{"0":{"pattern":""}}}'); + }); + }); + + describe('CMIObjectivesObject Tests', () => { + const objective = () => { + return new CMIObjectivesObject(); + }; + const objectiveInitialized = () => { + const cmi = new CMIObjectivesObject(); + cmi.initialize(); + return cmi; + }; + + /** + * cmi.objectives.n object + */ + h.checkReadAndWrite({ + cmi: objective(), + fieldName: 'cmi.id', + }); + h.checkReadAndWrite({ + cmi: objectiveInitialized(), + fieldName: 'cmi.id', + }); + h.checkRead({ + cmi: objective(), + fieldName: 'cmi.success_status', + expectedValue: 'unknown', + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.success_status', + validValues: scorm2004_values.validSStatus, + invalidValues: scorm2004_values.invalidSStatus, + }); + h.checkRead({ + cmi: objective(), + fieldName: 'cmi.completion_status', + expectedValue: 'unknown', + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.completion_status', + validValues: scorm2004_values.validCStatus, + invalidValues: scorm2004_values.invalidCStatus, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.progress_measure', + validValues: scorm2004_values.valid0To1Range, + invalidValues: scorm2004_values.invalid0To1Range, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.description', + validValues: scorm2004_values.validDescription, + invalidValues: scorm2004_values.invalidDescription, + }); + + /** + * cmi.objectives.n.score Properties + */ + h.checkInvalidSet({ + cmi: objective(), + fieldName: 'cmi.score._children', + expectedValue: scorm2004_constants.score_children, + expectedError: invalid_set, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.score.scaled', + validValues: scorm2004_values.validScaledRange, + invalidValues: scorm2004_values.invalidScaledRange, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.score.raw', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.score.min', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + h.checkValidValues({ + cmi: objective(), + fieldName: 'cmi.score.max', + validValues: scorm2004_values.validScoreRange, + invalidValues: scorm2004_values.invalidScoreRange, + }); + + it('should export JSON', () => { + const cmi = objective(); + expect( + JSON.stringify(cmi), + ). + to. + equal( + '{"id":"","success_status":"unknown","completion_status":"unknown","progress_measure":"","description":"","score":{"scaled":"","raw":"","min":"","max":""}}'); + }); + }); + + describe('CMIInteractionsObjectivesObject Tests', () => { + const interactionObjective = () => { + return new CMIInteractionsObjectivesObject(); + }; + + /** + * cmi.interactions.n.objectives.n object + */ + h.checkReadAndWrite({ + cmi: interactionObjective(), + fieldName: 'cmi.id', + }); + + it('should export JSON', () => { + const cmi = interactionObjective(); + expect( + JSON.stringify(cmi), + ).to.equal('{"id":""}'); + }); + }); + + describe('CMIInteractionsCorrectResponsesObject Tests', () => { + const correctResponse = () => { + return new CMIInteractionsCorrectResponsesObject(); + }; + + /** + * cmi.interactions.n.correct_responses.n object + */ + h.checkReadAndWrite({ + cmi: correctResponse(), + fieldName: 'cmi.pattern', + }); + + it('should export JSON', () => { + const cmi = correctResponse(); + expect( + JSON.stringify(cmi), + ).to.equal('{"pattern":""}'); + }); + }); + + describe('ADL Tests', () => { + describe('ADLNav Tests', () => { + const adl = () => { + return new ADL(); + }; + + /** + * cmi.interactions.n.correct_responses.n object + */ + h.checkRead({ + cmi: adl(), + fieldName: 'cmi.nav.request', + expectedValue: '_none_', + }); + + h.checkValidValues({ + cmi: adl(), + fieldName: 'cmi.nav.request', + validValues: scorm2004_values.validNavRequest, + invalidValues: scorm2004_values.invalidNavRequest, + }); + + it('should export JSON', () => { + const cmi = adl(); + expect( + JSON.stringify(cmi), + ).to.equal('{"nav":{"request":"_none_"}}'); + }); + }); }); }); }); diff --git a/test/utilities.spec.js b/test/utilities.spec.js index 3a8dd7e..0bbf14c 100644 --- a/test/utilities.spec.js +++ b/test/utilities.spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {describe, it} from 'mocha'; import * as Utilities from '../src/utilities'; -import {scorm12_regex, scorm2004_regex} from '../src/regex'; +import {scorm12_regex, scorm2004_regex} from '../src/constants/regex'; describe('Utility Tests', () => { describe('getSecondsAsHHMMSS()', () => {