scorm-again 1.5.3 → 1.7.0
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/.run/Mocha Unit Tests.run.xml +14 -0
- package/.run/compile.run.xml +12 -0
- package/README.md +12 -3
- package/dist/aicc.js +7362 -0
- package/dist/aicc.js.map +1 -0
- package/dist/aicc.min.js +40 -0
- package/dist/scorm-again.js +1353 -1006
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +52 -41
- package/dist/scorm12.js +5610 -0
- package/dist/scorm12.js.map +1 -0
- package/dist/scorm12.min.js +34 -0
- package/dist/scorm2004.js +7011 -0
- package/dist/scorm2004.js.map +1 -0
- package/dist/scorm2004.min.js +40 -0
- package/package.json +36 -28
- package/src/BaseAPI.js +71 -39
- package/src/Scorm12API.js +8 -15
- package/src/Scorm2004API.js +5 -8
- package/src/cmi/aicc_cmi.js +73 -35
- package/src/cmi/common.js +27 -21
- package/src/cmi/scorm12_cmi.js +24 -8
- package/src/cmi/scorm2004_cmi.js +67 -47
- package/src/constants/api_constants.js +8 -0
- package/src/constants/response_constants.js +2 -2
- package/src/exceptions.js +77 -6
- package/src/exports/aicc.js +3 -0
- package/src/exports/scorm-again.js +7 -0
- package/src/exports/scorm12.js +3 -0
- package/src/exports/scorm2004.js +3 -0
- package/test/Scorm2004API.spec.js +37 -7
- package/test/api_helpers.js +4 -4
- package/test/cmi_helpers.js +3 -3
- package/test/exceptions.spec.js +59 -4
- package/webpack.js +78 -0
- package/gruntfile.js +0 -87
- package/src/exports.js +0 -7
package/src/cmi/scorm2004_cmi.js
CHANGED
|
@@ -10,7 +10,7 @@ import APIConstants from '../constants/api_constants';
|
|
|
10
10
|
import Regex from '../constants/regex';
|
|
11
11
|
import ErrorCodes from '../constants/error_codes';
|
|
12
12
|
import Responses from '../constants/response_constants';
|
|
13
|
-
import {
|
|
13
|
+
import {Scorm2004ValidationError} from '../exceptions';
|
|
14
14
|
import * as Util from '../utilities';
|
|
15
15
|
|
|
16
16
|
const scorm2004_constants = APIConstants.scorm2004;
|
|
@@ -23,21 +23,35 @@ const scorm2004_regex = Regex.scorm2004;
|
|
|
23
23
|
* Helper method for throwing Read Only error
|
|
24
24
|
*/
|
|
25
25
|
function throwReadOnlyError() {
|
|
26
|
-
throw new
|
|
26
|
+
throw new Scorm2004ValidationError(scorm2004_error_codes.READ_ONLY_ELEMENT);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Helper method for throwing Write Only error
|
|
31
31
|
*/
|
|
32
32
|
function throwWriteOnlyError() {
|
|
33
|
-
throw new
|
|
33
|
+
throw new Scorm2004ValidationError(scorm2004_error_codes.WRITE_ONLY_ELEMENT);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Helper method for throwing Type Mismatch error
|
|
38
38
|
*/
|
|
39
39
|
function throwTypeMismatchError() {
|
|
40
|
-
throw new
|
|
40
|
+
throw new Scorm2004ValidationError(scorm2004_error_codes.TYPE_MISMATCH);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Helper method for throwing Dependency Not Established error
|
|
45
|
+
*/
|
|
46
|
+
function throwDependencyNotEstablishedError() {
|
|
47
|
+
throw new Scorm2004ValidationError(scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Helper method for throwing Dependency Not Established error
|
|
52
|
+
*/
|
|
53
|
+
function throwGeneralSetError() {
|
|
54
|
+
throw new Scorm2004ValidationError(scorm2004_error_codes.GENERAL_SET_FAILURE);
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
/**
|
|
@@ -51,8 +65,13 @@ function check2004ValidFormat(
|
|
|
51
65
|
value: String,
|
|
52
66
|
regexPattern: String,
|
|
53
67
|
allowEmptyString?: boolean) {
|
|
54
|
-
return checkValidFormat(
|
|
55
|
-
|
|
68
|
+
return checkValidFormat(
|
|
69
|
+
value,
|
|
70
|
+
regexPattern,
|
|
71
|
+
scorm2004_error_codes.TYPE_MISMATCH,
|
|
72
|
+
Scorm2004ValidationError,
|
|
73
|
+
allowEmptyString,
|
|
74
|
+
);
|
|
56
75
|
}
|
|
57
76
|
|
|
58
77
|
/**
|
|
@@ -62,8 +81,12 @@ function check2004ValidFormat(
|
|
|
62
81
|
* @return {boolean}
|
|
63
82
|
*/
|
|
64
83
|
function check2004ValidRange(value: any, rangePattern: String) {
|
|
65
|
-
return checkValidRange(
|
|
66
|
-
|
|
84
|
+
return checkValidRange(
|
|
85
|
+
value,
|
|
86
|
+
rangePattern,
|
|
87
|
+
scorm2004_error_codes.VALUE_OUT_OF_RANGE,
|
|
88
|
+
Scorm2004ValidationError,
|
|
89
|
+
);
|
|
67
90
|
}
|
|
68
91
|
|
|
69
92
|
/**
|
|
@@ -189,8 +212,8 @@ export class CMI extends BaseCMI {
|
|
|
189
212
|
*/
|
|
190
213
|
set completion_threshold(completion_threshold) {
|
|
191
214
|
!this.initialized ?
|
|
192
|
-
|
|
193
|
-
|
|
215
|
+
this.#completion_threshold = completion_threshold :
|
|
216
|
+
throwReadOnlyError();
|
|
194
217
|
}
|
|
195
218
|
|
|
196
219
|
/**
|
|
@@ -289,8 +312,8 @@ export class CMI extends BaseCMI {
|
|
|
289
312
|
*/
|
|
290
313
|
set learner_name(learner_name) {
|
|
291
314
|
!this.initialized ?
|
|
292
|
-
|
|
293
|
-
|
|
315
|
+
this.#learner_name = learner_name :
|
|
316
|
+
throwReadOnlyError();
|
|
294
317
|
}
|
|
295
318
|
|
|
296
319
|
/**
|
|
@@ -325,8 +348,8 @@ export class CMI extends BaseCMI {
|
|
|
325
348
|
*/
|
|
326
349
|
set max_time_allowed(max_time_allowed) {
|
|
327
350
|
!this.initialized ?
|
|
328
|
-
|
|
329
|
-
|
|
351
|
+
this.#max_time_allowed = max_time_allowed :
|
|
352
|
+
throwReadOnlyError();
|
|
330
353
|
}
|
|
331
354
|
|
|
332
355
|
/**
|
|
@@ -359,7 +382,7 @@ export class CMI extends BaseCMI {
|
|
|
359
382
|
*/
|
|
360
383
|
set progress_measure(progress_measure) {
|
|
361
384
|
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
|
|
362
|
-
|
|
385
|
+
check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) {
|
|
363
386
|
this.#progress_measure = progress_measure;
|
|
364
387
|
}
|
|
365
388
|
}
|
|
@@ -378,8 +401,8 @@ export class CMI extends BaseCMI {
|
|
|
378
401
|
*/
|
|
379
402
|
set scaled_passing_score(scaled_passing_score) {
|
|
380
403
|
!this.initialized ?
|
|
381
|
-
|
|
382
|
-
|
|
404
|
+
this.#scaled_passing_score = scaled_passing_score :
|
|
405
|
+
throwReadOnlyError();
|
|
383
406
|
}
|
|
384
407
|
|
|
385
408
|
/**
|
|
@@ -451,8 +474,8 @@ export class CMI extends BaseCMI {
|
|
|
451
474
|
*/
|
|
452
475
|
set time_limit_action(time_limit_action) {
|
|
453
476
|
!this.initialized ?
|
|
454
|
-
|
|
455
|
-
|
|
477
|
+
this.#time_limit_action = time_limit_action :
|
|
478
|
+
throwReadOnlyError();
|
|
456
479
|
}
|
|
457
480
|
|
|
458
481
|
/**
|
|
@@ -604,7 +627,7 @@ class CMILearnerPreference extends BaseCMI {
|
|
|
604
627
|
*/
|
|
605
628
|
set audio_level(audio_level) {
|
|
606
629
|
if (check2004ValidFormat(audio_level, scorm2004_regex.CMIDecimal) &&
|
|
607
|
-
|
|
630
|
+
check2004ValidRange(audio_level, scorm2004_regex.audio_range)) {
|
|
608
631
|
this.#audio_level = audio_level;
|
|
609
632
|
}
|
|
610
633
|
}
|
|
@@ -641,7 +664,7 @@ class CMILearnerPreference extends BaseCMI {
|
|
|
641
664
|
*/
|
|
642
665
|
set delivery_speed(delivery_speed) {
|
|
643
666
|
if (check2004ValidFormat(delivery_speed, scorm2004_regex.CMIDecimal) &&
|
|
644
|
-
|
|
667
|
+
check2004ValidRange(delivery_speed, scorm2004_regex.speed_range)) {
|
|
645
668
|
this.#delivery_speed = delivery_speed;
|
|
646
669
|
}
|
|
647
670
|
}
|
|
@@ -660,7 +683,7 @@ class CMILearnerPreference extends BaseCMI {
|
|
|
660
683
|
*/
|
|
661
684
|
set audio_captioning(audio_captioning) {
|
|
662
685
|
if (check2004ValidFormat(audio_captioning, scorm2004_regex.CMISInteger) &&
|
|
663
|
-
|
|
686
|
+
check2004ValidRange(audio_captioning, scorm2004_regex.text_range)) {
|
|
664
687
|
this.#audio_captioning = audio_captioning;
|
|
665
688
|
}
|
|
666
689
|
}
|
|
@@ -701,6 +724,7 @@ class CMIInteractions extends CMIArray {
|
|
|
701
724
|
super({
|
|
702
725
|
children: scorm2004_constants.interactions_children,
|
|
703
726
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
727
|
+
errorClass: Scorm2004ValidationError,
|
|
704
728
|
});
|
|
705
729
|
}
|
|
706
730
|
}
|
|
@@ -716,6 +740,7 @@ class CMIObjectives extends CMIArray {
|
|
|
716
740
|
super({
|
|
717
741
|
children: scorm2004_constants.objectives_children,
|
|
718
742
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
743
|
+
errorClass: Scorm2004ValidationError,
|
|
719
744
|
});
|
|
720
745
|
}
|
|
721
746
|
}
|
|
@@ -731,6 +756,7 @@ class CMICommentsFromLMS extends CMIArray {
|
|
|
731
756
|
super({
|
|
732
757
|
children: scorm2004_constants.comments_children,
|
|
733
758
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
759
|
+
errorClass: Scorm2004ValidationError,
|
|
734
760
|
});
|
|
735
761
|
}
|
|
736
762
|
}
|
|
@@ -746,6 +772,7 @@ class CMICommentsFromLearner extends CMIArray {
|
|
|
746
772
|
super({
|
|
747
773
|
children: scorm2004_constants.comments_children,
|
|
748
774
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
775
|
+
errorClass: Scorm2004ValidationError,
|
|
749
776
|
});
|
|
750
777
|
}
|
|
751
778
|
}
|
|
@@ -771,10 +798,12 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
771
798
|
|
|
772
799
|
this.objectives = new CMIArray({
|
|
773
800
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
801
|
+
errorClass: Scorm2004ValidationError,
|
|
774
802
|
children: scorm2004_constants.objectives_children,
|
|
775
803
|
});
|
|
776
804
|
this.correct_responses = new CMIArray({
|
|
777
805
|
errorCode: scorm2004_error_codes.READ_ONLY_ELEMENT,
|
|
806
|
+
errorClass: Scorm2004ValidationError,
|
|
778
807
|
children: scorm2004_constants.correct_responses_children,
|
|
779
808
|
});
|
|
780
809
|
}
|
|
@@ -820,8 +849,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
820
849
|
*/
|
|
821
850
|
set type(type) {
|
|
822
851
|
if (this.initialized && this.#id === '') {
|
|
823
|
-
|
|
824
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
852
|
+
throwDependencyNotEstablishedError();
|
|
825
853
|
} else {
|
|
826
854
|
if (check2004ValidFormat(type, scorm2004_regex.CMIType)) {
|
|
827
855
|
this.#type = type;
|
|
@@ -843,8 +871,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
843
871
|
*/
|
|
844
872
|
set timestamp(timestamp) {
|
|
845
873
|
if (this.initialized && this.#id === '') {
|
|
846
|
-
|
|
847
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
874
|
+
throwDependencyNotEstablishedError();
|
|
848
875
|
} else {
|
|
849
876
|
if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) {
|
|
850
877
|
this.#timestamp = timestamp;
|
|
@@ -866,8 +893,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
866
893
|
*/
|
|
867
894
|
set weighting(weighting) {
|
|
868
895
|
if (this.initialized && this.#id === '') {
|
|
869
|
-
|
|
870
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
896
|
+
throwDependencyNotEstablishedError();
|
|
871
897
|
} else {
|
|
872
898
|
if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) {
|
|
873
899
|
this.#weighting = weighting;
|
|
@@ -890,8 +916,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
890
916
|
*/
|
|
891
917
|
set learner_response(learner_response) {
|
|
892
918
|
if (this.initialized && (this.#type === '' || this.#id === '')) {
|
|
893
|
-
|
|
894
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
919
|
+
throwDependencyNotEstablishedError();
|
|
895
920
|
} else {
|
|
896
921
|
let nodes = [];
|
|
897
922
|
const response_type = learner_responses[this.type];
|
|
@@ -933,12 +958,12 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
933
958
|
}
|
|
934
959
|
}
|
|
935
960
|
} else {
|
|
936
|
-
|
|
961
|
+
throwGeneralSetError();
|
|
937
962
|
}
|
|
938
963
|
|
|
939
964
|
this.#learner_response = learner_response;
|
|
940
965
|
} else {
|
|
941
|
-
|
|
966
|
+
throwTypeMismatchError();
|
|
942
967
|
}
|
|
943
968
|
}
|
|
944
969
|
}
|
|
@@ -975,8 +1000,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
975
1000
|
*/
|
|
976
1001
|
set latency(latency) {
|
|
977
1002
|
if (this.initialized && this.#id === '') {
|
|
978
|
-
|
|
979
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1003
|
+
throwDependencyNotEstablishedError();
|
|
980
1004
|
} else {
|
|
981
1005
|
if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) {
|
|
982
1006
|
this.#latency = latency;
|
|
@@ -998,8 +1022,7 @@ export class CMIInteractionsObject extends BaseCMI {
|
|
|
998
1022
|
*/
|
|
999
1023
|
set description(description) {
|
|
1000
1024
|
if (this.initialized && this.#id === '') {
|
|
1001
|
-
|
|
1002
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1025
|
+
throwDependencyNotEstablishedError();
|
|
1003
1026
|
} else {
|
|
1004
1027
|
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
|
|
1005
1028
|
true)) {
|
|
@@ -1104,8 +1127,7 @@ export class CMIObjectivesObject extends BaseCMI {
|
|
|
1104
1127
|
*/
|
|
1105
1128
|
set success_status(success_status) {
|
|
1106
1129
|
if (this.initialized && this.#id === '') {
|
|
1107
|
-
|
|
1108
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1130
|
+
throwDependencyNotEstablishedError();
|
|
1109
1131
|
} else {
|
|
1110
1132
|
if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) {
|
|
1111
1133
|
this.#success_status = success_status;
|
|
@@ -1127,8 +1149,7 @@ export class CMIObjectivesObject extends BaseCMI {
|
|
|
1127
1149
|
*/
|
|
1128
1150
|
set completion_status(completion_status) {
|
|
1129
1151
|
if (this.initialized && this.#id === '') {
|
|
1130
|
-
|
|
1131
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1152
|
+
throwDependencyNotEstablishedError();
|
|
1132
1153
|
} else {
|
|
1133
1154
|
if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) {
|
|
1134
1155
|
this.#completion_status = completion_status;
|
|
@@ -1150,12 +1171,11 @@ export class CMIObjectivesObject extends BaseCMI {
|
|
|
1150
1171
|
*/
|
|
1151
1172
|
set progress_measure(progress_measure) {
|
|
1152
1173
|
if (this.initialized && this.#id === '') {
|
|
1153
|
-
|
|
1154
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1174
|
+
throwDependencyNotEstablishedError();
|
|
1155
1175
|
} else {
|
|
1156
1176
|
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
|
|
1157
|
-
|
|
1158
|
-
|
|
1177
|
+
check2004ValidRange(progress_measure,
|
|
1178
|
+
scorm2004_regex.progress_range)) {
|
|
1159
1179
|
this.#progress_measure = progress_measure;
|
|
1160
1180
|
}
|
|
1161
1181
|
}
|
|
@@ -1175,8 +1195,7 @@ export class CMIObjectivesObject extends BaseCMI {
|
|
|
1175
1195
|
*/
|
|
1176
1196
|
set description(description) {
|
|
1177
1197
|
if (this.initialized && this.#id === '') {
|
|
1178
|
-
|
|
1179
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
|
|
1198
|
+
throwDependencyNotEstablishedError();
|
|
1180
1199
|
} else {
|
|
1181
1200
|
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
|
|
1182
1201
|
true)) {
|
|
@@ -1232,6 +1251,7 @@ class Scorm2004CMIScore extends CMIScore {
|
|
|
1232
1251
|
invalidTypeCode: scorm2004_error_codes.TYPE_MISMATCH,
|
|
1233
1252
|
invalidRangeCode: scorm2004_error_codes.VALUE_OUT_OF_RANGE,
|
|
1234
1253
|
decimalRegex: scorm2004_regex.CMIDecimal,
|
|
1254
|
+
errorClass: Scorm2004ValidationError,
|
|
1235
1255
|
});
|
|
1236
1256
|
}
|
|
1237
1257
|
|
|
@@ -1249,7 +1269,7 @@ class Scorm2004CMIScore extends CMIScore {
|
|
|
1249
1269
|
*/
|
|
1250
1270
|
set scaled(scaled) {
|
|
1251
1271
|
if (check2004ValidFormat(scaled, scorm2004_regex.CMIDecimal) &&
|
|
1252
|
-
|
|
1272
|
+
check2004ValidRange(scaled, scorm2004_regex.scaled_range)) {
|
|
1253
1273
|
this.#scaled = scaled;
|
|
1254
1274
|
}
|
|
1255
1275
|
}
|
|
@@ -66,6 +66,14 @@ const scorm12 = {
|
|
|
66
66
|
basicMessage: 'Incorrect Data Type',
|
|
67
67
|
detailMessage: 'LMSSetValue was called with a value that is not consistent with the data format of the supplied data model element.',
|
|
68
68
|
},
|
|
69
|
+
'407': {
|
|
70
|
+
basicMessage: 'Element Value Out Of Range',
|
|
71
|
+
detailMessage: 'The numeric value supplied to a LMSSetValue call is outside of the numeric range allowed for the supplied data model element.',
|
|
72
|
+
},
|
|
73
|
+
'408': {
|
|
74
|
+
basicMessage: 'Data Model Dependency Not Established',
|
|
75
|
+
detailMessage: 'Some data model elements cannot be set until another data model element was set. This error condition indicates that the prerequisite element was not set before the dependent element.',
|
|
76
|
+
},
|
|
69
77
|
},
|
|
70
78
|
};
|
|
71
79
|
|
|
@@ -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,
|
package/src/exceptions.js
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
+
import APIConstants from './constants/api_constants';
|
|
4
|
+
|
|
5
|
+
const scorm12_errors = APIConstants.scorm12.error_descriptions;
|
|
6
|
+
const aicc_errors = APIConstants.aicc.error_descriptions;
|
|
7
|
+
const scorm2004_errors = APIConstants.scorm2004.error_descriptions;
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
|
-
*
|
|
10
|
+
* Base Validation Exception
|
|
5
11
|
*/
|
|
6
12
|
export class ValidationError extends Error {
|
|
7
13
|
/**
|
|
8
14
|
* Constructor to take in an error message and code
|
|
9
15
|
* @param {number} errorCode
|
|
16
|
+
* @param {string} errorMessage
|
|
17
|
+
* @param {string} detailedMessage
|
|
10
18
|
*/
|
|
11
|
-
constructor(errorCode: number) {
|
|
12
|
-
super(
|
|
19
|
+
constructor(errorCode: number, errorMessage: String, detailedMessage: String) {
|
|
20
|
+
super(errorMessage);
|
|
13
21
|
this.#errorCode = errorCode;
|
|
22
|
+
this.#errorMessage = errorMessage;
|
|
23
|
+
this.#detailedMessage = detailedMessage;
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
#errorCode;
|
|
27
|
+
#errorMessage;
|
|
28
|
+
#detailedMessage;
|
|
17
29
|
|
|
18
30
|
/**
|
|
19
31
|
* Getter for #errorCode
|
|
@@ -24,10 +36,69 @@ export class ValidationError extends Error {
|
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
/**
|
|
27
|
-
*
|
|
39
|
+
* Getter for #errorMessage
|
|
28
40
|
* @return {string}
|
|
29
41
|
*/
|
|
30
|
-
get
|
|
31
|
-
return this.#
|
|
42
|
+
get errorMessage() {
|
|
43
|
+
return this.#errorMessage;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Getter for #detailedMessage
|
|
48
|
+
* @return {string}
|
|
49
|
+
*/
|
|
50
|
+
get detailedMessage() {
|
|
51
|
+
return this.#detailedMessage;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* SCORM 1.2 Validation Error
|
|
57
|
+
*/
|
|
58
|
+
export class Scorm12ValidationError extends ValidationError {
|
|
59
|
+
/**
|
|
60
|
+
* Constructor to take in an error code
|
|
61
|
+
* @param {number} errorCode
|
|
62
|
+
*/
|
|
63
|
+
constructor(errorCode: number) {
|
|
64
|
+
if ({}.hasOwnProperty.call(scorm12_errors, String(errorCode))) {
|
|
65
|
+
super(errorCode, scorm12_errors[String(errorCode)].basicMessage, scorm12_errors[String(errorCode)].detailMessage);
|
|
66
|
+
} else {
|
|
67
|
+
super(101, scorm12_errors['101'].basicMessage, scorm12_errors['101'].detailMessage);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* AICC Validation Error
|
|
74
|
+
*/
|
|
75
|
+
export class AICCValidationError extends ValidationError {
|
|
76
|
+
/**
|
|
77
|
+
* Constructor to take in an error code
|
|
78
|
+
* @param {number} errorCode
|
|
79
|
+
*/
|
|
80
|
+
constructor(errorCode: number) {
|
|
81
|
+
if ({}.hasOwnProperty.call(aicc_errors, String(errorCode))) {
|
|
82
|
+
super(errorCode, aicc_errors[String(errorCode)].basicMessage, aicc_errors[String(errorCode)].detailMessage);
|
|
83
|
+
} else {
|
|
84
|
+
super(101, aicc_errors['101'].basicMessage, aicc_errors['101'].detailMessage);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* SCORM 2004 Validation Error
|
|
91
|
+
*/
|
|
92
|
+
export class Scorm2004ValidationError extends ValidationError {
|
|
93
|
+
/**
|
|
94
|
+
* Constructor to take in an error code
|
|
95
|
+
* @param {number} errorCode
|
|
96
|
+
*/
|
|
97
|
+
constructor(errorCode: number) {
|
|
98
|
+
if ({}.hasOwnProperty.call(scorm2004_errors, String(errorCode))) {
|
|
99
|
+
super(errorCode, scorm2004_errors[String(errorCode)].basicMessage, scorm2004_errors[String(errorCode)].detailMessage);
|
|
100
|
+
} else {
|
|
101
|
+
super(101, scorm2004_errors['101'].basicMessage, scorm2004_errors['101'].detailMessage);
|
|
102
|
+
}
|
|
32
103
|
}
|
|
33
104
|
}
|
|
@@ -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/test/api_helpers.js
CHANGED
|
@@ -45,7 +45,7 @@ export const checkLMSSetValue = (
|
|
|
45
45
|
if (expectedError > 0) {
|
|
46
46
|
if (errorThrown) {
|
|
47
47
|
expect(() => api.lmsSetValue(fieldName, valueToTest)).
|
|
48
|
-
to.throw(
|
|
48
|
+
to.throw().with.property('errorCode', expectedError);
|
|
49
49
|
} else {
|
|
50
50
|
api.lmsSetValue(fieldName, valueToTest);
|
|
51
51
|
expect(String(api.lmsGetLastError())).to.equal(String(expectedError));
|
|
@@ -71,7 +71,7 @@ export const checkLMSGetValue = (
|
|
|
71
71
|
initializeFirst = false,
|
|
72
72
|
initializationValue = '',
|
|
73
73
|
expectedError = 0,
|
|
74
|
-
errorThrown =
|
|
74
|
+
errorThrown = false,
|
|
75
75
|
}) => {
|
|
76
76
|
describe(`Field: ${fieldName}`, () => {
|
|
77
77
|
const status = expectedError > 0 ? 'fail to' : 'successfully';
|
|
@@ -84,7 +84,7 @@ export const checkLMSGetValue = (
|
|
|
84
84
|
if (expectedError > 0) {
|
|
85
85
|
if (errorThrown) {
|
|
86
86
|
expect(() => api.lmsGetValue(fieldName)).
|
|
87
|
-
to.throw(
|
|
87
|
+
to.throw().with.property('errorCode', expectedError);
|
|
88
88
|
} else {
|
|
89
89
|
api.lmsGetValue(fieldName);
|
|
90
90
|
expect(String(api.lmsGetLastError())).to.equal(String(expectedError));
|
|
@@ -110,7 +110,7 @@ export const checkSetCMIValue = (
|
|
|
110
110
|
if (expectedError > 0) {
|
|
111
111
|
if (errorThrown) {
|
|
112
112
|
expect(() => api.setCMIValue(fieldName, valueToTest)).
|
|
113
|
-
to.throw(
|
|
113
|
+
to.throw().with.property('errorCode', expectedError);
|
|
114
114
|
} else {
|
|
115
115
|
api.setCMIValue(fieldName, valueToTest);
|
|
116
116
|
expect(String(api.lmsGetLastError())).to.equal(String(expectedError));
|
package/test/cmi_helpers.js
CHANGED
|
@@ -23,7 +23,7 @@ export const checkFieldConstraintSize = (
|
|
|
23
23
|
it(`Should fail to write more than ${limit} characters to ${fieldName}`,
|
|
24
24
|
() => {
|
|
25
25
|
expect(() => eval(`${fieldName} = 'x'.repeat(${limit + 1})`)).
|
|
26
|
-
to.throw(
|
|
26
|
+
to.throw().with.property('errorCode', expectedError);
|
|
27
27
|
});
|
|
28
28
|
});
|
|
29
29
|
};
|
|
@@ -42,7 +42,7 @@ export const checkReadOnly = (
|
|
|
42
42
|
|
|
43
43
|
it(`Should fail to write to ${fieldName}`, () => {
|
|
44
44
|
expect(() => eval(`${fieldName} = 'xxx'`)).
|
|
45
|
-
to.throw(
|
|
45
|
+
to.throw().with.property('errorCode', expectedError);
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
};
|
|
@@ -89,7 +89,7 @@ export const checkWriteOnly = (
|
|
|
89
89
|
describe(`Field: ${fieldName}`, () => {
|
|
90
90
|
it(`Should fail to read from ${fieldName}`, () => {
|
|
91
91
|
expect(() => eval(`${fieldName}`)).
|
|
92
|
-
to.throw(
|
|
92
|
+
to.throw().with.property('errorCode', expectedError);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it(`Should successfully write to ${fieldName}`, () => {
|