AICC CMI Tests

This commit is contained in:
Jonathan Putney
2019-11-11 22:12:29 -05:00
parent 2f5c9804c9
commit 73ff260097
6 changed files with 1029 additions and 65 deletions

View File

@@ -1,17 +1,23 @@
// @flow // @flow
import Scorm12API from './Scorm12API'; import Scorm12API from './Scorm12API';
import {CMIEvaluationCommentsObject, CMITriesObject, NAV} from './cmi/aicc_cmi'; import {
CMI,
CMIEvaluationCommentsObject,
CMITriesObject,
NAV,
} from './cmi/aicc_cmi';
/** /**
* The AICC API class * The AICC API class
*/ */
class AICC extends Scorm12API { export default class AICC extends Scorm12API {
/** /**
* Constructor to create AICC API object * Constructor to create AICC API object
*/ */
constructor() { constructor() {
super(); super();
this.cmi = new CMI(this);
this.nav = new NAV(this); this.nav = new NAV(this);
} }

View File

@@ -389,7 +389,6 @@ export default class BaseAPI {
* @param {string} CMIElement * @param {string} CMIElement
* @param {*} value * @param {*} value
* @return {string} * @return {string}
* @private
*/ */
_commonSetCMIValue( _commonSetCMIValue(
methodName: String, scorm2004: boolean, CMIElement, value) { methodName: String, scorm2004: boolean, CMIElement, value) {

View File

@@ -13,7 +13,6 @@ import {scorm12_error_codes} from './constants/error_codes';
import {scorm12_regex} from './regex'; import {scorm12_regex} from './regex';
const constants = scorm12_constants; const constants = scorm12_constants;
let _self;
/** /**
* API class for SCORM 1.2 * API class for SCORM 1.2
@@ -24,18 +23,17 @@ export default class Scorm12API extends BaseAPI {
*/ */
constructor() { constructor() {
super(scorm12_error_codes); super(scorm12_error_codes);
_self = this;
_self.cmi = new CMI(this); this.cmi = new CMI(this);
// Rename functions to match 1.2 Spec and expose to modules // Rename functions to match 1.2 Spec and expose to modules
_self.LMSInitialize = _self.lmsInitialize; this.LMSInitialize = this.lmsInitialize;
_self.LMSFinish = _self.lmsFinish; this.LMSFinish = this.lmsFinish;
_self.LMSGetValue = _self.lmsGetValue; this.LMSGetValue = this.lmsGetValue;
_self.LMSSetValue = _self.lmsSetValue; this.LMSSetValue = this.lmsSetValue;
_self.LMSCommit = _self.lmsCommit; this.LMSCommit = this.lmsCommit;
_self.LMSGetLastError = _self.lmsGetLastError; this.LMSGetLastError = this.lmsGetLastError;
_self.LMSGetErrorString = _self.lmsGetErrorString; this.LMSGetErrorString = this.lmsGetErrorString;
_self.LMSGetDiagnostic = _self.lmsGetDiagnostic; this.LMSGetDiagnostic = this.lmsGetDiagnostic;
} }
/** /**
@@ -44,7 +42,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} bool * @return {string} bool
*/ */
lmsInitialize() { lmsInitialize() {
return _self.initialize('LMSInitialize', 'LMS was already initialized!', return this.initialize('LMSInitialize', 'LMS was already initialized!',
'LMS is already finished!'); 'LMS is already finished!');
} }
@@ -54,7 +52,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} bool * @return {string} bool
*/ */
lmsFinish() { lmsFinish() {
return _self.terminate('LMSFinish', false); return this.terminate('LMSFinish', false);
} }
/** /**
@@ -64,7 +62,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} * @return {string}
*/ */
lmsGetValue(CMIElement) { lmsGetValue(CMIElement) {
return _self.getValue('LMSGetValue', false, CMIElement); return this.getValue('LMSGetValue', false, CMIElement);
} }
/** /**
@@ -75,7 +73,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} * @return {string}
*/ */
lmsSetValue(CMIElement, value) { lmsSetValue(CMIElement, value) {
return _self.setValue('LMSSetValue', false, CMIElement, value); return this.setValue('LMSSetValue', false, CMIElement, value);
} }
/** /**
@@ -84,7 +82,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} bool * @return {string} bool
*/ */
lmsCommit() { lmsCommit() {
return _self.commit('LMSCommit', false); return this.commit('LMSCommit', false);
} }
/** /**
@@ -93,7 +91,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} * @return {string}
*/ */
lmsGetLastError() { lmsGetLastError() {
return _self.getLastError('LMSGetLastError'); return this.getLastError('LMSGetLastError');
} }
/** /**
@@ -103,7 +101,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} * @return {string}
*/ */
lmsGetErrorString(CMIErrorCode) { lmsGetErrorString(CMIErrorCode) {
return _self.getErrorString('LMSGetErrorString', CMIErrorCode); return this.getErrorString('LMSGetErrorString', CMIErrorCode);
} }
/** /**
@@ -113,7 +111,7 @@ export default class Scorm12API extends BaseAPI {
* @return {string} * @return {string}
*/ */
lmsGetDiagnostic(CMIErrorCode) { lmsGetDiagnostic(CMIErrorCode) {
return _self.getDiagnostic('LMSGetDiagnostic', CMIErrorCode); return this.getDiagnostic('LMSGetDiagnostic', CMIErrorCode);
} }
/** /**
@@ -123,7 +121,7 @@ export default class Scorm12API extends BaseAPI {
* @param {*} value * @param {*} value
*/ */
setCMIValue(CMIElement, value) { setCMIValue(CMIElement, value) {
_self._commonSetCMIValue('LMSSetValue', false, CMIElement, value); this._commonSetCMIValue('LMSSetValue', false, CMIElement, value);
} }
/** /**
@@ -133,7 +131,7 @@ export default class Scorm12API extends BaseAPI {
* @return {*} * @return {*}
*/ */
getCMIValue(CMIElement) { getCMIValue(CMIElement) {
return _self._commonGetCMIValue('getCMIValue', false, CMIElement); return this._commonGetCMIValue('getCMIValue', false, CMIElement);
} }
/** /**
@@ -146,13 +144,13 @@ export default class Scorm12API extends BaseAPI {
getChildElement(CMIElement, value) { getChildElement(CMIElement, value) {
let newChild; let newChild;
if (_self.stringContains(CMIElement, 'cmi.objectives')) { if (this.stringContains(CMIElement, 'cmi.objectives')) {
newChild = new CMIObjectivesObject(this); newChild = new CMIObjectivesObject(this);
} else if (_self.stringContains(CMIElement, '.correct_responses')) { } else if (this.stringContains(CMIElement, '.correct_responses')) {
newChild = new CMIInteractionsCorrectResponsesObject(this); newChild = new CMIInteractionsCorrectResponsesObject(this);
} else if (_self.stringContains(CMIElement, '.objectives')) { } else if (this.stringContains(CMIElement, '.objectives')) {
newChild = new CMIInteractionsObjectivesObject(this); newChild = new CMIInteractionsObjectivesObject(this);
} else if (_self.stringContains(CMIElement, 'cmi.interactions')) { } else if (this.stringContains(CMIElement, 'cmi.interactions')) {
newChild = new CMIInteractionsObject(this); newChild = new CMIInteractionsObject(this);
} }
@@ -199,8 +197,8 @@ export default class Scorm12API extends BaseAPI {
getCurrentTotalTime() { getCurrentTotalTime() {
const timeRegex = new RegExp(scorm12_regex.CMITime); const timeRegex = new RegExp(scorm12_regex.CMITime);
const totalTime = _self.cmi.core.total_time; const totalTime = this.cmi.core.total_time;
const sessionTime = _self.cmi.core.session_time; const sessionTime = this.cmi.core.session_time;
return Utilities.addHHMMSSTimeStrings(totalTime, sessionTime, timeRegex); return Utilities.addHHMMSSTimeStrings(totalTime, sessionTime, timeRegex);
} }
@@ -212,6 +210,6 @@ export default class Scorm12API extends BaseAPI {
*/ */
replaceWithAnotherScormAPI(newAPI) { replaceWithAnotherScormAPI(newAPI) {
// Data Model // Data Model
_self.cmi = newAPI.cmi; this.cmi = newAPI.cmi;
} }
} }

View File

@@ -1,7 +1,8 @@
import * as Scorm12CMI from './scorm12_cmi'; import * as Scorm12CMI from './scorm12_cmi';
import {BaseCMI, CMIArray, CMIScore} from './common'; import {BaseCMI, CMIArray, CMIScore} from './common';
import {aicc_constants, scorm12_error_codes} from '../constants/api_constants'; import {aicc_constants} from '../constants/api_constants';
import {aicc_regex} from '../regex'; import {aicc_regex} from '../regex';
import {scorm12_error_codes} from '../constants/error_codes';
const constants = aicc_constants; const constants = aicc_constants;
const regex = aicc_regex; const regex = aicc_regex;
@@ -23,8 +24,9 @@ export class CMI extends Scorm12CMI.CMI {
* @param {AICC} API * @param {AICC} API
*/ */
constructor(API) { constructor(API) {
super(API, constants.cmi_children, new AICCCMIStudentData(API)); super(API, constants.cmi_children);
this.student_data = new AICCCMIStudentData(API);
this.evaluation = new CMIEvaluation(API); this.evaluation = new CMIEvaluation(API);
} }
} }
@@ -40,16 +42,21 @@ class CMIEvaluation extends BaseCMI {
constructor(API) { constructor(API) {
super(API); super(API);
this.comments = new class extends CMIArray { this.comments = new CMIEvaluationComments(API);
/** }
* Constructor for AICC Evaluation Comments object }
* @param {AICC} API
*/ /**
constructor(API) { * Class representing AICC's cmi.evaluation.comments object
super(API, constants.comments_children, */
scorm12_error_codes.INVALID_SET_VALUE); class CMIEvaluationComments extends CMIArray {
} /**
}(API); * Constructor for AICC Evaluation Comments object
* @param {AICC} API
*/
constructor(API) {
super(API, constants.comments_children,
scorm12_error_codes.INVALID_SET_VALUE);
} }
} }
@@ -64,15 +71,7 @@ class AICCCMIStudentData extends Scorm12CMI.CMIStudentData {
constructor(API) { constructor(API) {
super(API, constants.student_data_children); super(API, constants.student_data_children);
this.tries = new class extends CMIArray { this.tries = new CMITries(API);
/**
* Constructor for inline Tries Array class
* @param {AICC} API
*/
constructor(API) {
super(API, aicc_constants.tries_children);
}
}(API);
} }
#tries_during_lesson = ''; #tries_during_lesson = '';
@@ -93,7 +92,20 @@ class AICCCMIStudentData extends Scorm12CMI.CMIStudentData {
set tries_during_lesson(tries_during_lesson) { set tries_during_lesson(tries_during_lesson) {
this.API.isNotInitialized() ? this.API.isNotInitialized() ?
this.#tries_during_lesson = tries_during_lesson : this.#tries_during_lesson = tries_during_lesson :
throwReadOnlyError(); throwReadOnlyError(this.API);
}
}
/**
* Class representing the AICC cmi.student_data.tries object
*/
export class CMITries extends CMIArray {
/**
* Constructor for inline Tries Array class
* @param {AICC} API
*/
constructor(API) {
super(API, aicc_constants.tries_children);
} }
} }

670
test/cmi/aicc_cmi.spec.js Normal file
View File

@@ -0,0 +1,670 @@
import {expect, assert} from 'chai';
import {describe, it, beforeEach, afterEach} from 'mocha';
import AICC from '../../src/AICC';
import {aicc_constants} from '../../src/constants/api_constants';
import {scorm12_error_codes} from '../../src/constants/error_codes';
let API;
const checkFieldConstraintSize = ({fieldName, limit, expectedValue = ''}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
it(`Should be able to write upto ${limit} characters to ${fieldName}`,
() => {
eval(`API.${fieldName} = 'x'.repeat(${limit})`);
expect(0).to.equal(API.lastErrorCode);
});
it(`Should fail to write more than ${limit} characters to ${fieldName}`,
() => {
eval(`API.${fieldName} = 'x'.repeat(${limit + 1})`);
expect(scorm12_error_codes.TYPE_MISMATCH + '').
to.
equal(API.lastErrorCode);
});
});
};
const checkInvalidSet = ({fieldName, expectedValue = ''}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
it(`Should fail to write to ${fieldName}`, () => {
eval(`API.${fieldName} = 'xxx'`);
expect(API.lastErrorCode).
to.
equal(scorm12_error_codes.INVALID_SET_VALUE + '');
});
});
};
const checkReadOnly = ({fieldName, expectedValue = ''}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
it(`Should fail to write to ${fieldName}`, () => {
eval(`API.${fieldName} = 'xxx'`);
expect(API.lastErrorCode).
to.
equal(scorm12_error_codes.READ_ONLY_ELEMENT + '');
});
});
};
const checkRead = ({fieldName, expectedValue = ''}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
});
};
const checkReadAndWrite = ({fieldName, expectedValue = '', valueToTest = 'xxx'}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
it(`Should successfully write to ${fieldName}`, () => {
eval(`API.${fieldName} = '${valueToTest}'`);
expect(API.lastErrorCode).to.equal(0);
});
});
};
const checkWriteOnly = ({fieldName, valueToTest = 'xxx'}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should fail to read from ${fieldName}`, () => {
eval(`API.${fieldName}`);
expect(API.lastErrorCode).
to.
equal(scorm12_error_codes.WRITE_ONLY_ELEMENT + '');
});
it(`Should successfully write to ${fieldName}`, () => {
eval(`API.${fieldName} = '${valueToTest}'`);
expect(API.lastErrorCode).to.equal(0);
});
});
};
const checkWrite = ({fieldName, valueToTest = 'xxx'}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should successfully write to ${fieldName}`, () => {
eval(`API.${fieldName} = '${valueToTest}'`);
expect(API.lastErrorCode).to.equal(0);
});
});
};
const checkValidValues = ({fieldName, expectedError, validValues, invalidValues}) => {
describe(`Field: ${fieldName}`, () => {
for (const idx in validValues) {
if ({}.hasOwnProperty.call(validValues, idx)) {
it(`Should successfully write '${validValues[idx]}' to ${fieldName}`,
() => {
eval(`API.${fieldName} = '${validValues[idx]}'`);
expect(API.lastErrorCode).to.equal(0);
});
}
}
for (const idx in invalidValues) {
if ({}.hasOwnProperty.call(invalidValues, idx)) {
it(`Should fail to write '${invalidValues[idx]}' to ${fieldName}`,
() => {
eval(`API.${fieldName} = '${invalidValues[idx]}'`);
expect(API.lastErrorCode).to.equal(expectedError + '');
});
}
}
});
};
describe('AICC CMI Tests', () => {
describe('CMI Spec Tests', () => {
beforeEach('Create the API object', () => {
API = new AICC();
API.lmsInitialize();
});
afterEach('Destroy API object', () => {
API = null;
});
it('lmsInitialize should create CMI object', () => {
assert(API.cmi !== undefined, 'CMI object is created');
});
it('Exporting CMI to JSON produces proper Object', () => {
expect(
JSON.parse(API.renderCMIToJSON()).cmi?.core !== undefined,
).to.be.true;
});
describe('Pre-Initialize Tests', () => {
beforeEach('Create the API object', () => {
API = new AICC();
});
afterEach('Destroy API object', () => {
API = null;
});
/**
* Base CMI Properties
*/
checkInvalidSet({fieldName: 'cmi._version', expectedValue: '3.4'});
checkInvalidSet({
fieldName: 'cmi._children',
expectedValue: aicc_constants.cmi_children,
});
checkFieldConstraintSize({fieldName: 'cmi.suspend_data', limit: 4096});
checkReadAndWrite({fieldName: 'cmi.launch_data'});
checkFieldConstraintSize({fieldName: 'cmi.comments', limit: 4096});
checkReadAndWrite({fieldName: 'cmi.comments_from_lms'});
/**
* cmi.core Properties
*/
checkInvalidSet({
fieldName: 'cmi.core._children',
expectedValue: aicc_constants.core_children,
});
checkReadAndWrite({fieldName: 'cmi.core.student_id'});
checkReadAndWrite({fieldName: 'cmi.core.student_name'});
checkFieldConstraintSize({
fieldName: 'cmi.core.lesson_location',
limit: 255,
});
checkReadAndWrite({fieldName: 'cmi.core.credit'});
checkRead({fieldName: 'cmi.core.lesson_status'});
checkValidValues({
fieldName: 'cmi.core.lesson_status',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'passed',
'completed',
'failed',
'incomplete',
'browsed',
],
invalidValues: [
'Passed',
'P',
'F',
'p',
'true',
'false',
'complete',
],
});
checkReadAndWrite({fieldName: 'cmi.core.entry'});
checkReadAndWrite({fieldName: 'cmi.core.total_time'});
checkReadAndWrite(
{fieldName: 'cmi.core.lesson_mode', expectedValue: 'normal'});
checkWrite({fieldName: 'cmi.core.exit', valueToTest: 'suspend'});
checkValidValues({
fieldName: 'cmi.core.exit',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'time-out',
'suspend',
'logout',
], invalidValues: [
'complete',
'exit',
],
});
checkWriteOnly({
fieldName: 'cmi.core.session_time',
valueToTest: '00:00:00',
});
checkValidValues({
fieldName: 'cmi.core.session_time',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'10:06:57',
'00:00:01.56',
'23:59:59',
'47:59:59',
],
invalidValues: [
'06:5:13',
'23:59:59.123',
'P1DT23H59M59S',
],
});
/**
* cmi.core.score Properties
*/
checkInvalidSet({
fieldName: 'cmi.core.score._children',
expectedValue: aicc_constants.score_children,
});
checkValidValues({
fieldName: 'cmi.core.score.raw',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.min',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.max',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
/**
* cmi.objectives Properties
*/
checkInvalidSet({
fieldName: 'cmi.objectives._children',
expectedValue: aicc_constants.objectives_children,
});
checkInvalidSet({fieldName: 'cmi.objectives._count', expectedValue: 0});
/**
* cmi.student_data Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_data._children',
expectedValue: aicc_constants.student_data_children,
});
checkReadAndWrite({fieldName: 'cmi.student_data.mastery_score'});
checkReadAndWrite({fieldName: 'cmi.student_data.max_time_allowed'});
checkReadAndWrite({fieldName: 'cmi.student_data.time_limit_action'});
checkReadAndWrite({fieldName: 'cmi.student_data.tries_during_lesson'});
/**
* cmi.student_preference Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_preference._children',
expectedValue: aicc_constants.student_preference_children,
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'5000000',
'-500',
],
});
checkFieldConstraintSize({
fieldName: 'cmi.student_preference.language',
limit: 255,
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-100',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'-101',
'5000000',
'-500',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'2',
'-2',
],
});
/**
* cmi.interactions Properties
*/
checkInvalidSet({
fieldName: 'cmi.interactions._children',
expectedValue: aicc_constants.interactions_children,
});
checkInvalidSet({fieldName: 'cmi.interactions._count', expectedValue: 0});
});
describe('Post-Initialize Tests', () => {
beforeEach('Create the API object', () => {
API = new AICC();
API.lmsInitialize();
});
afterEach('Destroy API object', () => {
API = null;
});
/**
* Base CMI Properties
*/
checkInvalidSet({fieldName: 'cmi._version', expectedValue: '3.4'});
checkInvalidSet({
fieldName: 'cmi._children',
expectedValue: aicc_constants.cmi_children,
});
checkFieldConstraintSize({fieldName: 'cmi.suspend_data', limit: 4096});
checkReadOnly({fieldName: 'cmi.launch_data'});
checkFieldConstraintSize({fieldName: 'cmi.comments', limit: 4096});
checkReadOnly({fieldName: 'cmi.comments_from_lms'});
/**
* cmi.core Properties
*/
checkInvalidSet({
fieldName: 'cmi.core._children',
expectedValue: aicc_constants.core_children,
});
checkReadOnly({fieldName: 'cmi.core.student_id'});
checkReadOnly({fieldName: 'cmi.core.student_name'});
checkFieldConstraintSize({
fieldName: 'cmi.core.lesson_location',
limit: 255,
});
checkReadOnly({fieldName: 'cmi.core.credit'});
checkRead({fieldName: 'cmi.core.lesson_status'});
checkValidValues({
fieldName: 'cmi.core.lesson_status',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'passed',
'completed',
'failed',
'incomplete',
'browsed',
],
invalidValues: [
'Passed',
'P',
'F',
'p',
'true',
'false',
'complete',
],
});
checkReadOnly({fieldName: 'cmi.core.entry'});
checkReadOnly({fieldName: 'cmi.core.total_time'});
checkReadOnly(
{fieldName: 'cmi.core.lesson_mode', expectedValue: 'normal'});
checkWrite({fieldName: 'cmi.core.exit', valueToTest: 'suspend'});
checkValidValues({
fieldName: 'cmi.core.exit',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'time-out',
'suspend',
'logout',
], invalidValues: [
'complete',
'exit',
],
});
checkWriteOnly({
fieldName: 'cmi.core.session_time',
valueToTest: '00:00:00',
});
checkValidValues({
fieldName: 'cmi.core.session_time',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'10:06:57',
'00:00:01.56',
'23:59:59',
'47:59:59',
],
invalidValues: [
'06:5:13',
'23:59:59.123',
'P1DT23H59M59S',
],
});
/**
* cmi.core.score Properties
*/
checkInvalidSet({
fieldName: 'cmi.core.score._children',
expectedValue: aicc_constants.score_children,
});
checkValidValues({
fieldName: 'cmi.core.score.raw',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.min',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.max',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
/**
* cmi.objectives Properties
*/
checkInvalidSet({
fieldName: 'cmi.objectives._children',
expectedValue: aicc_constants.objectives_children,
});
checkInvalidSet({fieldName: 'cmi.objectives._count', expectedValue: 0});
/**
* cmi.student_data Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_data._children',
expectedValue: aicc_constants.student_data_children,
});
checkReadOnly({fieldName: 'cmi.student_data.mastery_score'});
checkReadOnly({fieldName: 'cmi.student_data.max_time_allowed'});
checkReadOnly({fieldName: 'cmi.student_data.time_limit_action'});
checkReadOnly({fieldName: 'cmi.student_data.tries_during_lesson'});
/**
* cmi.student_preference Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_preference._children',
expectedValue: aicc_constants.student_preference_children,
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'5000000',
'-500',
],
});
checkFieldConstraintSize({
fieldName: 'cmi.student_preference.language',
limit: 255,
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-100',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'-101',
'5000000',
'-500',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'2',
'-2',
],
});
/**
* cmi.interactions Properties
*/
checkInvalidSet({
fieldName: 'cmi.interactions._children',
expectedValue: aicc_constants.interactions_children,
});
checkInvalidSet({fieldName: 'cmi.interactions._count', expectedValue: 0});
});
});
});

View File

@@ -66,6 +66,19 @@ const checkRead = ({fieldName, expectedValue = ''}) => {
}); });
}; };
const checkReadAndWrite = ({fieldName, expectedValue = '', valueToTest = 'xxx'}) => {
describe(`Field: ${fieldName}`, () => {
it(`Should be able to read from ${fieldName}`, () => {
expect(eval(`API.${fieldName}`)).to.equal(expectedValue);
});
it(`Should successfully write to ${fieldName}`, () => {
eval(`API.${fieldName} = '${valueToTest}'`);
expect(API.lastErrorCode).to.equal(0);
});
});
};
const checkWriteOnly = ({fieldName, valueToTest = 'xxx'}) => { const checkWriteOnly = ({fieldName, valueToTest = 'xxx'}) => {
describe(`Field: ${fieldName}`, () => { describe(`Field: ${fieldName}`, () => {
it(`Should fail to read from ${fieldName}`, () => { it(`Should fail to read from ${fieldName}`, () => {
@@ -115,9 +128,285 @@ const checkValidValues = ({fieldName, expectedError, validValues, invalidValues}
}); });
}; };
describe('SCORM 1.2 API Tests', () => { describe('SCORM 1.2 CMI Tests', () => {
describe('CMI Spec Tests', () => { describe('CMI Spec Tests', () => {
describe('Post-lmsInitialize Tests', () => { beforeEach('Create the API object', () => {
API = new Scorm12API();
API.lmsInitialize();
});
afterEach('Destroy API object', () => {
API = null;
});
it('lmsInitialize should create CMI object', () => {
assert(API.cmi !== undefined, 'CMI object is created');
});
it('Exporting CMI to JSON produces proper Object', () => {
expect(
JSON.parse(API.renderCMIToJSON()).cmi?.core !== undefined,
).to.be.true;
});
describe('Pre-Initialize Tests', () => {
beforeEach('Create the API object', () => {
API = new Scorm12API();
});
afterEach('Destroy API object', () => {
API = null;
});
/**
* Base CMI Properties
*/
checkInvalidSet({fieldName: 'cmi._version', expectedValue: '3.4'});
checkInvalidSet({
fieldName: 'cmi._children',
expectedValue: scorm12_constants.cmi_children,
});
checkFieldConstraintSize({fieldName: 'cmi.suspend_data', limit: 4096});
checkReadAndWrite({fieldName: 'cmi.launch_data'});
checkFieldConstraintSize({fieldName: 'cmi.comments', limit: 4096});
checkReadAndWrite({fieldName: 'cmi.comments_from_lms'});
/**
* cmi.core Properties
*/
checkInvalidSet({
fieldName: 'cmi.core._children',
expectedValue: scorm12_constants.core_children,
});
checkReadAndWrite({fieldName: 'cmi.core.student_id'});
checkReadAndWrite({fieldName: 'cmi.core.student_name'});
checkFieldConstraintSize({
fieldName: 'cmi.core.lesson_location',
limit: 255,
});
checkReadAndWrite({fieldName: 'cmi.core.credit'});
checkRead({fieldName: 'cmi.core.lesson_status'});
checkValidValues({
fieldName: 'cmi.core.lesson_status',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'passed',
'completed',
'failed',
'incomplete',
'browsed',
],
invalidValues: [
'Passed',
'P',
'F',
'p',
'true',
'false',
'complete',
],
});
checkReadAndWrite({fieldName: 'cmi.core.entry'});
checkReadAndWrite({fieldName: 'cmi.core.total_time'});
checkReadAndWrite(
{fieldName: 'cmi.core.lesson_mode', expectedValue: 'normal'});
checkWrite({fieldName: 'cmi.core.exit', valueToTest: 'suspend'});
checkValidValues({
fieldName: 'cmi.core.exit',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'time-out',
'suspend',
'logout',
], invalidValues: [
'complete',
'exit',
],
});
checkWriteOnly({
fieldName: 'cmi.core.session_time',
valueToTest: '00:00:00',
});
checkValidValues({
fieldName: 'cmi.core.session_time',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'10:06:57',
'00:00:01.56',
'23:59:59',
'47:59:59',
],
invalidValues: [
'06:5:13',
'23:59:59.123',
'P1DT23H59M59S',
],
});
/**
* cmi.core.score Properties
*/
checkInvalidSet({
fieldName: 'cmi.core.score._children',
expectedValue: scorm12_constants.score_children,
});
checkValidValues({
fieldName: 'cmi.core.score.raw',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.min',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
checkValidValues({
fieldName: 'cmi.core.score.max',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [
'0',
'25.1',
'50.5',
'75',
'100',
],
invalidValues: [
'-1',
'101',
],
});
/**
* cmi.objectives Properties
*/
checkInvalidSet({
fieldName: 'cmi.objectives._children',
expectedValue: scorm12_constants.objectives_children,
});
checkInvalidSet({fieldName: 'cmi.objectives._count', expectedValue: 0});
/**
* cmi.student_data Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_data._children',
expectedValue: scorm12_constants.student_data_children,
});
checkReadAndWrite({fieldName: 'cmi.student_data.mastery_score'});
checkReadAndWrite({fieldName: 'cmi.student_data.max_time_allowed'});
checkReadAndWrite({fieldName: 'cmi.student_data.time_limit_action'});
/**
* cmi.student_preference Properties
*/
checkInvalidSet({
fieldName: 'cmi.student_preference._children',
expectedValue: scorm12_constants.student_preference_children,
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.audio',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'5000000',
'-500',
],
});
checkFieldConstraintSize({
fieldName: 'cmi.student_preference.language',
limit: 255,
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-100',
'50',
'100',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.speed',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'101',
'-101',
'5000000',
'-500',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.TYPE_MISMATCH,
validValues: [
'1',
'-1',
],
invalidValues: [
'invalid',
'a100',
],
});
checkValidValues({
fieldName: 'cmi.student_preference.text',
expectedError: scorm12_error_codes.VALUE_OUT_OF_RANGE,
validValues: [],
invalidValues: [
'2',
'-2',
],
});
/**
* cmi.interactions Properties
*/
checkInvalidSet({
fieldName: 'cmi.interactions._children',
expectedValue: scorm12_constants.interactions_children,
});
checkInvalidSet({fieldName: 'cmi.interactions._count', expectedValue: 0});
});
describe('Post-Initialize Tests', () => {
beforeEach('Create the API object', () => { beforeEach('Create the API object', () => {
API = new Scorm12API(); API = new Scorm12API();
API.lmsInitialize(); API.lmsInitialize();
@@ -126,16 +415,6 @@ describe('SCORM 1.2 API Tests', () => {
API = null; API = null;
}); });
it('lmsInitialize should create CMI object', () => {
assert(API.cmi !== undefined, 'CMI object is created');
});
it('Exporting CMI to JSON produces proper Object', () => {
expect(
JSON.parse(API.renderCMIToJSON()).cmi?.core !== undefined,
).to.be.true;
});
/** /**
* Base CMI Properties * Base CMI Properties
*/ */