scorm-again 1.7.1 → 2.0.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.
Files changed (85) hide show
  1. package/.babelrc +18 -7
  2. package/.github/dependabot.yml +5 -0
  3. package/.github/workflows/main.yml +79 -0
  4. package/.jsdoc.json +4 -5
  5. package/.mocharc.json +8 -0
  6. package/.run/Mocha Unit Tests.run.xml +5 -2
  7. package/CONTRIBUTING.md +1 -1
  8. package/README.md +14 -1
  9. package/dist/aicc.js +3661 -7170
  10. package/dist/aicc.js.map +1 -1
  11. package/dist/aicc.min.js +2 -40
  12. package/dist/aicc.min.js.map +1 -0
  13. package/dist/scorm-again.js +5671 -10695
  14. package/dist/scorm-again.js.map +1 -1
  15. package/dist/scorm-again.min.js +2 -52
  16. package/dist/scorm-again.min.js.map +1 -0
  17. package/dist/scorm12.js +2871 -5433
  18. package/dist/scorm12.js.map +1 -1
  19. package/dist/scorm12.min.js +2 -34
  20. package/dist/scorm12.min.js.map +1 -0
  21. package/dist/scorm2004.js +3868 -6797
  22. package/dist/scorm2004.js.map +1 -1
  23. package/dist/scorm2004.min.js +2 -40
  24. package/dist/scorm2004.min.js.map +1 -0
  25. package/eslint.config.js +21 -0
  26. package/package.json +72 -34
  27. package/results.json +34254 -0
  28. package/src/{AICC.js → AICC.ts} +27 -21
  29. package/src/BaseAPI.ts +1449 -0
  30. package/src/Scorm12API.ts +360 -0
  31. package/src/{Scorm2004API.js → Scorm2004API.ts} +245 -163
  32. package/src/cmi/aicc_cmi.ts +1248 -0
  33. package/src/cmi/common.ts +411 -0
  34. package/src/cmi/scorm12_cmi.ts +1426 -0
  35. package/src/cmi/scorm2004_cmi.ts +1874 -0
  36. package/src/constants/api_constants.ts +318 -0
  37. package/src/constants/error_codes.ts +88 -0
  38. package/src/constants/language_constants.ts +394 -0
  39. package/src/constants/regex.ts +97 -0
  40. package/src/constants/{response_constants.js → response_constants.ts} +67 -62
  41. package/src/exceptions.ts +133 -0
  42. package/src/exports/aicc.js +1 -1
  43. package/src/exports/scorm-again.js +3 -3
  44. package/src/exports/scorm12.js +1 -1
  45. package/src/exports/scorm2004.js +1 -1
  46. package/src/{utilities.js → utilities.ts} +114 -74
  47. package/tea.yaml +6 -0
  48. package/test/{AICC.spec.js → AICC.spec.ts} +70 -72
  49. package/test/Scorm12API.spec.ts +580 -0
  50. package/test/Scorm2004API.spec.ts +812 -0
  51. package/test/api_helpers.ts +176 -0
  52. package/test/cmi/{aicc_cmi.spec.js → aicc_cmi.spec.ts} +193 -209
  53. package/test/cmi/{scorm12_cmi.spec.js → scorm12_cmi.spec.ts} +251 -269
  54. package/test/cmi/scorm2004_cmi.spec.ts +1031 -0
  55. package/test/cmi_helpers.ts +207 -0
  56. package/test/exceptions.spec.ts +79 -0
  57. package/test/field_values.ts +202 -0
  58. package/test/utilities.spec.ts +322 -0
  59. package/tsconfig.json +18 -0
  60. package/webpack.config.js +65 -0
  61. package/.circleci/config.yml +0 -99
  62. package/.codeclimate.yml +0 -7
  63. package/.eslintrc.js +0 -36
  64. package/src/.flowconfig +0 -11
  65. package/src/BaseAPI.js +0 -1275
  66. package/src/Scorm12API.js +0 -308
  67. package/src/cmi/aicc_cmi.js +0 -1141
  68. package/src/cmi/common.js +0 -328
  69. package/src/cmi/scorm12_cmi.js +0 -1312
  70. package/src/cmi/scorm2004_cmi.js +0 -1692
  71. package/src/constants/api_constants.js +0 -218
  72. package/src/constants/error_codes.js +0 -87
  73. package/src/constants/language_constants.js +0 -76
  74. package/src/constants/regex.js +0 -84
  75. package/src/exceptions.js +0 -104
  76. package/test/Scorm12API.spec.js +0 -528
  77. package/test/Scorm2004API.spec.js +0 -775
  78. package/test/abstract_classes.spec.js +0 -17
  79. package/test/api_helpers.js +0 -128
  80. package/test/cmi/scorm2004_cmi.spec.js +0 -1066
  81. package/test/cmi_helpers.js +0 -161
  82. package/test/exceptions.spec.js +0 -71
  83. package/test/field_values.js +0 -353
  84. package/test/utilities.spec.js +0 -339
  85. package/webpack.js +0 -78
@@ -0,0 +1,812 @@
1
+ import { expect } from "expect";
2
+ import { describe, it, before, after } from "mocha";
3
+ import * as sinon from "sinon";
4
+ import * as h from "./api_helpers";
5
+ import Pretender from "fetch-pretender";
6
+ import ErrorCodes from "../src/constants/error_codes";
7
+ import Scorm2004API from "../src/Scorm2004API";
8
+ import { scorm2004Values } from "./field_values";
9
+ import { DefaultSettings, RefObject, Settings } from "../src/BaseAPI";
10
+
11
+ const scorm2004_error_codes = ErrorCodes.scorm2004;
12
+
13
+ let clock: sinon.SinonFakeTimers;
14
+ const api = (settings?: Settings, startingData: RefObject = {}) => {
15
+ const API = new Scorm2004API(settings);
16
+ API.apiLogLevel = 5;
17
+ if (startingData) {
18
+ API.startingData = startingData;
19
+ }
20
+ return API;
21
+ };
22
+ const apiInitialized = (startingData?: RefObject) => {
23
+ const API = api();
24
+ API.loadFromJSON(startingData ? startingData : {}, "");
25
+ API.lmsInitialize();
26
+ return API;
27
+ };
28
+
29
+ describe("SCORM 2004 API Tests", () => {
30
+ before(() => {
31
+ clock = sinon.useFakeTimers();
32
+
33
+ const server = new Pretender();
34
+ server.post(
35
+ "/scorm2004",
36
+ () => {
37
+ return [200, { "Content-Type": "application/json" }, "{}"];
38
+ },
39
+ false,
40
+ );
41
+
42
+ server.post(
43
+ "/scorm2004/error",
44
+ () => {
45
+ return [500, { "Content-Type": "application/json" }, "{}"];
46
+ },
47
+ false,
48
+ );
49
+ });
50
+
51
+ after(() => {
52
+ clock.restore();
53
+ });
54
+
55
+ describe("SetValue()", () => {
56
+ h.checkValidValues({
57
+ api: apiInitialized(),
58
+ fieldName: "cmi.score.scaled",
59
+ validValues: scorm2004Values.validScaledRange,
60
+ invalidValues: scorm2004Values.invalidScaledRange,
61
+ });
62
+ h.checkValidValues({
63
+ api: apiInitialized(),
64
+ fieldName: "cmi.score.raw",
65
+ validValues: scorm2004Values.validScoreRange,
66
+ invalidValues: scorm2004Values.invalidScoreRange,
67
+ });
68
+ h.checkValidValues({
69
+ api: apiInitialized(),
70
+ fieldName: "cmi.score.min",
71
+ validValues: scorm2004Values.validScoreRange,
72
+ invalidValues: scorm2004Values.invalidScoreRange,
73
+ });
74
+ h.checkValidValues({
75
+ api: apiInitialized(),
76
+ fieldName: "cmi.score.max",
77
+ validValues: scorm2004Values.validScoreRange,
78
+ invalidValues: scorm2004Values.invalidScoreRange,
79
+ });
80
+ });
81
+
82
+ describe("setCMIValue()", () => {
83
+ describe("Invalid Sets - Should Always Fail", () => {
84
+ h.checkSetCMIValue({
85
+ api: api(),
86
+ fieldName: "cmi._version",
87
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
88
+ });
89
+ h.checkSetCMIValue({
90
+ api: api(),
91
+ fieldName: "cmi._children",
92
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
93
+ });
94
+ h.checkSetCMIValue({
95
+ api: api(),
96
+ fieldName: "cmi.comments_from_learner._children",
97
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
98
+ });
99
+ h.checkSetCMIValue({
100
+ api: api(),
101
+ fieldName: "cmi.comments_from_learner._count",
102
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
103
+ });
104
+ h.checkSetCMIValue({
105
+ api: api(),
106
+ fieldName: "cmi.comments_from_lms._children",
107
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
108
+ });
109
+ h.checkSetCMIValue({
110
+ api: api(),
111
+ fieldName: "cmi.comments_from_lms._count",
112
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
113
+ });
114
+ h.checkSetCMIValue({
115
+ api: api(),
116
+ fieldName: "cmi.interactions._children",
117
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
118
+ });
119
+ h.checkSetCMIValue({
120
+ api: api(),
121
+ fieldName: "cmi.interactions._count",
122
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
123
+ });
124
+ h.checkSetCMIValue({
125
+ api: api(),
126
+ fieldName: "cmi.interactions.0.objectives._count",
127
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
128
+ });
129
+ h.checkSetCMIValue({
130
+ api: api(),
131
+ fieldName: "cmi.interactions.0.correct_responses._count",
132
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
133
+ });
134
+ h.checkSetCMIValue({
135
+ api: api(),
136
+ fieldName: "cmi.learner_preference._children",
137
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
138
+ });
139
+ h.checkSetCMIValue({
140
+ api: api(),
141
+ fieldName: "cmi.objectives._children",
142
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
143
+ });
144
+ h.checkSetCMIValue({
145
+ api: api(),
146
+ fieldName: "cmi.objectives._count",
147
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
148
+ });
149
+ h.checkSetCMIValue({
150
+ api: api(),
151
+ fieldName: "cmi.objectives.0.score._children",
152
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
153
+ });
154
+ h.checkSetCMIValue({
155
+ api: api(),
156
+ fieldName: "cmi.score._children",
157
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
158
+ });
159
+ });
160
+
161
+ describe("Invalid Sets - Should Fail After Initialization", () => {
162
+ h.checkSetCMIValue({
163
+ api: apiInitialized(),
164
+ fieldName: "cmi.completion_threshold",
165
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
166
+ });
167
+ h.checkSetCMIValue({
168
+ api: apiInitialized(),
169
+ fieldName: "cmi.credit",
170
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
171
+ });
172
+ h.checkSetCMIValue({
173
+ api: apiInitialized(),
174
+ fieldName: "cmi.entry",
175
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
176
+ });
177
+ h.checkSetCMIValue({
178
+ api: apiInitialized(),
179
+ fieldName: "cmi.launch_data",
180
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
181
+ });
182
+ h.checkSetCMIValue({
183
+ api: apiInitialized(),
184
+ fieldName: "cmi.learner_id",
185
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
186
+ });
187
+ h.checkSetCMIValue({
188
+ api: apiInitialized(),
189
+ fieldName: "cmi.learner_name",
190
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
191
+ });
192
+ h.checkSetCMIValue({
193
+ api: apiInitialized(),
194
+ fieldName: "cmi.max_time_allowed",
195
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
196
+ });
197
+ h.checkSetCMIValue({
198
+ api: apiInitialized(),
199
+ fieldName: "cmi.mode",
200
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
201
+ });
202
+ h.checkSetCMIValue({
203
+ api: apiInitialized(),
204
+ fieldName: "cmi.scaled_passing_score",
205
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
206
+ });
207
+ h.checkSetCMIValue({
208
+ api: apiInitialized(),
209
+ fieldName: "cmi.time_limit_action",
210
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
211
+ });
212
+ h.checkSetCMIValue({
213
+ api: apiInitialized(),
214
+ fieldName: "cmi.total_time",
215
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
216
+ });
217
+ h.checkSetCMIValue({
218
+ api: apiInitialized(),
219
+ fieldName: "cmi.comments_from_lms.0.comment",
220
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
221
+ });
222
+ h.checkSetCMIValue({
223
+ api: apiInitialized(),
224
+ fieldName: "cmi.comments_from_lms.0.location",
225
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
226
+ });
227
+ h.checkSetCMIValue({
228
+ api: apiInitialized(),
229
+ fieldName: "cmi.comments_from_lms.0.timestamp",
230
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
231
+ });
232
+ });
233
+ });
234
+
235
+ describe("GetValue()", () => {
236
+ describe("Invalid Properties - Should Always Fail", () => {
237
+ h.checkLMSGetValue({
238
+ api: apiInitialized(),
239
+ fieldName: "cmi.core.close",
240
+ expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL,
241
+ errorThrown: false,
242
+ });
243
+ h.checkLMSGetValue({
244
+ api: apiInitialized(),
245
+ fieldName: "cmi.core.exit",
246
+ expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL,
247
+ errorThrown: false,
248
+ });
249
+ h.checkLMSGetValue({
250
+ api: apiInitialized(),
251
+ fieldName: "cmi.core.entry",
252
+ expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL,
253
+ errorThrown: false,
254
+ });
255
+ });
256
+
257
+ describe("Write-Only Properties - Should Always Fail", () => {
258
+ h.checkLMSGetValue({
259
+ api: apiInitialized(),
260
+ fieldName: "cmi.exit",
261
+ expectedError: scorm2004_error_codes.WRITE_ONLY_ELEMENT,
262
+ });
263
+ h.checkLMSGetValue({
264
+ api: apiInitialized(),
265
+ fieldName: "cmi.session_time",
266
+ expectedError: scorm2004_error_codes.WRITE_ONLY_ELEMENT,
267
+ });
268
+ });
269
+ });
270
+
271
+ describe("SetValue()", () => {
272
+ describe("Uninitialized - Should Fail", () => {
273
+ h.checkLMSSetValue({
274
+ api: api(),
275
+ fieldName: "cmi.objectives.0.id",
276
+ expectedError: scorm2004_error_codes.STORE_BEFORE_INIT,
277
+ });
278
+ h.checkLMSSetValue({
279
+ api: api(),
280
+ fieldName: "cmi.interactions.0.id",
281
+ expectedError: scorm2004_error_codes.STORE_BEFORE_INIT,
282
+ });
283
+ h.checkLMSSetValue({
284
+ api: api(),
285
+ fieldName: "cmi.comments_from_learner.0.comment",
286
+ expectedError: scorm2004_error_codes.STORE_BEFORE_INIT,
287
+ });
288
+ h.checkLMSSetValue({
289
+ api: api(),
290
+ fieldName: "cmi.comments_from_lms.0.comment",
291
+ expectedError: scorm2004_error_codes.STORE_BEFORE_INIT,
292
+ });
293
+ });
294
+
295
+ describe("Initialized - Should Succeed", () => {
296
+ h.checkLMSSetValue({
297
+ api: apiInitialized(),
298
+ fieldName: "cmi.objectives.0.id",
299
+ valueToTest: "AAA",
300
+ errorThrown: false,
301
+ });
302
+ h.checkLMSSetValue({
303
+ api: apiInitialized(),
304
+ fieldName: "cmi.interactions.0.id",
305
+ valueToTest: "AAA",
306
+ errorThrown: false,
307
+ });
308
+ h.checkLMSSetValue({
309
+ api: apiInitialized(),
310
+ fieldName: "cmi.comments_from_learner.0.comment",
311
+ valueToTest: "comment",
312
+ errorThrown: false,
313
+ });
314
+ h.checkLMSSetValue({
315
+ api: apiInitialized(),
316
+ fieldName: "cmi.comments_from_learner.0.location",
317
+ valueToTest: "location",
318
+ errorThrown: false,
319
+ });
320
+ h.checkLMSSetValue({
321
+ api: apiInitialized(),
322
+ fieldName: "cmi.comments_from_learner.0.timestamp",
323
+ valueToTest: scorm2004Values.validTimestamps[0],
324
+ errorThrown: false,
325
+ });
326
+ it("should allow cmi.interactions.0.correct_responses.0.pattern to be set - T/F", () => {
327
+ const scorm2004API = apiInitialized();
328
+ scorm2004API.setCMIValue(
329
+ "cmi.interactions.0.id",
330
+ "Scene1_Slide3_MultiChoice_0_0",
331
+ );
332
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "true-false");
333
+ scorm2004API.setCMIValue(
334
+ "cmi.interactions.0.correct_responses.0.pattern",
335
+ "true",
336
+ );
337
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
338
+ });
339
+ it("should allow cmi.interactions.10.correct_responses.0.pattern to be set - T/F", () => {
340
+ const scorm2004API = apiInitialized();
341
+ scorm2004API.setCMIValue(
342
+ "cmi.interactions.0.id",
343
+ "Scene1_Slide3_MultiChoice_0_0",
344
+ );
345
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "true-false");
346
+ scorm2004API.setCMIValue(
347
+ "cmi.interactions.0.correct_responses.0.pattern",
348
+ "true",
349
+ );
350
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
351
+ });
352
+ it("should allow cmi.interactions.0.correct_responses.0.pattern to be set - choice", () => {
353
+ const scorm2004API = apiInitialized();
354
+ scorm2004API.setCMIValue(
355
+ "cmi.interactions.0.id",
356
+ "Scene1_Slide3_MultiChoice_0_0",
357
+ );
358
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "choice");
359
+ scorm2004API.setCMIValue(
360
+ "cmi.interactions.0.correct_responses.0.pattern",
361
+ "VP_on-call_or_President",
362
+ );
363
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
364
+ });
365
+ it("should allow cmi.interactions.0.correct_responses.0.pattern to be set - choice for SCORM 2004 4th Edition", () => {
366
+ const scorm2004API = apiInitialized();
367
+ scorm2004API.setCMIValue(
368
+ "cmi.interactions.0.id",
369
+ "urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0",
370
+ );
371
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "choice");
372
+ scorm2004API.setCMIValue(
373
+ "cmi.interactions.0.correct_responses.0.pattern",
374
+ "urn:scormdriver:This%20is%20a%20choice.",
375
+ );
376
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
377
+ });
378
+ it("should allow cmi.interactions.0.objectives.0.id to be set", () => {
379
+ const scorm2004API = apiInitialized();
380
+ scorm2004API.setCMIValue(
381
+ "cmi.interactions.0.objectives.0.id",
382
+ "ID of the Obj - ID 2",
383
+ );
384
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
385
+ });
386
+ it("should allow cmi.interactions.0.learner_response to be set", () => {
387
+ const scorm2004API = apiInitialized();
388
+ scorm2004API.setCMIValue(
389
+ "cmi.interactions.0.id",
390
+ "Scene1_Slide3_MultiChoice_0_0",
391
+ );
392
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "choice");
393
+ scorm2004API.setCMIValue(
394
+ "cmi.interactions.0.learner_response",
395
+ "VP_on-call_or_President",
396
+ );
397
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
398
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.id")).toEqual(
399
+ "Scene1_Slide3_MultiChoice_0_0",
400
+ );
401
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.type")).toEqual(
402
+ "choice",
403
+ );
404
+ expect(
405
+ scorm2004API.getCMIValue("cmi.interactions.0.learner_response"),
406
+ ).toEqual("VP_on-call_or_President");
407
+ });
408
+ it("should allow cmi.interactions.0.learner_response to be set for SCORM 2004 4th Edition", () => {
409
+ const scorm2004API = apiInitialized();
410
+ scorm2004API.setCMIValue(
411
+ "cmi.interactions.0.id",
412
+ "urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0",
413
+ );
414
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "choice");
415
+ scorm2004API.setCMIValue(
416
+ "cmi.interactions.0.learner_response",
417
+ "urn:scormdriver:This%20is%20an%20incorrect%20response.",
418
+ );
419
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
420
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.id")).toEqual(
421
+ "urn:scormdriver:Test_Your_Knowledge.Select_the_ONE_TRUE_answer._0",
422
+ );
423
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.type")).toEqual(
424
+ "choice",
425
+ );
426
+ expect(
427
+ scorm2004API.getCMIValue("cmi.interactions.0.learner_response"),
428
+ ).toEqual("urn:scormdriver:This%20is%20an%20incorrect%20response.");
429
+ });
430
+ it("should allow `long-fill-in` cmi.interactions.0.learner_response to be set to 4000 characters", () => {
431
+ const scorm2004API = apiInitialized();
432
+ scorm2004API.setCMIValue(
433
+ "cmi.interactions.0.id",
434
+ "Scene1_Slide3_MultiChoice_0_0",
435
+ );
436
+ scorm2004API.setCMIValue("cmi.interactions.0.type", "long-fill-in");
437
+ scorm2004API.setCMIValue(
438
+ "cmi.interactions.0.learner_response",
439
+ "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",
440
+ );
441
+ expect(String(scorm2004API.lmsGetLastError())).toEqual(String(0));
442
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.id")).toEqual(
443
+ "Scene1_Slide3_MultiChoice_0_0",
444
+ );
445
+ expect(scorm2004API.getCMIValue("cmi.interactions.0.type")).toEqual(
446
+ "long-fill-in",
447
+ );
448
+ expect(
449
+ scorm2004API.getCMIValue("cmi.interactions.0.learner_response"),
450
+ ).toEqual(
451
+ "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",
452
+ );
453
+ });
454
+ });
455
+
456
+ describe("Initialized - Should Fail", () => {
457
+ h.checkLMSSetValue({
458
+ api: apiInitialized({
459
+ cmi: { interactions: { "0": { id: "interaction-id-1" } } },
460
+ }),
461
+ fieldName: "cmi.interactions.0.learner_response",
462
+ valueToTest:
463
+ "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 commod1",
464
+ errorThrown: false,
465
+ expectedError: scorm2004_error_codes.TYPE_MISMATCH,
466
+ });
467
+ h.checkLMSSetValue({
468
+ api: apiInitialized({
469
+ cmi: {
470
+ interactions: {
471
+ "0": {
472
+ id: "interaction-id-1",
473
+ type: "long-fill-in",
474
+ },
475
+ },
476
+ },
477
+ }),
478
+ fieldName: "cmi.interactions.0.type",
479
+ valueToTest: "unknown",
480
+ errorThrown: false,
481
+ expectedError: scorm2004_error_codes.TYPE_MISMATCH,
482
+ });
483
+ h.checkLMSSetValue({
484
+ api: apiInitialized(),
485
+ fieldName: "cmi.interactions.0.type",
486
+ valueToTest: "true-false",
487
+ errorThrown: false,
488
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
489
+ });
490
+ h.checkLMSSetValue({
491
+ api: apiInitialized(),
492
+ fieldName: "cmi.interactions.0.description",
493
+ valueToTest: "this is an interaction",
494
+ errorThrown: false,
495
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
496
+ });
497
+ h.checkLMSSetValue({
498
+ api: apiInitialized(),
499
+ fieldName: "cmi.interactions.0.timestamp",
500
+ valueToTest: "PT1S",
501
+ errorThrown: false,
502
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
503
+ });
504
+ h.checkLMSSetValue({
505
+ api: apiInitialized(),
506
+ fieldName: "cmi.interactions.0.weighting",
507
+ valueToTest: 1.0,
508
+ errorThrown: false,
509
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
510
+ });
511
+ h.checkLMSSetValue({
512
+ api: apiInitialized(),
513
+ fieldName: "cmi.interactions.0.learner_response",
514
+ valueToTest: "true",
515
+ errorThrown: false,
516
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
517
+ });
518
+ h.checkLMSSetValue({
519
+ api: apiInitialized(),
520
+ fieldName: "cmi.interactions.0.latency",
521
+ valueToTest: "PT1S",
522
+ errorThrown: false,
523
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
524
+ });
525
+ h.checkLMSSetValue({
526
+ api: apiInitialized(),
527
+ fieldName: "cmi.objectives.0.success_status",
528
+ valueToTest: "passed",
529
+ errorThrown: false,
530
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
531
+ });
532
+ h.checkLMSSetValue({
533
+ api: apiInitialized(),
534
+ fieldName: "cmi.objectives.0.completion_status",
535
+ valueToTest: "completed",
536
+ errorThrown: false,
537
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
538
+ });
539
+ h.checkLMSSetValue({
540
+ api: apiInitialized(),
541
+ fieldName: "cmi.objectives.0.progress_measure",
542
+ valueToTest: 1.0,
543
+ errorThrown: false,
544
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
545
+ });
546
+ h.checkLMSSetValue({
547
+ api: apiInitialized(),
548
+ fieldName: "cmi.objectives.0.description",
549
+ valueToTest: "this is an objective",
550
+ errorThrown: false,
551
+ expectedError: scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
552
+ });
553
+ h.checkLMSSetValue({
554
+ api: apiInitialized(),
555
+ fieldName: "cmi.comments_from_lms.0.comment",
556
+ valueToTest: "comment",
557
+ errorThrown: false,
558
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
559
+ });
560
+ h.checkLMSSetValue({
561
+ api: apiInitialized(),
562
+ fieldName: "cmi.comments_from_lms.0.location",
563
+ valueToTest: "location",
564
+ errorThrown: false,
565
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
566
+ });
567
+ h.checkLMSSetValue({
568
+ api: apiInitialized(),
569
+ fieldName: "cmi.comments_from_lms.0.timestamp",
570
+ valueToTest: scorm2004Values.validTimestamps[0],
571
+ errorThrown: false,
572
+ expectedError: scorm2004_error_codes.READ_ONLY_ELEMENT,
573
+ });
574
+ h.checkLMSSetValue({
575
+ api: apiInitialized(),
576
+ fieldName: "cmi.unknown",
577
+ valueToTest: "uknown",
578
+ errorThrown: false,
579
+ expectedError: scorm2004_error_codes.UNDEFINED_DATA_MODEL,
580
+ });
581
+ });
582
+ });
583
+
584
+ describe("loadFromFlattenedJSON()", () => {
585
+ it("should load data, even if out of order", () => {
586
+ const scorm2004API = api();
587
+ scorm2004API.loadFromFlattenedJSON(
588
+ {
589
+ "cmi.learner_id": "123",
590
+ "cmi.learner_name": "Bob The Builder",
591
+ "cmi.suspend_data":
592
+ "viewed=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31|lastviewedslide=31|7#1##,3,3,3,7,3,3,7,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,11#0#b5e89fbb-7cfb-46f0-a7cb-758165d3fe7e=236~262~2542812732762722742772682802752822882852892872832862962931000~3579~32590001001010101010101010101001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001010010010010010010010010011010010010010010010010010010010010112101021000171000~236a71d398e-4023-4967-88fe-1af18721422d06passed6failed000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105wrong110000000000000000000000000000000000~3185000000000000000000000000000000000000000000000000000000000000000000000000000000000~283~2191w11~21113101w41689~256~2100723031840~21007230314509062302670~2110723031061120000000000000000000~240~234531618~21601011000100000002814169400,#-1",
593
+ "cmi.interactions.0.timestamp": "2018-08-26T11:05:21",
594
+ "cmi.interactions.0.weighting": "1",
595
+ "cmi.interactions.0.learner_response": "HTH",
596
+ "cmi.interactions.0.id": "Question14_1",
597
+ "cmi.interactions.0.type": "choice",
598
+ "cmi.interactions.0.result": "incorrect",
599
+ "cmi.interactions.0.latency": "PT2M30S",
600
+ "cmi.interactions.0.objectives.0.id": "Question14_1",
601
+ "cmi.interactions.0.objectives.0.correct_responses.0.pattern": "CPR",
602
+ },
603
+ "",
604
+ );
605
+ scorm2004API.lmsInitialize();
606
+ expect(scorm2004API.lmsGetValue("cmi.interactions.0.id")).toEqual(
607
+ "Question14_1",
608
+ );
609
+ });
610
+ });
611
+
612
+ describe("renderCommitCMI()", () => {
613
+ it("should calculate total time when terminateCommit passed", () => {
614
+ const scorm2004API = api();
615
+ scorm2004API.cmi.total_time = "PT12H34M56S";
616
+ scorm2004API.cmi.session_time = "PT23H59M59S";
617
+ const cmiExport: RefObject = scorm2004API.renderCommitCMI(true);
618
+ expect(cmiExport.cmi.total_time).toEqual("P1DT12H34M55S");
619
+ });
620
+ });
621
+
622
+ describe("storeData()", () => {
623
+ it('should set cmi.completion_status to "completed"', () => {
624
+ const scorm2004API = api();
625
+ scorm2004API.cmi.credit = "credit";
626
+ scorm2004API.cmi.completion_threshold = "0.6";
627
+ scorm2004API.cmi.progress_measure = "0.75";
628
+ scorm2004API.storeData(true);
629
+ expect(scorm2004API.cmi.completion_status).toEqual("completed");
630
+ });
631
+ it('should set cmi.completion_status to "incomplete"', () => {
632
+ const scorm2004API = api();
633
+ scorm2004API.cmi.credit = "credit";
634
+ scorm2004API.cmi.completion_threshold = "0.7";
635
+ scorm2004API.cmi.progress_measure = "0.6";
636
+ scorm2004API.storeData(true);
637
+ expect(scorm2004API.cmi.completion_status).toEqual("incomplete");
638
+ });
639
+ it('should set cmi.success_status to "passed"', () => {
640
+ const scorm2004API = api();
641
+ scorm2004API.cmi.credit = "credit";
642
+ scorm2004API.cmi.score.scaled = "0.7";
643
+ scorm2004API.cmi.scaled_passing_score = "0.6";
644
+ scorm2004API.storeData(true);
645
+ expect(scorm2004API.cmi.success_status).toEqual("passed");
646
+ });
647
+ it('should set cmi.success_status to "failed"', () => {
648
+ const scorm2004API = api();
649
+ scorm2004API.cmi.credit = "credit";
650
+ scorm2004API.cmi.score.scaled = "0.6";
651
+ scorm2004API.cmi.scaled_passing_score = "0.7";
652
+ scorm2004API.storeData(true);
653
+ expect(scorm2004API.cmi.success_status).toEqual("failed");
654
+ });
655
+ });
656
+
657
+ describe("Event Handlers", () => {
658
+ it("Should handle SetValue.cmi.learner_id event", () => {
659
+ const scorm2004API = apiInitialized();
660
+ const callback = sinon.spy();
661
+ scorm2004API.on("SetValue.cmi.learner_id", callback);
662
+ scorm2004API.lmsSetValue("cmi.learner_id", "@jcputney");
663
+ expect(callback.called).toBe(true);
664
+ });
665
+ it("Should handle SetValue.cmi.* event", () => {
666
+ const scorm2004API = apiInitialized();
667
+ const callback = sinon.spy();
668
+ scorm2004API.on("SetValue.cmi.*", callback);
669
+ scorm2004API.lmsSetValue("cmi.learner_id", "@jcputney");
670
+ expect(callback.called).toBe(true);
671
+ });
672
+ it("Should handle CommitSuccess event", async () => {
673
+ const scorm2004API = api({
674
+ ...DefaultSettings,
675
+ ...{
676
+ lmsCommitUrl: "/scorm2004",
677
+ autocommit: true,
678
+ autocommitSeconds: 1,
679
+ },
680
+ });
681
+ scorm2004API.lmsInitialize();
682
+
683
+ const callback = sinon.spy();
684
+ scorm2004API.on("CommitSuccess", callback);
685
+
686
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
687
+ clock.tick(2000);
688
+
689
+ await clock.runAllAsync();
690
+
691
+ expect(callback.called).toBe(true);
692
+ });
693
+ it("Should clear all event listeners for CommitSuccess", async () => {
694
+ const scorm2004API = api({
695
+ ...DefaultSettings,
696
+ ...{
697
+ lmsCommitUrl: "/scorm2004",
698
+ autocommit: true,
699
+ autocommitSeconds: 1,
700
+ },
701
+ });
702
+ scorm2004API.lmsInitialize();
703
+
704
+ const callback = sinon.spy();
705
+ const callback2 = sinon.spy();
706
+ scorm2004API.on("CommitSuccess", callback);
707
+ scorm2004API.on("CommitSuccess", callback2);
708
+
709
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
710
+ clock.tick(2000);
711
+
712
+ await clock.runAllAsync();
713
+
714
+ expect(callback.calledOnce).toBe(true);
715
+ expect(callback2.calledOnce).toBe(true);
716
+
717
+ scorm2004API.clear("CommitSuccess");
718
+
719
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
720
+ clock.tick(2000);
721
+
722
+ await clock.runAllAsync();
723
+
724
+ expect(callback.calledTwice).toBe(false);
725
+ expect(callback2.calledTwice).toBe(false);
726
+ });
727
+ it("Should clear only the specific event listener for CommitSuccess", async () => {
728
+ const scorm2004API = api({
729
+ ...DefaultSettings,
730
+ ...{
731
+ lmsCommitUrl: "/scorm2004",
732
+ autocommit: true,
733
+ autocommitSeconds: 1,
734
+ },
735
+ });
736
+ scorm2004API.lmsInitialize();
737
+
738
+ const callback = sinon.spy(() => 1);
739
+ const callback2 = sinon.spy(() => 2);
740
+ const callback3 = sinon.spy(() => 3);
741
+ const callback4 = sinon.spy(() => 4);
742
+ scorm2004API.on("CommitSuccess", callback);
743
+ scorm2004API.on("CommitSuccess", callback2);
744
+ scorm2004API.on("Commit", callback3);
745
+ scorm2004API.on("SetValue", callback4);
746
+
747
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
748
+ clock.tick(2000);
749
+
750
+ await clock.runAllAsync();
751
+
752
+ expect(callback.calledOnce).toBe(true);
753
+ expect(callback2.calledOnce).toBe(true);
754
+ expect(callback3.calledOnce).toBe(true);
755
+ expect(callback4.calledOnce).toBe(true);
756
+
757
+ scorm2004API.off("CommitSuccess", callback);
758
+
759
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
760
+ clock.tick(2000);
761
+
762
+ await clock.runAllAsync();
763
+
764
+ expect(callback.calledTwice).toBe(false); // removed callback should not be called a second time
765
+ expect(callback2.calledTwice).toBe(true);
766
+ expect(callback3.calledTwice).toBe(true);
767
+ expect(callback4.calledTwice).toBe(true);
768
+ });
769
+ it("Should handle CommitError event", async () => {
770
+ const scorm2004API = api({
771
+ ...DefaultSettings,
772
+ ...{
773
+ lmsCommitUrl: "/scorm2004/error",
774
+ autocommit: true,
775
+ autocommitSeconds: 1,
776
+ },
777
+ });
778
+ scorm2004API.lmsInitialize();
779
+
780
+ const callback = sinon.spy();
781
+ scorm2004API.on("CommitError", callback);
782
+
783
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
784
+ clock.tick(2000);
785
+
786
+ await clock.runAllAsync();
787
+
788
+ expect(callback.called).toBe(true);
789
+ });
790
+ it("Should handle CommitError event when offline", async () => {
791
+ const scorm2004API = api({
792
+ ...DefaultSettings,
793
+ ...{
794
+ lmsCommitUrl: "/scorm2004/does_not_exist",
795
+ autocommit: true,
796
+ autocommitSeconds: 1,
797
+ },
798
+ });
799
+ scorm2004API.lmsInitialize();
800
+
801
+ const callback = sinon.spy();
802
+ scorm2004API.on("CommitError", callback);
803
+
804
+ scorm2004API.lmsSetValue("cmi.session_time", "PT1M0S");
805
+ clock.tick(2000);
806
+
807
+ await clock.runAllAsync();
808
+
809
+ expect(callback.called).toBe(true);
810
+ });
811
+ });
812
+ });