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.
@@ -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 {ValidationError} from '../exceptions';
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 ValidationError(scorm2004_error_codes.READ_ONLY_ELEMENT);
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 ValidationError(scorm2004_error_codes.WRITE_ONLY_ELEMENT);
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 ValidationError(scorm2004_error_codes.TYPE_MISMATCH);
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(value, regexPattern,
55
- scorm2004_error_codes.TYPE_MISMATCH, allowEmptyString);
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(value, rangePattern,
66
- scorm2004_error_codes.VALUE_OUT_OF_RANGE);
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
- this.#completion_threshold = completion_threshold :
193
- throwReadOnlyError();
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
- this.#learner_name = learner_name :
293
- throwReadOnlyError();
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
- this.#max_time_allowed = max_time_allowed :
329
- throwReadOnlyError();
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
- check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) {
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
- this.#scaled_passing_score = scaled_passing_score :
382
- throwReadOnlyError();
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
- this.#time_limit_action = time_limit_action :
455
- throwReadOnlyError();
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
- check2004ValidRange(audio_level, scorm2004_regex.audio_range)) {
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
- check2004ValidRange(delivery_speed, scorm2004_regex.speed_range)) {
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
- check2004ValidRange(audio_captioning, scorm2004_regex.text_range)) {
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(scorm2004_error_codes.GENERAL_SET_FAILURE);
961
+ throwGeneralSetError();
937
962
  }
938
963
 
939
964
  this.#learner_response = learner_response;
940
965
  } else {
941
- throw new ValidationError(scorm2004_error_codes.TYPE_MISMATCH);
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(
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
- throw new ValidationError(
1154
- scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
1174
+ throwDependencyNotEstablishedError();
1155
1175
  } else {
1156
1176
  if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
1157
- check2004ValidRange(progress_measure,
1158
- scorm2004_regex.progress_range)) {
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
- throw new ValidationError(
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
- check2004ValidRange(scaled, scorm2004_regex.scaled_range)) {
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.CMIShortIdentifier,
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.CMIShortIdentifier,
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
- * Data Validation Exception
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(errorCode);
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
- * Trying to override the default Error message
39
+ * Getter for #errorMessage
28
40
  * @return {string}
29
41
  */
30
- get message() {
31
- return this.#errorCode + '';
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
  }
@@ -0,0 +1,3 @@
1
+ import AICC from '../AICC';
2
+
3
+ window.AICC = AICC;
@@ -0,0 +1,7 @@
1
+ import Scorm2004API from '../Scorm2004API';
2
+ import Scorm12API from '../Scorm12API';
3
+ import AICC from '../AICC';
4
+
5
+ window.Scorm12API = Scorm12API;
6
+ window.Scorm2004API = Scorm2004API;
7
+ window.AICC = AICC;
@@ -0,0 +1,3 @@
1
+ import Scorm12API from '../Scorm12API';
2
+
3
+ window.Scorm12API = Scorm12API;
@@ -0,0 +1,3 @@
1
+ import Scorm2004API from '../Scorm2004API';
2
+
3
+ window.Scorm2004API = Scorm2004API;
@@ -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
- to.
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
 
@@ -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(String(expectedError));
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 = true,
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(String(expectedError));
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(String(expectedError));
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));
@@ -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(expectedError + '');
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(expectedError + '');
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(expectedError + '');
92
+ to.throw().with.property('errorCode', expectedError);
93
93
  });
94
94
 
95
95
  it(`Should successfully write to ${fieldName}`, () => {