scorm-again 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +4 -9
- package/README.md +7 -3
- package/dist/aicc.js +787 -690
- package/dist/aicc.js.map +1 -0
- package/dist/aicc.min.js +40 -7263
- package/dist/scorm-again.js +1075 -980
- package/dist/scorm-again.js.map +1 -0
- package/dist/scorm-again.min.js +52 -10873
- package/dist/scorm12.js +618 -510
- package/dist/scorm12.js.map +1 -0
- package/dist/scorm12.min.js +34 -5500
- package/dist/scorm2004.js +704 -579
- package/dist/scorm2004.js.map +1 -0
- package/dist/scorm2004.min.js +40 -6884
- package/package.json +35 -27
- package/src/BaseAPI.js +55 -38
- package/src/constants/response_constants.js +2 -2
- package/test/Scorm2004API.spec.js +37 -7
- package/webpack.js +78 -0
- package/gruntfile.js +0 -90
package/package.json
CHANGED
|
@@ -1,50 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scorm-again",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "A modern SCORM JavaScript run-time library for AICC, SCORM 1.2, and SCORM 2004",
|
|
5
5
|
"main": "dist/scorm-again.min.js",
|
|
6
|
+
"browserslist": [
|
|
7
|
+
"> 1%",
|
|
8
|
+
"edge >= 16",
|
|
9
|
+
"safari >= 9",
|
|
10
|
+
"firefox >= 57",
|
|
11
|
+
"ie >= 11",
|
|
12
|
+
"ios >= 9",
|
|
13
|
+
"chrome >= 49"
|
|
14
|
+
],
|
|
6
15
|
"directories": {
|
|
7
16
|
"test": "test"
|
|
8
17
|
},
|
|
9
18
|
"devDependencies": {
|
|
10
|
-
"@babel/cli": "^7.
|
|
11
|
-
"@babel/core": "^7.
|
|
12
|
-
"@babel/node": "^7.
|
|
13
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
14
|
-
"@babel/plugin-proposal-optional-chaining": "^7.
|
|
15
|
-
"@babel/plugin-proposal-private-methods": "^7.
|
|
16
|
-
"@babel/preset-env": "^7.
|
|
17
|
-
"@babel/preset-flow": "^7.
|
|
18
|
-
"@babel/register": "^7.
|
|
19
|
-
"@types/chai": "^4.
|
|
20
|
-
"@types/mocha": "^
|
|
19
|
+
"@babel/cli": "^7.17.10",
|
|
20
|
+
"@babel/core": "^7.18.5",
|
|
21
|
+
"@babel/node": "^7.18.5",
|
|
22
|
+
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
|
23
|
+
"@babel/plugin-proposal-optional-chaining": "^7.17.12",
|
|
24
|
+
"@babel/plugin-proposal-private-methods": "^7.17.12",
|
|
25
|
+
"@babel/preset-env": "^7.18.2",
|
|
26
|
+
"@babel/preset-flow": "^7.17.12",
|
|
27
|
+
"@babel/register": "^7.17.7",
|
|
28
|
+
"@types/chai": "^4.3.1",
|
|
29
|
+
"@types/mocha": "^9.1.1",
|
|
21
30
|
"babel-eslint": "^11.0.0-beta.2",
|
|
31
|
+
"babel-loader": "^8.2.5",
|
|
22
32
|
"babelify": "^10.0.0",
|
|
23
33
|
"browserify": "^17.0.0",
|
|
24
|
-
"chai": "^4.3.
|
|
25
|
-
"eslint": "^
|
|
34
|
+
"chai": "^4.3.6",
|
|
35
|
+
"eslint": "^8.18.0",
|
|
26
36
|
"eslint-config-google": "^0.14.0",
|
|
27
|
-
"eslint-plugin-import": "^2.
|
|
37
|
+
"eslint-plugin-import": "^2.26.0",
|
|
38
|
+
"eslint-webpack-plugin": "^3.1.1",
|
|
28
39
|
"fetch-pretender": "^1.5.0",
|
|
29
|
-
"
|
|
30
|
-
"grunt-browserify": "^6.0.0",
|
|
31
|
-
"grunt-cli": "^1.4.3",
|
|
32
|
-
"grunt-contrib-watch": "^1.1.0",
|
|
33
|
-
"grunt-mocha-test": "^0.13.3",
|
|
34
|
-
"jsdoc": "^3.6.7",
|
|
40
|
+
"jsdoc": "^3.6.10",
|
|
35
41
|
"jsdoc-babel": "^0.5.0",
|
|
36
42
|
"lodash.debounce": "^4.0.8",
|
|
37
43
|
"minimist": "^1.2.5",
|
|
38
|
-
"mocha": "^
|
|
39
|
-
"mocha-junit-reporter": "^2.0.
|
|
40
|
-
"mochawesome": "^
|
|
44
|
+
"mocha": "^10.0.0",
|
|
45
|
+
"mocha-junit-reporter": "^2.0.2",
|
|
46
|
+
"mochawesome": "^7.1.3",
|
|
41
47
|
"nyc": "^15.1.0",
|
|
42
|
-
"sinon": "^
|
|
43
|
-
"
|
|
48
|
+
"sinon": "^14.0.0",
|
|
49
|
+
"uglifyjs-webpack-plugin": "^2.2.0",
|
|
50
|
+
"webpack": "^5.73.0",
|
|
51
|
+
"webpack-cli": "^4.10.0"
|
|
44
52
|
},
|
|
45
53
|
"scripts": {
|
|
46
54
|
"test": "./node_modules/.bin/mocha --require @babel/register --bdd --recursive --reporter list",
|
|
47
|
-
"compile": "./node_modules/.bin/
|
|
55
|
+
"compile": "./node_modules/.bin/webpack --bail --config webpack.js",
|
|
48
56
|
"fix": "./node_modules/.bin/eslint ./src --fix"
|
|
49
57
|
},
|
|
50
58
|
"repository": {
|
package/src/BaseAPI.js
CHANGED
|
@@ -29,6 +29,8 @@ export default class BaseAPI {
|
|
|
29
29
|
selfReportSessionTime: false,
|
|
30
30
|
alwaysSendTotalTime: false,
|
|
31
31
|
strict_errors: true,
|
|
32
|
+
xhrHeaders: {},
|
|
33
|
+
xhrWithCredentials: false,
|
|
32
34
|
responseHandler: function(xhr) {
|
|
33
35
|
let result;
|
|
34
36
|
if (typeof xhr !== 'undefined') {
|
|
@@ -46,6 +48,29 @@ export default class BaseAPI {
|
|
|
46
48
|
}
|
|
47
49
|
return result;
|
|
48
50
|
},
|
|
51
|
+
requestHandler: function(commitObject) {
|
|
52
|
+
return commitObject;
|
|
53
|
+
},
|
|
54
|
+
onLogMessage: function(messageLevel, logMessage) {
|
|
55
|
+
switch (messageLevel) {
|
|
56
|
+
case global_constants.LOG_LEVEL_ERROR:
|
|
57
|
+
console.error(logMessage);
|
|
58
|
+
break;
|
|
59
|
+
case global_constants.LOG_LEVEL_WARNING:
|
|
60
|
+
console.warn(logMessage);
|
|
61
|
+
break;
|
|
62
|
+
case global_constants.LOG_LEVEL_INFO:
|
|
63
|
+
console.info(logMessage);
|
|
64
|
+
break;
|
|
65
|
+
case global_constants.LOG_LEVEL_DEBUG:
|
|
66
|
+
if (console.debug) {
|
|
67
|
+
console.debug(logMessage);
|
|
68
|
+
} else {
|
|
69
|
+
console.log(logMessage);
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
49
74
|
};
|
|
50
75
|
cmi;
|
|
51
76
|
startingData: {};
|
|
@@ -149,11 +174,11 @@ export default class BaseAPI {
|
|
|
149
174
|
|
|
150
175
|
const result = this.storeData(true);
|
|
151
176
|
if (!this.settings.sendBeaconCommit && !this.settings.asyncCommit &&
|
|
152
|
-
|
|
177
|
+
typeof result.errorCode !== 'undefined' && result.errorCode > 0) {
|
|
153
178
|
this.throwSCORMError(result.errorCode);
|
|
154
179
|
}
|
|
155
180
|
returnValue = (typeof result !== 'undefined' && result.result) ?
|
|
156
|
-
|
|
181
|
+
result.result : global_constants.SCORM_FALSE;
|
|
157
182
|
|
|
158
183
|
if (checkTerminated) this.lastErrorCode = 0;
|
|
159
184
|
|
|
@@ -290,11 +315,11 @@ export default class BaseAPI {
|
|
|
290
315
|
this.#error_codes.COMMIT_AFTER_TERM)) {
|
|
291
316
|
const result = this.storeData(false);
|
|
292
317
|
if (!this.settings.sendBeaconCommit && !this.settings.asyncCommit &&
|
|
293
|
-
|
|
318
|
+
result.errorCode && result.errorCode > 0) {
|
|
294
319
|
this.throwSCORMError(result.errorCode);
|
|
295
320
|
}
|
|
296
321
|
returnValue = (typeof result !== 'undefined' && result.result) ?
|
|
297
|
-
|
|
322
|
+
result.result : global_constants.SCORM_FALSE;
|
|
298
323
|
|
|
299
324
|
this.apiLog(callbackName, 'HttpRequest', ' Result: ' + returnValue,
|
|
300
325
|
global_constants.LOG_LEVEL_DEBUG);
|
|
@@ -408,24 +433,7 @@ export default class BaseAPI {
|
|
|
408
433
|
logMessage = this.formatMessage(functionName, CMIElement, logMessage);
|
|
409
434
|
|
|
410
435
|
if (messageLevel >= this.apiLogLevel) {
|
|
411
|
-
|
|
412
|
-
case global_constants.LOG_LEVEL_ERROR:
|
|
413
|
-
console.error(logMessage);
|
|
414
|
-
break;
|
|
415
|
-
case global_constants.LOG_LEVEL_WARNING:
|
|
416
|
-
console.warn(logMessage);
|
|
417
|
-
break;
|
|
418
|
-
case global_constants.LOG_LEVEL_INFO:
|
|
419
|
-
console.info(logMessage);
|
|
420
|
-
break;
|
|
421
|
-
case global_constants.LOG_LEVEL_DEBUG:
|
|
422
|
-
if (console.debug) {
|
|
423
|
-
console.debug(logMessage);
|
|
424
|
-
} else {
|
|
425
|
-
console.log(logMessage);
|
|
426
|
-
}
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
436
|
+
this.settings.onLogMessage(messageLevel, logMessage);
|
|
429
437
|
}
|
|
430
438
|
}
|
|
431
439
|
|
|
@@ -490,9 +498,9 @@ export default class BaseAPI {
|
|
|
490
498
|
*/
|
|
491
499
|
_checkObjectHasProperty(refObject, attribute: String) {
|
|
492
500
|
return Object.hasOwnProperty.call(refObject, attribute) ||
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
501
|
+
Object.getOwnPropertyDescriptor(
|
|
502
|
+
Object.getPrototypeOf(refObject), attribute) ||
|
|
503
|
+
(attribute in refObject);
|
|
496
504
|
}
|
|
497
505
|
|
|
498
506
|
/**
|
|
@@ -556,21 +564,21 @@ export default class BaseAPI {
|
|
|
556
564
|
|
|
557
565
|
const invalidErrorMessage = `The data model element passed to ${methodName} (${CMIElement}) is not a valid SCORM data model element.`;
|
|
558
566
|
const invalidErrorCode = scorm2004 ?
|
|
559
|
-
|
|
560
|
-
|
|
567
|
+
this.#error_codes.UNDEFINED_DATA_MODEL :
|
|
568
|
+
this.#error_codes.GENERAL;
|
|
561
569
|
|
|
562
570
|
for (let i = 0; i < structure.length; i++) {
|
|
563
571
|
const attribute = structure[i];
|
|
564
572
|
|
|
565
573
|
if (i === structure.length - 1) {
|
|
566
574
|
if (scorm2004 && (attribute.substr(0, 8) === '{target=') &&
|
|
567
|
-
|
|
575
|
+
(typeof refObject._isTargetValid == 'function')) {
|
|
568
576
|
this.throwSCORMError(this.#error_codes.READ_ONLY_ELEMENT);
|
|
569
577
|
} else if (!this._checkObjectHasProperty(refObject, attribute)) {
|
|
570
578
|
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
|
|
571
579
|
} else {
|
|
572
580
|
if (this.isInitialized() &&
|
|
573
|
-
|
|
581
|
+
this.stringMatches(CMIElement, '\\.correct_responses\\.\\d+')) {
|
|
574
582
|
this.validateCorrectResponse(CMIElement, value);
|
|
575
583
|
}
|
|
576
584
|
|
|
@@ -671,8 +679,8 @@ export default class BaseAPI {
|
|
|
671
679
|
const uninitializedErrorMessage = `The data model element passed to ${methodName} (${CMIElement}) has not been initialized.`;
|
|
672
680
|
const invalidErrorMessage = `The data model element passed to ${methodName} (${CMIElement}) is not a valid SCORM data model element.`;
|
|
673
681
|
const invalidErrorCode = scorm2004 ?
|
|
674
|
-
|
|
675
|
-
|
|
682
|
+
this.#error_codes.UNDEFINED_DATA_MODEL :
|
|
683
|
+
this.#error_codes.GENERAL;
|
|
676
684
|
|
|
677
685
|
for (let i = 0; i < structure.length; i++) {
|
|
678
686
|
attribute = structure[i];
|
|
@@ -686,9 +694,8 @@ export default class BaseAPI {
|
|
|
686
694
|
}
|
|
687
695
|
} else {
|
|
688
696
|
if ((String(attribute).substr(0, 8) === '{target=') &&
|
|
689
|
-
|
|
690
|
-
const target = String(attribute).
|
|
691
|
-
substr(8, String(attribute).length - 9);
|
|
697
|
+
(typeof refObject._isTargetValid == 'function')) {
|
|
698
|
+
const target = String(attribute).substr(8, String(attribute).length - 9);
|
|
692
699
|
return refObject._isTargetValid(target);
|
|
693
700
|
} else if (!this._checkObjectHasProperty(refObject, attribute)) {
|
|
694
701
|
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
|
|
@@ -818,7 +825,7 @@ export default class BaseAPI {
|
|
|
818
825
|
const removeIndex = this.listenerArray.findIndex((obj) =>
|
|
819
826
|
obj.functionName === functionName &&
|
|
820
827
|
obj.CMIElement === CMIElement &&
|
|
821
|
-
obj.callback === callback
|
|
828
|
+
obj.callback === callback,
|
|
822
829
|
);
|
|
823
830
|
if (removeIndex !== -1) {
|
|
824
831
|
this.listenerArray.splice(removeIndex, 1);
|
|
@@ -867,8 +874,8 @@ export default class BaseAPI {
|
|
|
867
874
|
const listenerHasCMIElement = !!listener.CMIElement;
|
|
868
875
|
let CMIElementsMatch = false;
|
|
869
876
|
if (CMIElement && listener.CMIElement &&
|
|
870
|
-
|
|
871
|
-
|
|
877
|
+
listener.CMIElement.substring(listener.CMIElement.length - 1) ===
|
|
878
|
+
'*') {
|
|
872
879
|
CMIElementsMatch = CMIElement.indexOf(listener.CMIElement.substring(0,
|
|
873
880
|
listener.CMIElement.length - 1)) === 0;
|
|
874
881
|
} else {
|
|
@@ -1093,6 +1100,15 @@ export default class BaseAPI {
|
|
|
1093
1100
|
if (!settings.sendBeaconCommit) {
|
|
1094
1101
|
const httpReq = new XMLHttpRequest();
|
|
1095
1102
|
httpReq.open('POST', url, settings.asyncCommit);
|
|
1103
|
+
|
|
1104
|
+
if (Object.keys(settings.xhrHeaders).length) {
|
|
1105
|
+
Object.keys(settings.xhrHeaders).forEach((header) => {
|
|
1106
|
+
httpReq.setRequestHeader(header, settings.xhrHeaders[header]);
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
httpReq.withCredentials = settings.xhrWithCredentials;
|
|
1111
|
+
|
|
1096
1112
|
if (settings.asyncCommit) {
|
|
1097
1113
|
httpReq.onload = function(e) {
|
|
1098
1114
|
if (typeof settings.responseHandler === 'function') {
|
|
@@ -1103,6 +1119,7 @@ export default class BaseAPI {
|
|
|
1103
1119
|
};
|
|
1104
1120
|
}
|
|
1105
1121
|
try {
|
|
1122
|
+
params = settings.requestHandler(params);
|
|
1106
1123
|
if (params instanceof Array) {
|
|
1107
1124
|
httpReq.setRequestHeader('Content-Type',
|
|
1108
1125
|
'application/x-www-form-urlencoded');
|
|
@@ -1164,7 +1181,7 @@ export default class BaseAPI {
|
|
|
1164
1181
|
}
|
|
1165
1182
|
|
|
1166
1183
|
if (result.result === true ||
|
|
1167
|
-
|
|
1184
|
+
result.result === global_constants.SCORM_TRUE) {
|
|
1168
1185
|
api.processListeners('CommitSuccess');
|
|
1169
1186
|
} else {
|
|
1170
1187
|
api.processListeners('CommitError');
|
|
@@ -11,7 +11,7 @@ const learner = {
|
|
|
11
11
|
unique: false,
|
|
12
12
|
},
|
|
13
13
|
'choice': {
|
|
14
|
-
format: scorm2004_regex.
|
|
14
|
+
format: scorm2004_regex.CMILongIdentifier,
|
|
15
15
|
max: 36,
|
|
16
16
|
delimiter: '[,]',
|
|
17
17
|
unique: true,
|
|
@@ -85,7 +85,7 @@ const correct = {
|
|
|
85
85
|
delimiter: '[,]',
|
|
86
86
|
unique: true,
|
|
87
87
|
duplicate: false,
|
|
88
|
-
format: scorm2004_regex.
|
|
88
|
+
format: scorm2004_regex.CMILongIdentifier,
|
|
89
89
|
},
|
|
90
90
|
'fill-in': {
|
|
91
91
|
max: 10,
|
|
@@ -356,6 +356,19 @@ describe('SCORM 2004 API Tests', () => {
|
|
|
356
356
|
String(scorm2004API.lmsGetLastError()),
|
|
357
357
|
).to.equal(String(0));
|
|
358
358
|
});
|
|
359
|
+
it('should allow cmi.interactions.0.correct_responses.0.pattern to be set - choice for SCORM 2004 4th Edition',
|
|
360
|
+
() => {
|
|
361
|
+
const scorm2004API = apiInitialized();
|
|
362
|
+
scorm2004API.setCMIValue('cmi.interactions.0.id',
|
|
363
|
+
'urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0');
|
|
364
|
+
scorm2004API.setCMIValue('cmi.interactions.0.type', 'choice');
|
|
365
|
+
scorm2004API.setCMIValue(
|
|
366
|
+
'cmi.interactions.0.correct_responses.0.pattern',
|
|
367
|
+
'urn:scormdriver:This%20is%20a%20choice.');
|
|
368
|
+
expect(
|
|
369
|
+
String(scorm2004API.lmsGetLastError()),
|
|
370
|
+
).to.equal(String(0));
|
|
371
|
+
});
|
|
359
372
|
it('should allow cmi.interactions.0.objectives.0.id to be set',
|
|
360
373
|
() => {
|
|
361
374
|
const scorm2004API = apiInitialized();
|
|
@@ -386,6 +399,27 @@ describe('SCORM 2004 API Tests', () => {
|
|
|
386
399
|
scorm2004API.getCMIValue('cmi.interactions.0.learner_response'),
|
|
387
400
|
).to.equal('VP_on-call_or_President');
|
|
388
401
|
});
|
|
402
|
+
it('should allow cmi.interactions.0.learner_response to be set for SCORM 2004 4th Edition',
|
|
403
|
+
() => {
|
|
404
|
+
const scorm2004API = apiInitialized();
|
|
405
|
+
scorm2004API.setCMIValue('cmi.interactions.0.id',
|
|
406
|
+
'urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0');
|
|
407
|
+
scorm2004API.setCMIValue('cmi.interactions.0.type', 'choice');
|
|
408
|
+
scorm2004API.setCMIValue('cmi.interactions.0.learner_response',
|
|
409
|
+
'urn:scormdriver:This%20is%20an%20incorrect%20response.');
|
|
410
|
+
expect(
|
|
411
|
+
String(scorm2004API.lmsGetLastError()),
|
|
412
|
+
).to.equal(String(0));
|
|
413
|
+
expect(
|
|
414
|
+
scorm2004API.getCMIValue('cmi.interactions.0.id'),
|
|
415
|
+
).to.equal('urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0');
|
|
416
|
+
expect(
|
|
417
|
+
scorm2004API.getCMIValue('cmi.interactions.0.type'),
|
|
418
|
+
).to.equal('choice');
|
|
419
|
+
expect(
|
|
420
|
+
scorm2004API.getCMIValue('cmi.interactions.0.learner_response'),
|
|
421
|
+
).to.equal('urn:scormdriver:This%20is%20an%20incorrect%20response.');
|
|
422
|
+
});
|
|
389
423
|
it('should allow `long-fill-in` cmi.interactions.0.learner_response to be set to 4000 characters',
|
|
390
424
|
() => {
|
|
391
425
|
const scorm2004API = apiInitialized();
|
|
@@ -405,10 +439,8 @@ describe('SCORM 2004 API Tests', () => {
|
|
|
405
439
|
).to.equal('long-fill-in');
|
|
406
440
|
expect(
|
|
407
441
|
scorm2004API.getCMIValue('cmi.interactions.0.learner_response'),
|
|
408
|
-
).
|
|
409
|
-
|
|
410
|
-
equal(
|
|
411
|
-
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer et sodales purus, in aliquam ex. Nunc suscipit interdum tortor ut hendrerit. Donec auctor erat suscipit justo hendrerit, at lacinia ipsum ullamcorper. Cras sollicitudin vestibulum malesuada. Sed non nibh pharetra, suscipit ipsum sed, maximus tortor. Morbi pharetra accumsan turpis id fringilla. In volutpat metus a dui semper, nec tincidunt nibh aliquam. Praesent viverra neque in elementum commodo. Integer hendrerit placerat ante, ac finibus urna tincidunt at. Phasellus consectetur mauris vitae orci viverra luctus. Proin vestibulum blandit mauris quis pellentesque. Proin volutpat hendrerit nisi. Etiam pellentesque urna nec massa congue ultricies. Mauris at eros viverra, posuere tortor id, elementum nisi. In hac habitasse platea dictumst. Pellentesque semper tristique arcu, in tristique metus. Vestibulum ut lacus dui. Aenean mattis malesuada arcu non ullamcorper. Suspendisse tincidunt euismod tincidunt. In tincidunt at nunc rhoncus vehicula. Quisque nulla massa, vestibulum nec laoreet sit amet, posuere eu massa. Donec accumsan efficitur turpis, quis eleifend odio aliquam a. Phasellus placerat ante id dui consectetur dictum. Morbi aliquam, nibh id elementum suscipit, neque ante scelerisque velit, at feugiat turpis odio ac ligula. Phasellus vel urna nulla. Donec vulputate nulla vel purus pellentesque gravida. Vestibulum rutrum, est vel cursus ultrices, orci arcu scelerisque magna, id facilisis mauris arcu ut turpis. Vestibulum consectetur faucibus ante, eu posuere quam ornare et. Aenean vitae dictum neque. Donec nisl justo, porta a sapien quis, luctus congue diam. Integer id metus dolor. Maecenas euismod vulputate leo in lobortis. Vestibulum dignissim finibus est, sed sollicitudin ipsum hendrerit ac. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque diam lorem, mattis vel orci interdum, tempor luctus elit. Ut id porta nisi. In dignissim quam urna, et iaculis lectus eleifend ut. Nam vitae felis ac risus tincidunt elementum. Nunc hendrerit augue a nulla hendrerit rutrum. Integer euismod est at orci eleifend, sed laoreet justo auctor. Sed sem orci, imperdiet at erat non, vehicula convallis libero. Aenean hendrerit cursus leo ut malesuada. Donec eu placerat lorem. Sed mattis tristique lorem, eget placerat erat scelerisque faucibus. Vivamus eleifend in augue id mollis. Nulla vehicula, metus eu auctor accumsan, lectus sapien pretium dui, non scelerisque magna augue a sem. Suspendisse sem enim, mattis ac augue non, placerat accumsan sem. Vivamus hendrerit, sapien sit amet consectetur pulvinar, ante nisl pulvinar purus, a ullamcorper dolor leo id arcu. Aliquam sed metus arcu. Quisque erat libero, tincidunt non dictum vel, bibendum ut ante. Nunc vel imperdiet risus. Sed sit amet porta enim. Mauris metus tortor, mattis vitae convallis vitae, dictum nec dui. Aliquam volutpat nisi consequat, gravida tellus eget, cursus purus. Nunc at venenatis enim. Proin dictum, magna ultrices tempor aliquam, metus lacus consectetur odio, quis pharetra massa est at est. Nullam non nibh massa. Duis scelerisque massa a luctus vehicula. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec tortor lacus, consequat eget neque sit amet, imperdiet porttitor felis. Duis ante erat, cursus sed venenatis nec, semper sollicitudin felis. Sed tincidunt et tortor quis vehicula. Morbi porta dapibus quam quis iaculis. Nunc mauris dolor, rutrum non pellentesque consectetur, ornare quis lacus. Maecenas eget feugiat odio. Proin vitae magna ut justo bibendum lacinia consequat at orci. Phasellus tincidunt lorem eu justo mollis sagittis. Maecenas fermentum nunc augue, et bibendum augue varius venenatis. Donec eu purus at tellus ullamcorper imperdiet. Duis id orci laoreet, semper eros et, tincidunt nisl. Suspendisse vehicula sed enim ut dignissim. Nam ornare leo eu nibh malesuada, eget ullamcorper sapien egestas. In at commod');
|
|
442
|
+
).to.equal(
|
|
443
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer et sodales purus, in aliquam ex. Nunc suscipit interdum tortor ut hendrerit. Donec auctor erat suscipit justo hendrerit, at lacinia ipsum ullamcorper. Cras sollicitudin vestibulum malesuada. Sed non nibh pharetra, suscipit ipsum sed, maximus tortor. Morbi pharetra accumsan turpis id fringilla. In volutpat metus a dui semper, nec tincidunt nibh aliquam. Praesent viverra neque in elementum commodo. Integer hendrerit placerat ante, ac finibus urna tincidunt at. Phasellus consectetur mauris vitae orci viverra luctus. Proin vestibulum blandit mauris quis pellentesque. Proin volutpat hendrerit nisi. Etiam pellentesque urna nec massa congue ultricies. Mauris at eros viverra, posuere tortor id, elementum nisi. In hac habitasse platea dictumst. Pellentesque semper tristique arcu, in tristique metus. Vestibulum ut lacus dui. Aenean mattis malesuada arcu non ullamcorper. Suspendisse tincidunt euismod tincidunt. In tincidunt at nunc rhoncus vehicula. Quisque nulla massa, vestibulum nec laoreet sit amet, posuere eu massa. Donec accumsan efficitur turpis, quis eleifend odio aliquam a. Phasellus placerat ante id dui consectetur dictum. Morbi aliquam, nibh id elementum suscipit, neque ante scelerisque velit, at feugiat turpis odio ac ligula. Phasellus vel urna nulla. Donec vulputate nulla vel purus pellentesque gravida. Vestibulum rutrum, est vel cursus ultrices, orci arcu scelerisque magna, id facilisis mauris arcu ut turpis. Vestibulum consectetur faucibus ante, eu posuere quam ornare et. Aenean vitae dictum neque. Donec nisl justo, porta a sapien quis, luctus congue diam. Integer id metus dolor. Maecenas euismod vulputate leo in lobortis. Vestibulum dignissim finibus est, sed sollicitudin ipsum hendrerit ac. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque diam lorem, mattis vel orci interdum, tempor luctus elit. Ut id porta nisi. In dignissim quam urna, et iaculis lectus eleifend ut. Nam vitae felis ac risus tincidunt elementum. Nunc hendrerit augue a nulla hendrerit rutrum. Integer euismod est at orci eleifend, sed laoreet justo auctor. Sed sem orci, imperdiet at erat non, vehicula convallis libero. Aenean hendrerit cursus leo ut malesuada. Donec eu placerat lorem. Sed mattis tristique lorem, eget placerat erat scelerisque faucibus. Vivamus eleifend in augue id mollis. Nulla vehicula, metus eu auctor accumsan, lectus sapien pretium dui, non scelerisque magna augue a sem. Suspendisse sem enim, mattis ac augue non, placerat accumsan sem. Vivamus hendrerit, sapien sit amet consectetur pulvinar, ante nisl pulvinar purus, a ullamcorper dolor leo id arcu. Aliquam sed metus arcu. Quisque erat libero, tincidunt non dictum vel, bibendum ut ante. Nunc vel imperdiet risus. Sed sit amet porta enim. Mauris metus tortor, mattis vitae convallis vitae, dictum nec dui. Aliquam volutpat nisi consequat, gravida tellus eget, cursus purus. Nunc at venenatis enim. Proin dictum, magna ultrices tempor aliquam, metus lacus consectetur odio, quis pharetra massa est at est. Nullam non nibh massa. Duis scelerisque massa a luctus vehicula. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec tortor lacus, consequat eget neque sit amet, imperdiet porttitor felis. Duis ante erat, cursus sed venenatis nec, semper sollicitudin felis. Sed tincidunt et tortor quis vehicula. Morbi porta dapibus quam quis iaculis. Nunc mauris dolor, rutrum non pellentesque consectetur, ornare quis lacus. Maecenas eget feugiat odio. Proin vitae magna ut justo bibendum lacinia consequat at orci. Phasellus tincidunt lorem eu justo mollis sagittis. Maecenas fermentum nunc augue, et bibendum augue varius venenatis. Donec eu purus at tellus ullamcorper imperdiet. Duis id orci laoreet, semper eros et, tincidunt nisl. Suspendisse vehicula sed enim ut dignissim. Nam ornare leo eu nibh malesuada, eget ullamcorper sapien egestas. In at commod');
|
|
412
444
|
});
|
|
413
445
|
});
|
|
414
446
|
|
|
@@ -558,9 +590,7 @@ describe('SCORM 2004 API Tests', () => {
|
|
|
558
590
|
'cmi.interactions.0.objectives.0.correct_responses.0.pattern': 'CPR',
|
|
559
591
|
}, '');
|
|
560
592
|
scorm2004API.lmsInitialize();
|
|
561
|
-
expect(scorm2004API.lmsGetValue('cmi.interactions.0.id')).
|
|
562
|
-
to.
|
|
563
|
-
eq('Question14_1');
|
|
593
|
+
expect(scorm2004API.lmsGetValue('cmi.interactions.0.id')).to.eq('Question14_1');
|
|
564
594
|
});
|
|
565
595
|
});
|
|
566
596
|
|
package/webpack.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const webpack = require('webpack');
|
|
3
|
+
const ESLintPlugin = require('eslint-webpack-plugin');
|
|
4
|
+
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
|
5
|
+
|
|
6
|
+
const JSLoader = {
|
|
7
|
+
test: /\.js$/i,
|
|
8
|
+
use: {
|
|
9
|
+
loader: 'babel-loader',
|
|
10
|
+
options: {
|
|
11
|
+
presets: [
|
|
12
|
+
[
|
|
13
|
+
'@babel/preset-env',
|
|
14
|
+
{
|
|
15
|
+
'corejs': '3',
|
|
16
|
+
'useBuiltIns': 'entry',
|
|
17
|
+
'targets': {
|
|
18
|
+
'browsers': [
|
|
19
|
+
'edge >= 16',
|
|
20
|
+
'safari >= 9',
|
|
21
|
+
'firefox >= 57',
|
|
22
|
+
'ie >= 11',
|
|
23
|
+
'ios >= 9',
|
|
24
|
+
'chrome >= 49',
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
['@babel/preset-flow'],
|
|
30
|
+
],
|
|
31
|
+
plugins: [
|
|
32
|
+
'@babel/plugin-proposal-class-properties',
|
|
33
|
+
'@babel/plugin-proposal-private-methods',
|
|
34
|
+
'@babel/plugin-proposal-optional-chaining',
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
mode: 'development',
|
|
42
|
+
devtool: 'source-map',
|
|
43
|
+
entry: {
|
|
44
|
+
'aicc': './src/exports/aicc.js',
|
|
45
|
+
'scorm12': './src/exports/scorm12.js',
|
|
46
|
+
'scorm2004': './src/exports/scorm2004.js',
|
|
47
|
+
'scorm-again': './src/exports/scorm-again.js',
|
|
48
|
+
'aicc.min': './src/exports/aicc.js',
|
|
49
|
+
'scorm12.min': './src/exports/scorm12.js',
|
|
50
|
+
'scorm2004.min': './src/exports/scorm2004.js',
|
|
51
|
+
'scorm-again.min': './src/exports/scorm-again.js',
|
|
52
|
+
},
|
|
53
|
+
target: ['web', 'es5'],
|
|
54
|
+
module: {
|
|
55
|
+
rules: [
|
|
56
|
+
JSLoader,
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
output: {
|
|
60
|
+
path: path.resolve(__dirname, 'dist'),
|
|
61
|
+
environment: {
|
|
62
|
+
arrowFunction: false,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
optimization: {
|
|
66
|
+
minimize: true,
|
|
67
|
+
minimizer: [new UglifyJsPlugin({
|
|
68
|
+
include: /\.min\.js$/,
|
|
69
|
+
})],
|
|
70
|
+
},
|
|
71
|
+
plugins: [
|
|
72
|
+
new ESLintPlugin({
|
|
73
|
+
overrideConfigFile: path.resolve(__dirname, '.eslintrc.js'),
|
|
74
|
+
context: path.resolve(__dirname, '../src'),
|
|
75
|
+
files: '**/*.js',
|
|
76
|
+
}),
|
|
77
|
+
],
|
|
78
|
+
};
|
package/gruntfile.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
module.exports = function(grunt) {
|
|
2
|
-
grunt.initConfig({
|
|
3
|
-
mochaTest: {
|
|
4
|
-
test: {
|
|
5
|
-
options: {
|
|
6
|
-
reporter: 'list',
|
|
7
|
-
require: '@babel/register',
|
|
8
|
-
noFail: false,
|
|
9
|
-
recursive: true,
|
|
10
|
-
captureFile: false,
|
|
11
|
-
},
|
|
12
|
-
src: ['test/**/*.spec.js'],
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
watch: {
|
|
16
|
-
scripts: {
|
|
17
|
-
files: ['src/**/*.js'],
|
|
18
|
-
tasks: ['default'],
|
|
19
|
-
options: {
|
|
20
|
-
spawn: false,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
browserify: {
|
|
25
|
-
development: {
|
|
26
|
-
files: [{
|
|
27
|
-
expand: true,
|
|
28
|
-
cwd: 'src/exports/',
|
|
29
|
-
src: ['*.js'],
|
|
30
|
-
dest: 'dist/',
|
|
31
|
-
ext: '.js',
|
|
32
|
-
extDot: 'first',
|
|
33
|
-
}],
|
|
34
|
-
options: {
|
|
35
|
-
browserifyOptions: {debug: true},
|
|
36
|
-
transform: [
|
|
37
|
-
[
|
|
38
|
-
'babelify', {
|
|
39
|
-
'presets': ['@babel/preset-env', '@babel/preset-flow'],
|
|
40
|
-
'plugins': [
|
|
41
|
-
'@babel/plugin-proposal-class-properties',
|
|
42
|
-
'@babel/plugin-proposal-private-methods',
|
|
43
|
-
'@babel/plugin-proposal-optional-chaining',
|
|
44
|
-
],
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
production: {
|
|
51
|
-
files: [{
|
|
52
|
-
expand: true,
|
|
53
|
-
cwd: 'src/exports/',
|
|
54
|
-
src: ['*.js'],
|
|
55
|
-
dest: 'dist/',
|
|
56
|
-
ext: '.min.js',
|
|
57
|
-
extDot: 'first',
|
|
58
|
-
}],
|
|
59
|
-
options: {
|
|
60
|
-
browserifyOptions: {debug: false},
|
|
61
|
-
transform: [
|
|
62
|
-
[
|
|
63
|
-
'babelify', {
|
|
64
|
-
'presets': ['@babel/preset-env', '@babel/preset-flow'],
|
|
65
|
-
'plugins': [
|
|
66
|
-
'@babel/plugin-proposal-class-properties',
|
|
67
|
-
'@babel/plugin-proposal-private-methods',
|
|
68
|
-
'@babel/plugin-proposal-optional-chaining',
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
'uglifyify', {
|
|
72
|
-
sourceMap: true,
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
grunt.loadNpmTasks('grunt-browserify');
|
|
83
|
-
grunt.loadNpmTasks('grunt-mocha-test');
|
|
84
|
-
grunt.loadNpmTasks('grunt-contrib-watch');
|
|
85
|
-
|
|
86
|
-
grunt.registerTask('test', 'mochaTest');
|
|
87
|
-
|
|
88
|
-
grunt.registerTask('default',
|
|
89
|
-
['browserify:development', 'browserify:production']);
|
|
90
|
-
};
|