@itwin/core-backend
Version:
iTwin.js backend components
288 lines • 18.9 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 { expect } from "chai";
import { join } from "path";
import { Guid, Logger, LogLevel, OpenMode } from "@itwin/core-bentley";
import { ViewStore } from "../../ViewStore";
import { KnownTestLocations } from "../KnownTestLocations";
describe("ViewStore", function () {
this.timeout(0);
let vs1;
before(async () => {
Logger.setLevel("SQLite", LogLevel.None); // we're expecting errors
const dbName = join(KnownTestLocations.outputDir, "viewStore.db");
ViewStore.ViewDb.createNewDb(dbName);
vs1 = new ViewStore.ViewDb({ guidMap: {} });
vs1.openDb(dbName, OpenMode.ReadWrite);
});
after(async () => {
vs1.closeDb(true);
Logger.setLevel("SQLite", LogLevel.Error);
});
it("ViewDb", async () => {
const c1 = vs1.addCategorySelectorRow({ name: "first cat", json: "cat1-json" });
const ds1 = vs1.addDisplayStyleRow({ name: "first style", json: "style1-json" });
expect(vs1.getViewByNameSync({ name: "view1" })).to.be.undefined;
const v1Id = vs1.addViewRow({ className: "spatial", name: "view1", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 });
expect(v1Id).equals(1);
const v1 = vs1.getViewByNameSync({ name: "view1" });
expect(vs1.findViewIdByName({ name: "view1" })).equals(v1Id);
expect(vs1.findViewIdByName({ name: "/view1" })).equals(v1Id);
expect(v1.owner).equals("owner10");
expect(v1.className).equals("spatial");
expect(v1.groupId).equals("@1");
expect(v1.isPrivate).to.be.true;
expect(v1.name).equals("view1");
await vs1.updateViewShared({ viewId: v1Id, isShared: true, owner: "owner10" });
const v1Updated = vs1.getViewByNameSync({ name: "view1" });
expect(v1Updated.isPrivate).to.be.false;
const v1Id2 = vs1.addViewRow({ className: "spatial", name: "v2", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 });
expect(v1Id2).equals(2);
const v2 = vs1.getViewRow(v1Id2);
expect(v2.name).equals("v2");
vs1.deleteViewRow(v1Id2);
expect(vs1.findViewIdByName({ name: "v2", groupId: 1 })).equals(0);
expect(() => vs1.addViewGroupRow({ name: "", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewGroupRow({ name: " ", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewGroupRow({ name: "@bad", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewGroupRow({ name: "bad/name", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewGroupRow({ name: "^fd", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewGroupRow({ name: "sd#fd", json: "" })).to.throw("illegal group");
expect(() => vs1.addViewRow({ className: "spatial", name: "@bad", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 })).to.throw("illegal view");
expect(() => vs1.addViewRow({ className: "spatial", name: "bad/name", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 })).to.throw("illegal view");
const g1 = vs1.addViewGroupRow({ name: "group1", json: "group1-json" });
const g2 = vs1.addViewGroupRow({ name: "group2", json: "group2-json" });
const g3 = vs1.addViewGroupRow({ name: "group 3", parentId: g2, json: "group3-json" });
const g4 = vs1.addViewGroupRow({ name: "group4", parentId: g3, json: "group3-json" });
const v2Id = vs1.addViewRow({ className: "spatial2", name: "view2", json: "json2", groupId: g4, categorySel: c1, displayStyle: ds1 });
expect(v2Id).equals(3);
for (let i = 0; i < 100; i++)
vs1.addViewRow({ className: "spatial", name: `test view ${i}`, json: `json${i}`, owner: "owner1", groupId: g2, categorySel: c1, displayStyle: ds1 });
// duplicate name in a group should throw
expect(() => vs1.addViewRow({ className: "spatial3", name: "test view 0", json: "json-blah", owner: "owner1", groupId: g2, categorySel: c1, displayStyle: ds1 })).to.throw("UNIQUE");
// allow the same name in different groups
const v103 = vs1.addViewRow({ className: "spatial3", name: "test view 0", json: "json-blah", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 });
const v104 = vs1.addViewRow({ className: "spatial3", name: "another view", json: "json-blah", owner: "owner10", groupId: 1, categorySel: c1, displayStyle: ds1 });
const g3Id = vs1.getViewGroupByName("group 3", g2);
expect(g3Id).equals(g3);
expect(vs1.findViewGroup("group1")).equals(g1);
expect(vs1.findViewGroup("group 3")).equals(0); // not in the root group
expect(vs1.findViewGroup("/group2/group 3/")).equals(g3);
expect(vs1.findViewGroup("/group2/group 3/group4")).equals(g4);
expect(vs1.findViewGroup("group2/group 3/group4")).equals(g4);
expect(vs1.findViewGroup(ViewStore.fromRowId(g4))).equals(g4);
expect(vs1.findViewGroup("group2/group 3/group4/blah")).equals(0);
expect(vs1.findViewGroup("group2/blah/group4")).equals(0);
expect(vs1.findViewGroup("blah")).equals(0);
expect(vs1.findViewGroup("/")).equals(1);
expect(vs1.findViewGroup("")).equals(1);
expect(vs1.getViewByNameSync({ name: "view2", groupId: g4 })?.groupId).equals(ViewStore.fromRowId(g4));
expect(vs1.findViewIdByName({ name: "/group2/group 3/group4/view2" })).equals(v2Id);
expect(vs1.findViewIdByName({ name: "group2/group 3/group4/view2" })).equals(v2Id);
expect(vs1.findViewIdByName({ name: `${ViewStore.fromRowId(g4)}/view2` })).equals(v2Id);
expect(vs1.findViewIdByName({ name: "group2/group 3/group4/not there" })).equals(0);
expect(vs1.findViewIdByName({ name: "group2/test view 3" })).not.equal(0);
const group3 = vs1.getViewGroup(g3Id);
expect(group3.name).equals("group 3");
expect(group3.parentId).equals(g2);
expect(group3.json).equals("group3-json");
await vs1.renameViewGroup({ groupId: g3Id, name: "group3-updated" });
vs1.updateViewGroupJson(g3Id, "group3-json-updated");
const g3Updated = vs1.getViewGroup(g3Id);
expect(g3Updated.name).equals("group3-updated");
expect(g3Updated.json).equals("group3-json-updated");
expect(vs1.queryViewsSync({ group: "group2", classNames: ["spatial"] }).length).equals(100);
expect(vs1.queryViewsSync({ group: ViewStore.fromRowId(g4), classNames: ["spatial2"] }).length).equals(1);
expect(vs1.queryViewsSync({ classNames: ["spatial", "spatial3", "blah"] }).length).equals(3);
expect(vs1.queryViewsSync({ classNames: [] }).length).equals(0);
expect(vs1.queryViewsSync({ classNames: ["blah"] }).length).equals(0);
expect((await vs1.findViewsByOwner({ owner: "owner1" })).length).equals(101);
const thumbnail1 = new Uint8Array([2, 33, 23, 0, 202]);
const format1 = { width: 100, height: 200, format: "jpeg" };
const format2 = { width: 10, height: 20, format: "png" };
vs1.addOrReplaceThumbnailRow({ data: thumbnail1, viewId: v1Id, format: format1 });
vs1.addOrReplaceThumbnailRow({ data: thumbnail1, viewId: v2Id, format: format2 });
const thumbnail2 = vs1.getThumbnailRow(v2Id);
expect(thumbnail2?.data).deep.equals(thumbnail1);
expect(thumbnail2?.format).deep.equals(format2);
const thumb3 = new Uint8Array([2, 33, 23, 0, 203]);
vs1.addOrReplaceThumbnailRow({ data: thumb3, viewId: v2Id, format: format2 });
const thumbnail3 = vs1.getThumbnailRow(v2Id);
expect(thumbnail3?.data).deep.equals(thumb3);
vs1.addOrReplaceThumbnailRow({ data: thumbnail1, viewId: 33, format: format1 });
expect(vs1.getThumbnailRow(33)).to.not.be.undefined;
vs1.deleteThumbnailSync(ViewStore.fromRowId(33));
expect(vs1.getThumbnailRow(33)).to.be.undefined;
await vs1.deleteViewGroup({ name: "group1" });
expect(vs1.getViewByNameSync({ name: "view2", groupId: g1 })).to.be.undefined;
const cat01 = vs1.addCategorySelectorRow({ name: "cat1", json: "cat1-json" });
vs1.addCategorySelectorRow({ name: "cat2", json: "cat2-json" });
const cat1Id = vs1.findCategorySelectorByName("cat1");
expect(cat1Id).equals(cat01);
let cat1 = vs1.getCategorySelectorRow(cat1Id);
expect(cat1.name).equals("cat1");
expect(cat1.json).equals("cat1-json");
await vs1.updateCategorySelectorJson(cat1Id, "cat1-json-updated"); // eslint-disable-line @typescript-eslint/await-thenable
cat1 = vs1.getCategorySelectorRow(cat1Id);
expect(cat1.json).equals("cat1-json-updated");
vs1.deleteCategorySelectorSync(cat1Id);
expect(vs1.findCategorySelectorByName("cat1")).equals(0);
const ds01 = vs1.addDisplayStyleRow({ name: "style1", json: "style1-json" });
vs1.addDisplayStyleRow({ name: "style2", json: "style2-json" });
const style1Id = vs1.findDisplayStyleByName("style1");
expect(style1Id).equals(ds01);
const style1 = vs1.getDisplayStyleRow(style1Id);
expect(style1.name).equals("style1");
expect(style1.json).equals("style1-json");
await vs1.renameDisplayStyle({ id: style1Id, name: "style1-updated" });
const style1UpdatedNameId = vs1.findDisplayStyleByName("style1-updated");
expect(style1UpdatedNameId).equals(style1Id);
vs1.updateDisplayStyleJson(style1Id, "style1-json-updated");
const style1Updated = vs1.getDisplayStyleRow(style1Id);
expect(style1Updated.json).equals("style1-json-updated");
vs1.deleteDisplayStyleSync(style1Id);
expect(vs1.findDisplayStyleByName("style1")).equals(0);
expect(vs1.findDisplayStyleByName("style2")).equals(3);
vs1.addModelSelectorRow({ name: "model1", json: "model1-json" });
const ms2 = vs1.addModelSelectorRow({ json: "model2-json" });
const model1Id = vs1.findModelSelectorByName("model1");
expect(model1Id).equals(1);
const model1 = vs1.getModelSelectorRow(model1Id);
expect(model1.name).equals("model1");
expect(model1.json).equals("model1-json");
const model2 = vs1.getModelSelectorRow(ms2);
expect(model2.name).undefined;
expect(model2.json).equals("model2-json");
await vs1.renameModelSelector({ id: model1Id, name: "model1-updated" });
const model1UpdatedNameId = vs1.findModelSelectorByName("model1-updated");
expect(model1UpdatedNameId).equals(model1Id);
await vs1.renameModelSelector({ id: model1Id, name: undefined });
expect(vs1.getModelSelectorRow(model1Id).name).undefined;
vs1.updateModelSelectorJson(model1Id, "model1-json-updated");
const model1Updated = vs1.getModelSelectorRow(model1Id);
expect(model1Updated.json).equals("model1-json-updated");
vs1.deleteModelSelectorSync(model1Id);
expect(vs1.findModelSelectorByName("model1")).equals(0);
vs1.addTimelineRow({ name: "timeline1", json: "timeline1-json" });
vs1.addTimelineRow({ name: "timeline2", json: "timeline2-json" });
const timeline1Id = vs1.findTimelineByName("timeline1");
const timeline2Id = vs1.findTimelineByName("timeline2");
expect(timeline1Id).equals(1);
const timeline1 = vs1.getTimelineRow(timeline1Id);
expect(timeline1.name).equals("timeline1");
expect(timeline1.json).equals("timeline1-json");
await vs1.renameTimeline({ id: timeline1Id, name: "timeline1-updated" });
const timeline1UpdatedNameId = vs1.findTimelineByName("timeline1-updated");
expect(timeline1UpdatedNameId).equals(timeline1Id);
vs1.updateTimelineJson(timeline1Id, "timeline1-json-updated");
const timeline1Updated = vs1.getTimelineRow(timeline1Id);
expect(timeline1Updated.json).equals("timeline1-json-updated");
vs1.deleteTimelineSync(timeline2Id);
expect(vs1.findTimelineByName("timeline2")).equals(0);
const t1 = vs1.addTag({ name: "tag1", json: "tag1-json", owner: "owner1" });
vs1.addTag({ name: "tag2", json: "tag2-json" });
const tag1Id = vs1.findTagByName("tag1");
expect(tag1Id).equals(t1);
const tag1 = vs1.getTag(tag1Id);
expect(tag1.name).equals("tag1");
expect(tag1.json).equals("tag1-json");
expect(tag1.owner).equals("owner1");
for (let i = 0; i < 5; i++)
vs1.addTag({ name: `test tag ${i}`, json: `newTag${i}-json` });
vs1.addTagToView({ viewId: v1Id, tagId: tag1Id });
vs1.addTagToView({ viewId: v1Id, tagId: 2 });
vs1.addTagToView({ viewId: v103, tagId: 2 });
vs1.addTagToView({ viewId: v104, tagId: 2 });
vs1.addTagToView({ viewId: v1Id, tagId: 3 });
const taggedViewIds = vs1.findViewsForTag(tag1Id);
expect(taggedViewIds.length).equals(1);
expect(taggedViewIds[0]).equals(v1Id);
const tags = vs1.getTagsForView(v1Id);
expect(tags.length).equals(3);
expect(tags[0]).equals("tag1");
expect(tags[1]).equals("tag2");
expect(tags[2]).equals("test tag 0");
vs1.addViewRow({ className: "BisCore:SpatialViewDefinition", name: "my private 2", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 });
vs1.addViewRow({ className: "BisCore:OrthographicViewDefinition", name: "my private 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 });
vs1.addViewRow({ className: "BisCore:SheetViewDefinition", name: "sheet 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 });
vs1.addViewRow({ className: "BisCore:DrawingViewDefinition", name: "drawing 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 });
let views = vs1.queryViewsSync({ group: "/" });
expect(views.length).equals(3);
expect(views[0].name).equals("another view");
expect(vs1.queryViewsSync({ group: "group1" }).length).equals(0);
expect(vs1.queryViewsSync({ group: "group2" }).length).equal(100);
expect(vs1.queryViewsSync({ group: "group2", offset: 20, limit: 10 }).length).equals(10);
expect(vs1.queryViewsSync({ group: "group2", offset: 20, limit: 100 }).length).equals(80);
views = vs1.queryViewsSync({ group: "group2", nameSearch: "%20%", nameCompare: "LIKE" });
expect(views.length).equals(1);
expect(views[0].name).equals("test view 20");
views = vs1.queryViewsSync({ group: "group2", nameSearch: "*2*", nameCompare: "GLOB" });
expect(views.length).equals(19);
expect(vs1.queryViewsSync({ group: "group2", tags: ["tag1"] }).length).equal(0);
expect(vs1.queryViewsSync({ tags: ["tag1"] }).length).equal(1);
views = vs1.queryViewsSync({ tags: ["tag2", "tag1"] });
expect(views.length).equal(3);
expect(views[2].tags?.length).equal(3);
views = vs1.queryViewsSync({ owner: "owner10" });
expect(views.length).equal(7);
views = vs1.queryViewsSync({ owner: "owner10", nameSearch: "my%", nameCompare: "LIKE" });
expect(views.length).equal(2);
expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:SpatialViewDefinition"] }).length).equal(1);
expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:SpatialViewDefinition", "BisCore:OrthographicViewDefinition"] }).length).equal(2);
expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:DrawingViewDefinition"] }).length).equal(1);
expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:DrawingViewDefinition", "BisCore:SheetViewDefinition"] }).length).equal(2);
await vs1.renameTag({ oldName: "tag2", newName: "tag2-renamed" });
views = vs1.queryViewsSync({ tags: ["tag2-renamed"] });
expect(views.length).equal(3);
vs1.deleteTagSync({ name: "tag2-renamed" });
const tagIdsAfterDelete = vs1.getTagsForView(v1Id);
expect(tagIdsAfterDelete.length).equals(2);
expect(tagIdsAfterDelete[0]).equals("tag1");
expect(tagIdsAfterDelete[1]).equals("test tag 0");
await vs1.addSearch({ name: "search1", json: "search1-json" });
const search2 = await vs1.addSearch({ name: "search2", json: "search2-json" });
await expect(vs1.addSearch({ name: "search1", json: "search1-json" })).to.be.rejectedWith("UNIQUE");
const search1Id = vs1.findSearchByName("search1");
expect(search1Id).equals(1);
const search1 = vs1.getSearch(search1Id);
expect(search1.name).equals("search1");
expect(search1.json).equals("search1-json");
await vs1.renameSearch({ id: search1Id, name: "search1-updated" });
const search1UpdatedNameId = vs1.findSearchByName("search1-updated");
expect(search1UpdatedNameId).equals(search1Id);
vs1.updateSearchJson(search1Id, "search1-json-updated");
const search1Updated = vs1.getSearch(search1Id);
expect(search1Updated.json).equals("search1-json-updated");
vs1.deleteSearch(search2);
expect(vs1.findSearchByName("search2")).equals(0);
const guids = [];
const rowIds = [];
const nGuids = 1000;
for (let i = 0; i < nGuids; i++) {
const guid = Guid.createValue();
const rowId = vs1.addGuid(guid);
guids.push(guid);
rowIds.push(rowId);
}
for (let i = 0; i < nGuids; i++) {
expect(vs1.getGuid(rowIds[i])).equals(guids[i]);
expect(vs1.addGuid(guids[i])).equals(rowIds[i]);
}
let count = 0;
vs1.iterateGuids(rowIds, (guid, row) => {
count++;
expect(guid).not.undefined;
expect(guids.indexOf(guid)).not.equals(-1);
const rowString1 = ViewStore.fromRowId(row);
expect(rowString1.startsWith("@")).true;
expect(ViewStore.toRowId(rowString1)).equals(row); // round trip
});
expect(count).equals(nGuids);
const largeNumber = 0x7ffffffffffff;
expect(ViewStore.toRowId(ViewStore.fromRowId(largeNumber))).equals(largeNumber);
vs1.vacuum();
});
});
//# sourceMappingURL=ViewStoreDb.test.js.map