@itwin/core-backend 5.14.0-dev.1 → 5.14.0-dev.11

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 (120) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/lib/cjs/BriefcaseManager.d.ts +6 -0
  3. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  4. package/lib/cjs/BriefcaseManager.js +12 -6
  5. package/lib/cjs/BriefcaseManager.js.map +1 -1
  6. package/lib/cjs/ChangesetReader.d.ts.map +1 -1
  7. package/lib/cjs/ChangesetReader.js +1 -0
  8. package/lib/cjs/ChangesetReader.js.map +1 -1
  9. package/lib/cjs/ChangesetReaderTypes.d.ts +2 -1
  10. package/lib/cjs/ChangesetReaderTypes.d.ts.map +1 -1
  11. package/lib/cjs/ChangesetReaderTypes.js.map +1 -1
  12. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  13. package/lib/cjs/CloudSqlite.js +9 -2
  14. package/lib/cjs/CloudSqlite.js.map +1 -1
  15. package/lib/cjs/ECDb.d.ts.map +1 -1
  16. package/lib/cjs/ECDb.js +1 -0
  17. package/lib/cjs/ECDb.js.map +1 -1
  18. package/lib/cjs/Element.d.ts +1 -1
  19. package/lib/cjs/Element.js +1 -1
  20. package/lib/cjs/Element.js.map +1 -1
  21. package/lib/cjs/Entity.d.ts +3 -3
  22. package/lib/cjs/Entity.js +3 -3
  23. package/lib/cjs/Entity.js.map +1 -1
  24. package/lib/cjs/IModelDb.d.ts +83 -35
  25. package/lib/cjs/IModelDb.d.ts.map +1 -1
  26. package/lib/cjs/IModelDb.js +196 -89
  27. package/lib/cjs/IModelDb.js.map +1 -1
  28. package/lib/cjs/IpcHost.d.ts.map +1 -1
  29. package/lib/cjs/IpcHost.js +51 -17
  30. package/lib/cjs/IpcHost.js.map +1 -1
  31. package/lib/cjs/SchemaSync.d.ts +126 -18
  32. package/lib/cjs/SchemaSync.d.ts.map +1 -1
  33. package/lib/cjs/SchemaSync.js +303 -81
  34. package/lib/cjs/SchemaSync.js.map +1 -1
  35. package/lib/cjs/SqliteChangesetReader.d.ts +16 -8
  36. package/lib/cjs/SqliteChangesetReader.d.ts.map +1 -1
  37. package/lib/cjs/SqliteChangesetReader.js +11 -1
  38. package/lib/cjs/SqliteChangesetReader.js.map +1 -1
  39. package/lib/cjs/SynchronousChannel.d.ts +11 -1
  40. package/lib/cjs/SynchronousChannel.d.ts.map +1 -1
  41. package/lib/cjs/SynchronousChannel.js.map +1 -1
  42. package/lib/cjs/TxnManager.d.ts.map +1 -1
  43. package/lib/cjs/TxnManager.js +16 -13
  44. package/lib/cjs/TxnManager.js.map +1 -1
  45. package/lib/cjs/internal/IntegrityCheck.d.ts +57 -0
  46. package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -1
  47. package/lib/cjs/internal/IntegrityCheck.js.map +1 -1
  48. package/lib/cjs/internal/SchemaSyncReservations.d.ts.map +1 -1
  49. package/lib/cjs/internal/SchemaSyncReservations.js +13 -3
  50. package/lib/cjs/internal/SchemaSyncReservations.js.map +1 -1
  51. package/lib/esm/BriefcaseManager.d.ts +6 -0
  52. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  53. package/lib/esm/BriefcaseManager.js +12 -6
  54. package/lib/esm/BriefcaseManager.js.map +1 -1
  55. package/lib/esm/ChangesetReader.d.ts.map +1 -1
  56. package/lib/esm/ChangesetReader.js +1 -0
  57. package/lib/esm/ChangesetReader.js.map +1 -1
  58. package/lib/esm/ChangesetReaderTypes.d.ts +2 -1
  59. package/lib/esm/ChangesetReaderTypes.d.ts.map +1 -1
  60. package/lib/esm/ChangesetReaderTypes.js.map +1 -1
  61. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  62. package/lib/esm/CloudSqlite.js +10 -3
  63. package/lib/esm/CloudSqlite.js.map +1 -1
  64. package/lib/esm/ECDb.d.ts.map +1 -1
  65. package/lib/esm/ECDb.js +1 -0
  66. package/lib/esm/ECDb.js.map +1 -1
  67. package/lib/esm/Element.d.ts +1 -1
  68. package/lib/esm/Element.js +1 -1
  69. package/lib/esm/Element.js.map +1 -1
  70. package/lib/esm/Entity.d.ts +3 -3
  71. package/lib/esm/Entity.js +3 -3
  72. package/lib/esm/Entity.js.map +1 -1
  73. package/lib/esm/IModelDb.d.ts +83 -35
  74. package/lib/esm/IModelDb.d.ts.map +1 -1
  75. package/lib/esm/IModelDb.js +196 -89
  76. package/lib/esm/IModelDb.js.map +1 -1
  77. package/lib/esm/IpcHost.d.ts.map +1 -1
  78. package/lib/esm/IpcHost.js +52 -18
  79. package/lib/esm/IpcHost.js.map +1 -1
  80. package/lib/esm/SchemaSync.d.ts +126 -18
  81. package/lib/esm/SchemaSync.d.ts.map +1 -1
  82. package/lib/esm/SchemaSync.js +304 -82
  83. package/lib/esm/SchemaSync.js.map +1 -1
  84. package/lib/esm/SqliteChangesetReader.d.ts +16 -8
  85. package/lib/esm/SqliteChangesetReader.d.ts.map +1 -1
  86. package/lib/esm/SqliteChangesetReader.js +11 -1
  87. package/lib/esm/SqliteChangesetReader.js.map +1 -1
  88. package/lib/esm/SynchronousChannel.d.ts +11 -1
  89. package/lib/esm/SynchronousChannel.d.ts.map +1 -1
  90. package/lib/esm/SynchronousChannel.js.map +1 -1
  91. package/lib/esm/TxnManager.d.ts.map +1 -1
  92. package/lib/esm/TxnManager.js +17 -14
  93. package/lib/esm/TxnManager.js.map +1 -1
  94. package/lib/esm/internal/IntegrityCheck.d.ts +57 -0
  95. package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -1
  96. package/lib/esm/internal/IntegrityCheck.js.map +1 -1
  97. package/lib/esm/internal/SchemaSyncReservations.d.ts.map +1 -1
  98. package/lib/esm/internal/SchemaSyncReservations.js +13 -3
  99. package/lib/esm/internal/SchemaSyncReservations.js.map +1 -1
  100. package/lib/esm/test/annotations/FrameGeometry.test.js +1 -1
  101. package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
  102. package/lib/esm/test/hubaccess/BriefcaseManager.test.js +65 -1
  103. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  104. package/lib/esm/test/hubaccess/Rebase.test.js +3 -1
  105. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
  106. package/lib/esm/test/hubaccess/SemanticRebase.test.js +218 -28
  107. package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
  108. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts +3 -0
  109. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts.map +1 -0
  110. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js +15 -0
  111. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js.map +1 -0
  112. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  113. package/lib/esm/test/standalone/SQLiteDb.test.d.ts.map +1 -1
  114. package/lib/esm/test/standalone/SQLiteDb.test.js +116 -0
  115. package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
  116. package/lib/esm/test/standalone/SchemaSyncDb.test.js +5 -25
  117. package/lib/esm/test/standalone/SchemaSyncDb.test.js.map +1 -1
  118. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js +1 -0
  119. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js.map +1 -1
  120. package/package.json +14 -14
@@ -11,6 +11,7 @@ import { EditTxn, withEditTxn } from "../../EditTxn";
11
11
  import { HubMock } from "../../internal/HubMock";
12
12
  import { EntityClass } from "@itwin/ecschema-metadata";
13
13
  import { TestUtils } from "../TestUtils";
14
+ import { semanticRebaseExtendedDescribe, semanticRebaseExtendedIt } from "./SemanticRebaseTestUtils";
14
15
  function startTestTxn(iModel, description = "semantic rebase") {
15
16
  const txn = new EditTxn(iModel, description);
16
17
  txn.start();
@@ -216,6 +217,58 @@ class TestIModel {
216
217
  <BaseClass>A</BaseClass>
217
218
  <ECProperty propertyName="PropD" typeName="string"/>
218
219
  </ECEntityClass>
220
+ </ECSchema>`,
221
+ /** v01x00x01 - Adds a link-table relationship class ARefersToA (ElementRefersToElements subclass) between A elements */
222
+ v01x00x01WithRelationship: `<?xml version="1.0" encoding="UTF-8"?>
223
+ <ECSchema schemaName="TestDomain" alias="td" version="01.00.01" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
224
+ <ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
225
+ <ECEntityClass typeName="A">
226
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
227
+ <ECProperty propertyName="PropA" typeName="string"/>
228
+ </ECEntityClass>
229
+ <ECEntityClass typeName="C">
230
+ <BaseClass>A</BaseClass>
231
+ <ECProperty propertyName="PropC" typeName="string"/>
232
+ </ECEntityClass>
233
+ <ECEntityClass typeName="D">
234
+ <BaseClass>A</BaseClass>
235
+ <ECProperty propertyName="PropD" typeName="string"/>
236
+ </ECEntityClass>
237
+ <ECRelationshipClass typeName="ARefersToA" strength="referencing" modifier="None">
238
+ <BaseClass>bis:ElementRefersToElements</BaseClass>
239
+ <Source multiplicity="(0..*)" roleLabel="refers to" polymorphic="true">
240
+ <Class class="A"/>
241
+ </Source>
242
+ <Target multiplicity="(0..*)" roleLabel="is referred to by" polymorphic="true">
243
+ <Class class="A"/>
244
+ </Target>
245
+ </ECRelationshipClass>
246
+ </ECSchema>`,
247
+ /** v01x00x02 - Moves PropC from C to A (transforming) while keeping the ARefersToA relationship class */
248
+ v01x00x02WithRelationshipMovePropCToA: `<?xml version="1.0" encoding="UTF-8"?>
249
+ <ECSchema schemaName="TestDomain" alias="td" version="01.00.02" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
250
+ <ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
251
+ <ECEntityClass typeName="A">
252
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
253
+ <ECProperty propertyName="PropA" typeName="string"/>
254
+ <ECProperty propertyName="PropC" typeName="string"/>
255
+ </ECEntityClass>
256
+ <ECEntityClass typeName="C">
257
+ <BaseClass>A</BaseClass>
258
+ </ECEntityClass>
259
+ <ECEntityClass typeName="D">
260
+ <BaseClass>A</BaseClass>
261
+ <ECProperty propertyName="PropD" typeName="string"/>
262
+ </ECEntityClass>
263
+ <ECRelationshipClass typeName="ARefersToA" strength="referencing" modifier="None">
264
+ <BaseClass>bis:ElementRefersToElements</BaseClass>
265
+ <Source multiplicity="(0..*)" roleLabel="refers to" polymorphic="true">
266
+ <Class class="A"/>
267
+ </Source>
268
+ <Target multiplicity="(0..*)" roleLabel="is referred to by" polymorphic="true">
269
+ <Class class="A"/>
270
+ </Target>
271
+ </ECRelationshipClass>
219
272
  </ECSchema>`,
220
273
  };
221
274
  /** Additional schemas for extended edge-case tests */
@@ -739,7 +792,7 @@ describe("Semantic Rebase", function () {
739
792
  chai.expect(element2.propA).to.equal("local_update_a", "Element 2 local update should be preserved");
740
793
  chai.expect(element2.propC).to.equal("value_c2", "Element 2 propC should be unchanged");
741
794
  });
742
- it("local trivial schema changes onto incoming trivial schema changes (local newer)", async () => {
795
+ semanticRebaseExtendedIt("local trivial schema changes onto incoming trivial schema changes (local newer)", async () => {
743
796
  t = await TestIModel.initialize("TrivialSchemaLocalNewer");
744
797
  const localTxn = startTestTxn(t.local, "local trivial schema changes onto incoming trivial schema changes local newer local");
745
798
  const farTxn = startTestTxn(t.far, "local trivial schema changes onto incoming trivial schema changes local newer far");
@@ -764,7 +817,7 @@ describe("Semantic Rebase", function () {
764
817
  const schema = t.local.getSchemaProps("TestDomain");
765
818
  chai.expect(schema.version).to.equal("01.00.02", "Local schema (newer) should be preserved");
766
819
  });
767
- it("local trivial schema changes onto incoming trivial schema changes (incoming newer)", async () => {
820
+ semanticRebaseExtendedIt("local trivial schema changes onto incoming trivial schema changes (incoming newer)", async () => {
768
821
  t = await TestIModel.initialize("TrivialSchemaIncomingNewer");
769
822
  const localTxn = startTestTxn(t.local, "local trivial schema changes onto incoming trivial schema changes incoming newer local");
770
823
  const farTxn = startTestTxn(t.far, "local trivial schema changes onto incoming trivial schema changes incoming newer far");
@@ -790,7 +843,7 @@ describe("Semantic Rebase", function () {
790
843
  const schema = t.local.getSchemaProps("TestDomain");
791
844
  chai.expect(schema.version).to.equal("01.00.02", "Incoming schema (newer) should win, local should not override");
792
845
  });
793
- it("local trivial schema changes onto incoming identical schema changes with data changes on both sides", async () => {
846
+ semanticRebaseExtendedIt("local trivial schema changes onto incoming identical schema changes with data changes on both sides", async () => {
794
847
  t = await TestIModel.initialize("TrivialSchemaIdenticalWithData");
795
848
  const localTxn = startTestTxn(t.local, "local trivial schema changes onto incoming identical schema changes with data local");
796
849
  let farTxn = startTestTxn(t.far, "local trivial schema changes onto incoming identical schema changes with data far");
@@ -841,7 +894,7 @@ describe("Semantic Rebase", function () {
841
894
  chai.expect(localElement.propC).to.equal("local_value_c", "Local element propC should be preserved");
842
895
  chai.expect(localElement.propC2).to.equal("local_value_c2", "Local element propC2 should be preserved");
843
896
  });
844
- it("both add different properties, increment to same version number", async () => {
897
+ semanticRebaseExtendedIt("both add different properties, increment to same version number", async () => {
845
898
  t = await TestIModel.initialize("TrivialSchemaIncompatible");
846
899
  const localTxn = startTestTxn(t.local, "both add different properties increment to same version local");
847
900
  const farTxn = startTestTxn(t.far, "both add different properties increment to same version far");
@@ -853,7 +906,7 @@ describe("Semantic Rebase", function () {
853
906
  const schema = t.local.getSchemaProps("TestDomain");
854
907
  chai.expect(schema.version).to.equal("01.00.01", "Schema should be v01.00.01");
855
908
  });
856
- it("both add compatible properties, local version number higher", async () => {
909
+ semanticRebaseExtendedIt("both add compatible properties, local version number higher", async () => {
857
910
  t = await TestIModel.initialize("CompatibleSchemaLocalHigher");
858
911
  const localTxn = startTestTxn(t.local, "both add compatible properties local version higher local");
859
912
  const farTxn = startTestTxn(t.far, "both add compatible properties local version higher far");
@@ -874,7 +927,7 @@ describe("Semantic Rebase", function () {
874
927
  chai.expect(classD).to.not.be.undefined;
875
928
  chai.expect(await classD.getProperty("PropD2")).to.exist;
876
929
  });
877
- it("both add compatible properties, incoming version number higher", async () => {
930
+ semanticRebaseExtendedIt("both add compatible properties, incoming version number higher", async () => {
878
931
  t = await TestIModel.initialize("CompatibleSchemaIncomingHigher");
879
932
  const localTxn = startTestTxn(t.local, "both add compatible properties incoming version higher local");
880
933
  const farTxn = startTestTxn(t.far, "both add compatible properties incoming version higher far");
@@ -905,7 +958,7 @@ describe("Semantic Rebase", function () {
905
958
  // Local pulls and rebases - this should detect the incompatibility and fail
906
959
  await chai.expect(pullChanges(localTxn)).to.be.rejectedWith("ECSchema Upgrade failed");
907
960
  });
908
- it("both add same but incompatible property, incoming version number higher", async () => {
961
+ semanticRebaseExtendedIt("both add same but incompatible property, incoming version number higher", async () => {
909
962
  t = await TestIModel.initialize("TrivialSchemaIncompatible");
910
963
  const localTxn = startTestTxn(t.local, "both add same but incompatible property incoming version higher local");
911
964
  const farTxn = startTestTxn(t.far, "both add same but incompatible property incoming version higher far");
@@ -917,7 +970,7 @@ describe("Semantic Rebase", function () {
917
970
  // Local pulls and rebases - this should detect the incompatibility and fail
918
971
  await chai.expect(pullChanges(localTxn)).to.be.rejectedWith("ECSchema Upgrade failed");
919
972
  });
920
- it("local transforming schema change onto incoming trivial schema change", async () => {
973
+ semanticRebaseExtendedIt("local transforming schema change onto incoming trivial schema change", async () => {
921
974
  t = await TestIModel.initialize("LocalTransformIncomingTrivial");
922
975
  const farTxn = startTestTxn(t.far, "local transforming schema change onto incoming trivial schema change far");
923
976
  const localTxn = startTestTxn(t.local, "local transforming schema change onto incoming trivial schema change local");
@@ -959,7 +1012,7 @@ describe("Semantic Rebase", function () {
959
1012
  chai.expect(localElement.propA).to.equal("local_value_a", "Local element propA should be preserved");
960
1013
  chai.expect(localElement.propC).to.equal("local_value_c", "Local element propC should be preserved after transform");
961
1014
  });
962
- it("local trivial schema change onto incoming transforming schema change", async () => {
1015
+ semanticRebaseExtendedIt("local trivial schema change onto incoming transforming schema change", async () => {
963
1016
  t = await TestIModel.initialize("LocalTrivialIncomingTransform");
964
1017
  const farTxn = startTestTxn(t.far, "local trivial schema change onto incoming transforming schema change far");
965
1018
  const localTxn = startTestTxn(t.local, "local trivial schema change onto incoming transforming schema change local");
@@ -1099,7 +1152,7 @@ describe("Semantic Rebase", function () {
1099
1152
  const schema = t.local.getSchemaProps("TestDomain");
1100
1153
  chai.expect(schema.version).to.equal("01.00.02", "Schema should be transformed to v01.00.02");
1101
1154
  });
1102
- it("Incoming data update onto local transforming schema change", async () => {
1155
+ semanticRebaseExtendedIt("Incoming data update onto local transforming schema change", async () => {
1103
1156
  t = await TestIModel.initialize("IncomingDataLocalTransform");
1104
1157
  const farTxn = startTestTxn(t.far, "Incoming data update onto local transforming schema change far");
1105
1158
  const localTxn = startTestTxn(t.local, "Incoming data update onto local transforming schema change local");
@@ -1138,7 +1191,7 @@ describe("Semantic Rebase", function () {
1138
1191
  const schema = t.local.getSchemaProps("TestDomain");
1139
1192
  chai.expect(schema.version).to.equal("01.00.02", "Schema should be transformed to v01.00.02");
1140
1193
  });
1141
- it("Check if associated rebase folders get deleted when a briefcase is deleted or not", async () => {
1194
+ semanticRebaseExtendedIt("Check if associated rebase folders get deleted when a briefcase is deleted or not", async () => {
1142
1195
  t = await TestIModel.initialize("IncomingDataLocalTransform");
1143
1196
  // Must close briefcases before deleting their files - on Windows, open files are locked by the OS.
1144
1197
  // Save paths before closing since pathName getter throws on closed dbs.
@@ -1153,7 +1206,7 @@ describe("Semantic Rebase", function () {
1153
1206
  await BriefcaseManager.deleteBriefcaseFiles(farPath);
1154
1207
  chai.expect(IModelJsFs.existsSync(farRebasePath)).to.be.false; // after briefcase deletion the rebase folder should also be deleted
1155
1208
  });
1156
- it("local multiple data transactions onto incoming transforming schema change", async () => {
1209
+ semanticRebaseExtendedIt("local multiple data transactions onto incoming transforming schema change", async () => {
1157
1210
  t = await TestIModel.initialize("LocalMultipleDataIncomingTransform");
1158
1211
  let farTxn = startTestTxn(t.far, "local multiple data transactions onto incoming transforming schema change far");
1159
1212
  let localTxn = startTestTxn(t.local, "local multiple data transactions onto incoming transforming schema change local");
@@ -1195,7 +1248,7 @@ describe("Semantic Rebase", function () {
1195
1248
  const schema = t.local.getSchemaProps("TestDomain");
1196
1249
  chai.expect(schema.version).to.equal("01.00.02", "Schema should be transformed to v01.00.02");
1197
1250
  });
1198
- it("local transforming schema change onto incoming multiple data transactions", async () => {
1251
+ semanticRebaseExtendedIt("local transforming schema change onto incoming multiple data transactions", async () => {
1199
1252
  t = await TestIModel.initialize("LocalTransformIncomingMultipleData");
1200
1253
  let farTxn = startTestTxn(t.far, "local transforming schema change onto incoming multiple data transactions far");
1201
1254
  let localTxn = startTestTxn(t.local, "local transforming schema change onto incoming multiple data transactions local");
@@ -1237,7 +1290,7 @@ describe("Semantic Rebase", function () {
1237
1290
  const schema = t.local.getSchemaProps("TestDomain");
1238
1291
  chai.expect(schema.version).to.equal("01.00.02", "Local schema transformation should be preserved");
1239
1292
  });
1240
- it("bulk local elements survive semantic rebase with incoming transforming schema change", async function () {
1293
+ semanticRebaseExtendedIt("bulk local elements survive semantic rebase with incoming transforming schema change", async function () {
1241
1294
  const runBulkRebaseTest = async (count) => {
1242
1295
  t = await TestIModel.initialize(`BulkElements${count}`);
1243
1296
  const farTxn = startTestTxn(t.far, `${count} elements rebase far`);
@@ -1269,7 +1322,7 @@ describe("Semantic Rebase", function () {
1269
1322
  await runBulkRebaseTest(100);
1270
1323
  await runBulkRebaseTest(101);
1271
1324
  });
1272
- it("should fail when importing schema with unsaved data changes", async () => {
1325
+ semanticRebaseExtendedIt("should fail when importing schema with unsaved data changes", async () => {
1273
1326
  t = await TestIModel.initialize("UnsavedDataChangesSchemaImport");
1274
1327
  const localTxn = startTestTxn(t.local, "should fail when importing schema with unsaved data changes local");
1275
1328
  // Create element but DO NOT save changes
@@ -1286,11 +1339,148 @@ describe("Semantic Rebase", function () {
1286
1339
  chai.expect(schema.version).to.equal("01.00.00", "Schema should remain at v01.00.00");
1287
1340
  chai.expect(t.local.isOpen).to.be.true;
1288
1341
  });
1342
+ it("navigation property (parent) with explicit relationship class survives trivial schema rebase", async () => {
1343
+ t = await TestIModel.initialize("ClassIdNavTrivial");
1344
+ const localTxn = startTestTxn(t.local, "nav parent trivial local");
1345
+ const farTxn = startTestTxn(t.far, "nav parent trivial far");
1346
+ // Far imports a trivial additive schema change and pushes it (incoming change to rebase onto).
1347
+ await t.far.locks.acquireLocks({ shared: t.drawingModelId });
1348
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x01AddPropC2]);
1349
+ await pushChanges(farTxn, "add PropC2 to class C");
1350
+ // Local inserts (unpushed) a parent element and a child whose `parent` navigation property
1351
+ // carries an explicit relationship class (RelECClassId). These inserts are the changes that
1352
+ // get captured and reinstated during the rebase.
1353
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1354
+ const parentId = t.insertElement(localTxn, "TestDomain:A", { propA: "parent_a" });
1355
+ const childId = t.insertElement(localTxn, "TestDomain:C", {
1356
+ propA: "child_a",
1357
+ propC: "child_c",
1358
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1359
+ });
1360
+ localTxn.saveChanges("local insert parent + child");
1361
+ // Local pulls and rebases its local inserts onto the incoming schema change.
1362
+ await pullChanges(localTxn);
1363
+ t.local.clearCaches();
1364
+ // The navigation property (id + relClassName) captured from the insert must survive the rebase.
1365
+ const child = t.getElementProps(t.local, childId);
1366
+ chai.expect(child.parent).to.not.be.undefined;
1367
+ chai.expect(child.parent.id).to.equal(parentId, "parent navigation id must be preserved");
1368
+ chai.expect(child.parent.relClassName.replace(":", ".")).to.equal("BisCore.ElementOwnsChildElements", "parent navigation relationship class name must be preserved");
1369
+ chai.expect(child.classFullName).to.equal("TestDomain:C", "child classFullName must be preserved");
1370
+ chai.expect(child.propA).to.equal("child_a", "propA must be preserved");
1371
+ chai.expect(child.propC).to.equal("child_c", "propC must be preserved");
1372
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.01");
1373
+ });
1374
+ it("navigation property + multi-class ECClassId survive transforming schema rebase", async () => {
1375
+ t = await TestIModel.initialize("ClassIdNavTransforming");
1376
+ let localTxn = startTestTxn(t.local, "nav parent transforming local");
1377
+ let farTxn = startTestTxn(t.far, "nav parent transforming far");
1378
+ // Baseline: bump both briefcases to v01.00.01 so the incoming transforming change (v01.00.02
1379
+ // MovePropCToA) applies cleanly on top of it.
1380
+ await importSchemaStrings(localTxn, [TestIModel.schemas.v01x00x01AddPropC2]);
1381
+ await pushChanges(localTxn, "baseline v01.00.01");
1382
+ localTxn = startTestTxn(t.local, "nav parent transforming local");
1383
+ await pullChanges(farTxn);
1384
+ farTxn = startTestTxn(t.far, "nav parent transforming far");
1385
+ // Local inserts a parent (class A) and children of classes C and D, with explicit parent
1386
+ // relationship classes, then makes them local (unpushed) changes.
1387
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1388
+ const parentId = t.insertElement(localTxn, "TestDomain:A", { propA: "parent_a" });
1389
+ const cChildId = t.insertElement(localTxn, "TestDomain:C", {
1390
+ propA: "c_a",
1391
+ propC: "c_c",
1392
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1393
+ });
1394
+ const dChildId = t.insertElement(localTxn, "TestDomain:D", {
1395
+ propA: "d_a",
1396
+ propD: "d_d",
1397
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1398
+ });
1399
+ localTxn.saveChanges("local insert parent + C + D children");
1400
+ // Far pushes a transforming schema change (moves PropC from C to A).
1401
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x02MovePropCToA]);
1402
+ await pushChanges(farTxn, "far transforming schema v01.00.02");
1403
+ // Local pulls and rebases its local inserts onto the transforming schema change.
1404
+ await pullChanges(localTxn);
1405
+ t.local.clearCaches();
1406
+ // ECClassId of each element (a class-id-typed value) must resolve to the correct class name.
1407
+ const cChild = t.getElementProps(t.local, cChildId);
1408
+ chai.expect(cChild.classFullName).to.equal("TestDomain:C", "C child classFullName must be preserved");
1409
+ chai.expect(cChild.propC).to.equal("c_c", "propC value must survive column migration C→A");
1410
+ chai.expect(cChild.parent.id).to.equal(parentId, "C child parent id must be preserved");
1411
+ chai.expect(cChild.parent.relClassName.replace(":", ".")).to.equal("BisCore.ElementOwnsChildElements");
1412
+ const dChild = t.getElementProps(t.local, dChildId);
1413
+ chai.expect(dChild.classFullName).to.equal("TestDomain:D", "D child classFullName must be preserved");
1414
+ chai.expect(dChild.propD).to.equal("d_d");
1415
+ chai.expect(dChild.parent.id).to.equal(parentId, "D child parent id must be preserved");
1416
+ // ECSql resolves ECClassId to the correct class names after rebase.
1417
+ const rows = await TestIModel.queryToMap(t.local, `SELECT ECInstanceId, ec_className(ECClassId) AS className FROM TestDomain.A`);
1418
+ chai.expect(rows.get(cChildId)?.className).to.include("C");
1419
+ chai.expect(rows.get(dChildId)?.className).to.include("D");
1420
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.02");
1421
+ });
1422
+ it("link-table relationship (with constraint class ids) survives transforming schema rebase", async () => {
1423
+ t = await TestIModel.initialize("LinkTableRelTransforming");
1424
+ let localTxn = startTestTxn(t.local, "link table rel transforming local");
1425
+ let farTxn = startTestTxn(t.far, "link table rel transforming far");
1426
+ // Baseline: bump both briefcases to v01.00.01 so the ARefersToA link-table relationship class
1427
+ // exists on both sides and the incoming transforming change (v01.00.02 MovePropCToA) applies cleanly.
1428
+ await importSchemaStrings(localTxn, [TestIModel.schemas.v01x00x01WithRelationship]);
1429
+ await pushChanges(localTxn, "baseline v01.00.01 with relationship class");
1430
+ localTxn = startTestTxn(t.local, "link table rel transforming local");
1431
+ await pullChanges(farTxn);
1432
+ farTxn = startTestTxn(t.far, "link table rel transforming far");
1433
+ // Local inserts a source (class C) and a target (class D) element and a link-table relationship
1434
+ // (ARefersToA) between them - all unpushed local changes to be reinstated during rebase.
1435
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1436
+ const sourceId = t.insertElement(localTxn, "TestDomain:C", { propA: "src_a", propC: "src_c" });
1437
+ const targetId = t.insertElement(localTxn, "TestDomain:D", { propA: "tgt_a", propD: "tgt_d" });
1438
+ const relId = localTxn.insertRelationship({
1439
+ classFullName: "TestDomain:ARefersToA",
1440
+ sourceId,
1441
+ targetId,
1442
+ });
1443
+ localTxn.saveChanges("local insert source + target + relationship");
1444
+ // Far pushes a transforming schema change (moves PropC from C to A) which migrates the source
1445
+ // element's column, so the relationship's SourceECClassId must survive the migration.
1446
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x02WithRelationshipMovePropCToA]);
1447
+ await pushChanges(farTxn, "far transforming schema v01.00.02");
1448
+ // Local pulls and rebases its local inserts onto the transforming schema change.
1449
+ await pullChanges(localTxn);
1450
+ t.local.clearCaches();
1451
+ // The relationship instance and its endpoints must survive the rebase.
1452
+ const rel = t.local.relationships.tryGetInstanceProps("TestDomain:ARefersToA", relId);
1453
+ chai.expect(rel, "relationship should exist after rebase").to.not.be.undefined;
1454
+ chai.expect(rel.sourceId).to.equal(sourceId, "relationship source id must be preserved");
1455
+ chai.expect(rel.targetId).to.equal(targetId, "relationship target id must be preserved");
1456
+ // ECSql resolves the relationship's ECClassId and its constraint class ids (Source/Target) to the
1457
+ // correct class names even after the transforming schema change migrated the endpoint columns.
1458
+ const rows = await TestIModel.queryToMap(t.local, `SELECT ECInstanceId, SourceECInstanceId AS sourceId, TargetECInstanceId AS targetId,
1459
+ ec_className(ECClassId, 's.c') AS className,
1460
+ ec_className(SourceECClassId, 's.c') AS sourceClassName,
1461
+ ec_className(TargetECClassId, 's.c') AS targetClassName
1462
+ FROM TestDomain.ARefersToA`);
1463
+ const relRow = rows.get(relId);
1464
+ chai.expect(relRow, "relationship row should be queryable after rebase").to.not.be.undefined;
1465
+ chai.expect(relRow.sourceId).to.equal(sourceId);
1466
+ chai.expect(relRow.targetId).to.equal(targetId);
1467
+ chai.expect(relRow.className).to.equal("TestDomain.ARefersToA", "relationship class id must resolve to ARefersToA");
1468
+ chai.expect(relRow.sourceClassName).to.equal("TestDomain.C", "source constraint class id must resolve to class C");
1469
+ chai.expect(relRow.targetClassName).to.equal("TestDomain.D", "target constraint class id must resolve to class D");
1470
+ // The endpoint elements themselves survive the transforming change with values intact.
1471
+ const source = t.getElementProps(t.local, sourceId);
1472
+ chai.expect(source.classFullName).to.equal("TestDomain:C", "source classFullName must be preserved");
1473
+ chai.expect(source.propC).to.equal("src_c", "propC value must survive column migration C→A");
1474
+ const target = t.getElementProps(t.local, targetId);
1475
+ chai.expect(target.classFullName).to.equal("TestDomain:D", "target classFullName must be preserved");
1476
+ chai.expect(target.propD).to.equal("tgt_d", "propD value must be preserved");
1477
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.02");
1478
+ });
1289
1479
  });
1290
1480
  /**
1291
1481
  * Test suite for tests related to rebase logic with schema changes (for indirect changes) that require data transformations.
1292
1482
  */
1293
- describe("Semantic Rebase with indirect changes", function () {
1483
+ semanticRebaseExtendedDescribe("Semantic Rebase with indirect changes", function () {
1294
1484
  this.timeout(90000); // operations can be slow
1295
1485
  let t;
1296
1486
  before(async () => {
@@ -1575,7 +1765,7 @@ describe("Semantic Rebase with indirect changes", function () {
1575
1765
  /**
1576
1766
  * Test suite for data conflicts, conflict handlers, lifecycle events, and mixed schema+conflict scenarios during semantic rebase.
1577
1767
  */
1578
- describe("Semantic Rebase - Data Correctness Under Conflict", function () {
1768
+ semanticRebaseExtendedDescribe("Semantic Rebase - Data Correctness Under Conflict", function () {
1579
1769
  this.timeout(90000);
1580
1770
  let t;
1581
1771
  before(async () => {
@@ -1787,7 +1977,7 @@ describe("Semantic Rebase - Data Correctness Under Conflict", function () {
1787
1977
  * Multi-step schema upgrade chains.
1788
1978
  * Tests scenarios where one or both sides import schemas in multiple sequential steps before the rebase.
1789
1979
  */
1790
- describe("Semantic Rebase - Multi-Step Schema Upgrade Chains", function () {
1980
+ semanticRebaseExtendedDescribe("Semantic Rebase - Multi-Step Schema Upgrade Chains", function () {
1791
1981
  this.timeout(90000);
1792
1982
  let t;
1793
1983
  before(async () => {
@@ -1971,7 +2161,7 @@ describe("Semantic Rebase - Multi-Step Schema Upgrade Chains", function () {
1971
2161
  * ElementAspect changes during semantic rebase.
1972
2162
  * Tests that aspect insert/update/delete operations are correctly captured and reinstated.
1973
2163
  */
1974
- describe("Semantic Rebase - ElementAspect Changes", function () {
2164
+ semanticRebaseExtendedDescribe("Semantic Rebase - ElementAspect Changes", function () {
1975
2165
  this.timeout(90000);
1976
2166
  let t;
1977
2167
  before(async () => {
@@ -2178,7 +2368,7 @@ describe("Semantic Rebase - ElementAspect Changes", function () {
2178
2368
  * Property type variations during semantic rebase.
2179
2369
  * Ensures int, double, and boolean property values are preserved correctly through rebase.
2180
2370
  */
2181
- describe("Semantic Rebase - Property Type Variations", function () {
2371
+ semanticRebaseExtendedDescribe("Semantic Rebase - Property Type Variations", function () {
2182
2372
  this.timeout(90000);
2183
2373
  let t;
2184
2374
  before(async () => {
@@ -2366,7 +2556,7 @@ describe("Semantic Rebase - Property Type Variations", function () {
2366
2556
  * Both sides delete the same element.
2367
2557
  * Edge case where both local and far delete the same element independently.
2368
2558
  */
2369
- describe("Semantic Rebase - Both Sides Delete Same Element", function () {
2559
+ semanticRebaseExtendedDescribe("Semantic Rebase - Both Sides Delete Same Element", function () {
2370
2560
  this.timeout(90000);
2371
2561
  let t;
2372
2562
  before(async () => {
@@ -2424,7 +2614,7 @@ describe("Semantic Rebase - Both Sides Delete Same Element", function () {
2424
2614
  * Three-briefcase scenarios.
2425
2615
  * Tests interactions when three separate briefcases are involved in schema+data operations.
2426
2616
  */
2427
- describe("Semantic Rebase - Three Briefcase Scenarios", function () {
2617
+ semanticRebaseExtendedDescribe("Semantic Rebase - Three Briefcase Scenarios", function () {
2428
2618
  this.timeout(90000);
2429
2619
  let t;
2430
2620
  before(async () => {
@@ -2540,7 +2730,7 @@ describe("Semantic Rebase - Three Briefcase Scenarios", function () {
2540
2730
  * Tests that semantic rebase state is handled correctly when the local briefcase
2541
2731
  * pulls multiple times before pushing, accumulating rebase operations.
2542
2732
  */
2543
- describe("Semantic Rebase - Multiple Pulls Without Push", function () {
2733
+ semanticRebaseExtendedDescribe("Semantic Rebase - Multiple Pulls Without Push", function () {
2544
2734
  this.timeout(90000);
2545
2735
  let t;
2546
2736
  before(async () => {
@@ -2623,7 +2813,7 @@ describe("Semantic Rebase - Multiple Pulls Without Push", function () {
2623
2813
  * New class addition to schema.
2624
2814
  * Tests that newly added entity classes and their instances survive semantic rebase.
2625
2815
  */
2626
- describe("Semantic Rebase - New Class Addition to Schema", function () {
2816
+ semanticRebaseExtendedDescribe("Semantic Rebase - New Class Addition to Schema", function () {
2627
2817
  this.timeout(90000);
2628
2818
  let t;
2629
2819
  before(async () => {
@@ -2751,7 +2941,7 @@ describe("Semantic Rebase - New Class Addition to Schema", function () {
2751
2941
  * Guard conditions and error paths for semantic rebase.
2752
2942
  * Tests boundary conditions like importing schema while rebasing, concurrent pull attempts, etc.
2753
2943
  */
2754
- describe("Semantic Rebase - Guard Conditions and Error Paths", function () {
2944
+ semanticRebaseExtendedDescribe("Semantic Rebase - Guard Conditions and Error Paths", function () {
2755
2945
  this.timeout(90000);
2756
2946
  let t;
2757
2947
  before(async () => {
@@ -2871,7 +3061,7 @@ describe("Semantic Rebase - Guard Conditions and Error Paths", function () {
2871
3061
  * Tests scenarios where local txns contain a mix of insert, update, and delete operations
2872
3062
  * that need to be correctly captured and reinstated during semantic rebase.
2873
3063
  */
2874
- describe("Semantic Rebase - Complex Insert-Update-Delete Sequences", function () {
3064
+ semanticRebaseExtendedDescribe("Semantic Rebase - Complex Insert-Update-Delete Sequences", function () {
2875
3065
  this.timeout(90000);
2876
3066
  let t;
2877
3067
  before(async () => {
@@ -3036,7 +3226,7 @@ describe("Semantic Rebase - Complex Insert-Update-Delete Sequences", function ()
3036
3226
  * Cleanup and folder lifecycle edge cases.
3037
3227
  * Tests that rebase folder state is correctly managed in unusual lifecycle scenarios.
3038
3228
  */
3039
- describe("Semantic Rebase - Cleanup and Folder Lifecycle", function () {
3229
+ semanticRebaseExtendedDescribe("Semantic Rebase - Cleanup and Folder Lifecycle", function () {
3040
3230
  this.timeout(90000);
3041
3231
  let t;
3042
3232
  before(async () => {
@@ -3129,7 +3319,7 @@ describe("Semantic Rebase - Cleanup and Folder Lifecycle", function () {
3129
3319
  chai.expect(schema.version).to.equal("01.00.02", "Schema should be at v02 after cycle 2");
3130
3320
  });
3131
3321
  });
3132
- describe("Semantic Rebase - Multi-Pull Verification", function () {
3322
+ semanticRebaseExtendedDescribe("Semantic Rebase - Multi-Pull Verification", function () {
3133
3323
  this.timeout(120000);
3134
3324
  let t;
3135
3325
  before(async () => {