@itwin/core-backend 5.14.0-dev.1 → 5.14.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.
- package/CHANGELOG.md +21 -1
- package/lib/cjs/BriefcaseManager.d.ts +6 -0
- package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
- package/lib/cjs/BriefcaseManager.js +12 -6
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/ChangesetReader.d.ts.map +1 -1
- package/lib/cjs/ChangesetReader.js +1 -0
- package/lib/cjs/ChangesetReader.js.map +1 -1
- package/lib/cjs/ChangesetReaderTypes.d.ts +2 -1
- package/lib/cjs/ChangesetReaderTypes.d.ts.map +1 -1
- package/lib/cjs/ChangesetReaderTypes.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js +9 -2
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +1 -0
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/Element.d.ts +1 -1
- package/lib/cjs/Element.js +1 -1
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/Entity.d.ts +3 -3
- package/lib/cjs/Entity.js +3 -3
- package/lib/cjs/Entity.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +83 -35
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +196 -89
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IpcHost.d.ts.map +1 -1
- package/lib/cjs/IpcHost.js +51 -17
- package/lib/cjs/IpcHost.js.map +1 -1
- package/lib/cjs/SchemaSync.d.ts +126 -18
- package/lib/cjs/SchemaSync.d.ts.map +1 -1
- package/lib/cjs/SchemaSync.js +303 -81
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/SynchronousChannel.d.ts +11 -1
- package/lib/cjs/SynchronousChannel.d.ts.map +1 -1
- package/lib/cjs/SynchronousChannel.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +16 -13
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/internal/IntegrityCheck.d.ts +57 -0
- package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -1
- package/lib/cjs/internal/IntegrityCheck.js.map +1 -1
- package/lib/cjs/internal/SchemaSyncReservations.d.ts.map +1 -1
- package/lib/cjs/internal/SchemaSyncReservations.js +13 -3
- package/lib/cjs/internal/SchemaSyncReservations.js.map +1 -1
- package/lib/esm/BriefcaseManager.d.ts +6 -0
- package/lib/esm/BriefcaseManager.d.ts.map +1 -1
- package/lib/esm/BriefcaseManager.js +12 -6
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/ChangesetReader.d.ts.map +1 -1
- package/lib/esm/ChangesetReader.js +1 -0
- package/lib/esm/ChangesetReader.js.map +1 -1
- package/lib/esm/ChangesetReaderTypes.d.ts +2 -1
- package/lib/esm/ChangesetReaderTypes.d.ts.map +1 -1
- package/lib/esm/ChangesetReaderTypes.js.map +1 -1
- package/lib/esm/CloudSqlite.d.ts.map +1 -1
- package/lib/esm/CloudSqlite.js +10 -3
- package/lib/esm/CloudSqlite.js.map +1 -1
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +1 -0
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/Element.d.ts +1 -1
- package/lib/esm/Element.js +1 -1
- package/lib/esm/Element.js.map +1 -1
- package/lib/esm/Entity.d.ts +3 -3
- package/lib/esm/Entity.js +3 -3
- package/lib/esm/Entity.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +83 -35
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +196 -89
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/IpcHost.d.ts.map +1 -1
- package/lib/esm/IpcHost.js +52 -18
- package/lib/esm/IpcHost.js.map +1 -1
- package/lib/esm/SchemaSync.d.ts +126 -18
- package/lib/esm/SchemaSync.d.ts.map +1 -1
- package/lib/esm/SchemaSync.js +304 -82
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/SynchronousChannel.d.ts +11 -1
- package/lib/esm/SynchronousChannel.d.ts.map +1 -1
- package/lib/esm/SynchronousChannel.js.map +1 -1
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +17 -14
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/internal/IntegrityCheck.d.ts +57 -0
- package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -1
- package/lib/esm/internal/IntegrityCheck.js.map +1 -1
- package/lib/esm/internal/SchemaSyncReservations.d.ts.map +1 -1
- package/lib/esm/internal/SchemaSyncReservations.js +13 -3
- package/lib/esm/internal/SchemaSyncReservations.js.map +1 -1
- package/lib/esm/test/annotations/FrameGeometry.test.js +1 -1
- package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js +65 -1
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
- package/lib/esm/test/hubaccess/Rebase.test.js +3 -1
- package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SemanticRebase.test.js +218 -28
- package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts +3 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts.map +1 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js +15 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js.map +1 -0
- package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
- package/lib/esm/test/standalone/SchemaSyncDb.test.js +5 -25
- package/lib/esm/test/standalone/SchemaSyncDb.test.js.map +1 -1
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js +1 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js.map +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3322
|
+
semanticRebaseExtendedDescribe("Semantic Rebase - Multi-Pull Verification", function () {
|
|
3133
3323
|
this.timeout(120000);
|
|
3134
3324
|
let t;
|
|
3135
3325
|
before(async () => {
|