scorm-again 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/stale.yml +14 -0
- package/.run/{Mocha Unit Tests.run.xml → Mocha Unit Tests (watch).run.xml } +1 -1
- package/.run/Template Mocha.run.xml +17 -0
- package/README.md +171 -72
- package/dist/aicc.js +1441 -1140
- package/dist/aicc.js.map +1 -1
- package/dist/aicc.min.js +1 -1
- package/dist/aicc.min.js.map +1 -1
- package/dist/scorm-again.js +2703 -2212
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm-again.min.js.map +1 -1
- package/dist/scorm12.js +1069 -852
- package/dist/scorm12.js.map +1 -1
- package/dist/scorm12.min.js +1 -1
- package/dist/scorm12.min.js.map +1 -1
- package/dist/scorm2004.js +1861 -1571
- package/dist/scorm2004.js.map +1 -1
- package/dist/scorm2004.min.js +1 -1
- package/dist/scorm2004.min.js.map +1 -1
- package/package.json +10 -6
- package/src/AICC.ts +15 -17
- package/src/BaseAPI.ts +268 -417
- package/src/Scorm12API.ts +65 -38
- package/src/Scorm2004API.ts +151 -117
- package/src/cmi/aicc/attempts.ts +94 -0
- package/src/cmi/aicc/cmi.ts +100 -0
- package/src/cmi/aicc/core.ts +360 -0
- package/src/cmi/aicc/evaluation.ts +157 -0
- package/src/cmi/aicc/paths.ts +180 -0
- package/src/cmi/aicc/student_data.ts +86 -0
- package/src/cmi/aicc/student_demographics.ts +367 -0
- package/src/cmi/aicc/student_preferences.ts +176 -0
- package/src/cmi/aicc/tries.ts +116 -0
- package/src/cmi/aicc/validation.ts +25 -0
- package/src/cmi/common/array.ts +77 -0
- package/src/cmi/common/base_cmi.ts +46 -0
- package/src/cmi/common/score.ts +203 -0
- package/src/cmi/common/validation.ts +60 -0
- package/src/cmi/scorm12/cmi.ts +224 -0
- package/src/cmi/scorm12/interactions.ts +368 -0
- package/src/cmi/scorm12/nav.ts +54 -0
- package/src/cmi/scorm12/objectives.ts +112 -0
- package/src/cmi/scorm12/student_data.ts +130 -0
- package/src/cmi/scorm12/student_preference.ts +158 -0
- package/src/cmi/scorm12/validation.ts +48 -0
- package/src/cmi/scorm2004/adl.ts +272 -0
- package/src/cmi/scorm2004/cmi.ts +599 -0
- package/src/cmi/scorm2004/comments.ts +163 -0
- package/src/cmi/scorm2004/interactions.ts +466 -0
- package/src/cmi/scorm2004/learner_preference.ts +152 -0
- package/src/cmi/scorm2004/objectives.ts +212 -0
- package/src/cmi/scorm2004/score.ts +78 -0
- package/src/cmi/scorm2004/validation.ts +42 -0
- package/src/constants/default_settings.ts +81 -0
- package/src/constants/enums.ts +5 -0
- package/src/constants/regex.ts +2 -2
- package/src/constants/response_constants.ts +2 -0
- package/src/exceptions.ts +22 -1
- package/src/helpers/scheduled_commit.ts +42 -0
- package/src/interfaces/IBaseAPI.ts +35 -0
- package/src/types/api_types.ts +32 -0
- package/src/utilities/debounce.ts +31 -0
- package/src/utilities.ts +56 -0
- package/test/AICC.spec.ts +11 -1
- package/test/Scorm12API.spec.ts +262 -9
- package/test/Scorm2004API.spec.ts +488 -2
- package/test/cmi/aicc_cmi.spec.ts +188 -11
- package/test/cmi/scorm12_cmi.spec.ts +5 -5
- package/test/cmi/scorm2004_cmi.spec.ts +8 -8
- package/test/cmi_helpers.ts +1 -1
- package/test/types/api_types.spec.ts +126 -0
- package/test/utilities/debounce.spec.ts +56 -0
- package/src/cmi/aicc_cmi.ts +0 -1248
- package/src/cmi/common.ts +0 -411
- package/src/cmi/scorm12_cmi.ts +0 -1426
- package/src/cmi/scorm2004_cmi.ts +0 -1874
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { expect } from "expect";
|
|
2
|
-
import {
|
|
2
|
+
import { after, before, describe, it } from "mocha";
|
|
3
3
|
import * as sinon from "sinon";
|
|
4
4
|
import * as h from "./api_helpers";
|
|
5
5
|
import Pretender from "fetch-pretender";
|
|
6
6
|
import ErrorCodes from "../src/constants/error_codes";
|
|
7
7
|
import Scorm2004API from "../src/Scorm2004API";
|
|
8
8
|
import { scorm2004Values } from "./field_values";
|
|
9
|
-
import
|
|
9
|
+
import APIConstants from "../src/constants/api_constants";
|
|
10
|
+
import { RefObject, Settings } from "../src/types/api_types";
|
|
11
|
+
import { DefaultSettings } from "../src/constants/default_settings";
|
|
12
|
+
import { CMI } from "../src/cmi/scorm2004/cmi";
|
|
10
13
|
|
|
11
14
|
const scorm2004_error_codes = ErrorCodes.scorm2004;
|
|
12
15
|
|
|
@@ -27,6 +30,9 @@ const apiInitialized = (startingData?: RefObject) => {
|
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
describe("SCORM 2004 API Tests", () => {
|
|
33
|
+
let terminateStub: sinon.SinonStub;
|
|
34
|
+
let processListenersSpy: sinon.SinonSpy;
|
|
35
|
+
|
|
30
36
|
before(() => {
|
|
31
37
|
clock = sinon.useFakeTimers();
|
|
32
38
|
|
|
@@ -581,6 +587,158 @@ describe("SCORM 2004 API Tests", () => {
|
|
|
581
587
|
});
|
|
582
588
|
});
|
|
583
589
|
|
|
590
|
+
describe("reset()", () => {
|
|
591
|
+
it("should reset all CMI values to their default state", () => {
|
|
592
|
+
const scorm2004API = api();
|
|
593
|
+
scorm2004API.cmi.learner_id = "student_1";
|
|
594
|
+
scorm2004API.cmi.session_time = "PT1H0M0S";
|
|
595
|
+
|
|
596
|
+
scorm2004API.reset();
|
|
597
|
+
|
|
598
|
+
expect(scorm2004API.cmi).toEqual(new CMI());
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it("should keep original settings", () => {
|
|
602
|
+
const scorm2004API = api({
|
|
603
|
+
dataCommitFormat: "flattened",
|
|
604
|
+
autocommit: true,
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
scorm2004API.reset();
|
|
608
|
+
|
|
609
|
+
expect(scorm2004API.settings.sendFullCommit).toEqual(
|
|
610
|
+
DefaultSettings.sendFullCommit,
|
|
611
|
+
);
|
|
612
|
+
expect(scorm2004API.settings.dataCommitFormat).toEqual("flattened");
|
|
613
|
+
expect(scorm2004API.settings.autocommit).toEqual(true);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it("should be able to override original settings", () => {
|
|
617
|
+
const scorm2004API = api({
|
|
618
|
+
...DefaultSettings,
|
|
619
|
+
dataCommitFormat: "flattened",
|
|
620
|
+
autocommit: true,
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
scorm2004API.reset({
|
|
624
|
+
alwaysSendTotalTime: !DefaultSettings.alwaysSendTotalTime,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
expect(scorm2004API.settings.sendFullCommit).toEqual(
|
|
628
|
+
DefaultSettings.sendFullCommit,
|
|
629
|
+
);
|
|
630
|
+
expect(scorm2004API.settings.dataCommitFormat).toEqual("flattened");
|
|
631
|
+
expect(scorm2004API.settings.autocommit).toEqual(true);
|
|
632
|
+
expect(scorm2004API.settings.alwaysSendTotalTime).toEqual(
|
|
633
|
+
!DefaultSettings.alwaysSendTotalTime,
|
|
634
|
+
);
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
it("should call commonReset from the superclass", () => {
|
|
638
|
+
const scorm2004API = api();
|
|
639
|
+
const commonResetSpy = sinon.spy(scorm2004API, "commonReset");
|
|
640
|
+
|
|
641
|
+
scorm2004API.reset();
|
|
642
|
+
|
|
643
|
+
expect(commonResetSpy.calledOnce).toBe(true);
|
|
644
|
+
commonResetSpy.restore();
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
describe("Scorm2004API.Finish", () => {
|
|
649
|
+
let scorm2004API = api();
|
|
650
|
+
|
|
651
|
+
beforeEach(() => {
|
|
652
|
+
scorm2004API = api();
|
|
653
|
+
terminateStub = sinon.stub(scorm2004API, "terminate");
|
|
654
|
+
processListenersSpy = sinon.spy(scorm2004API, "processListeners");
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
afterEach(() => {
|
|
658
|
+
terminateStub.restore();
|
|
659
|
+
processListenersSpy.restore();
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
describe("lmsFinish()", () => {
|
|
663
|
+
it("should call internalFinish and return SCORM_TRUE", async () => {
|
|
664
|
+
const internalFinishStub = sinon
|
|
665
|
+
.stub(scorm2004API, "internalFinish")
|
|
666
|
+
.resolves(APIConstants.global.SCORM_TRUE);
|
|
667
|
+
const result = scorm2004API.lmsFinish();
|
|
668
|
+
expect(result).toEqual(APIConstants.global.SCORM_TRUE);
|
|
669
|
+
expect(internalFinishStub.calledOnce).toBe(true);
|
|
670
|
+
internalFinishStub.restore();
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
describe("internalFinish()", () => {
|
|
675
|
+
const navActions: { [key: string]: string } = {
|
|
676
|
+
previous: "SequencePrevious",
|
|
677
|
+
continue: "SequenceNext",
|
|
678
|
+
choice: "SequenceChoice",
|
|
679
|
+
jump: "SequenceJump",
|
|
680
|
+
"{target=next-sco}choice": "SequenceChoice",
|
|
681
|
+
exit: "SequenceExit",
|
|
682
|
+
exitAll: "SequenceExitAll",
|
|
683
|
+
abandon: "SequenceAbandon",
|
|
684
|
+
abandonAll: "SequenceAbandonAll",
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
it("should call terminate with 'Terminate' and true", async () => {
|
|
688
|
+
terminateStub.resolves(APIConstants.global.SCORM_TRUE);
|
|
689
|
+
await scorm2004API.internalFinish();
|
|
690
|
+
expect(terminateStub.calledWith("Terminate", true)).toBe(true);
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
for (const navRequest of Object.keys(navActions)) {
|
|
694
|
+
it(`should process the correct navigation action based on adl.nav.request = ${navRequest}`, async () => {
|
|
695
|
+
terminateStub.resolves(APIConstants.global.SCORM_TRUE);
|
|
696
|
+
scorm2004API.adl.nav.request = navRequest;
|
|
697
|
+
await scorm2004API.internalFinish();
|
|
698
|
+
expect(processListenersSpy.calledWith(navActions[navRequest])).toBe(
|
|
699
|
+
true,
|
|
700
|
+
);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
it("should process 'SequenceNext' if adl.nav.request is '_none_' and autoProgress is true", async () => {
|
|
705
|
+
terminateStub.resolves(APIConstants.global.SCORM_TRUE);
|
|
706
|
+
scorm2004API.adl.nav.request = "_none_";
|
|
707
|
+
scorm2004API.settings.autoProgress = true;
|
|
708
|
+
await scorm2004API.internalFinish();
|
|
709
|
+
expect(processListenersSpy.calledWith("SequenceNext")).toBe(true);
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
it("should not process any action if adl.nav.request is '_none_' and autoProgress is false", async () => {
|
|
713
|
+
terminateStub.resolves(APIConstants.global.SCORM_TRUE);
|
|
714
|
+
scorm2004API.adl.nav.request = "_none_";
|
|
715
|
+
scorm2004API.settings.autoProgress = false;
|
|
716
|
+
await scorm2004API.internalFinish();
|
|
717
|
+
expect(processListenersSpy.called).toBe(false);
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
it("should return the result of terminate", async () => {
|
|
721
|
+
terminateStub.resolves(APIConstants.global.SCORM_TRUE);
|
|
722
|
+
const result = await scorm2004API.internalFinish();
|
|
723
|
+
expect(result).toEqual(APIConstants.global.SCORM_TRUE);
|
|
724
|
+
});
|
|
725
|
+
});
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
describe("lmsCommit()", () => {
|
|
729
|
+
const scorm2004API = api();
|
|
730
|
+
|
|
731
|
+
it("should call commit and return SCORM_TRUE", async () => {
|
|
732
|
+
const commitStub = sinon
|
|
733
|
+
.stub(scorm2004API, "commit")
|
|
734
|
+
.resolves(APIConstants.global.SCORM_TRUE);
|
|
735
|
+
const result = scorm2004API.lmsCommit();
|
|
736
|
+
expect(result).toEqual(APIConstants.global.SCORM_TRUE);
|
|
737
|
+
expect(commitStub.calledOnce).toBe(true);
|
|
738
|
+
commitStub.restore();
|
|
739
|
+
});
|
|
740
|
+
});
|
|
741
|
+
|
|
584
742
|
describe("loadFromFlattenedJSON()", () => {
|
|
585
743
|
it("should load data, even if out of order", () => {
|
|
586
744
|
const scorm2004API = api();
|
|
@@ -599,6 +757,8 @@ describe("SCORM 2004 API Tests", () => {
|
|
|
599
757
|
"cmi.interactions.0.latency": "PT2M30S",
|
|
600
758
|
"cmi.interactions.0.objectives.0.id": "Question14_1",
|
|
601
759
|
"cmi.interactions.0.objectives.0.correct_responses.0.pattern": "CPR",
|
|
760
|
+
"adl.nav.request": "continue",
|
|
761
|
+
"adl.nav.request_valid.choice.{target=sco-id}": "true",
|
|
602
762
|
},
|
|
603
763
|
"",
|
|
604
764
|
);
|
|
@@ -617,6 +777,281 @@ describe("SCORM 2004 API Tests", () => {
|
|
|
617
777
|
const cmiExport: RefObject = scorm2004API.renderCommitCMI(true);
|
|
618
778
|
expect(cmiExport.cmi.total_time).toEqual("P1DT12H34M55S");
|
|
619
779
|
});
|
|
780
|
+
|
|
781
|
+
it("should return flattened format when dataCommitFormat is 'flattened'", function () {
|
|
782
|
+
const scorm2004API = api({
|
|
783
|
+
...DefaultSettings,
|
|
784
|
+
dataCommitFormat: "flattened",
|
|
785
|
+
});
|
|
786
|
+
const result = scorm2004API.renderCommitCMI(false);
|
|
787
|
+
expect(result).toBeInstanceOf(Object);
|
|
788
|
+
expect({}.hasOwnProperty.call(result, "cmi.learner_id")).toBe(true);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it("should return params format when dataCommitFormat is 'params'", function () {
|
|
792
|
+
const scorm2004API = api();
|
|
793
|
+
scorm2004API.settings.dataCommitFormat = "params";
|
|
794
|
+
const result = scorm2004API.renderCommitCMI(false);
|
|
795
|
+
expect(result).toBeInstanceOf(Array);
|
|
796
|
+
expect(result).toContain("cmi.credit=credit");
|
|
797
|
+
// Add more specific assertions based on expected params output
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
it("should return JSON format when dataCommitFormat is 'json'", function () {
|
|
801
|
+
const scorm2004API = api();
|
|
802
|
+
scorm2004API.settings.dataCommitFormat = "json";
|
|
803
|
+
const result = scorm2004API.renderCommitCMI(false) as any;
|
|
804
|
+
expect(result).toBeInstanceOf(Object);
|
|
805
|
+
expect(result).toHaveProperty("cmi");
|
|
806
|
+
expect(result.cmi).toBeInstanceOf(Object);
|
|
807
|
+
expect(result.cmi.credit).toEqual("credit");
|
|
808
|
+
// Add more specific assertions based on expected JSON output
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
it("should include total_time if terminateCommit is true", function () {
|
|
812
|
+
const scorm2004API = api();
|
|
813
|
+
const spy = sinon.spy(scorm2004API.cmi, "getCurrentTotalTime");
|
|
814
|
+
const cmiExport = scorm2004API.renderCommitCMI(true) as any;
|
|
815
|
+
expect(spy.calledOnce).toBe(true);
|
|
816
|
+
expect(cmiExport.cmi.total_time).toEqual(spy.returnValues[0]);
|
|
817
|
+
spy.restore();
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
it("should not include total_time if terminateCommit is false", function () {
|
|
821
|
+
const scorm2004API = api();
|
|
822
|
+
const spy = sinon.spy(scorm2004API.cmi, "getCurrentTotalTime");
|
|
823
|
+
const cmiExport = scorm2004API.renderCommitCMI(false) as any;
|
|
824
|
+
expect(spy.called).toBe(false);
|
|
825
|
+
expect(cmiExport.cmi).not.toHaveProperty("total_time");
|
|
826
|
+
spy.restore();
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
describe("lmsGetDiagnostic()", () => {
|
|
831
|
+
it("should return diagnostic information for a given error code", () => {
|
|
832
|
+
const scorm2004API = api();
|
|
833
|
+
const errorCode = scorm2004_error_codes.GENERAL;
|
|
834
|
+
const diagnosticInfo = scorm2004API.lmsGetDiagnostic(errorCode);
|
|
835
|
+
expect(diagnosticInfo).toEqual(
|
|
836
|
+
APIConstants.scorm2004.error_descriptions[errorCode].detailMessage,
|
|
837
|
+
);
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
it("should return an empty string for an unknown error code", () => {
|
|
841
|
+
const scorm2004API = api();
|
|
842
|
+
const unknownErrorCode = 9999;
|
|
843
|
+
const diagnosticInfo = scorm2004API.lmsGetDiagnostic(unknownErrorCode);
|
|
844
|
+
expect(diagnosticInfo).toEqual("");
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
describe("lmsGetErrorString()", () => {
|
|
849
|
+
it("should return the error string for a given error code", () => {
|
|
850
|
+
const scorm2004API = api();
|
|
851
|
+
const errorCode = scorm2004_error_codes.GENERAL;
|
|
852
|
+
const errorString = scorm2004API.lmsGetErrorString(errorCode);
|
|
853
|
+
expect(errorString).toEqual("General Exception");
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
it("should return an empty string for an unknown error code", () => {
|
|
857
|
+
const scorm2004API = api();
|
|
858
|
+
const unknownErrorCode = 9999;
|
|
859
|
+
const errorString = scorm2004API.lmsGetErrorString(unknownErrorCode);
|
|
860
|
+
expect(errorString).toEqual("");
|
|
861
|
+
});
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
describe("replaceWithAnotherScormAPI()", () => {
|
|
865
|
+
it("should replace the current API with another API", () => {
|
|
866
|
+
const firstAPI = api();
|
|
867
|
+
const secondAPI = api();
|
|
868
|
+
|
|
869
|
+
firstAPI.cmi.learner_id = "student_1";
|
|
870
|
+
firstAPI.adl.nav.request = "continue";
|
|
871
|
+
secondAPI.cmi.learner_id = "student_2";
|
|
872
|
+
secondAPI.adl.nav.request = "exit";
|
|
873
|
+
|
|
874
|
+
firstAPI.replaceWithAnotherScormAPI(secondAPI);
|
|
875
|
+
expect(firstAPI.cmi.learner_id).toEqual("student_2");
|
|
876
|
+
expect(firstAPI.adl.nav.request).toEqual("exit");
|
|
877
|
+
});
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
describe("checkCorrectResponseValue()", () => {
|
|
881
|
+
it("should properly handle the true-false response type for unknown value", () => {
|
|
882
|
+
const scorm2004API = new Scorm2004API();
|
|
883
|
+
scorm2004API.checkCorrectResponseValue("true-false", ["unknown"], "true");
|
|
884
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
885
|
+
String(scorm2004_error_codes.TYPE_MISMATCH),
|
|
886
|
+
);
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
it("should properly handle the true-false response type for correct value", () => {
|
|
890
|
+
const scorm2004API = new Scorm2004API();
|
|
891
|
+
scorm2004API.checkCorrectResponseValue("true-false", ["true"], "true");
|
|
892
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(String(0));
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
it("should properly handle the choice response type for value over 4000 characters", () => {
|
|
896
|
+
const scorm2004API = new Scorm2004API();
|
|
897
|
+
scorm2004API.checkCorrectResponseValue(
|
|
898
|
+
"choice",
|
|
899
|
+
["x".repeat(4001)],
|
|
900
|
+
"true",
|
|
901
|
+
);
|
|
902
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
903
|
+
String(scorm2004_error_codes.TYPE_MISMATCH),
|
|
904
|
+
);
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it("should properly handle the choice response type for correct value", () => {
|
|
908
|
+
const scorm2004API = new Scorm2004API();
|
|
909
|
+
scorm2004API.checkCorrectResponseValue("choice", ["true"], "true");
|
|
910
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(String(0));
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
it("should properly handle the fill-in response type for correct value", () => {
|
|
914
|
+
const scorm2004API = new Scorm2004API();
|
|
915
|
+
scorm2004API.checkCorrectResponseValue("fill-in", ["true"], "true");
|
|
916
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(String(0));
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
it("should properly handle the long-fill-in response type for correct value", () => {
|
|
920
|
+
const scorm2004API = new Scorm2004API();
|
|
921
|
+
scorm2004API.checkCorrectResponseValue("long-fill-in", ["true"], "true");
|
|
922
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(String(0));
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
it("should properly handle the matching response type for correct value", () => {
|
|
926
|
+
const scorm2004API = new Scorm2004API();
|
|
927
|
+
scorm2004API.checkCorrectResponseValue(
|
|
928
|
+
"matching",
|
|
929
|
+
["{order_matters=true}0[.]1"],
|
|
930
|
+
"true",
|
|
931
|
+
);
|
|
932
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(String(0));
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
describe("removeCorrectResponsePrefixes()", () => {
|
|
937
|
+
it("should remove the prefix from the string", () => {
|
|
938
|
+
const scorm2004API = new Scorm2004API();
|
|
939
|
+
const input = "{order_matters=true}correctResponse";
|
|
940
|
+
const result = scorm2004API.removeCorrectResponsePrefixes(input);
|
|
941
|
+
expect(result).toBe("correctResponse");
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it("should return the original string if no prefix is present", () => {
|
|
945
|
+
const scorm2004API = new Scorm2004API();
|
|
946
|
+
const input = "correctResponse";
|
|
947
|
+
const result = scorm2004API.removeCorrectResponsePrefixes(input);
|
|
948
|
+
expect(result).toBe("correctResponse");
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
it("should handle empty strings correctly", () => {
|
|
952
|
+
const scorm2004API = new Scorm2004API();
|
|
953
|
+
const input = "";
|
|
954
|
+
const result = scorm2004API.removeCorrectResponsePrefixes(input);
|
|
955
|
+
expect(result).toBe("");
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
it("should handle multiple prefixes correctly", () => {
|
|
959
|
+
const scorm2004API = new Scorm2004API();
|
|
960
|
+
const input =
|
|
961
|
+
"{lang=en}{order_matters=true}{case_matters=false}correctResponse";
|
|
962
|
+
const result = scorm2004API.removeCorrectResponsePrefixes(input);
|
|
963
|
+
expect(result).toBe("correctResponse");
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
it("should throw an error for invalid order_matters value", () => {
|
|
967
|
+
const scorm2004API = new Scorm2004API();
|
|
968
|
+
const input = "{order_matters=invalid}correctResponse";
|
|
969
|
+
scorm2004API.removeCorrectResponsePrefixes(input);
|
|
970
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
971
|
+
String(scorm2004_error_codes.TYPE_MISMATCH),
|
|
972
|
+
);
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
it("should throw an error for invalid case_matters value", () => {
|
|
976
|
+
const scorm2004API = new Scorm2004API();
|
|
977
|
+
const input = "{case_matters=invalid}correctResponse";
|
|
978
|
+
scorm2004API.removeCorrectResponsePrefixes(input);
|
|
979
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
980
|
+
String(scorm2004_error_codes.TYPE_MISMATCH),
|
|
981
|
+
);
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
it("should ignore an unknown prefix", () => {
|
|
985
|
+
const scorm2004API = new Scorm2004API();
|
|
986
|
+
const input = "{unknown=true}correctResponse";
|
|
987
|
+
const result = scorm2004API.removeCorrectResponsePrefixes(input);
|
|
988
|
+
expect(result).toBe("{unknown=true}correctResponse");
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
it("should throw an error with an invalid language code", () => {
|
|
992
|
+
const scorm2004API = new Scorm2004API();
|
|
993
|
+
const input = "{lang=xyz}correctResponse";
|
|
994
|
+
scorm2004API.removeCorrectResponsePrefixes(input);
|
|
995
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
996
|
+
String(scorm2004_error_codes.TYPE_MISMATCH),
|
|
997
|
+
);
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
describe("getChildElement()", () => {
|
|
1002
|
+
it("should handle missing interaction type", () => {
|
|
1003
|
+
const scorm2004API = apiInitialized({
|
|
1004
|
+
cmi: {
|
|
1005
|
+
interactions: {
|
|
1006
|
+
childArray: [{ id: "interaction-id-1" }],
|
|
1007
|
+
},
|
|
1008
|
+
},
|
|
1009
|
+
});
|
|
1010
|
+
const result = scorm2004API.getChildElement(
|
|
1011
|
+
"cmi.interactions.0.correct_responses.0",
|
|
1012
|
+
"response-value",
|
|
1013
|
+
true,
|
|
1014
|
+
);
|
|
1015
|
+
expect(result).toBeNull();
|
|
1016
|
+
expect(scorm2004API.lmsGetLastError()).toEqual(
|
|
1017
|
+
String(scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED),
|
|
1018
|
+
);
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
it("should call throwSCORMError with the correct arguments in createCorrectResponsesObject", () => {
|
|
1022
|
+
const scorm2004API = new Scorm2004API();
|
|
1023
|
+
const interaction = {
|
|
1024
|
+
id: "interaction-id-1",
|
|
1025
|
+
type: "invalid-type",
|
|
1026
|
+
correct_responses: { _count: 1 },
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
// Initialize the childArray with an empty array
|
|
1030
|
+
scorm2004API.cmi.interactions.childArray = [];
|
|
1031
|
+
|
|
1032
|
+
// Add the interaction object to the childArray
|
|
1033
|
+
scorm2004API.cmi.interactions.childArray[0] = interaction;
|
|
1034
|
+
|
|
1035
|
+
sinon.stub(scorm2004API, "isInitialized").returns(true);
|
|
1036
|
+
const throwSCORMErrorSpy = sinon.spy(scorm2004API, "throwSCORMError");
|
|
1037
|
+
|
|
1038
|
+
try {
|
|
1039
|
+
scorm2004API.getChildElement(
|
|
1040
|
+
"cmi.interactions.0.correct_responses.0",
|
|
1041
|
+
"response-value",
|
|
1042
|
+
true,
|
|
1043
|
+
);
|
|
1044
|
+
} catch (e) {
|
|
1045
|
+
// Expected to throw, so we catch it to prevent the test from failing
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
expect(
|
|
1049
|
+
throwSCORMErrorSpy.calledWith(
|
|
1050
|
+
ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
|
|
1051
|
+
"Incorrect Response Type: " + interaction.type,
|
|
1052
|
+
),
|
|
1053
|
+
).toBe(true);
|
|
1054
|
+
});
|
|
620
1055
|
});
|
|
621
1056
|
|
|
622
1057
|
describe("storeData()", () => {
|
|
@@ -809,4 +1244,55 @@ describe("SCORM 2004 API Tests", () => {
|
|
|
809
1244
|
expect(callback.called).toBe(true);
|
|
810
1245
|
});
|
|
811
1246
|
});
|
|
1247
|
+
|
|
1248
|
+
describe("Test issues from users", () => {
|
|
1249
|
+
it("Should be able to load the JSON data from issue #678", () => {
|
|
1250
|
+
const scorm20004api = api(
|
|
1251
|
+
{
|
|
1252
|
+
...DefaultSettings,
|
|
1253
|
+
autocommit: false,
|
|
1254
|
+
lmsCommitUrl: "/scorm2004",
|
|
1255
|
+
logLevel: 1,
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
comments_from_learner: {},
|
|
1259
|
+
comments_from_lms: {},
|
|
1260
|
+
completion_status: "incomplete",
|
|
1261
|
+
completion_threshold: "",
|
|
1262
|
+
credit: "credit",
|
|
1263
|
+
entry: "resume",
|
|
1264
|
+
exit: "suspend",
|
|
1265
|
+
interactions: {},
|
|
1266
|
+
launch_data: "",
|
|
1267
|
+
learner_id: "Test",
|
|
1268
|
+
learner_name: "User,Sample",
|
|
1269
|
+
learner_preference: {
|
|
1270
|
+
audio_level: "1",
|
|
1271
|
+
language: "",
|
|
1272
|
+
delivery_speed: "1",
|
|
1273
|
+
audio_captioning: "0",
|
|
1274
|
+
},
|
|
1275
|
+
location: "1",
|
|
1276
|
+
max_time_allowed: "",
|
|
1277
|
+
mode: "normal",
|
|
1278
|
+
objectives: {},
|
|
1279
|
+
progress_measure: "",
|
|
1280
|
+
scaled_passing_score: "",
|
|
1281
|
+
score: {
|
|
1282
|
+
scaled: "",
|
|
1283
|
+
raw: "",
|
|
1284
|
+
min: "",
|
|
1285
|
+
max: "",
|
|
1286
|
+
},
|
|
1287
|
+
session_time: "PT19.57S",
|
|
1288
|
+
success_status: "unknown",
|
|
1289
|
+
suspend_data: "",
|
|
1290
|
+
time_limit_action: "continue,no message",
|
|
1291
|
+
total_time: "PT19.57S",
|
|
1292
|
+
},
|
|
1293
|
+
);
|
|
1294
|
+
|
|
1295
|
+
expect(scorm20004api.cmi.learner_preference).not.toBeNull();
|
|
1296
|
+
});
|
|
1297
|
+
});
|
|
812
1298
|
});
|