scorm-again 2.2.0 → 2.4.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 (52) hide show
  1. package/README.md +2 -1
  2. package/dist/aicc.js +3161 -2799
  3. package/dist/aicc.js.map +1 -1
  4. package/dist/aicc.min.js +1 -1
  5. package/dist/aicc.min.js.map +1 -1
  6. package/dist/esm/aicc.js +4569 -0
  7. package/dist/esm/aicc.js.map +1 -0
  8. package/dist/esm/aicc.min.js +2 -0
  9. package/dist/esm/aicc.min.js.map +1 -0
  10. package/dist/esm/scorm-again.js +6955 -0
  11. package/dist/esm/scorm-again.js.map +1 -0
  12. package/dist/esm/scorm-again.min.js +2 -0
  13. package/dist/esm/scorm-again.min.js.map +1 -0
  14. package/dist/esm/scorm12.js +3637 -0
  15. package/dist/esm/scorm12.js.map +1 -0
  16. package/dist/esm/scorm12.min.js +2 -0
  17. package/dist/esm/scorm12.min.js.map +1 -0
  18. package/dist/esm/scorm2004.js +4631 -0
  19. package/dist/esm/scorm2004.js.map +1 -0
  20. package/dist/esm/scorm2004.min.js +2 -0
  21. package/dist/esm/scorm2004.min.js.map +1 -0
  22. package/dist/scorm-again.js +4498 -4082
  23. package/dist/scorm-again.js.map +1 -1
  24. package/dist/scorm-again.min.js +1 -1
  25. package/dist/scorm-again.min.js.map +1 -1
  26. package/dist/scorm12.js +3074 -2756
  27. package/dist/scorm12.js.map +1 -1
  28. package/dist/scorm12.min.js +1 -1
  29. package/dist/scorm12.min.js.map +1 -1
  30. package/dist/scorm2004.js +2430 -2221
  31. package/dist/scorm2004.js.map +1 -1
  32. package/dist/scorm2004.min.js +1 -1
  33. package/dist/scorm2004.min.js.map +1 -1
  34. package/index.d.ts +70 -0
  35. package/package.json +11 -8
  36. package/src/AICC.ts +6 -4
  37. package/src/BaseAPI.ts +38 -21
  38. package/src/Scorm12API.ts +24 -29
  39. package/src/Scorm2004API.ts +13 -18
  40. package/src/ScormAgain.ts +9 -0
  41. package/src/constants/default_settings.ts +1 -0
  42. package/src/types/api_types.ts +1 -0
  43. package/test/AICC.spec.ts +2 -2
  44. package/test/Scorm12API.spec.ts +73 -2
  45. package/test/Scorm2004API.spec.ts +18 -18
  46. package/webpack.config.js +38 -15
  47. package/src/exports/aicc.js +0 -3
  48. package/src/exports/scorm-again.js +0 -7
  49. package/src/exports/scorm12.js +0 -3
  50. package/src/exports/scorm2004.js +0 -3
  51. package/src/utilities/debounce.ts +0 -31
  52. package/test/utilities/debounce.spec.ts +0 -56
package/index.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import { Scorm12Impl } from "./src/Scorm12API";
2
+ import { CMI as Scorm12CMI } from "./src/cmi/scorm12/cmi";
3
+ import { NAV as Scorm12NAV } from "./src/cmi/scorm12/nav";
4
+ import { CMI as Scorm2004CMI } from "./src/cmi/scorm2004/cmi";
5
+ import { ADL as Scorm2004ADL } from "./src/cmi/scorm2004/adl";
6
+ import { Settings } from "./src/types/api_types";
7
+ import { Scorm2004Impl } from "./src/Scorm2004API";
8
+ import { AICCImpl } from "./src/AICC";
9
+
10
+ declare class Scorm12API extends Scorm12Impl {
11
+ constructor(settings?: Settings);
12
+
13
+ cmi: Scorm12CMI;
14
+ nav: Scorm12NAV;
15
+ LMSInitialize: () => string;
16
+ LMSFinish: () => string;
17
+ LMSGetValue: (CMIElement: string) => string;
18
+ LMSSetValue: (CMIElement: string, value: any) => string;
19
+ LMSCommit: () => string;
20
+ LMSGetLastError: () => string;
21
+ LMSGetErrorString: (CMIErrorCode: string) => string;
22
+ LMSGetDiagnostic: (CMIErrorCode: string) => string;
23
+
24
+ /**
25
+ * Called when the API needs to be reset
26
+ */
27
+ reset(settings?: Settings): void;
28
+ }
29
+
30
+ declare class Scorm2004API extends Scorm2004Impl {
31
+ constructor(settings?: Settings);
32
+
33
+ cmi: Scorm2004CMI;
34
+ adl: Scorm2004ADL;
35
+ Initialize: () => string;
36
+ Terminate: () => string;
37
+ GetValue: (CMIElement: string) => string;
38
+ SetValue: (CMIElement: string, value: any) => string;
39
+ Commit: () => string;
40
+ GetLastError: () => string;
41
+ GetErrorString: (CMIErrorCode: string) => string;
42
+ GetDiagnostic: (CMIErrorCode: string) => string;
43
+
44
+ /**
45
+ * Called when the API needs to be reset
46
+ */
47
+ reset(settings?: Settings): void;
48
+ }
49
+
50
+ declare class AICC extends AICCImpl {
51
+ constructor(settings?: Settings);
52
+
53
+ cmi: Scorm12CMI;
54
+ nav: Scorm12NAV;
55
+ LMSInitialize: () => string;
56
+ LMSFinish: () => string;
57
+ LMSGetValue: (CMIElement: string) => string;
58
+ LMSSetValue: (CMIElement: string, value: any) => string;
59
+ LMSCommit: () => string;
60
+ LMSGetLastError: () => string;
61
+ LMSGetErrorString: (CMIErrorCode: string) => string;
62
+ LMSGetDiagnostic: (CMIErrorCode: string) => string;
63
+
64
+ /**
65
+ * Called when the API needs to be reset
66
+ */
67
+ reset(settings?: Settings): void;
68
+ }
69
+
70
+ export { Scorm12API, Scorm2004API, AICC, Settings };
package/package.json CHANGED
@@ -1,8 +1,10 @@
1
1
  {
2
2
  "name": "scorm-again",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "A modern SCORM JavaScript run-time library for AICC, SCORM 1.2, and SCORM 2004",
5
- "main": "dist/scorm-again.min.js",
5
+ "main": "dist/scorm-again.js",
6
+ "types": "index.d.ts",
7
+ "module": "dist/esm/scorm-again.js",
6
8
  "type": "module",
7
9
  "browser": {
8
10
  "electron": false
@@ -21,11 +23,11 @@
21
23
  },
22
24
  "devDependencies": {
23
25
  "@babel/cli": "^7.25.9",
24
- "@babel/core": "^7.25.9",
26
+ "@babel/core": "^7.26.0",
25
27
  "@babel/eslint-parser": "^7.25.9",
26
- "@babel/node": "^7.25.9",
27
- "@babel/preset-env": "^7.25.9",
28
- "@babel/preset-typescript": "^7.25.9",
28
+ "@babel/node": "^7.26.0",
29
+ "@babel/preset-env": "^7.26.0",
30
+ "@babel/preset-typescript": "^7.26.0",
29
31
  "@eslint/eslintrc": "^3.1.0",
30
32
  "@eslint/js": "^9.13.0",
31
33
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
@@ -66,7 +68,7 @@
66
68
  "scripts": {
67
69
  "test": "./node_modules/.bin/mocha --import=tsx --bdd --recursive --reporter list",
68
70
  "test:coverage": "./node_modules/.bin/c8 ./node_modules/.bin/mocha --import=tsx --recursive --timeout=10000 --exit --reporter json --reporter-option output=test-results.json",
69
- "compile": "./node_modules/.bin/webpack --bail --config webpack.config.js",
71
+ "compile": "./node_modules/.bin/webpack --bail --config webpack.config.js --mode production",
70
72
  "fix": "./node_modules/.bin/eslint ./src --fix",
71
73
  "prettier": "./node_modules/.bin/prettier --write src/**/*.ts test/**/*.ts src/*.ts test/*.ts"
72
74
  },
@@ -97,7 +99,8 @@
97
99
  "test/**/*.*",
98
100
  "src/exports/*.*",
99
101
  "src/interfaces/*.*",
100
- "src/types/*.*"
102
+ "src/types/*.*",
103
+ "src/ScormAgain.ts"
101
104
  ],
102
105
  "extension": [
103
106
  ".ts"
package/src/AICC.ts CHANGED
@@ -1,4 +1,4 @@
1
- import Scorm12API from "./Scorm12API";
1
+ import { Scorm12Impl } from "./Scorm12API";
2
2
  import { CMI } from "./cmi/aicc/cmi";
3
3
 
4
4
  import { BaseCMI } from "./cmi/common/base_cmi";
@@ -13,7 +13,7 @@ import { stringMatches } from "./utilities";
13
13
  /**
14
14
  * The AICC API class
15
15
  */
16
- export default class AICC extends Scorm12API {
16
+ class AICCImpl extends Scorm12Impl {
17
17
  /**
18
18
  * Constructor to create AICC API object
19
19
  * @param {Settings} settings
@@ -62,11 +62,13 @@ export default class AICC extends Scorm12API {
62
62
  /**
63
63
  * Replace the whole API with another
64
64
  *
65
- * @param {AICC} newAPI
65
+ * @param {AICCImpl} newAPI
66
66
  */
67
- replaceWithAnotherScormAPI(newAPI: AICC) {
67
+ replaceWithAnotherScormAPI(newAPI: AICCImpl) {
68
68
  // Data Model
69
69
  this.cmi = newAPI.cmi;
70
70
  this.nav = newAPI.nav;
71
71
  }
72
72
  }
73
+
74
+ export { AICCImpl };
package/src/BaseAPI.ts CHANGED
@@ -4,10 +4,9 @@ import ErrorCodes, { ErrorCode } from "./constants/error_codes";
4
4
  import APIConstants from "./constants/api_constants";
5
5
  import { formatMessage, stringMatches, unflatten } from "./utilities";
6
6
  import { BaseCMI } from "./cmi/common/base_cmi";
7
- import { debounce } from "./utilities/debounce";
8
7
  import {
9
- RefObject,
10
8
  CommitObject,
9
+ RefObject,
11
10
  ResultObject,
12
11
  Settings,
13
12
  } from "./types/api_types";
@@ -360,7 +359,7 @@ export default abstract class BaseAPI implements IBaseAPI {
360
359
  // If we didn't have any errors while setting the data, go ahead and
361
360
  // schedule a commit, if autocommit is turned on
362
361
  if (String(this.lastErrorCode) === "0") {
363
- if (this.settings.autocommit && !this._timeout) {
362
+ if (this.settings.autocommit) {
364
363
  this.scheduleCommit(
365
364
  this.settings.autocommitSeconds * 1000,
366
365
  commitCallback,
@@ -389,6 +388,7 @@ export default abstract class BaseAPI implements IBaseAPI {
389
388
  callbackName: string,
390
389
  checkTerminated: boolean = false,
391
390
  ): Promise<string> {
391
+ console.log("commit");
392
392
  this.clearScheduledCommit();
393
393
 
394
394
  let returnValue = APIConstants.global.SCORM_FALSE;
@@ -1174,17 +1174,7 @@ export default abstract class BaseAPI implements IBaseAPI {
1174
1174
  }
1175
1175
  };
1176
1176
 
1177
- if (this.settings.asyncCommit) {
1178
- const debouncedProcess = debounce(process, 500, immediate);
1179
- debouncedProcess(url, params, this.settings);
1180
-
1181
- return {
1182
- result: APIConstants.global.SCORM_TRUE,
1183
- errorCode: 0,
1184
- };
1185
- } else {
1186
- return await process(url, params, this.settings);
1187
- }
1177
+ return await process(url, params, this.settings);
1188
1178
  }
1189
1179
 
1190
1180
  /**
@@ -1194,13 +1184,15 @@ export default abstract class BaseAPI implements IBaseAPI {
1194
1184
  * @param {string} callback - the name of the commit event callback
1195
1185
  */
1196
1186
  scheduleCommit(when: number, callback: string) {
1197
- this._timeout = new ScheduledCommit(this, when, callback);
1198
- this.apiLog(
1199
- "scheduleCommit",
1200
- "scheduled",
1201
- APIConstants.global.LOG_LEVEL_DEBUG,
1202
- "",
1203
- );
1187
+ if (!this._timeout) {
1188
+ this._timeout = new ScheduledCommit(this, when, callback);
1189
+ this.apiLog(
1190
+ "scheduleCommit",
1191
+ "scheduled",
1192
+ APIConstants.global.LOG_LEVEL_DEBUG,
1193
+ "",
1194
+ );
1195
+ }
1204
1196
  }
1205
1197
 
1206
1198
  /**
@@ -1262,6 +1254,30 @@ export default abstract class BaseAPI implements IBaseAPI {
1262
1254
  return returnValue;
1263
1255
  }
1264
1256
 
1257
+ /**
1258
+ * Builds the commit object to be sent to the LMS
1259
+ * @param {boolean} terminateCommit
1260
+ * @return {CommitObject|RefObject|Array}
1261
+ * @private
1262
+ */
1263
+ protected getCommitObject(
1264
+ terminateCommit: boolean,
1265
+ ): CommitObject | RefObject | Array<any> {
1266
+ const shouldTerminateCommit =
1267
+ terminateCommit || this.settings.alwaysSendTotalTime;
1268
+ const commitObject = this.settings.renderCommonCommitFields
1269
+ ? this.renderCommitObject(shouldTerminateCommit)
1270
+ : this.renderCommitCMI(shouldTerminateCommit);
1271
+
1272
+ if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
1273
+ console.debug(
1274
+ "Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
1275
+ );
1276
+ console.debug(commitObject);
1277
+ }
1278
+ return commitObject;
1279
+ }
1280
+
1265
1281
  /**
1266
1282
  * Perform the fetch request to the LMS
1267
1283
  * @param {string} url
@@ -1275,6 +1291,7 @@ export default abstract class BaseAPI implements IBaseAPI {
1275
1291
  ): Promise<Response> {
1276
1292
  return fetch(url, {
1277
1293
  method: "POST",
1294
+ mode: this.settings.fetchMode,
1278
1295
  body: params instanceof Array ? params.join("&") : JSON.stringify(params),
1279
1296
  headers: {
1280
1297
  ...this.settings.xhrHeaders,
package/src/Scorm12API.ts CHANGED
@@ -1,4 +1,3 @@
1
- import BaseAPI from "./BaseAPI";
2
1
  import { CMI } from "./cmi/scorm12/cmi";
3
2
  import * as Utilities from "./utilities";
4
3
  import { stringMatches } from "./utilities";
@@ -22,11 +21,12 @@ import {
22
21
  } from "./types/api_types";
23
22
  import Regex from "./constants/regex";
24
23
  import { CompletionStatus, SuccessStatus } from "./constants/enums";
24
+ import BaseAPI from "./BaseAPI";
25
25
 
26
26
  /**
27
27
  * API class for SCORM 1.2
28
28
  */
29
- export default class Scorm12API extends BaseAPI {
29
+ class Scorm12Impl extends BaseAPI {
30
30
  /**
31
31
  * Constructor for SCORM 1.2 API
32
32
  * @param {object} settings
@@ -56,17 +56,17 @@ export default class Scorm12API extends BaseAPI {
56
56
 
57
57
  public statusSetByModule = false;
58
58
 
59
- public cmi: CMI;
60
- public nav: NAV;
59
+ cmi: CMI;
60
+ nav: NAV;
61
61
 
62
- public LMSInitialize: () => string;
63
- public LMSFinish: () => string;
64
- public LMSGetValue: (CMIElement: string) => string;
65
- public LMSSetValue: (CMIElement: string, value: any) => string;
66
- public LMSCommit: () => string;
67
- public LMSGetLastError: () => string;
68
- public LMSGetErrorString: (CMIErrorCode: string) => string;
69
- public LMSGetDiagnostic: (CMIErrorCode: string) => string;
62
+ LMSInitialize: () => string;
63
+ LMSFinish: () => string;
64
+ LMSGetValue: (CMIElement: string) => string;
65
+ LMSSetValue: (CMIElement: string, value: any) => string;
66
+ LMSCommit: () => string;
67
+ LMSGetLastError: () => string;
68
+ LMSGetErrorString: (CMIErrorCode: string) => string;
69
+ LMSGetDiagnostic: (CMIErrorCode: string) => string;
70
70
 
71
71
  /**
72
72
  * Called when the API needs to be reset
@@ -157,9 +157,13 @@ export default class Scorm12API extends BaseAPI {
157
157
  * @return {string} bool
158
158
  */
159
159
  lmsCommit(): string {
160
- (async () => {
161
- await this.commit("LMSCommit", false);
162
- })();
160
+ if (this.settings.asyncCommit) {
161
+ this.scheduleCommit(500, "LMSCommit");
162
+ } else {
163
+ (async () => {
164
+ await this.commit("LMSCommit", false);
165
+ })();
166
+ }
163
167
  return APIConstants.global.SCORM_TRUE;
164
168
  }
165
169
 
@@ -290,9 +294,9 @@ export default class Scorm12API extends BaseAPI {
290
294
  /**
291
295
  * Replace the whole API with another
292
296
  *
293
- * @param {Scorm12API} newAPI
297
+ * @param {Scorm12Impl} newAPI
294
298
  */
295
- replaceWithAnotherScormAPI(newAPI: Scorm12API) {
299
+ replaceWithAnotherScormAPI(newAPI: Scorm12Impl) {
296
300
  // Data Model
297
301
  this.cmi = newAPI.cmi;
298
302
  }
@@ -424,18 +428,7 @@ export default class Scorm12API extends BaseAPI {
424
428
  }
425
429
  }
426
430
 
427
- const shouldTerminateCommit =
428
- terminateCommit || this.settings.alwaysSendTotalTime;
429
- const commitObject = this.settings.renderCommonCommitFields
430
- ? this.renderCommitObject(shouldTerminateCommit)
431
- : this.renderCommitCMI(shouldTerminateCommit);
432
-
433
- if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
434
- console.debug(
435
- "Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
436
- );
437
- console.debug(commitObject);
438
- }
431
+ const commitObject = this.getCommitObject(terminateCommit);
439
432
  if (typeof this.settings.lmsCommitUrl === "string") {
440
433
  return await this.processHttpRequest(
441
434
  this.settings.lmsCommitUrl,
@@ -450,3 +443,5 @@ export default class Scorm12API extends BaseAPI {
450
443
  }
451
444
  }
452
445
  }
446
+
447
+ export { Scorm12Impl };
@@ -30,7 +30,7 @@ import { CompletionStatus, SuccessStatus } from "./constants/enums";
30
30
  /**
31
31
  * API class for SCORM 2004
32
32
  */
33
- export default class Scorm2004API extends BaseAPI {
33
+ class Scorm2004Impl extends BaseAPI {
34
34
  private _version: string = "1.0";
35
35
 
36
36
  /**
@@ -180,9 +180,13 @@ export default class Scorm2004API extends BaseAPI {
180
180
  * @return {string} bool
181
181
  */
182
182
  lmsCommit(): string {
183
- (async () => {
184
- await this.commit("Commit");
185
- })();
183
+ if (this.settings.asyncCommit) {
184
+ this.scheduleCommit(500, "LMSCommit");
185
+ } else {
186
+ (async () => {
187
+ await this.commit("LMSCommit", false);
188
+ })();
189
+ }
186
190
  return APIConstants.global.SCORM_TRUE;
187
191
  }
188
192
 
@@ -581,9 +585,9 @@ export default class Scorm2004API extends BaseAPI {
581
585
 
582
586
  /**
583
587
  * Replace the whole API with another
584
- * @param {Scorm2004API} newAPI
588
+ * @param {Scorm2004Impl} newAPI
585
589
  */
586
- replaceWithAnotherScormAPI(newAPI: Scorm2004API) {
590
+ replaceWithAnotherScormAPI(newAPI: Scorm2004Impl) {
587
591
  // Data Model
588
592
  this.cmi = newAPI.cmi;
589
593
  this.adl = newAPI.adl;
@@ -718,18 +722,7 @@ export default class Scorm2004API extends BaseAPI {
718
722
  navRequest = true;
719
723
  }
720
724
 
721
- const shouldTerminateCommit =
722
- terminateCommit || this.settings.alwaysSendTotalTime;
723
- const commitObject = this.settings.renderCommonCommitFields
724
- ? this.renderCommitObject(shouldTerminateCommit)
725
- : this.renderCommitCMI(shouldTerminateCommit);
726
-
727
- if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
728
- console.debug(
729
- "Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
730
- );
731
- console.debug(commitObject);
732
- }
725
+ const commitObject = this.getCommitObject(terminateCommit);
733
726
  if (typeof this.settings.lmsCommitUrl === "string") {
734
727
  const result = await this.processHttpRequest(
735
728
  this.settings.lmsCommitUrl,
@@ -756,3 +749,5 @@ export default class Scorm2004API extends BaseAPI {
756
749
  }
757
750
  }
758
751
  }
752
+
753
+ export { Scorm2004Impl };
@@ -0,0 +1,9 @@
1
+ import { AICCImpl } from "./AICC";
2
+ import { Scorm12Impl } from "./Scorm12API";
3
+ import { Scorm2004Impl } from "./Scorm2004API";
4
+
5
+ const Scorm12API = Scorm12Impl;
6
+ const Scorm2004API = Scorm2004Impl;
7
+ const AICC = AICCImpl;
8
+
9
+ export { Scorm12API, Scorm2004API, AICC };
@@ -20,6 +20,7 @@ export const DefaultSettings: Settings = {
20
20
  strict_errors: true,
21
21
  xhrHeaders: {},
22
22
  xhrWithCredentials: false,
23
+ fetchMode: "cors",
23
24
  responseHandler: async function (response: Response): Promise<ResultObject> {
24
25
  if (typeof response !== "undefined") {
25
26
  const httpResult = JSON.parse(await response.text());
@@ -15,6 +15,7 @@ export type Settings = {
15
15
  strict_errors?: boolean;
16
16
  xhrHeaders?: RefObject;
17
17
  xhrWithCredentials?: boolean;
18
+ fetchMode?: "cors" | "no-cors" | "same-origin" | "navigate";
18
19
  responseHandler?: (response: Response) => Promise<ResultObject>;
19
20
  requestHandler?: (commitObject: any) => any;
20
21
  onLogMessage?: (messageLevel: number, logMessage: string) => void;
package/test/AICC.spec.ts CHANGED
@@ -2,12 +2,12 @@ import { expect } from "expect";
2
2
  import { describe } from "mocha";
3
3
  import * as h from "./api_helpers";
4
4
  import ErrorCodes from "../src/constants/error_codes";
5
- import AICC from "../src/AICC";
5
+ import { AICCImpl } from "../src/AICC";
6
6
 
7
7
  const scorm12_error_codes = ErrorCodes.scorm12;
8
8
 
9
9
  const api = () => {
10
- const API = new AICC();
10
+ const API = new AICCImpl();
11
11
  API.apiLogLevel = 1;
12
12
  return API;
13
13
  };
@@ -1,6 +1,6 @@
1
1
  import { expect } from "expect";
2
2
  import { after, before, describe, it } from "mocha";
3
- import Scorm12API from "../src/Scorm12API";
3
+ import { Scorm12Impl } from "../src/Scorm12API";
4
4
  import * as h from "./api_helpers";
5
5
  import ErrorCodes from "../src/constants/error_codes";
6
6
  import { scorm12Values } from "./field_values";
@@ -13,7 +13,7 @@ const scorm12_error_codes = ErrorCodes.scorm12;
13
13
 
14
14
  let clock: sinon.SinonFakeTimers;
15
15
  const api = (settings?: Settings, startingData: RefObject = {}) => {
16
- const API = new Scorm12API(settings);
16
+ const API = new Scorm12Impl(settings);
17
17
  API.apiLogLevel = 5;
18
18
  API.startingData = startingData;
19
19
  return API;
@@ -537,6 +537,77 @@ describe("SCORM 1.2 API Tests", () => {
537
537
  });
538
538
  });
539
539
 
540
+ describe("LMSCommit Debounce Tests", () => {
541
+ it("should debounce LMSCommit calls when autocommit is true", async () => {
542
+ const scorm12API = api({
543
+ ...DefaultSettings,
544
+ autocommit: true,
545
+ autocommitSeconds: 1,
546
+ });
547
+ scorm12API.lmsInitialize();
548
+
549
+ const commitSpy = sinon.spy(scorm12API, "commit");
550
+
551
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:01:00");
552
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:02:00");
553
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:03:00");
554
+
555
+ clock.tick(2000);
556
+ await clock.runAllAsync();
557
+
558
+ expect(commitSpy.calledOnce).toBe(true);
559
+ });
560
+
561
+ it("should call LMSCommit only once within the debounce period ", async () => {
562
+ const scorm12API = api({
563
+ ...DefaultSettings,
564
+ asyncCommit: true,
565
+ autocommit: true,
566
+ });
567
+ scorm12API.lmsInitialize();
568
+
569
+ const commitSpy = sinon.spy(scorm12API, "commit");
570
+
571
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:01:00");
572
+
573
+ scorm12API.lmsCommit();
574
+ clock.tick(100);
575
+
576
+ scorm12API.lmsCommit();
577
+ clock.tick(100);
578
+
579
+ scorm12API.lmsCommit();
580
+ clock.tick(100);
581
+
582
+ clock.tick(1000);
583
+ await clock.runAllAsync();
584
+
585
+ expect(commitSpy.calledOnce).toBe(true);
586
+ });
587
+
588
+ it("should call LMSCommit multiple times if debounce period is exceeded", async () => {
589
+ const scorm12API = api({
590
+ ...DefaultSettings,
591
+ autocommit: true,
592
+ autocommitSeconds: 1,
593
+ });
594
+ scorm12API.lmsInitialize();
595
+
596
+ const commitSpy = sinon.spy(scorm12API, "commit");
597
+
598
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:01:00");
599
+ clock.tick(2000);
600
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:02:00");
601
+ clock.tick(2000);
602
+ scorm12API.lmsSetValue("cmi.core.session_time", "00:03:00");
603
+
604
+ clock.tick(2000);
605
+ await clock.runAllAsync();
606
+
607
+ expect(commitSpy.calledThrice).toBe(true);
608
+ });
609
+ });
610
+
540
611
  describe("Event Handlers", () => {
541
612
  it("Should handle SetValue.cmi.core.student_name event", () => {
542
613
  const scorm12API = apiInitialized();