scorm-again 2.4.0 → 2.5.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 (61) hide show
  1. package/README.md +23 -23
  2. package/dist/aicc.js +65 -41
  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 +65 -41
  7. package/dist/esm/aicc.js.map +1 -1
  8. package/dist/esm/aicc.min.js +1 -1
  9. package/dist/esm/aicc.min.js.map +1 -1
  10. package/dist/esm/scorm-again.js +78 -48
  11. package/dist/esm/scorm-again.js.map +1 -1
  12. package/dist/esm/scorm-again.min.js +1 -1
  13. package/dist/esm/scorm-again.min.js.map +1 -1
  14. package/dist/esm/scorm12.js +65 -41
  15. package/dist/esm/scorm12.js.map +1 -1
  16. package/dist/esm/scorm12.min.js +1 -1
  17. package/dist/esm/scorm12.min.js.map +1 -1
  18. package/dist/esm/scorm2004.js +78 -48
  19. package/dist/esm/scorm2004.js.map +1 -1
  20. package/dist/esm/scorm2004.min.js +1 -1
  21. package/dist/esm/scorm2004.min.js.map +1 -1
  22. package/dist/scorm-again.js +78 -48
  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 +65 -41
  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 +78 -48
  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/package.json +4 -4
  35. package/src/AICC.ts +2 -2
  36. package/src/BaseAPI.ts +28 -66
  37. package/src/Scorm12API.ts +3 -3
  38. package/src/Scorm2004API.ts +11 -7
  39. package/src/cmi/aicc/attempts.ts +7 -7
  40. package/src/cmi/aicc/cmi.ts +4 -4
  41. package/src/cmi/aicc/core.ts +1 -1
  42. package/src/cmi/aicc/evaluation.ts +1 -1
  43. package/src/cmi/aicc/student_data.ts +2 -2
  44. package/src/cmi/aicc/student_preferences.ts +2 -2
  45. package/src/cmi/aicc/tries.ts +7 -7
  46. package/src/cmi/scorm12/cmi.ts +1 -1
  47. package/src/cmi/scorm12/interactions.ts +1 -1
  48. package/src/cmi/scorm2004/adl.ts +2 -2
  49. package/src/cmi/scorm2004/cmi.ts +1 -1
  50. package/src/cmi/scorm2004/interactions.ts +1 -1
  51. package/src/cmi/scorm2004/objectives.ts +1 -1
  52. package/src/cmi/scorm2004/score.ts +1 -1
  53. package/src/constants/api_constants.ts +0 -10
  54. package/src/constants/default_settings.ts +25 -8
  55. package/src/constants/enums.ts +9 -0
  56. package/src/constants/regex.ts +1 -1
  57. package/src/exceptions.ts +1 -5
  58. package/src/types/api_types.ts +26 -3
  59. package/test/Scorm12API.spec.ts +101 -1
  60. package/test/types/api_types.spec.ts +38 -45
  61. package/tsconfig.json +1 -0
@@ -1,5 +1,6 @@
1
- import { ResultObject, Settings } from "../types/api_types";
1
+ import { LogLevel, ResultObject, Settings } from "../types/api_types";
2
2
  import APIConstants from "./api_constants";
3
+ import { LogLevelEnum } from "./enums";
3
4
 
4
5
  /**
5
6
  * Default settings for the SCORM API
@@ -13,7 +14,7 @@ export const DefaultSettings: Settings = {
13
14
  dataCommitFormat: "json",
14
15
  commitRequestDataType: "application/json;charset=UTF-8",
15
16
  autoProgress: false,
16
- logLevel: APIConstants.global.LOG_LEVEL_ERROR,
17
+ logLevel: LogLevelEnum.ERROR,
17
18
  selfReportSessionTime: false,
18
19
  alwaysSendTotalTime: false,
19
20
  renderCommonCommitFields: false,
@@ -23,7 +24,11 @@ export const DefaultSettings: Settings = {
23
24
  fetchMode: "cors",
24
25
  responseHandler: async function (response: Response): Promise<ResultObject> {
25
26
  if (typeof response !== "undefined") {
26
- const httpResult = JSON.parse(await response.text());
27
+ const responseText = await response.text();
28
+ let httpResult = null;
29
+ if (responseText) {
30
+ httpResult = JSON.parse(responseText);
31
+ }
27
32
  if (
28
33
  httpResult === null ||
29
34
  !{}.hasOwnProperty.call(httpResult, "result")
@@ -58,18 +63,30 @@ export const DefaultSettings: Settings = {
58
63
  requestHandler: function (commitObject) {
59
64
  return commitObject;
60
65
  },
61
- onLogMessage: function (messageLevel, logMessage) {
66
+ onLogMessage: function (messageLevel: LogLevel, logMessage) {
62
67
  switch (messageLevel) {
63
- case APIConstants.global.LOG_LEVEL_ERROR:
68
+ case "4":
69
+ case 4:
70
+ case "ERROR":
71
+ case LogLevelEnum.ERROR:
64
72
  console.error(logMessage);
65
73
  break;
66
- case APIConstants.global.LOG_LEVEL_WARNING:
74
+ case "3":
75
+ case 3:
76
+ case "WARN":
77
+ case LogLevelEnum.WARN:
67
78
  console.warn(logMessage);
68
79
  break;
69
- case APIConstants.global.LOG_LEVEL_INFO:
80
+ case "2":
81
+ case 2:
82
+ case "INFO":
83
+ case LogLevelEnum.INFO:
70
84
  console.info(logMessage);
71
85
  break;
72
- case APIConstants.global.LOG_LEVEL_DEBUG:
86
+ case "1":
87
+ case 1:
88
+ case "DEBUG":
89
+ case LogLevelEnum.DEBUG:
73
90
  if (console.debug) {
74
91
  console.debug(logMessage);
75
92
  } else {
@@ -15,3 +15,12 @@ export enum CompletionStatus {
15
15
  incomplete = "incomplete",
16
16
  unknown = "unknown",
17
17
  }
18
+
19
+ export enum LogLevelEnum {
20
+ _,
21
+ DEBUG,
22
+ INFO,
23
+ WARN,
24
+ ERROR,
25
+ NONE,
26
+ }
@@ -78,7 +78,7 @@ const scorm2004 = {
78
78
  CMIResult:
79
79
  "^(correct|incorrect|unanticipated|neutral|-?([0-9]{1,4})(\\.[0-9]{1,18})?)$",
80
80
  NAVEvent:
81
- "^(previous|continue|exit|exitAll|abandon|abandonAll|suspendAll|_none_|(\\{target=\\S{0,}[a-zA-Z0-9-_]+})?choice|(\\{target=\\S{0,}[a-zA-Z0-9-_]+})?jump)$",
81
+ "^(previous|continue|exit|exitAll|abandon|abandonAll|suspendAll|_none_|(\\{target=(?<choice_target>\\S{0,}[a-zA-Z0-9-_]+)})?choice|(\\{target=(?<jump_target>\\S{0,}[a-zA-Z0-9-_]+)})?jump)$",
82
82
 
83
83
  NAVBoolean: "^(unknown|true|false$)",
84
84
  NAVTarget: "^{target=\\S{0,}[a-zA-Z0-9-_]+}$",
package/src/exceptions.ts CHANGED
@@ -26,10 +26,6 @@ export class BaseScormValidationError extends Error {
26
26
  get errorCode(): number {
27
27
  return this._errorCode;
28
28
  }
29
-
30
- setMessage(message: string) {
31
- this.message = message;
32
- }
33
29
  }
34
30
 
35
31
  /**
@@ -51,7 +47,7 @@ export class ValidationError
51
47
  detailedMessage?: string,
52
48
  ) {
53
49
  super(errorCode);
54
- this.setMessage(errorMessage);
50
+ this.message = errorMessage;
55
51
  this._errorMessage = errorMessage;
56
52
  if (detailedMessage) {
57
53
  this._detailedMessage = detailedMessage;
@@ -1,4 +1,8 @@
1
- import { CompletionStatus, SuccessStatus } from "../constants/enums";
1
+ import {
2
+ CompletionStatus,
3
+ LogLevelEnum,
4
+ SuccessStatus,
5
+ } from "../constants/enums";
2
6
 
3
7
  export type Settings = {
4
8
  autocommit?: boolean;
@@ -9,7 +13,7 @@ export type Settings = {
9
13
  dataCommitFormat?: string;
10
14
  commitRequestDataType?: string;
11
15
  autoProgress?: boolean;
12
- logLevel?: number;
16
+ logLevel?: LogLevel;
13
17
  selfReportSessionTime?: boolean;
14
18
  alwaysSendTotalTime?: boolean;
15
19
  strict_errors?: boolean;
@@ -18,7 +22,7 @@ export type Settings = {
18
22
  fetchMode?: "cors" | "no-cors" | "same-origin" | "navigate";
19
23
  responseHandler?: (response: Response) => Promise<ResultObject>;
20
24
  requestHandler?: (commitObject: any) => any;
21
- onLogMessage?: (messageLevel: number, logMessage: string) => void;
25
+ onLogMessage?: (messageLevel: LogLevel, logMessage: string) => void;
22
26
  scoItemIds?: string[];
23
27
  scoItemIdValidator?: false | ((scoItemId: string) => boolean);
24
28
  mastery_override?: boolean;
@@ -49,3 +53,22 @@ export type CommitObject = {
49
53
  runtimeData: RefObject;
50
54
  score?: ScoreObject;
51
55
  };
56
+
57
+ export type LogLevel =
58
+ | 1
59
+ | 2
60
+ | 3
61
+ | 4
62
+ | 5
63
+ | "1"
64
+ | "2"
65
+ | "3"
66
+ | "4"
67
+ | "5"
68
+ | "DEBUG"
69
+ | "INFO"
70
+ | "WARN"
71
+ | "ERROR"
72
+ | "NONE"
73
+ | LogLevelEnum
74
+ | undefined;
@@ -20,7 +20,7 @@ const api = (settings?: Settings, startingData: RefObject = {}) => {
20
20
  };
21
21
  const apiInitialized = (settings?: Settings, startingData: RefObject = {}) => {
22
22
  const API = api(settings);
23
- API.loadFromJSON(startingData ? startingData : {}, "");
23
+ API.loadFromJSON(startingData ? startingData : {});
24
24
  API.lmsInitialize();
25
25
  return API;
26
26
  };
@@ -51,6 +51,106 @@ describe("SCORM 1.2 API Tests", () => {
51
51
  clock.restore();
52
52
  });
53
53
 
54
+ describe("loadFromJSON()", () => {
55
+ it("should load JSON data into the CMI object", () => {
56
+ const scorm12API = api();
57
+ const jsonData = {
58
+ cmi: {
59
+ core: {
60
+ student_id: "student_1",
61
+ student_name: "John Doe",
62
+ lesson_status: "incomplete",
63
+ },
64
+ },
65
+ };
66
+
67
+ scorm12API.loadFromJSON(jsonData);
68
+ scorm12API.lmsInitialize();
69
+
70
+ expect(scorm12API.cmi.core.student_id).toEqual("student_1");
71
+ expect(scorm12API.cmi.core.student_name).toEqual("John Doe");
72
+ expect(scorm12API.cmi.core.lesson_status).toEqual("incomplete");
73
+ });
74
+
75
+ it("should load nested JSON data into the CMI object", () => {
76
+ const scorm12API = api();
77
+ const jsonData = {
78
+ cmi: {
79
+ objectives: {
80
+ "0": {
81
+ id: "obj_1",
82
+ score: {
83
+ raw: "85",
84
+ min: "0",
85
+ max: "100",
86
+ },
87
+ },
88
+ },
89
+ },
90
+ };
91
+
92
+ scorm12API.loadFromJSON(jsonData);
93
+
94
+ expect(scorm12API.cmi.objectives.childArray[0].id).toEqual("obj_1");
95
+ expect(scorm12API.cmi.objectives.childArray[0].score.raw).toEqual("85");
96
+ expect(scorm12API.cmi.objectives.childArray[0].score.min).toEqual("0");
97
+ expect(scorm12API.cmi.objectives.childArray[0].score.max).toEqual("100");
98
+ });
99
+
100
+ it("should load nested cmi JSON data into the CMI object", () => {
101
+ const scorm12API = api();
102
+ const jsonData = {
103
+ objectives: {
104
+ "0": {
105
+ id: "obj_1",
106
+ score: {
107
+ raw: "85",
108
+ min: "0",
109
+ max: "100",
110
+ },
111
+ },
112
+ },
113
+ };
114
+
115
+ scorm12API.loadFromJSON(jsonData, "cmi");
116
+
117
+ expect(scorm12API.cmi.objectives.childArray[0].id).toEqual("obj_1");
118
+ expect(scorm12API.cmi.objectives.childArray[0].score.raw).toEqual("85");
119
+ expect(scorm12API.cmi.objectives.childArray[0].score.min).toEqual("0");
120
+ expect(scorm12API.cmi.objectives.childArray[0].score.max).toEqual("100");
121
+ });
122
+
123
+ it("should handle empty JSON data", () => {
124
+ const scorm12API = api();
125
+ const jsonData = {};
126
+
127
+ scorm12API.loadFromJSON(jsonData);
128
+
129
+ expect(scorm12API.cmi.core.student_id).toBeFalsy();
130
+ expect(scorm12API.cmi.core.student_name).toBeFalsy();
131
+ expect(scorm12API.cmi.core.lesson_status).toBe("not attempted");
132
+ });
133
+
134
+ it("should not load data if API is initialized", () => {
135
+ const scorm12API = apiInitialized();
136
+ const jsonData = {
137
+ cmi: {
138
+ core: {
139
+ student_id: "student_1",
140
+ student_name: "John Doe",
141
+ lesson_status: "incomplete",
142
+ },
143
+ },
144
+ };
145
+
146
+ scorm12API.loadFromJSON(jsonData);
147
+
148
+ expect(scorm12API.cmi.core.student_id).toBeFalsy();
149
+ expect(scorm12API.cmi.core.student_name).toBeFalsy();
150
+ expect(scorm12API.cmi.core.lesson_status).toBe("not attempted");
151
+ });
152
+ });
153
+
54
154
  describe("LMSSetValue()", () => {
55
155
  h.checkValidValues({
56
156
  api: apiInitialized(),
@@ -1,7 +1,10 @@
1
1
  import { expect } from "expect";
2
2
  import * as sinon from "sinon";
3
- import { ResultObject, Settings } from "../../src/types/api_types";
3
+ import { LogLevel, ResultObject, Settings } from "../../src/types/api_types";
4
4
  import APIConstants from "../../src/constants/api_constants";
5
+ import { LogLevelEnum } from "../../src/constants/enums";
6
+ import { DefaultSettings } from "../../src/constants/default_settings";
7
+ import { SinonStub } from "sinon";
5
8
 
6
9
  describe("Settings Type", () => {
7
10
  const defaultSettings: Settings = {
@@ -13,7 +16,7 @@ describe("Settings Type", () => {
13
16
  dataCommitFormat: "json",
14
17
  commitRequestDataType: "application/json;charset=UTF-8",
15
18
  autoProgress: false,
16
- logLevel: APIConstants.global.LOG_LEVEL_ERROR,
19
+ logLevel: LogLevelEnum.ERROR,
17
20
  selfReportSessionTime: false,
18
21
  alwaysSendTotalTime: false,
19
22
  strict_errors: true,
@@ -28,26 +31,7 @@ describe("Settings Type", () => {
28
31
  };
29
32
  },
30
33
  requestHandler: (commitObject: any) => commitObject,
31
- onLogMessage: (messageLevel: number, logMessage: string) => {
32
- switch (messageLevel) {
33
- case APIConstants.global.LOG_LEVEL_ERROR:
34
- console.error(logMessage);
35
- break;
36
- case APIConstants.global.LOG_LEVEL_WARNING:
37
- console.warn(logMessage);
38
- break;
39
- case APIConstants.global.LOG_LEVEL_INFO:
40
- console.info(logMessage);
41
- break;
42
- case APIConstants.global.LOG_LEVEL_DEBUG:
43
- if (console.debug) {
44
- console.debug(logMessage);
45
- } else {
46
- console.log(logMessage);
47
- }
48
- break;
49
- }
50
- },
34
+ onLogMessage: DefaultSettings.onLogMessage,
51
35
  };
52
36
 
53
37
  it("should have correct default values", () => {
@@ -61,9 +45,7 @@ describe("Settings Type", () => {
61
45
  "application/json;charset=UTF-8",
62
46
  );
63
47
  expect(defaultSettings.autoProgress).toBe(false);
64
- expect(defaultSettings.logLevel).toEqual(
65
- APIConstants.global.LOG_LEVEL_ERROR,
66
- );
48
+ expect(defaultSettings.logLevel).toEqual(LogLevelEnum.ERROR);
67
49
  expect(defaultSettings.selfReportSessionTime).toBe(false);
68
50
  expect(defaultSettings.alwaysSendTotalTime).toBe(false);
69
51
  expect(defaultSettings.strict_errors).toBe(true);
@@ -93,29 +75,40 @@ describe("Settings Type", () => {
93
75
  const consoleDebugStub = sinon.stub(console, "debug");
94
76
  const consoleLogStub = sinon.stub(console, "log");
95
77
 
96
- defaultSettings.onLogMessage(
97
- APIConstants.global.LOG_LEVEL_ERROR,
98
- "Error message",
99
- );
100
- expect(consoleErrorStub.calledWith("Error message")).toBe(true);
78
+ const testLog = function (
79
+ stub: SinonStub,
80
+ level: LogLevel,
81
+ shouldBeLogged = true,
82
+ ) {
83
+ const message = `${level} message - ${typeof level}`;
84
+ defaultSettings.onLogMessage(level, message);
85
+ expect(stub.calledWith(message)).toBe(shouldBeLogged);
86
+ };
101
87
 
102
- defaultSettings.onLogMessage(
103
- APIConstants.global.LOG_LEVEL_WARNING,
104
- "Warning message",
105
- );
106
- expect(consoleWarnStub.calledWith("Warning message")).toBe(true);
88
+ testLog(consoleErrorStub, LogLevelEnum.ERROR);
89
+ testLog(consoleErrorStub, 4);
90
+ testLog(consoleErrorStub, "4");
91
+ testLog(consoleErrorStub, "ERROR");
107
92
 
108
- defaultSettings.onLogMessage(
109
- APIConstants.global.LOG_LEVEL_INFO,
110
- "Info message",
111
- );
112
- expect(consoleInfoStub.calledWith("Info message")).toBe(true);
93
+ testLog(consoleWarnStub, LogLevelEnum.WARN);
94
+ testLog(consoleWarnStub, 3);
95
+ testLog(consoleWarnStub, "3");
96
+ testLog(consoleWarnStub, "WARN");
113
97
 
114
- defaultSettings.onLogMessage(
115
- APIConstants.global.LOG_LEVEL_DEBUG,
116
- "Debug message",
117
- );
118
- expect(consoleDebugStub.calledWith("Debug message")).toBe(true);
98
+ testLog(consoleInfoStub, LogLevelEnum.INFO);
99
+ testLog(consoleInfoStub, 2);
100
+ testLog(consoleInfoStub, "2");
101
+ testLog(consoleInfoStub, "INFO");
102
+
103
+ testLog(consoleDebugStub, LogLevelEnum.DEBUG);
104
+ testLog(consoleDebugStub, 1);
105
+ testLog(consoleDebugStub, "1");
106
+ testLog(consoleDebugStub, "DEBUG");
107
+
108
+ testLog(consoleLogStub, LogLevelEnum.NONE, false);
109
+ testLog(consoleLogStub, 5, false);
110
+ testLog(consoleLogStub, "5", false);
111
+ testLog(consoleLogStub, "NONE", false);
119
112
 
120
113
  consoleErrorStub.restore();
121
114
  consoleWarnStub.restore();
package/tsconfig.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "sourceMap": true,
4
4
  "noImplicitAny": true,
5
+ "noImplicitOverride": true,
5
6
  "declaration": false,
6
7
  "module": "es2015",
7
8
  "moduleResolution": "Node",