@itwin/core-backend
Version:
iTwin.js backend components
176 lines • 11.8 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { assert } from "chai";
import { Guid } from "@itwin/core-bentley";
import { BriefcaseIdValue } from "@itwin/core-common";
import { HubWrappers, IModelTestUtils } from "../IModelTestUtils";
import { KnownTestLocations } from "../KnownTestLocations";
import { HubMock } from "../../internal/HubMock";
import { TestChangeSetUtility } from "../TestChangeSetUtility";
import { _nativeDb, ChannelControl } from "../../core-backend";
describe("BriefcaseManager", async () => {
const testITwinId = Guid.createValue();
const managerAccessToken = "manager mock token";
const accessToken = "access token";
// contested version0 files can cause errors that cause tests to not call shutdown, so always do it here
afterEach(() => HubMock.shutdown());
it("Open iModels with various names causing potential issues on Windows/Unix", async () => {
HubMock.startup("bad names", KnownTestLocations.outputDir);
let iModelName = "iModel Name With Spaces";
let iModelId = await HubWrappers.createIModel(managerAccessToken, testITwinId, iModelName);
const args = { accessToken, iTwinId: testITwinId, iModelId };
assert.isDefined(iModelId);
let iModel = await HubWrappers.openCheckpointUsingRpc(args);
assert.isDefined(iModel);
iModelName = "iModel Name With :\/<>?* Characters";
iModelId = await HubWrappers.createIModel(managerAccessToken, testITwinId, iModelName);
assert.isDefined(iModelId);
iModel = await HubWrappers.openCheckpointUsingRpc(args);
assert.isDefined(iModel);
iModelName = "iModel Name Thats Excessively Long " +
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
"01234567890123456789"; // 35 + 2*100 + 20 = 255
// Note: iModelHub does not accept a name that's longer than 255 characters.
assert.equal(255, iModelName.length);
iModelId = await HubWrappers.createIModel(managerAccessToken, testITwinId, iModelName);
assert.isDefined(iModelId);
iModel = await HubWrappers.openCheckpointUsingRpc(args);
assert.isDefined(iModel);
iModel.close();
});
it("should set appropriate briefcase ids for FixedVersion, PullOnly and PullAndPush workflows", async () => {
HubMock.startup("briefcaseIds", KnownTestLocations.outputDir);
const iModelId = await HubWrappers.createIModel(accessToken, testITwinId, "imodel1");
const args = { accessToken, iTwinId: testITwinId, iModelId, deleteFirst: true };
const iModel1 = await HubWrappers.openCheckpointUsingRpc(args);
assert.equal(BriefcaseIdValue.Unassigned, iModel1.getBriefcaseId(), "checkpoint should be 0");
try {
const iModelFailure = await HubWrappers.openBriefcaseUsingRpc({ ...args, briefcaseId: 0 });
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModelFailure);
assert.fail("iModelFailure should fail due to iModel1 already being open as a SnapshotDb");
}
catch (err) {
assert.isTrue(err.message.includes("iModel is already open as a SnapshotDb"), "iModelFailure failure must be due to db being open as a SnapshotDb");
}
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel1);
const iModel2 = await HubWrappers.openBriefcaseUsingRpc({ ...args, briefcaseId: 0 });
assert.equal(BriefcaseIdValue.Unassigned, iModel2.briefcaseId, "pullOnly should be 0");
const iModel2Dup = await HubWrappers.openBriefcaseUsingRpc({ ...args, briefcaseId: 0 });
const iModel3 = await HubWrappers.openBriefcaseUsingRpc(args);
assert.isTrue(iModel3.briefcaseId >= BriefcaseIdValue.FirstValid && iModel3.briefcaseId <= BriefcaseIdValue.LastValid, "valid briefcaseId");
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel2);
try {
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel2Dup);
assert.fail("iModel2Dup failure should fail due to already being closed when iModel2 closed");
}
catch (err) {
assert.isTrue(err.message.includes("db is not open"), "iModel2Dup failure must be due to db not being open");
}
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel3);
});
it("should reuse a briefcaseId when re-opening iModels for pullAndPush workflows", async () => {
HubMock.startup("briefcaseIdsReopen", KnownTestLocations.outputDir);
const iModelId = await HubWrappers.createIModel(accessToken, testITwinId, "imodel1");
const args = { accessToken, iTwinId: testITwinId, iModelId, deleteFirst: false };
const iModel1 = await HubWrappers.openBriefcaseUsingRpc(args);
const briefcaseId1 = iModel1.briefcaseId;
iModel1.close(); // Keeps the briefcase by default
const iModel3 = await HubWrappers.openBriefcaseUsingRpc(args);
const briefcaseId3 = iModel3.briefcaseId;
assert.strictEqual(briefcaseId3, briefcaseId1);
await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel3);
});
it("should reuse a briefcaseId when re-opening iModels of different versions for pullAndPush and pullOnly workflows", async () => {
HubMock.startup("workflow", KnownTestLocations.outputDir);
const userToken1 = "manager token";
const userToken2 = "super manager token";
// User1 creates an iModel on the Hub
const testUtility = new TestChangeSetUtility(userToken1, IModelTestUtils.generateUniqueName("BriefcaseReuseTest"));
await testUtility.createTestIModel();
// User2 opens and then closes the iModel pullOnly/pullPush, keeping the briefcase
const args = { accessToken: userToken2, iTwinId: testUtility.iTwinId, iModelId: testUtility.iModelId };
const iModelPullAndPush = await HubWrappers.openBriefcaseUsingRpc(args);
const briefcaseIdPullAndPush = iModelPullAndPush.briefcaseId;
const changesetPullAndPush = iModelPullAndPush.changeset;
iModelPullAndPush.close();
const iModelPullOnly = await HubWrappers.openBriefcaseUsingRpc({ ...args, briefcaseId: 0 });
const briefcaseIdPullOnly = iModelPullOnly.briefcaseId;
const changesetPullOnly = iModelPullOnly.changeset;
iModelPullOnly.close();
// User1 pushes a change set
await testUtility.pushTestChangeSet();
// User 2 reopens the iModel pullOnly/pullPush => Expect the same briefcase to be re-used, but the changeset should have been updated!!
const iModelPullAndPush2 = await HubWrappers.openBriefcaseUsingRpc(args);
const briefcaseIdPullAndPush2 = iModelPullAndPush2.briefcaseId;
assert.strictEqual(briefcaseIdPullAndPush2, briefcaseIdPullAndPush);
const changesetPullAndPush2 = iModelPullAndPush2.changeset;
assert.notStrictEqual(changesetPullAndPush2, changesetPullAndPush);
await HubWrappers.closeAndDeleteBriefcaseDb(userToken2, iModelPullAndPush2);
const iModelPullOnly2 = await HubWrappers.openBriefcaseUsingRpc({ ...args, briefcaseId: 0 });
const briefcaseIdPullOnly2 = iModelPullOnly2.briefcaseId;
assert.strictEqual(briefcaseIdPullOnly2, briefcaseIdPullOnly);
const changesetPullOnly2 = iModelPullOnly2.changeset;
assert.notStrictEqual(changesetPullOnly2, changesetPullOnly);
await HubWrappers.closeAndDeleteBriefcaseDb(userToken2, iModelPullOnly2);
// Delete iModel from the Hub and disk
await testUtility.deleteTestIModel();
});
it("should be able to edit a PullAndPush briefcase, reopen it as of a new version, and then push changes", async () => {
HubMock.startup("pullPush", KnownTestLocations.outputDir);
const userToken1 = "manager token"; // User1 is just used to create and update the iModel
const userToken2 = "super manager token"; // User2 is used for the test
// User1 creates an iModel on the Hub
const testUtility = new TestChangeSetUtility(userToken1, "PullAndPushTest");
await testUtility.createTestIModel();
// User2 opens the iModel pullAndPush and is able to edit and save changes
const args = { accessToken: userToken2, iTwinId: testUtility.iTwinId, iModelId: testUtility.iModelId };
let iModelPullAndPush = await HubWrappers.openBriefcaseUsingRpc(args);
assert.exists(iModelPullAndPush);
const briefcaseId = iModelPullAndPush.briefcaseId;
const pathname = iModelPullAndPush.pathName;
iModelPullAndPush.channels.addAllowedChannel(ChannelControl.sharedChannelName);
const rootEl = iModelPullAndPush.elements.getRootSubject();
rootEl.userLabel = `${rootEl.userLabel}changed`;
iModelPullAndPush.elements.updateElement(rootEl.toJSON());
assert.isTrue(iModelPullAndPush[_nativeDb].hasUnsavedChanges());
assert.isFalse(iModelPullAndPush[_nativeDb].hasPendingTxns());
iModelPullAndPush.saveChanges();
assert.isFalse(iModelPullAndPush[_nativeDb].hasUnsavedChanges());
assert.isTrue(iModelPullAndPush[_nativeDb].hasPendingTxns());
iModelPullAndPush.close();
// User2 should be able to re-open the iModel pullAndPush again
// - the changes will still be there
iModelPullAndPush = await HubWrappers.openBriefcaseUsingRpc(args);
const changesetPullAndPush = iModelPullAndPush.changeset;
assert.strictEqual(iModelPullAndPush.briefcaseId, briefcaseId);
assert.strictEqual(iModelPullAndPush.pathName, pathname);
assert.isFalse(iModelPullAndPush[_nativeDb].hasUnsavedChanges());
assert.isTrue(iModelPullAndPush[_nativeDb].hasPendingTxns());
// User1 pushes a change set
await testUtility.pushTestChangeSet();
// User2 should be able to re-open the iModel
await HubWrappers.openBriefcaseUsingRpc(args);
// User2 closes and reopens the iModel pullAndPush as of the newer version
// - the changes will still be there, AND
// - the briefcase will be upgraded to the newer version since it was closed and re-opened.
iModelPullAndPush.close();
iModelPullAndPush = await HubWrappers.openBriefcaseUsingRpc(args);
const changesetPullAndPush3 = iModelPullAndPush.changeset;
assert.notStrictEqual(changesetPullAndPush3, changesetPullAndPush);
assert.strictEqual(iModelPullAndPush.briefcaseId, briefcaseId);
assert.strictEqual(iModelPullAndPush.pathName, pathname);
assert.isFalse(iModelPullAndPush[_nativeDb].hasUnsavedChanges());
assert.isTrue(iModelPullAndPush[_nativeDb].hasPendingTxns());
// User2 should be able to push the changes now
await iModelPullAndPush.pushChanges({ accessToken: userToken2, description: "test change" });
const changesetPullAndPush4 = iModelPullAndPush.changeset;
assert.notStrictEqual(changesetPullAndPush4, changesetPullAndPush3);
// Delete iModel from the Hub and disk
await HubWrappers.closeAndDeleteBriefcaseDb(userToken2, iModelPullAndPush);
await testUtility.deleteTestIModel();
});
});
//# sourceMappingURL=BriefcaseManager.test.js.map