@itwin/core-backend 5.3.0 → 5.4.0-dev.10

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 (54) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/lib/cjs/CloudSqlite.d.ts +9 -0
  3. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  4. package/lib/cjs/CloudSqlite.js.map +1 -1
  5. package/lib/cjs/IModelDb.d.ts +2 -1
  6. package/lib/cjs/IModelDb.d.ts.map +1 -1
  7. package/lib/cjs/IModelDb.js +8 -1
  8. package/lib/cjs/IModelDb.js.map +1 -1
  9. package/lib/cjs/LocalhostIpcHost.d.ts +1 -0
  10. package/lib/cjs/LocalhostIpcHost.d.ts.map +1 -1
  11. package/lib/cjs/LocalhostIpcHost.js +1 -1
  12. package/lib/cjs/LocalhostIpcHost.js.map +1 -1
  13. package/lib/cjs/TxnManager.d.ts +17 -0
  14. package/lib/cjs/TxnManager.d.ts.map +1 -1
  15. package/lib/cjs/TxnManager.js +31 -2
  16. package/lib/cjs/TxnManager.js.map +1 -1
  17. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  18. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  19. package/lib/cjs/internal/ElementLRUCache.d.ts.map +1 -1
  20. package/lib/cjs/internal/ElementLRUCache.js +2 -0
  21. package/lib/cjs/internal/ElementLRUCache.js.map +1 -1
  22. package/lib/esm/CloudSqlite.d.ts +9 -0
  23. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  24. package/lib/esm/CloudSqlite.js.map +1 -1
  25. package/lib/esm/IModelDb.d.ts +2 -1
  26. package/lib/esm/IModelDb.d.ts.map +1 -1
  27. package/lib/esm/IModelDb.js +8 -1
  28. package/lib/esm/IModelDb.js.map +1 -1
  29. package/lib/esm/LocalhostIpcHost.d.ts +1 -0
  30. package/lib/esm/LocalhostIpcHost.d.ts.map +1 -1
  31. package/lib/esm/LocalhostIpcHost.js +1 -1
  32. package/lib/esm/LocalhostIpcHost.js.map +1 -1
  33. package/lib/esm/TxnManager.d.ts +17 -0
  34. package/lib/esm/TxnManager.d.ts.map +1 -1
  35. package/lib/esm/TxnManager.js +31 -2
  36. package/lib/esm/TxnManager.js.map +1 -1
  37. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  38. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  39. package/lib/esm/internal/ElementLRUCache.d.ts.map +1 -1
  40. package/lib/esm/internal/ElementLRUCache.js +2 -0
  41. package/lib/esm/internal/ElementLRUCache.js.map +1 -1
  42. package/lib/esm/test/ElementLRUCache.test.js +6 -0
  43. package/lib/esm/test/ElementLRUCache.test.js.map +1 -1
  44. package/lib/esm/test/hubaccess/Rebase.test.js +342 -2
  45. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
  46. package/lib/esm/test/imodel/Code.test.d.ts +2 -0
  47. package/lib/esm/test/imodel/Code.test.d.ts.map +1 -0
  48. package/lib/esm/test/imodel/Code.test.js +272 -0
  49. package/lib/esm/test/imodel/Code.test.js.map +1 -0
  50. package/lib/esm/test/imodel/IModel.test.js +1 -1
  51. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  52. package/lib/esm/test/standalone/ChangesetReader.test.js +7 -4
  53. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  54. package/package.json +15 -15
@@ -2,12 +2,12 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- import { Guid } from "@itwin/core-bentley";
5
+ import { DbResult, Guid } from "@itwin/core-bentley";
6
6
  import { Code, IModel, QueryBinder, SubCategoryAppearance } from "@itwin/core-common";
7
7
  import * as chai from "chai";
8
8
  import * as chaiAsPromised from "chai-as-promised";
9
9
  import { HubWrappers, IModelTestUtils, KnownTestLocations } from "..";
10
- import { BriefcaseManager, ChannelControl, DrawingCategory, IModelHost, SqliteChangesetReader } from "../../core-backend";
10
+ import { BriefcaseManager, ChangesetECAdaptor, ChannelControl, DrawingCategory, IModelHost, SqliteChangesetReader } from "../../core-backend";
11
11
  import { HubMock } from "../../internal/HubMock";
12
12
  import { StashManager } from "../../StashManager";
13
13
  import { existsSync, unlinkSync, writeFileSync } from "fs";
@@ -739,6 +739,41 @@ describe("rebase changes & stashing api", function () {
739
739
  chai.expect(b2.elements.tryGetElementProps(e3)).to.undefined; // add by rebase so should not exist either
740
740
  chai.expect(BriefcaseManager.containsRestorePoint(b2, BriefcaseManager.PULL_MERGE_RESTORE_POINT_NAME)).is.false;
741
741
  });
742
+ it("calling discardChanges() from inside indirect scope is not allowed", async () => {
743
+ const b1 = await testIModel.openBriefcase();
744
+ await testIModel.insertElement(b1);
745
+ b1.saveChanges();
746
+ const p1 = b1.txns.withIndirectTxnModeAsync(async () => {
747
+ await b1.discardChanges();
748
+ });
749
+ await chai.expect(p1).to.be.rejectedWith("Cannot discard changes when there are indirect changes");
750
+ b1.saveChanges();
751
+ });
752
+ it("calling discardChanges() during rebasing is not allowed", async () => {
753
+ const b1 = await testIModel.openBriefcase();
754
+ const b2 = await testIModel.openBriefcase();
755
+ await testIModel.insertElement(b1);
756
+ await testIModel.insertElement(b1);
757
+ b1.saveChanges();
758
+ await b1.pushChanges({ description: "inserted element" });
759
+ await testIModel.insertElement(b2);
760
+ await testIModel.insertElement(b2);
761
+ b2.saveChanges();
762
+ b2.txns.rebaser.setCustomHandler({
763
+ shouldReinstate: (_txnProps) => {
764
+ return true;
765
+ },
766
+ recompute: async (_txnProps) => {
767
+ chai.expect(b2.txns.rebaser.isAborting).is.false;
768
+ await b2.discardChanges();
769
+ },
770
+ });
771
+ chai.expect(b2.txns.rebaser.isAborting).is.false;
772
+ const p1 = b2.pullChanges();
773
+ await chai.expect(p1).to.be.rejectedWith("Cannot discard changes while a rebase is in progress");
774
+ chai.expect(b2.txns.rebaser.canAbort()).is.true;
775
+ await b2.txns.rebaser.abort();
776
+ });
742
777
  it("getStash() should throw exception", async () => {
743
778
  const b1 = await testIModel.openBriefcase();
744
779
  chai.expect(() => StashManager.getStash({ db: b1, stash: "invalid_stash" })).to.throw("Invalid stash");
@@ -803,5 +838,310 @@ describe("rebase changes & stashing api", function () {
803
838
  const e3Props = await findElement(e3);
804
839
  chai.expect(e3Props).to.exist;
805
840
  });
841
+ it("enum txn changes in recompute", async () => {
842
+ const b1 = await testIModel.openBriefcase();
843
+ const b2 = await testIModel.openBriefcase();
844
+ const e1 = await testIModel.insertElement(b1);
845
+ const e2 = await testIModel.insertElement(b1, true);
846
+ b1.saveChanges();
847
+ await b1.pushChanges({ description: "insert element 1 direct and 1 indirect" });
848
+ await b2.pullChanges();
849
+ await testIModel.updateElement(b1, e1);
850
+ await testIModel.updateElement(b1, e2, true);
851
+ b1.saveChanges();
852
+ await b1.pushChanges({ description: "update element 1 direct and 1 indirect" });
853
+ await testIModel.insertElement(b2);
854
+ await testIModel.insertElement(b2, true);
855
+ b2.saveChanges("first change");
856
+ await testIModel.insertElement(b2);
857
+ await testIModel.insertElement(b2, true);
858
+ b2.saveChanges("second change");
859
+ await testIModel.insertElement(b2);
860
+ await testIModel.insertElement(b2, true);
861
+ b2.saveChanges("third change");
862
+ let txnVerified = 0;
863
+ b2.txns.rebaser.setCustomHandler({
864
+ shouldReinstate: (_txn) => {
865
+ return true;
866
+ },
867
+ recompute: async (txn) => {
868
+ const reader = SqliteChangesetReader.openTxn({ txnId: txn.id, db: b2, disableSchemaCheck: true });
869
+ const adaptor = new ChangesetECAdaptor(reader);
870
+ adaptor.acceptClass("TestDomain:a1");
871
+ const ids = new Set();
872
+ while (adaptor.step()) {
873
+ if (!adaptor.reader.isIndirect)
874
+ ids.add(adaptor.inserted?.ECInstanceId || adaptor.deleted?.ECInstanceId);
875
+ }
876
+ adaptor.close();
877
+ if (txn.props.description === "first change") {
878
+ chai.expect(Array.from(ids.keys())).deep.equal(["0x40000000001"]);
879
+ txnVerified++;
880
+ }
881
+ else if (txn.props.description === "second change") {
882
+ chai.expect(Array.from(ids.keys())).deep.equal(["0x40000000003"]);
883
+ txnVerified++;
884
+ }
885
+ else if (txn.props.description === "third change") {
886
+ chai.expect(Array.from(ids.keys())).deep.equal(["0x40000000005"]);
887
+ txnVerified++;
888
+ }
889
+ else {
890
+ txnVerified++;
891
+ }
892
+ },
893
+ });
894
+ await b2.pullChanges();
895
+ chai.expect(txnVerified).to.equal(3);
896
+ });
897
+ it("before and after rebase events", async () => {
898
+ const b1 = await testIModel.openBriefcase();
899
+ const b2 = await testIModel.openBriefcase();
900
+ const e1 = await testIModel.insertElement(b1);
901
+ const e2 = await testIModel.insertElement(b1, true);
902
+ b1.saveChanges();
903
+ await b1.pushChanges({ description: "insert element 1 direct and 1 indirect" });
904
+ await b2.pullChanges();
905
+ await testIModel.updateElement(b1, e1);
906
+ await testIModel.updateElement(b1, e2, true);
907
+ b1.saveChanges();
908
+ await b1.pushChanges({ description: "update element 1 direct and 1 indirect" });
909
+ await testIModel.insertElement(b2);
910
+ await testIModel.insertElement(b2, true);
911
+ b2.saveChanges("first change");
912
+ await testIModel.insertElement(b2);
913
+ await testIModel.insertElement(b2, true);
914
+ b2.saveChanges("second change");
915
+ await testIModel.insertElement(b2);
916
+ await testIModel.insertElement(b2, true);
917
+ b2.saveChanges("third change");
918
+ const events = {
919
+ onRebase: {
920
+ beginCount: 0,
921
+ endCount: 0,
922
+ beginIds: [],
923
+ },
924
+ onRebaseTxn: {
925
+ beginTxns: [],
926
+ endTxns: [],
927
+ },
928
+ rebaseHandler: {
929
+ shouldReinstate: [],
930
+ recompute: [],
931
+ }
932
+ };
933
+ const resetEvent = () => {
934
+ events.onRebase.beginCount = 0;
935
+ events.onRebase.endCount = 0;
936
+ events.onRebase.beginIds = [];
937
+ events.onRebaseTxn.beginTxns = [];
938
+ events.onRebaseTxn.endTxns = [];
939
+ events.rebaseHandler.shouldReinstate = [];
940
+ events.rebaseHandler.recompute = [];
941
+ };
942
+ b2.txns.onRebaseBegin.addListener((ids) => {
943
+ events.onRebase.beginCount++;
944
+ events.onRebase.beginIds.push(...ids);
945
+ });
946
+ b2.txns.onRebaseEnd.addListener(() => {
947
+ events.onRebase.endCount++;
948
+ });
949
+ b2.txns.onRebaseTxnBegin.addListener((txn) => {
950
+ events.onRebaseTxn.beginTxns.push(txn);
951
+ });
952
+ b2.txns.onRebaseTxnEnd.addListener((txn) => {
953
+ events.onRebaseTxn.endTxns.push(txn);
954
+ });
955
+ b2.txns.rebaser.setCustomHandler({
956
+ shouldReinstate: (_txn) => {
957
+ events.rebaseHandler.shouldReinstate.push(_txn);
958
+ return true;
959
+ },
960
+ recompute: async (_txn) => {
961
+ events.rebaseHandler.recompute.push(_txn);
962
+ },
963
+ });
964
+ resetEvent();
965
+ await b2.pullChanges();
966
+ chai.expect(events.onRebase.beginCount).to.equal(1);
967
+ chai.expect(events.onRebase.endCount).to.equal(1);
968
+ chai.expect(events.onRebase.beginIds).to.deep.equal(["0x100000000", "0x100000001", "0x100000002"]);
969
+ chai.expect(events.onRebaseTxn.beginTxns.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002"]);
970
+ chai.expect(events.onRebaseTxn.endTxns.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002"]);
971
+ chai.expect(events.rebaseHandler.shouldReinstate.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002"]);
972
+ chai.expect(events.rebaseHandler.recompute.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002"]);
973
+ await testIModel.updateElement(b1, e1);
974
+ await testIModel.updateElement(b1, e2, true);
975
+ b1.saveChanges();
976
+ await b1.pushChanges({ description: "update element 1 direct and 1 indirect" });
977
+ await testIModel.insertElement(b2);
978
+ await testIModel.insertElement(b2, true);
979
+ b2.saveChanges("forth change");
980
+ resetEvent();
981
+ await b2.pullChanges();
982
+ chai.expect(events.onRebase.beginCount).to.equal(1);
983
+ chai.expect(events.onRebase.endCount).to.equal(1);
984
+ chai.expect(events.onRebase.beginIds).to.deep.equal(["0x100000000", "0x100000001", "0x100000002", "0x100000003"]);
985
+ chai.expect(events.onRebaseTxn.beginTxns.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002", "0x100000003"]);
986
+ chai.expect(events.onRebaseTxn.endTxns.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002", "0x100000003"]);
987
+ chai.expect(events.rebaseHandler.shouldReinstate.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002", "0x100000003"]);
988
+ chai.expect(events.rebaseHandler.recompute.map((txn) => txn.id)).to.deep.equal(["0x100000000", "0x100000001", "0x100000002", "0x100000003"]);
989
+ });
990
+ it("rebase multi txn", async () => {
991
+ const b1 = await testIModel.openBriefcase();
992
+ const b2 = await testIModel.openBriefcase();
993
+ const e1 = await testIModel.insertElement(b1);
994
+ const e2 = await testIModel.insertElement(b1, true);
995
+ b1.saveChanges();
996
+ await b1.pushChanges({ description: "insert element 1 direct and 1 indirect" });
997
+ await b2.pullChanges();
998
+ chai.expect(b2.txns.beginMultiTxnOperation()).to.be.equals(DbResult.BE_SQLITE_OK);
999
+ let elId = await testIModel.insertElement(b2);
1000
+ b2.saveChanges(`insert element ${elId}`);
1001
+ elId = await testIModel.insertElement(b2);
1002
+ b2.saveChanges(`insert element ${elId}`);
1003
+ elId = await testIModel.insertElement(b2);
1004
+ b2.saveChanges(`insert element ${elId}`);
1005
+ chai.expect(b2.txns.endMultiTxnOperation()).to.be.equals(DbResult.BE_SQLITE_OK);
1006
+ b2.saveChanges();
1007
+ elId = await testIModel.insertElement(b2);
1008
+ b2.saveChanges(`insert element ${elId}`);
1009
+ let txns = Array.from(b2.txns.queryTxns());
1010
+ chai.expect(txns[0].id).to.be.equals("0x100000000"); // 1st after beginMultiTxnOperation()
1011
+ chai.expect(txns[0].props.description).to.be.equals("insert element 0x40000000001");
1012
+ chai.expect(txns[0].sessionId).to.be.equals(1);
1013
+ chai.expect(txns[0].grouped).to.be.equals(false);
1014
+ chai.expect(txns[0].reversed).to.be.equals(false);
1015
+ chai.expect(txns[1].id).to.be.equals("0x100000001"); // 2nd after beginMultiTxnOperation()
1016
+ chai.expect(txns[1].props.description).to.be.equals("insert element 0x40000000002");
1017
+ chai.expect(txns[1].sessionId).to.be.equals(1);
1018
+ chai.expect(txns[1].grouped).to.be.equals(true);
1019
+ chai.expect(txns[1].reversed).to.be.equals(false);
1020
+ chai.expect(txns[2].id).to.be.equals("0x100000002"); // 3rd after beginMultiTxnOperation() & before endMultiTxnOperation()
1021
+ chai.expect(txns[2].props.description).to.be.equals("insert element 0x40000000003");
1022
+ chai.expect(txns[2].sessionId).to.be.equals(1);
1023
+ chai.expect(txns[2].grouped).to.be.equals(true);
1024
+ chai.expect(txns[2].reversed).to.be.equals(false);
1025
+ chai.expect(txns[3].id).to.be.equals("0x100000003"); // 4th after endMultiTxnOperation()
1026
+ chai.expect(txns[3].props.description).to.be.equals("insert element 0x40000000004");
1027
+ chai.expect(txns[3].type).to.be.equals("Data");
1028
+ chai.expect(txns[3].grouped).to.be.equals(false);
1029
+ chai.expect(txns[3].reversed).to.be.equals(false);
1030
+ // reverse single txn 0x100000003
1031
+ chai.expect(b2.txns.reverseSingleTxn()).to.be.equals(DbResult.BE_SQLITE_OK);
1032
+ txns = Array.from(b2.txns.queryTxns());
1033
+ chai.expect(txns[0].id).to.be.equals("0x100000000"); // 1st after beginMultiTxnOperation()
1034
+ chai.expect(txns[0].props.description).to.be.equals("insert element 0x40000000001");
1035
+ chai.expect(txns[0].sessionId).to.be.equals(1);
1036
+ chai.expect(txns[0].grouped).to.be.equals(false);
1037
+ chai.expect(txns[0].reversed).to.be.equals(false);
1038
+ chai.expect(txns[1].id).to.be.equals("0x100000001"); // 2nd after beginMultiTxnOperation()
1039
+ chai.expect(txns[1].props.description).to.be.equals("insert element 0x40000000002");
1040
+ chai.expect(txns[1].sessionId).to.be.equals(1);
1041
+ chai.expect(txns[1].grouped).to.be.equals(true);
1042
+ chai.expect(txns[1].reversed).to.be.equals(false);
1043
+ chai.expect(txns[2].id).to.be.equals("0x100000002"); // 3rd after beginMultiTxnOperation() & before endMultiTxnOperation()
1044
+ chai.expect(txns[2].props.description).to.be.equals("insert element 0x40000000003");
1045
+ chai.expect(txns[2].sessionId).to.be.equals(1);
1046
+ chai.expect(txns[2].grouped).to.be.equals(true);
1047
+ chai.expect(txns[2].reversed).to.be.equals(false);
1048
+ chai.expect(txns[3].id).to.be.equals("0x100000003"); // 4th after endMultiTxnOperation()
1049
+ chai.expect(txns[3].props.description).to.be.equals("insert element 0x40000000004");
1050
+ chai.expect(txns[3].type).to.be.equals("Data");
1051
+ chai.expect(txns[3].grouped).to.be.equals(false);
1052
+ chai.expect(txns[3].reversed).to.be.equals(true);
1053
+ // reverse multi txn. should reverse 0x100000000, 0x100000001 & 0x100000002
1054
+ chai.expect(b2.txns.reverseSingleTxn()).to.be.equals(DbResult.BE_SQLITE_OK);
1055
+ txns = Array.from(b2.txns.queryTxns());
1056
+ chai.expect(txns[0].id).to.be.equals("0x100000000"); // 1st after beginMultiTxnOperation()
1057
+ chai.expect(txns[0].props.description).to.be.equals("insert element 0x40000000001");
1058
+ chai.expect(txns[0].sessionId).to.be.equals(1);
1059
+ chai.expect(txns[0].grouped).to.be.equals(false);
1060
+ chai.expect(txns[0].reversed).to.be.equals(true);
1061
+ chai.expect(txns[1].id).to.be.equals("0x100000001"); // 2nd after beginMultiTxnOperation()
1062
+ chai.expect(txns[1].props.description).to.be.equals("insert element 0x40000000002");
1063
+ chai.expect(txns[1].sessionId).to.be.equals(1);
1064
+ chai.expect(txns[1].grouped).to.be.equals(true);
1065
+ chai.expect(txns[1].reversed).to.be.equals(true);
1066
+ chai.expect(txns[2].id).to.be.equals("0x100000002"); // 3rd after beginMultiTxnOperation() & before endMultiTxnOperation()
1067
+ chai.expect(txns[2].props.description).to.be.equals("insert element 0x40000000003");
1068
+ chai.expect(txns[2].sessionId).to.be.equals(1);
1069
+ chai.expect(txns[2].grouped).to.be.equals(true);
1070
+ chai.expect(txns[2].reversed).to.be.equals(true);
1071
+ chai.expect(txns[3].id).to.be.equals("0x100000003"); // 4th after endMultiTxnOperation()
1072
+ chai.expect(txns[3].props.description).to.be.equals("insert element 0x40000000004");
1073
+ chai.expect(txns[3].type).to.be.equals("Data");
1074
+ chai.expect(txns[3].grouped).to.be.equals(false);
1075
+ chai.expect(txns[3].reversed).to.be.equals(true);
1076
+ // reinstate the transaction
1077
+ chai.expect(b2.txns.isRedoPossible).to.be.equals(true);
1078
+ chai.expect(b2.txns.reinstateTxn()).to.be.equals(DbResult.BE_SQLITE_OK);
1079
+ txns = Array.from(b2.txns.queryTxns());
1080
+ chai.expect(txns[0].id).to.be.equals("0x100000000"); // 1st after beginMultiTxnOperation()
1081
+ chai.expect(txns[0].props.description).to.be.equals("insert element 0x40000000001");
1082
+ chai.expect(txns[0].sessionId).to.be.equals(1);
1083
+ chai.expect(txns[0].grouped).to.be.equals(false);
1084
+ chai.expect(txns[0].reversed).to.be.equals(false);
1085
+ chai.expect(txns[1].id).to.be.equals("0x100000001"); // 2nd after beginMultiTxnOperation()
1086
+ chai.expect(txns[1].props.description).to.be.equals("insert element 0x40000000002");
1087
+ chai.expect(txns[1].sessionId).to.be.equals(1);
1088
+ chai.expect(txns[1].grouped).to.be.equals(true);
1089
+ chai.expect(txns[1].reversed).to.be.equals(false);
1090
+ chai.expect(txns[2].id).to.be.equals("0x100000002"); // 3rd after beginMultiTxnOperation() & before endMultiTxnOperation()
1091
+ chai.expect(txns[2].props.description).to.be.equals("insert element 0x40000000003");
1092
+ chai.expect(txns[2].sessionId).to.be.equals(1);
1093
+ chai.expect(txns[2].grouped).to.be.equals(true);
1094
+ chai.expect(txns[2].reversed).to.be.equals(false);
1095
+ chai.expect(txns[3].id).to.be.equals("0x100000003"); // 4th after endMultiTxnOperation()
1096
+ chai.expect(txns[3].props.description).to.be.equals("insert element 0x40000000004");
1097
+ chai.expect(txns[3].type).to.be.equals("Data");
1098
+ chai.expect(txns[3].grouped).to.be.equals(false);
1099
+ chai.expect(txns[3].reversed).to.be.equals(true);
1100
+ // reinstate the transaction
1101
+ chai.expect(b2.txns.isRedoPossible).to.be.equals(true);
1102
+ chai.expect(b2.txns.reinstateTxn()).to.be.equals(DbResult.BE_SQLITE_OK);
1103
+ txns = Array.from(b2.txns.queryTxns());
1104
+ chai.expect(txns[0].id).to.be.equals("0x100000000"); // 1st after beginMultiTxnOperation()
1105
+ chai.expect(txns[0].props.description).to.be.equals("insert element 0x40000000001");
1106
+ chai.expect(txns[0].sessionId).to.be.equals(1);
1107
+ chai.expect(txns[0].grouped).to.be.equals(false);
1108
+ chai.expect(txns[0].reversed).to.be.equals(false);
1109
+ chai.expect(txns[1].id).to.be.equals("0x100000001"); // 2nd after beginMultiTxnOperation()
1110
+ chai.expect(txns[1].props.description).to.be.equals("insert element 0x40000000002");
1111
+ chai.expect(txns[1].sessionId).to.be.equals(1);
1112
+ chai.expect(txns[1].grouped).to.be.equals(true);
1113
+ chai.expect(txns[1].reversed).to.be.equals(false);
1114
+ chai.expect(txns[2].id).to.be.equals("0x100000002"); // 3rd after beginMultiTxnOperation() & before endMultiTxnOperation()
1115
+ chai.expect(txns[2].props.description).to.be.equals("insert element 0x40000000003");
1116
+ chai.expect(txns[2].sessionId).to.be.equals(1);
1117
+ chai.expect(txns[2].grouped).to.be.equals(true);
1118
+ chai.expect(txns[2].reversed).to.be.equals(false);
1119
+ chai.expect(txns[3].id).to.be.equals("0x100000003"); // 4th after endMultiTxnOperation()
1120
+ chai.expect(txns[3].props.description).to.be.equals("insert element 0x40000000004");
1121
+ chai.expect(txns[3].type).to.be.equals("Data");
1122
+ chai.expect(txns[3].grouped).to.be.equals(false);
1123
+ chai.expect(txns[3].reversed).to.be.equals(false);
1124
+ chai.expect(b2.txns.isRedoPossible).to.be.equals(false);
1125
+ await testIModel.updateElement(b1, e1);
1126
+ await testIModel.updateElement(b1, e2, true);
1127
+ b1.saveChanges();
1128
+ await b1.pushChanges({ description: "update element 1 direct and 1 indirect" });
1129
+ const recomputeTxnIds = [];
1130
+ b2.txns.rebaser.setCustomHandler({
1131
+ shouldReinstate: (_txn) => {
1132
+ return true;
1133
+ },
1134
+ recompute: async (txn) => {
1135
+ recomputeTxnIds.push(txn.id);
1136
+ },
1137
+ });
1138
+ await b2.pullChanges();
1139
+ chai.expect(recomputeTxnIds).to.deep.equals([
1140
+ "0x100000000",
1141
+ "0x100000001",
1142
+ "0x100000002",
1143
+ "0x100000003",
1144
+ ]);
1145
+ });
806
1146
  });
807
1147
  //# sourceMappingURL=Rebase.test.js.map