@itwin/core-backend 5.15.0-dev.9 → 5.16.0-dev.3
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 +11 -1
- package/lib/cjs/BlobContainerService.d.ts +2 -0
- package/lib/cjs/BlobContainerService.d.ts.map +1 -1
- package/lib/cjs/BlobContainerService.js.map +1 -1
- package/lib/cjs/BriefcaseManager.d.ts +2 -1
- package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
- package/lib/cjs/BriefcaseManager.js +39 -9
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/ChangeUnifier.d.ts +82 -0
- package/lib/cjs/ChangeUnifier.d.ts.map +1 -0
- package/lib/cjs/ChangeUnifier.js +163 -0
- package/lib/cjs/ChangeUnifier.js.map +1 -0
- package/lib/cjs/ChangesetReader.d.ts +21 -2
- package/lib/cjs/ChangesetReader.d.ts.map +1 -1
- package/lib/cjs/ChangesetReader.js +37 -1
- package/lib/cjs/ChangesetReader.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +15 -0
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/ECDb.d.ts +1 -0
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +4 -1
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/EditTxn.d.ts +5 -0
- package/lib/cjs/EditTxn.d.ts.map +1 -1
- package/lib/cjs/EditTxn.js +30 -10
- package/lib/cjs/EditTxn.js.map +1 -1
- package/lib/cjs/GeoCoordConfig.d.ts +1 -0
- package/lib/cjs/GeoCoordConfig.d.ts.map +1 -1
- package/lib/cjs/GeoCoordConfig.js +12 -8
- package/lib/cjs/GeoCoordConfig.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +19 -6
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +50 -9
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/NativeHost.d.ts.map +1 -1
- package/lib/cjs/NativeHost.js +5 -1
- package/lib/cjs/NativeHost.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +28 -0
- package/lib/cjs/Relationship.d.ts.map +1 -1
- package/lib/cjs/Relationship.js +78 -0
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/SchemaSync.d.ts.map +1 -1
- package/lib/cjs/SchemaSync.js +1 -0
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +126 -89
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +114 -76
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewStateHydrator.d.ts.map +1 -1
- package/lib/cjs/ViewStateHydrator.js.map +1 -1
- package/lib/cjs/ViewStore.d.ts.map +1 -1
- package/lib/cjs/ViewStore.js +62 -19
- package/lib/cjs/ViewStore.js.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.js +3 -0
- package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
- package/lib/cjs/core-backend.d.ts +1 -0
- package/lib/cjs/core-backend.d.ts.map +1 -1
- package/lib/cjs/core-backend.js +1 -0
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/internal/BriefcaseUtils.d.ts +19 -0
- package/lib/cjs/internal/BriefcaseUtils.d.ts.map +1 -0
- package/lib/cjs/internal/BriefcaseUtils.js +65 -0
- package/lib/cjs/internal/BriefcaseUtils.js.map +1 -0
- package/lib/cjs/internal/QueryMetadataCache.d.ts +44 -0
- package/lib/cjs/internal/QueryMetadataCache.d.ts.map +1 -0
- package/lib/cjs/internal/QueryMetadataCache.js +107 -0
- package/lib/cjs/internal/QueryMetadataCache.js.map +1 -0
- package/lib/cjs/internal/Symbols.d.ts +9 -0
- package/lib/cjs/internal/Symbols.d.ts.map +1 -1
- package/lib/cjs/internal/Symbols.js +10 -1
- package/lib/cjs/internal/Symbols.js.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.js +20 -6
- package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.d.ts +4 -3
- package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.js +7 -5
- package/lib/cjs/workspace/SettingsEditor.js.map +1 -1
- package/lib/esm/BlobContainerService.d.ts +2 -0
- package/lib/esm/BlobContainerService.d.ts.map +1 -1
- package/lib/esm/BlobContainerService.js.map +1 -1
- package/lib/esm/BriefcaseManager.d.ts +2 -1
- package/lib/esm/BriefcaseManager.d.ts.map +1 -1
- package/lib/esm/BriefcaseManager.js +40 -10
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/ChangeUnifier.d.ts +82 -0
- package/lib/esm/ChangeUnifier.d.ts.map +1 -0
- package/lib/esm/ChangeUnifier.js +159 -0
- package/lib/esm/ChangeUnifier.js.map +1 -0
- package/lib/esm/ChangesetReader.d.ts +21 -2
- package/lib/esm/ChangesetReader.d.ts.map +1 -1
- package/lib/esm/ChangesetReader.js +38 -2
- package/lib/esm/ChangesetReader.js.map +1 -1
- package/lib/esm/CloudSqlite.d.ts +15 -0
- package/lib/esm/CloudSqlite.d.ts.map +1 -1
- package/lib/esm/CloudSqlite.js.map +1 -1
- package/lib/esm/ECDb.d.ts +1 -0
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +4 -1
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/EditTxn.d.ts +5 -0
- package/lib/esm/EditTxn.d.ts.map +1 -1
- package/lib/esm/EditTxn.js +32 -12
- package/lib/esm/EditTxn.js.map +1 -1
- package/lib/esm/GeoCoordConfig.d.ts +1 -0
- package/lib/esm/GeoCoordConfig.d.ts.map +1 -1
- package/lib/esm/GeoCoordConfig.js +12 -8
- package/lib/esm/GeoCoordConfig.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +19 -6
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +52 -11
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/NativeHost.d.ts.map +1 -1
- package/lib/esm/NativeHost.js +5 -1
- package/lib/esm/NativeHost.js.map +1 -1
- package/lib/esm/Relationship.d.ts +28 -0
- package/lib/esm/Relationship.d.ts.map +1 -1
- package/lib/esm/Relationship.js +78 -0
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/SchemaSync.d.ts.map +1 -1
- package/lib/esm/SchemaSync.js +1 -0
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/TxnManager.d.ts +126 -89
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +116 -78
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/ViewStateHydrator.d.ts.map +1 -1
- package/lib/esm/ViewStateHydrator.js.map +1 -1
- package/lib/esm/ViewStore.d.ts.map +1 -1
- package/lib/esm/ViewStore.js +62 -19
- package/lib/esm/ViewStore.js.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.js +3 -0
- package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
- package/lib/esm/core-backend.d.ts +1 -0
- package/lib/esm/core-backend.d.ts.map +1 -1
- package/lib/esm/core-backend.js +1 -0
- package/lib/esm/core-backend.js.map +1 -1
- package/lib/esm/internal/BriefcaseUtils.d.ts +19 -0
- package/lib/esm/internal/BriefcaseUtils.d.ts.map +1 -0
- package/lib/esm/internal/BriefcaseUtils.js +61 -0
- package/lib/esm/internal/BriefcaseUtils.js.map +1 -0
- package/lib/esm/internal/QueryMetadataCache.d.ts +44 -0
- package/lib/esm/internal/QueryMetadataCache.d.ts.map +1 -0
- package/lib/esm/internal/QueryMetadataCache.js +103 -0
- package/lib/esm/internal/QueryMetadataCache.js.map +1 -0
- package/lib/esm/internal/Symbols.d.ts +9 -0
- package/lib/esm/internal/Symbols.d.ts.map +1 -1
- package/lib/esm/internal/Symbols.js +9 -0
- package/lib/esm/internal/Symbols.js.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.js +20 -6
- package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
- package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
- package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/esm/test/annotations/LeaderGeometry.test.js +15 -1
- package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
- package/lib/esm/test/ecdb/CTE.test.js +21 -0
- package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js +144 -30
- package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts +2 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts.map +1 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js +630 -0
- package/lib/esm/test/ecdb/QueryMetadataCache.test.js.map +1 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts +2 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts.map +1 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.js +202 -0
- package/lib/esm/test/element/RelationshipBatchLookup.test.js.map +1 -0
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js +187 -1
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts +2 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts.map +1 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js +142 -0
- package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.js +8 -6
- package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -1
- package/lib/esm/test/imodel/IModelProps.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelProps.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelProps.test.js +411 -0
- package/lib/esm/test/imodel/IModelProps.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js +240 -0
- package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.js +2 -8
- package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -1
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts +2 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js +159 -0
- package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js.map +1 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.d.ts +2 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.js +732 -0
- package/lib/esm/test/standalone/ChangeUnifier.test.js.map +1 -0
- package/lib/esm/test/standalone/EditTxn.test.js +72 -1
- package/lib/esm/test/standalone/EditTxn.test.js.map +1 -1
- package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts +2 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.js +158 -0
- package/lib/esm/test/standalone/GeoCoordConfig.test.js.map +1 -0
- package/lib/esm/test/standalone/ViewStoreDb.test.js +53 -0
- package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
- package/lib/esm/test/workspace/SettingsContainers.test.d.ts +2 -0
- package/lib/esm/test/workspace/SettingsContainers.test.d.ts.map +1 -0
- package/lib/esm/test/workspace/SettingsContainers.test.js +95 -0
- package/lib/esm/test/workspace/SettingsContainers.test.js.map +1 -0
- package/lib/esm/workspace/SettingsEditor.d.ts +4 -3
- package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/esm/workspace/SettingsEditor.js +7 -5
- package/lib/esm/workspace/SettingsEditor.js.map +1 -1
- package/package.json +18 -18
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { IModelStatus, Logger, OpenMode, UnexpectedErrors } from "@itwin/core-bentley";
|
|
6
|
+
import { Cartographic, EcefLocation, GeographicCRS } from "@itwin/core-common";
|
|
7
|
+
import { Range3d } from "@itwin/core-geometry";
|
|
8
|
+
import { expect } from "chai";
|
|
9
|
+
import * as sinon from "sinon";
|
|
10
|
+
import { BackendLoggerCategory, EditTxn, getAvailableVerticalCoordinateReferenceSystems, IModelJsFs, StandaloneDb, withEditTxn } from "../../core-backend";
|
|
11
|
+
import { _nativeDb, _refreshIModelProps } from "../../internal/Symbols";
|
|
12
|
+
import { IModelTestUtils } from "../IModelTestUtils";
|
|
13
|
+
import { TestUtils } from "../TestUtils";
|
|
14
|
+
import { getIModelError } from "./IModelTestFixtures";
|
|
15
|
+
describe("iModel property updates", () => {
|
|
16
|
+
let iModel;
|
|
17
|
+
let fileName;
|
|
18
|
+
const initialGcs = { horizontalCRS: { id: "LL84" }, verticalCRS: { id: "ELLIPSOID" } };
|
|
19
|
+
const changedGcs = {
|
|
20
|
+
...initialGcs,
|
|
21
|
+
additionalTransform: { helmert2DWithZOffset: { translationX: 1, translationY: 2, translationZ: 3, rotDeg: 0, scale: 1 } },
|
|
22
|
+
};
|
|
23
|
+
const extents = Range3d.createXYZXYZ(-10, -10, -10, 10, 10, 10);
|
|
24
|
+
const changedGcsJson = new GeographicCRS(changedGcs).toJSON();
|
|
25
|
+
before(async () => {
|
|
26
|
+
await TestUtils.shutdownBackend();
|
|
27
|
+
await TestUtils.startBackend({ loadGcsWorkspaces: true });
|
|
28
|
+
});
|
|
29
|
+
after(async () => {
|
|
30
|
+
await TestUtils.shutdownBackend();
|
|
31
|
+
await TestUtils.startBackend();
|
|
32
|
+
});
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
fileName = IModelTestUtils.prepareOutputFile("IModelProps", "IModelProps.bim");
|
|
35
|
+
iModel = StandaloneDb.createEmpty(fileName, { rootSubject: { name: "IModelProps" }, enableTransactions: true });
|
|
36
|
+
withEditTxn(iModel, (txn) => {
|
|
37
|
+
iModel.setGeographicCoordinateSystem(initialGcs);
|
|
38
|
+
txn.updateIModelProps();
|
|
39
|
+
});
|
|
40
|
+
expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.verticalCRS?.id).to.equal("ELLIPSOID");
|
|
41
|
+
});
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
sinon.restore();
|
|
44
|
+
if (iModel.isOpen)
|
|
45
|
+
iModel.close();
|
|
46
|
+
IModelJsFs.removeSync(fileName);
|
|
47
|
+
});
|
|
48
|
+
it("omits unchanged GCS data from general, extents, and ECEF updates", () => {
|
|
49
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
50
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
51
|
+
iModel.setGeographicCoordinateSystem(initialGcs);
|
|
52
|
+
const ecef = EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 }));
|
|
53
|
+
withEditTxn(iModel, (txn) => {
|
|
54
|
+
txn.updateIModelProps();
|
|
55
|
+
txn.updateProjectExtents(extents);
|
|
56
|
+
txn.updateEcefLocation(ecef);
|
|
57
|
+
});
|
|
58
|
+
expect(update.callCount).to.equal(3);
|
|
59
|
+
for (const call of update.getCalls())
|
|
60
|
+
expect(call.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
61
|
+
expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem).to.deep.equal(originalGcs);
|
|
62
|
+
expect(iModel[_nativeDb].getIModelProps().projectExtents).to.deep.equal(extents.toJSON());
|
|
63
|
+
});
|
|
64
|
+
it("preserves full named vertical metadata without asking native code to resolve it again", () => {
|
|
65
|
+
const namedGcs = {
|
|
66
|
+
horizontalCRS: { id: "LL84" },
|
|
67
|
+
verticalCRS: { id: "GEOID", crsName: "EGM96 height" },
|
|
68
|
+
};
|
|
69
|
+
withEditTxn(iModel, (txn) => {
|
|
70
|
+
iModel.setGeographicCoordinateSystem(namedGcs);
|
|
71
|
+
txn.updateIModelProps();
|
|
72
|
+
});
|
|
73
|
+
iModel[_refreshIModelProps]();
|
|
74
|
+
expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal("EGM96 height");
|
|
75
|
+
const property = { namespace: "dgn_Db", name: "DgnGCSVerticalCRS" };
|
|
76
|
+
const storedDefinition = iModel.queryFilePropertyString(property);
|
|
77
|
+
expect(storedDefinition).to.be.a("string").and.to.contain('"transforms"');
|
|
78
|
+
const nativeUpdate = iModel[_nativeDb].updateIModelProps.bind(iModel[_nativeDb]);
|
|
79
|
+
const update = sinon.stub(iModel[_nativeDb], "updateIModelProps").callsFake((props) => {
|
|
80
|
+
if (props.geographicCoordinateSystem)
|
|
81
|
+
throw new Error("GCS dictionary unavailable");
|
|
82
|
+
nativeUpdate(props);
|
|
83
|
+
});
|
|
84
|
+
withEditTxn(iModel, (txn) => {
|
|
85
|
+
txn.updateIModelProps();
|
|
86
|
+
txn.updateProjectExtents(extents);
|
|
87
|
+
txn.updateEcefLocation(EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 })));
|
|
88
|
+
});
|
|
89
|
+
expect(update.callCount).to.equal(3);
|
|
90
|
+
for (const call of update.getCalls())
|
|
91
|
+
expect(call.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
92
|
+
expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);
|
|
93
|
+
iModel.close();
|
|
94
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
95
|
+
expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal("EGM96 height");
|
|
96
|
+
expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);
|
|
97
|
+
});
|
|
98
|
+
it("preserves an inline named vertical definition that is absent from the dictionary", () => {
|
|
99
|
+
const crsName = "EditTxn custom height";
|
|
100
|
+
expect(getAvailableVerticalCoordinateReferenceSystems().some((entry) => entry.crsName === crsName)).to.be.false;
|
|
101
|
+
const customGcs = {
|
|
102
|
+
horizontalCRS: { id: "LL84" },
|
|
103
|
+
verticalCRS: {
|
|
104
|
+
id: "ELLIPSOID",
|
|
105
|
+
crsName,
|
|
106
|
+
datumName: crsName,
|
|
107
|
+
type: "ELLIPSOID",
|
|
108
|
+
units: "Meter",
|
|
109
|
+
extent: { southWest: { latitude: -90, longitude: -180 }, northEast: { latitude: 90, longitude: 180 } },
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
withEditTxn(iModel, () => {
|
|
113
|
+
iModel[_nativeDb].updateIModelProps({ ...iModel.toJSON(), geographicCoordinateSystem: customGcs });
|
|
114
|
+
});
|
|
115
|
+
iModel[_refreshIModelProps]();
|
|
116
|
+
expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(crsName);
|
|
117
|
+
const property = { namespace: "dgn_Db", name: "DgnGCSVerticalCRS" };
|
|
118
|
+
const storedDefinition = iModel.queryFilePropertyString(property);
|
|
119
|
+
expect(storedDefinition).to.be.a("string").and.to.contain(crsName);
|
|
120
|
+
withEditTxn(iModel, (txn) => {
|
|
121
|
+
txn.updateIModelProps();
|
|
122
|
+
txn.updateProjectExtents(extents);
|
|
123
|
+
txn.updateEcefLocation(EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 })));
|
|
124
|
+
});
|
|
125
|
+
expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);
|
|
126
|
+
iModel.close();
|
|
127
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
128
|
+
expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(crsName);
|
|
129
|
+
expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);
|
|
130
|
+
});
|
|
131
|
+
it("writes a pending GCS change through convenience methods only once", () => {
|
|
132
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
133
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
134
|
+
withEditTxn(iModel, (txn) => {
|
|
135
|
+
txn.updateProjectExtents(extents);
|
|
136
|
+
txn.updateIModelProps();
|
|
137
|
+
txn.saveChanges();
|
|
138
|
+
txn.updateProjectExtents(extents);
|
|
139
|
+
});
|
|
140
|
+
expect(update.firstCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);
|
|
141
|
+
expect(update.secondCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
142
|
+
expect(update.thirdCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
143
|
+
expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.additionalTransform).to.deep.equal(changedGcs.additionalTransform);
|
|
144
|
+
});
|
|
145
|
+
it("restores the GCS and comparison baseline after abandoning an update", () => {
|
|
146
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
147
|
+
expect(originalGcs).not.to.equal(undefined);
|
|
148
|
+
const txn = new EditTxn(iModel, "abandon GCS update");
|
|
149
|
+
txn.start();
|
|
150
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
151
|
+
txn.updateIModelProps();
|
|
152
|
+
txn.abandonChanges();
|
|
153
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
154
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
155
|
+
txn.updateProjectExtents(extents);
|
|
156
|
+
expect(update.firstCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
157
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
158
|
+
txn.updateIModelProps();
|
|
159
|
+
expect(update.secondCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);
|
|
160
|
+
txn.end("abandon");
|
|
161
|
+
});
|
|
162
|
+
it("does not treat a rejected native update as persisted", () => {
|
|
163
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
164
|
+
const nativeUpdate = iModel[_nativeDb].updateIModelProps.bind(iModel[_nativeDb]);
|
|
165
|
+
const update = sinon.stub(iModel[_nativeDb], "updateIModelProps");
|
|
166
|
+
update.onFirstCall().throws(new Error("GCS update rejected"));
|
|
167
|
+
update.onSecondCall().callsFake(nativeUpdate);
|
|
168
|
+
withEditTxn(iModel, (txn) => {
|
|
169
|
+
expect(() => txn.updateIModelProps()).to.throw("GCS update rejected");
|
|
170
|
+
txn.updateIModelProps();
|
|
171
|
+
});
|
|
172
|
+
expect(update.firstCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);
|
|
173
|
+
expect(update.secondCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);
|
|
174
|
+
expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.additionalTransform).to.deep.equal(changedGcs.additionalTransform);
|
|
175
|
+
});
|
|
176
|
+
it("rejects reentrant explicit and implicit writes while restoring an abandoned GCS", () => {
|
|
177
|
+
sinon.stub(EditTxn, "implicitWriteEnforcement").value("allow");
|
|
178
|
+
const unexpectedError = sinon.spy(UnexpectedErrors, "handle");
|
|
179
|
+
const originalProps = iModel[_nativeDb].getIModelProps();
|
|
180
|
+
const failure = new Error("abandon this edit");
|
|
181
|
+
const listener = sinon.spy(() => {
|
|
182
|
+
expect(() => iModel.getIndirectTxn().updateIModelProps()).to.throw("Cannot write while restoring the geographic coordinate system");
|
|
183
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- Exercise the legacy implicit write path.
|
|
184
|
+
expect(() => iModel.updateIModelProps()).to.throw("Cannot write while restoring the geographic coordinate system");
|
|
185
|
+
});
|
|
186
|
+
expect(() => withEditTxn(iModel, (txn) => {
|
|
187
|
+
iModel.rootSubject = { name: "Abandoned root subject" };
|
|
188
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
189
|
+
txn.updateIModelProps();
|
|
190
|
+
iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
191
|
+
throw failure;
|
|
192
|
+
})).to.throw(failure);
|
|
193
|
+
expect(listener.calledOnce).to.be.true;
|
|
194
|
+
expect(unexpectedError.called).to.be.false;
|
|
195
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
196
|
+
expect(iModel[_nativeDb].getIModelProps().rootSubject).to.deep.equal(originalProps.rootSubject);
|
|
197
|
+
iModel.close();
|
|
198
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
199
|
+
expect(iModel.rootSubject).to.deep.equal(originalProps.rootSubject);
|
|
200
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalProps.geographicCoordinateSystem).toJSON());
|
|
201
|
+
});
|
|
202
|
+
it("releases the transaction and write guard when a rollback listener throws", () => {
|
|
203
|
+
const unexpectedError = sinon.stub(UnexpectedErrors, "handle");
|
|
204
|
+
const txn = new EditTxn(iModel, "rollback listener");
|
|
205
|
+
txn.start();
|
|
206
|
+
iModel.rootSubject = { name: "Abandoned root subject" };
|
|
207
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
208
|
+
txn.updateIModelProps();
|
|
209
|
+
const listener = sinon.spy(() => iModel.getIndirectTxn().updateIModelProps());
|
|
210
|
+
const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
211
|
+
try {
|
|
212
|
+
txn.end("abandon");
|
|
213
|
+
expect(listener.threw()).to.be.true;
|
|
214
|
+
expect(listener.firstCall.exception).to.have.property("message", "Cannot write while restoring the geographic coordinate system");
|
|
215
|
+
expect(unexpectedError.calledOnceWithExactly(listener.firstCall.exception)).to.be.true;
|
|
216
|
+
expect(txn.isActive).to.be.false;
|
|
217
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
removeListener();
|
|
221
|
+
}
|
|
222
|
+
withEditTxn(iModel, (nextTxn) => nextTxn.saveFileProperty({ namespace: "test", name: "after-rollback" }, "allowed"));
|
|
223
|
+
iModel.close();
|
|
224
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
225
|
+
expect(iModel.rootSubject.name).to.equal("IModelProps");
|
|
226
|
+
expect(iModel.queryFilePropertyString({ namespace: "test", name: "after-rollback" })).to.equal("allowed");
|
|
227
|
+
});
|
|
228
|
+
it("rejects scoped transaction activation during undo abandonment without retaining ownership", () => {
|
|
229
|
+
sinon.stub(EditTxn, "implicitWriteEnforcement").value("allow");
|
|
230
|
+
const unexpectedError = sinon.stub(UnexpectedErrors, "handle");
|
|
231
|
+
iModel[_nativeDb].deleteAllTxns();
|
|
232
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
233
|
+
iModel.getIndirectTxn().updateIModelProps();
|
|
234
|
+
const edit = sinon.spy((txn) => txn.updateIModelProps());
|
|
235
|
+
const listener = sinon.spy(() => withEditTxn(iModel, edit));
|
|
236
|
+
const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
237
|
+
try {
|
|
238
|
+
expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.NothingToUndo);
|
|
239
|
+
expect(listener.calledOnce).to.be.true;
|
|
240
|
+
expect(unexpectedError.calledOnceWithExactly(listener.firstCall.exception)).to.be.true;
|
|
241
|
+
expect(listener.firstCall.exception).to.have.property("message", "Cannot write while restoring the geographic coordinate system");
|
|
242
|
+
expect(edit.called).to.be.false;
|
|
243
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
removeListener();
|
|
247
|
+
}
|
|
248
|
+
withEditTxn(iModel, (txn) => txn.saveFileProperty({ namespace: "test", name: "after-listener-start" }, "allowed"));
|
|
249
|
+
expect(iModel.queryFilePropertyString({ namespace: "test", name: "after-listener-start" })).to.equal("allowed");
|
|
250
|
+
});
|
|
251
|
+
for (const endTxn of [false, true]) {
|
|
252
|
+
it(`${endTxn ? "releases" : "retains"} transaction ownership when a rollback notification propagates`, () => {
|
|
253
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
254
|
+
const txn = new EditTxn(iModel, "propagating rollback listener");
|
|
255
|
+
txn.start();
|
|
256
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
257
|
+
txn.updateIModelProps();
|
|
258
|
+
const listener = sinon.spy(() => txn.updateIModelProps());
|
|
259
|
+
const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
260
|
+
const previousHandler = UnexpectedErrors.setHandler(UnexpectedErrors.reThrowImmediate);
|
|
261
|
+
try {
|
|
262
|
+
expect(() => endTxn ? txn.end("abandon") : txn.abandonChanges()).to.throw("Cannot write while restoring the geographic coordinate system");
|
|
263
|
+
expect(listener.calledOnce).to.be.true;
|
|
264
|
+
expect(txn.isActive).to.equal(!endTxn);
|
|
265
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
266
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
UnexpectedErrors.setHandler(previousHandler);
|
|
270
|
+
removeListener();
|
|
271
|
+
}
|
|
272
|
+
if (!endTxn)
|
|
273
|
+
txn.end("save");
|
|
274
|
+
withEditTxn(iModel, (nextTxn) => nextTxn.saveFileProperty({ namespace: "test", name: "after-propagated-notification" }, "allowed"));
|
|
275
|
+
expect(iModel.queryFilePropertyString({ namespace: "test", name: "after-propagated-notification" })).to.equal("allowed");
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
for (const asynchronous of [false, true]) {
|
|
279
|
+
it(`preserves the ${asynchronous ? "asynchronous" : "synchronous"} callback error when a rollback notification propagates`, async () => {
|
|
280
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
281
|
+
const failure = new Error("initiating edit failure");
|
|
282
|
+
const logError = sinon.spy(Logger, "logError");
|
|
283
|
+
let activeTxn;
|
|
284
|
+
let removeListener;
|
|
285
|
+
const listener = sinon.spy(() => iModel.getIndirectTxn().updateIModelProps());
|
|
286
|
+
const edit = (txn) => {
|
|
287
|
+
activeTxn = txn;
|
|
288
|
+
iModel.rootSubject = { name: "Abandoned root subject" };
|
|
289
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
290
|
+
txn.updateIModelProps();
|
|
291
|
+
removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
292
|
+
throw failure;
|
|
293
|
+
};
|
|
294
|
+
const previousHandler = UnexpectedErrors.setHandler(UnexpectedErrors.reThrowImmediate);
|
|
295
|
+
try {
|
|
296
|
+
if (asynchronous) {
|
|
297
|
+
const error = await withEditTxn(iModel, async (txn) => {
|
|
298
|
+
await Promise.resolve();
|
|
299
|
+
edit(txn);
|
|
300
|
+
}).catch((err) => err);
|
|
301
|
+
expect(error).to.equal(failure);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
expect(() => withEditTxn(iModel, edit)).to.throw(failure);
|
|
305
|
+
}
|
|
306
|
+
expect(listener.calledOnce).to.be.true;
|
|
307
|
+
expect(listener.firstCall.exception).to.have.property("message", "Cannot write while restoring the geographic coordinate system");
|
|
308
|
+
expect(logError.calledOnceWithExactly(BackendLoggerCategory.IModelDb, listener.firstCall.exception)).to.be.true;
|
|
309
|
+
expect(activeTxn?.isActive).to.be.false;
|
|
310
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
311
|
+
}
|
|
312
|
+
finally {
|
|
313
|
+
UnexpectedErrors.setHandler(previousHandler);
|
|
314
|
+
removeListener?.();
|
|
315
|
+
}
|
|
316
|
+
withEditTxn(iModel, (txn) => txn.saveFileProperty({ namespace: "test", name: "after-failed-scope" }, "allowed"));
|
|
317
|
+
iModel.close();
|
|
318
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
319
|
+
expect(iModel.rootSubject.name).to.equal("IModelProps");
|
|
320
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
321
|
+
expect(iModel.queryFilePropertyString({ namespace: "test", name: "after-failed-scope" })).to.equal("allowed");
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
it("refreshes the GCS and its baseline after undo", () => {
|
|
325
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
326
|
+
withEditTxn(iModel, (txn) => {
|
|
327
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
328
|
+
txn.updateIModelProps();
|
|
329
|
+
});
|
|
330
|
+
expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);
|
|
331
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
332
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
333
|
+
withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));
|
|
334
|
+
expect(update.firstCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
335
|
+
expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem).to.deep.equal(originalGcs);
|
|
336
|
+
});
|
|
337
|
+
it("refreshes the GCS and its baseline after redo", () => {
|
|
338
|
+
withEditTxn(iModel, (txn) => {
|
|
339
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
340
|
+
txn.updateIModelProps();
|
|
341
|
+
});
|
|
342
|
+
const persistedGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
343
|
+
expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);
|
|
344
|
+
expect(iModel.txns.reinstateTxn()).to.equal(IModelStatus.Success);
|
|
345
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(persistedGcs).toJSON());
|
|
346
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
347
|
+
withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));
|
|
348
|
+
expect(update.firstCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
349
|
+
});
|
|
350
|
+
it("refreshes an abandoned GCS even when there is nothing to undo", () => {
|
|
351
|
+
iModel[_nativeDb].deleteAllTxns();
|
|
352
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
353
|
+
const txn = new EditTxn(iModel, "undo unsaved GCS");
|
|
354
|
+
txn.start();
|
|
355
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
356
|
+
txn.updateIModelProps();
|
|
357
|
+
expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.NothingToUndo);
|
|
358
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
359
|
+
txn.end("abandon");
|
|
360
|
+
});
|
|
361
|
+
it("refreshes an abandoned GCS even when asynchronous redo fails", async () => {
|
|
362
|
+
iModel[_nativeDb].deleteAllTxns();
|
|
363
|
+
const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;
|
|
364
|
+
const txn = new EditTxn(iModel, "redo unsaved GCS");
|
|
365
|
+
txn.start();
|
|
366
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
367
|
+
txn.updateIModelProps();
|
|
368
|
+
const error = await getIModelError(iModel.txns.reinstateTxnAsync());
|
|
369
|
+
expect(error?.errorNumber).to.equal(IModelStatus.NothingToRedo);
|
|
370
|
+
expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());
|
|
371
|
+
txn.end("abandon");
|
|
372
|
+
});
|
|
373
|
+
it("rejects implicit listener writes during undo and redo cache restoration", () => {
|
|
374
|
+
sinon.stub(EditTxn, "implicitWriteEnforcement").value("allow");
|
|
375
|
+
const unexpectedError = sinon.spy(UnexpectedErrors, "handle");
|
|
376
|
+
withEditTxn(iModel, (txn) => {
|
|
377
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
378
|
+
txn.updateIModelProps();
|
|
379
|
+
});
|
|
380
|
+
const listener = sinon.spy(() => {
|
|
381
|
+
expect(() => iModel.getIndirectTxn().updateIModelProps()).to.throw("Cannot write while restoring the geographic coordinate system");
|
|
382
|
+
});
|
|
383
|
+
const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);
|
|
384
|
+
try {
|
|
385
|
+
expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);
|
|
386
|
+
expect(iModel.txns.reinstateTxn()).to.equal(IModelStatus.Success);
|
|
387
|
+
expect(listener.callCount).to.equal(2);
|
|
388
|
+
expect(unexpectedError.called).to.be.false;
|
|
389
|
+
expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;
|
|
390
|
+
}
|
|
391
|
+
finally {
|
|
392
|
+
removeListener();
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
it("uses the reloaded GCS as its baseline", () => {
|
|
396
|
+
iModel.close();
|
|
397
|
+
iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);
|
|
398
|
+
const update = sinon.spy(iModel[_nativeDb], "updateIModelProps");
|
|
399
|
+
withEditTxn(iModel, (txn) => txn.updateIModelProps());
|
|
400
|
+
expect(update.firstCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
401
|
+
withEditTxn(iModel, (txn) => {
|
|
402
|
+
iModel.setGeographicCoordinateSystem(changedGcs);
|
|
403
|
+
txn.updateIModelProps();
|
|
404
|
+
});
|
|
405
|
+
iModel[_refreshIModelProps]();
|
|
406
|
+
update.resetHistory();
|
|
407
|
+
withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));
|
|
408
|
+
expect(update.firstCall.args[0]).not.to.have.property("geographicCoordinateSystem");
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
//# sourceMappingURL=IModelProps.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IModelProps.test.js","sourceRoot":"","sources":["../../../../src/test/imodel/IModelProps.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport { IModelStatus, Logger, OpenMode, UnexpectedErrors } from \"@itwin/core-bentley\";\r\nimport { Cartographic, EcefLocation, GeographicCRS, GeographicCRSProps } from \"@itwin/core-common\";\r\nimport { Range3d } from \"@itwin/core-geometry\";\r\nimport { expect } from \"chai\";\r\nimport * as sinon from \"sinon\";\r\nimport { BackendLoggerCategory, EditTxn, getAvailableVerticalCoordinateReferenceSystems, IModelJsFs, StandaloneDb, withEditTxn } from \"../../core-backend\";\r\nimport { _nativeDb, _refreshIModelProps } from \"../../internal/Symbols\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\nimport { TestUtils } from \"../TestUtils\";\r\nimport { getIModelError } from \"./IModelTestFixtures\";\r\n\r\ndescribe(\"iModel property updates\", () => {\r\n let iModel: StandaloneDb;\r\n let fileName: string;\r\n const initialGcs: GeographicCRSProps = { horizontalCRS: { id: \"LL84\" }, verticalCRS: { id: \"ELLIPSOID\" } };\r\n const changedGcs: GeographicCRSProps = {\r\n ...initialGcs,\r\n additionalTransform: { helmert2DWithZOffset: { translationX: 1, translationY: 2, translationZ: 3, rotDeg: 0, scale: 1 } },\r\n };\r\n const extents = Range3d.createXYZXYZ(-10, -10, -10, 10, 10, 10);\r\n const changedGcsJson = new GeographicCRS(changedGcs).toJSON();\r\n\r\n before(async () => {\r\n await TestUtils.shutdownBackend();\r\n await TestUtils.startBackend({ loadGcsWorkspaces: true });\r\n });\r\n\r\n after(async () => {\r\n await TestUtils.shutdownBackend();\r\n await TestUtils.startBackend();\r\n });\r\n\r\n beforeEach(() => {\r\n fileName = IModelTestUtils.prepareOutputFile(\"IModelProps\", \"IModelProps.bim\");\r\n iModel = StandaloneDb.createEmpty(fileName, { rootSubject: { name: \"IModelProps\" }, enableTransactions: true });\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(initialGcs);\r\n txn.updateIModelProps();\r\n });\r\n expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.verticalCRS?.id).to.equal(\"ELLIPSOID\");\r\n });\r\n\r\n afterEach(() => {\r\n sinon.restore();\r\n if (iModel.isOpen)\r\n iModel.close();\r\n IModelJsFs.removeSync(fileName);\r\n });\r\n\r\n it(\"omits unchanged GCS data from general, extents, and ECEF updates\", () => {\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n iModel.setGeographicCoordinateSystem(initialGcs);\r\n const ecef = EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 }));\r\n withEditTxn(iModel, (txn) => {\r\n txn.updateIModelProps();\r\n txn.updateProjectExtents(extents);\r\n txn.updateEcefLocation(ecef);\r\n });\r\n expect(update.callCount).to.equal(3);\r\n for (const call of update.getCalls())\r\n expect(call.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n\r\n expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem).to.deep.equal(originalGcs);\r\n expect(iModel[_nativeDb].getIModelProps().projectExtents).to.deep.equal(extents.toJSON());\r\n });\r\n\r\n it(\"preserves full named vertical metadata without asking native code to resolve it again\", () => {\r\n const namedGcs: GeographicCRSProps = {\r\n horizontalCRS: { id: \"LL84\" },\r\n verticalCRS: { id: \"GEOID\", crsName: \"EGM96 height\" },\r\n };\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(namedGcs);\r\n txn.updateIModelProps();\r\n });\r\n iModel[_refreshIModelProps]();\r\n expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(\"EGM96 height\");\r\n const property = { namespace: \"dgn_Db\", name: \"DgnGCSVerticalCRS\" };\r\n const storedDefinition = iModel.queryFilePropertyString(property);\r\n expect(storedDefinition).to.be.a(\"string\").and.to.contain('\"transforms\"');\r\n const nativeUpdate = iModel[_nativeDb].updateIModelProps.bind(iModel[_nativeDb]);\r\n const update = sinon.stub(iModel[_nativeDb], \"updateIModelProps\").callsFake((props) => {\r\n if (props.geographicCoordinateSystem)\r\n throw new Error(\"GCS dictionary unavailable\");\r\n nativeUpdate(props);\r\n });\r\n withEditTxn(iModel, (txn) => {\r\n txn.updateIModelProps();\r\n txn.updateProjectExtents(extents);\r\n txn.updateEcefLocation(EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 })));\r\n });\r\n expect(update.callCount).to.equal(3);\r\n for (const call of update.getCalls())\r\n expect(call.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);\r\n\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(\"EGM96 height\");\r\n expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);\r\n });\r\n\r\n it(\"preserves an inline named vertical definition that is absent from the dictionary\", () => {\r\n const crsName = \"EditTxn custom height\";\r\n expect(getAvailableVerticalCoordinateReferenceSystems().some((entry) => entry.crsName === crsName)).to.be.false;\r\n const customGcs = {\r\n horizontalCRS: { id: \"LL84\" },\r\n verticalCRS: {\r\n id: \"ELLIPSOID\" as const,\r\n crsName,\r\n datumName: crsName,\r\n type: \"ELLIPSOID\",\r\n units: \"Meter\",\r\n extent: { southWest: { latitude: -90, longitude: -180 }, northEast: { latitude: 90, longitude: 180 } },\r\n },\r\n };\r\n withEditTxn(iModel, () => {\r\n iModel[_nativeDb].updateIModelProps({ ...iModel.toJSON(), geographicCoordinateSystem: customGcs });\r\n });\r\n iModel[_refreshIModelProps]();\r\n expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(crsName);\r\n const property = { namespace: \"dgn_Db\", name: \"DgnGCSVerticalCRS\" };\r\n const storedDefinition = iModel.queryFilePropertyString(property);\r\n expect(storedDefinition).to.be.a(\"string\").and.to.contain(crsName);\r\n withEditTxn(iModel, (txn) => {\r\n txn.updateIModelProps();\r\n txn.updateProjectExtents(extents);\r\n txn.updateEcefLocation(EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: 0, latitude: 0, height: 0 })));\r\n });\r\n expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n expect(iModel.geographicCoordinateSystem?.verticalCRS?.crsName).to.equal(crsName);\r\n expect(iModel.queryFilePropertyString(property)).to.equal(storedDefinition);\r\n });\r\n\r\n it(\"writes a pending GCS change through convenience methods only once\", () => {\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n withEditTxn(iModel, (txn) => {\r\n txn.updateProjectExtents(extents);\r\n txn.updateIModelProps();\r\n txn.saveChanges();\r\n txn.updateProjectExtents(extents);\r\n });\r\n expect(update.firstCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);\r\n expect(update.secondCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n expect(update.thirdCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.additionalTransform).to.deep.equal(changedGcs.additionalTransform);\r\n });\r\n\r\n it(\"restores the GCS and comparison baseline after abandoning an update\", () => {\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n expect(originalGcs).not.to.equal(undefined);\r\n const txn = new EditTxn(iModel, \"abandon GCS update\");\r\n txn.start();\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n txn.abandonChanges();\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n txn.updateProjectExtents(extents);\r\n expect(update.firstCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n expect(update.secondCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);\r\n txn.end(\"abandon\");\r\n });\r\n\r\n it(\"does not treat a rejected native update as persisted\", () => {\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n const nativeUpdate = iModel[_nativeDb].updateIModelProps.bind(iModel[_nativeDb]);\r\n const update = sinon.stub(iModel[_nativeDb], \"updateIModelProps\");\r\n update.onFirstCall().throws(new Error(\"GCS update rejected\"));\r\n update.onSecondCall().callsFake(nativeUpdate);\r\n withEditTxn(iModel, (txn) => {\r\n expect(() => txn.updateIModelProps()).to.throw(\"GCS update rejected\");\r\n txn.updateIModelProps();\r\n });\r\n expect(update.firstCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);\r\n expect(update.secondCall.args[0].geographicCoordinateSystem).to.deep.equal(changedGcsJson);\r\n expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem?.additionalTransform).to.deep.equal(changedGcs.additionalTransform);\r\n });\r\n\r\n it(\"rejects reentrant explicit and implicit writes while restoring an abandoned GCS\", () => {\r\n sinon.stub(EditTxn, \"implicitWriteEnforcement\").value(\"allow\");\r\n const unexpectedError = sinon.spy(UnexpectedErrors, \"handle\");\r\n const originalProps = iModel[_nativeDb].getIModelProps();\r\n const failure = new Error(\"abandon this edit\");\r\n const listener = sinon.spy(() => {\r\n expect(() => iModel.getIndirectTxn().updateIModelProps()).to.throw(\"Cannot write while restoring the geographic coordinate system\");\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Exercise the legacy implicit write path.\r\n expect(() => iModel.updateIModelProps()).to.throw(\"Cannot write while restoring the geographic coordinate system\");\r\n });\r\n expect(() => withEditTxn(iModel, (txn) => {\r\n iModel.rootSubject = { name: \"Abandoned root subject\" };\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n throw failure;\r\n })).to.throw(failure);\r\n expect(listener.calledOnce).to.be.true;\r\n expect(unexpectedError.called).to.be.false;\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n expect(iModel[_nativeDb].getIModelProps().rootSubject).to.deep.equal(originalProps.rootSubject);\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n expect(iModel.rootSubject).to.deep.equal(originalProps.rootSubject);\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalProps.geographicCoordinateSystem).toJSON());\r\n });\r\n\r\n it(\"releases the transaction and write guard when a rollback listener throws\", () => {\r\n const unexpectedError = sinon.stub(UnexpectedErrors, \"handle\");\r\n const txn = new EditTxn(iModel, \"rollback listener\");\r\n txn.start();\r\n iModel.rootSubject = { name: \"Abandoned root subject\" };\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n const listener = sinon.spy(() => iModel.getIndirectTxn().updateIModelProps());\r\n const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n try {\r\n txn.end(\"abandon\");\r\n expect(listener.threw()).to.be.true;\r\n expect(listener.firstCall.exception).to.have.property(\"message\", \"Cannot write while restoring the geographic coordinate system\");\r\n expect(unexpectedError.calledOnceWithExactly(listener.firstCall.exception)).to.be.true;\r\n expect(txn.isActive).to.be.false;\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n } finally {\r\n removeListener();\r\n }\r\n withEditTxn(iModel, (nextTxn) => nextTxn.saveFileProperty({ namespace: \"test\", name: \"after-rollback\" }, \"allowed\"));\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n expect(iModel.rootSubject.name).to.equal(\"IModelProps\");\r\n expect(iModel.queryFilePropertyString({ namespace: \"test\", name: \"after-rollback\" })).to.equal(\"allowed\");\r\n });\r\n it(\"rejects scoped transaction activation during undo abandonment without retaining ownership\", () => {\r\n sinon.stub(EditTxn, \"implicitWriteEnforcement\").value(\"allow\");\r\n const unexpectedError = sinon.stub(UnexpectedErrors, \"handle\");\r\n iModel[_nativeDb].deleteAllTxns();\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n iModel.getIndirectTxn().updateIModelProps();\r\n const edit = sinon.spy((txn: EditTxn) => txn.updateIModelProps());\r\n const listener = sinon.spy(() => withEditTxn(iModel, edit));\r\n const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n try {\r\n expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.NothingToUndo);\r\n expect(listener.calledOnce).to.be.true;\r\n expect(unexpectedError.calledOnceWithExactly(listener.firstCall.exception)).to.be.true;\r\n expect(listener.firstCall.exception).to.have.property(\"message\", \"Cannot write while restoring the geographic coordinate system\");\r\n expect(edit.called).to.be.false;\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n } finally {\r\n removeListener();\r\n }\r\n withEditTxn(iModel, (txn) => txn.saveFileProperty({ namespace: \"test\", name: \"after-listener-start\" }, \"allowed\"));\r\n expect(iModel.queryFilePropertyString({ namespace: \"test\", name: \"after-listener-start\" })).to.equal(\"allowed\");\r\n });\r\n\r\n for (const endTxn of [false, true]) {\r\n it(`${endTxn ? \"releases\" : \"retains\"} transaction ownership when a rollback notification propagates`, () => {\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n const txn = new EditTxn(iModel, \"propagating rollback listener\");\r\n txn.start();\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n const listener = sinon.spy(() => txn.updateIModelProps());\r\n const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n const previousHandler = UnexpectedErrors.setHandler(UnexpectedErrors.reThrowImmediate);\r\n try {\r\n expect(() => endTxn ? txn.end(\"abandon\") : txn.abandonChanges()).to.throw(\"Cannot write while restoring the geographic coordinate system\");\r\n expect(listener.calledOnce).to.be.true;\r\n expect(txn.isActive).to.equal(!endTxn);\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n } finally {\r\n UnexpectedErrors.setHandler(previousHandler);\r\n removeListener();\r\n }\r\n if (!endTxn)\r\n txn.end(\"save\");\r\n withEditTxn(iModel, (nextTxn) => nextTxn.saveFileProperty({ namespace: \"test\", name: \"after-propagated-notification\" }, \"allowed\"));\r\n expect(iModel.queryFilePropertyString({ namespace: \"test\", name: \"after-propagated-notification\" })).to.equal(\"allowed\");\r\n });\r\n }\r\n\r\n for (const asynchronous of [false, true]) {\r\n it(`preserves the ${asynchronous ? \"asynchronous\" : \"synchronous\"} callback error when a rollback notification propagates`, async () => {\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n const failure = new Error(\"initiating edit failure\");\r\n const logError = sinon.spy(Logger, \"logError\");\r\n let activeTxn: EditTxn | undefined;\r\n let removeListener: (() => void) | undefined;\r\n const listener = sinon.spy(() => iModel.getIndirectTxn().updateIModelProps());\r\n const edit = (txn: EditTxn) => {\r\n activeTxn = txn;\r\n iModel.rootSubject = { name: \"Abandoned root subject\" };\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n throw failure;\r\n };\r\n const previousHandler = UnexpectedErrors.setHandler(UnexpectedErrors.reThrowImmediate);\r\n try {\r\n if (asynchronous) {\r\n const error = await withEditTxn(iModel, async (txn) => {\r\n await Promise.resolve();\r\n edit(txn);\r\n }).catch((err: unknown) => err);\r\n expect(error).to.equal(failure);\r\n } else {\r\n expect(() => withEditTxn(iModel, edit)).to.throw(failure);\r\n }\r\n expect(listener.calledOnce).to.be.true;\r\n expect(listener.firstCall.exception).to.have.property(\"message\", \"Cannot write while restoring the geographic coordinate system\");\r\n expect(logError.calledOnceWithExactly(BackendLoggerCategory.IModelDb, listener.firstCall.exception)).to.be.true;\r\n expect(activeTxn?.isActive).to.be.false;\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n } finally {\r\n UnexpectedErrors.setHandler(previousHandler);\r\n removeListener?.();\r\n }\r\n withEditTxn(iModel, (txn) => txn.saveFileProperty({ namespace: \"test\", name: \"after-failed-scope\" }, \"allowed\"));\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n expect(iModel.rootSubject.name).to.equal(\"IModelProps\");\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n expect(iModel.queryFilePropertyString({ namespace: \"test\", name: \"after-failed-scope\" })).to.equal(\"allowed\");\r\n });\r\n }\r\n\r\n it(\"refreshes the GCS and its baseline after undo\", () => {\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n });\r\n expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));\r\n expect(update.firstCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n expect(iModel[_nativeDb].getIModelProps().geographicCoordinateSystem).to.deep.equal(originalGcs);\r\n });\r\n\r\n it(\"refreshes the GCS and its baseline after redo\", () => {\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n });\r\n const persistedGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);\r\n expect(iModel.txns.reinstateTxn()).to.equal(IModelStatus.Success);\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(persistedGcs).toJSON());\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));\r\n expect(update.firstCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n });\r\n\r\n it(\"refreshes an abandoned GCS even when there is nothing to undo\", () => {\r\n iModel[_nativeDb].deleteAllTxns();\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n const txn = new EditTxn(iModel, \"undo unsaved GCS\");\r\n txn.start();\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.NothingToUndo);\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n txn.end(\"abandon\");\r\n });\r\n\r\n it(\"refreshes an abandoned GCS even when asynchronous redo fails\", async () => {\r\n iModel[_nativeDb].deleteAllTxns();\r\n const originalGcs = iModel[_nativeDb].getIModelProps().geographicCoordinateSystem;\r\n const txn = new EditTxn(iModel, \"redo unsaved GCS\");\r\n txn.start();\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n const error = await getIModelError(iModel.txns.reinstateTxnAsync());\r\n expect(error?.errorNumber).to.equal(IModelStatus.NothingToRedo);\r\n expect(iModel.geographicCoordinateSystem?.toJSON()).to.deep.equal(new GeographicCRS(originalGcs).toJSON());\r\n txn.end(\"abandon\");\r\n });\r\n\r\n it(\"rejects implicit listener writes during undo and redo cache restoration\", () => {\r\n sinon.stub(EditTxn, \"implicitWriteEnforcement\").value(\"allow\");\r\n const unexpectedError = sinon.spy(UnexpectedErrors, \"handle\");\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n });\r\n const listener = sinon.spy(() => {\r\n expect(() => iModel.getIndirectTxn().updateIModelProps()).to.throw(\"Cannot write while restoring the geographic coordinate system\");\r\n });\r\n const removeListener = iModel.onGeographicCoordinateSystemChanged.addListener(listener);\r\n try {\r\n expect(iModel.txns.reverseTxns(1)).to.equal(IModelStatus.Success);\r\n expect(iModel.txns.reinstateTxn()).to.equal(IModelStatus.Success);\r\n expect(listener.callCount).to.equal(2);\r\n expect(unexpectedError.called).to.be.false;\r\n expect(iModel[_nativeDb].hasUnsavedChanges()).to.be.false;\r\n } finally {\r\n removeListener();\r\n }\r\n });\r\n\r\n it(\"uses the reloaded GCS as its baseline\", () => {\r\n iModel.close();\r\n iModel = StandaloneDb.openFile(fileName, OpenMode.ReadWrite);\r\n const update = sinon.spy(iModel[_nativeDb], \"updateIModelProps\");\r\n withEditTxn(iModel, (txn) => txn.updateIModelProps());\r\n expect(update.firstCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n withEditTxn(iModel, (txn) => {\r\n iModel.setGeographicCoordinateSystem(changedGcs);\r\n txn.updateIModelProps();\r\n });\r\n iModel[_refreshIModelProps]();\r\n update.resetHistory();\r\n withEditTxn(iModel, (txn) => txn.updateProjectExtents(extents));\r\n expect(update.firstCall.args[0]).not.to.have.property(\"geographicCoordinateSystem\");\r\n });\r\n});\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaViewPropertyOverrides.test.d.ts","sourceRoot":"","sources":["../../../../src/test/schema/SchemaViewPropertyOverrides.test.ts"],"names":[],"mappings":""}
|