Skip to content

Commit 687d248

Browse files
committed
Add integration test
1 parent fc0d9b3 commit 687d248

File tree

3 files changed

+111
-10
lines changed

3 files changed

+111
-10
lines changed

packages/itwin/tree-widget/src/test/trees/models-tree/ModelsTreeFiltering.test.ts

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { IModel, IModelReadRpcInterface } from "@itwin/core-common";
99
import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common";
1010
import { ECSchemaRpcImpl } from "@itwin/ecschema-rpcinterface-impl";
1111
import { PresentationRpcInterface } from "@itwin/presentation-common";
12-
import { HierarchyNodeIdentifier } from "@itwin/presentation-hierarchies";
12+
import { HierarchyFilteringPath, HierarchyNodeIdentifier } from "@itwin/presentation-hierarchies";
1313
import { HierarchyCacheMode, initialize as initializePresentationTesting, terminate as terminatePresentationTesting } from "@itwin/presentation-testing";
14+
import { joinHierarchyFilteringPaths } from "../../../tree-widget-react/components/trees/common/Utils.js";
1415
import { ModelsTreeIdsCache } from "../../../tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js";
1516
import { defaultHierarchyConfiguration, ModelsTreeDefinition } from "../../../tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js";
1617
import {
@@ -29,11 +30,9 @@ import { createClassGroupingHierarchyNode, createModelsTreeProvider } from "./Ut
2930
import type { Id64String } from "@itwin/core-bentley";
3031
import type { IModelConnection } from "@itwin/core-frontend";
3132
import type { InstanceKey } from "@itwin/presentation-common";
32-
import type { HierarchyFilteringPath } from "@itwin/presentation-hierarchies";
3333
import type { TestIModelBuilder } from "@itwin/presentation-testing";
3434
import type { ExpectedHierarchyDef } from "../HierarchyValidation.js";
3535
import type { ElementsGroupInfo } from "../../../tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js";
36-
3736
type ModelsTreeHierarchyConfiguration = ConstructorParameters<typeof ModelsTreeDefinition>[0]["hierarchyConfig"];
3837

3938
interface TreeFilteringTestCaseDefinition<TIModelSetupResult extends {}> {
@@ -100,6 +99,102 @@ describe("Models tree", () => {
10099
await terminatePresentationTesting();
101100
});
102101

102+
it("sets auto-expand on correct nodes with merged sub-tree and filter paths", async function () {
103+
await using buildIModelResult = await buildIModel(this, async (builder) => {
104+
const rootSubject: InstanceKey = { className: "BisCore.Subject", id: IModel.rootSubjectId };
105+
const model = insertPhysicalModelWithPartition({ builder, codeValue: `model`, partitionParentId: rootSubject.id });
106+
const category = insertSpatialCategory({ builder, codeValue: "category" });
107+
const parentElement = insertPhysicalElement({
108+
builder,
109+
userLabel: `parent el`,
110+
modelId: model.id,
111+
categoryId: category.id,
112+
});
113+
const childElement = insertPhysicalElement({
114+
builder,
115+
userLabel: `child el`,
116+
modelId: model.id,
117+
categoryId: category.id,
118+
parentId: parentElement.id,
119+
});
120+
insertPhysicalElement({
121+
builder,
122+
userLabel: `unrelated el`,
123+
modelId: model.id,
124+
categoryId: category.id,
125+
});
126+
return { rootSubject, model, category, parentElement, childElement };
127+
});
128+
const { imodel, ...keys } = buildIModelResult;
129+
const imodelAccess = createIModelAccess(imodel);
130+
const config = { ...defaultHierarchyConfiguration, hideRootSubject: true, elementClassSpecification: keys.parentElement.className };
131+
using idsCache = new ModelsTreeIdsCache(imodelAccess, config);
132+
const [subTreePaths, filterPaths] = await Promise.all([
133+
ModelsTreeDefinition.createInstanceKeyPaths({
134+
imodelAccess,
135+
idsCache,
136+
hierarchyConfig: config,
137+
targetItems: [{ id: keys.childElement.id, className: keys.childElement.className }],
138+
}),
139+
ModelsTreeDefinition.createInstanceKeyPaths({ imodelAccess, idsCache, hierarchyConfig: config, label: "parent" }),
140+
]);
141+
const joinedPaths = joinHierarchyFilteringPaths(
142+
subTreePaths.map((path) => HierarchyFilteringPath.normalize(path).path),
143+
filterPaths.map((path) => {
144+
const normalizedPath = HierarchyFilteringPath.normalize(path);
145+
normalizedPath.options = { autoExpand: true };
146+
return normalizedPath;
147+
}),
148+
);
149+
150+
using provider = createModelsTreeProvider({
151+
imodel,
152+
hierarchyConfig: config,
153+
filteredNodePaths: joinedPaths,
154+
imodelAccess,
155+
idsCache,
156+
});
157+
await validateHierarchy({
158+
provider,
159+
expect: [
160+
NodeValidators.createForInstanceNode({
161+
instanceKeys: [keys.model],
162+
supportsFiltering: true,
163+
autoExpand: true,
164+
children: [
165+
NodeValidators.createForInstanceNode({
166+
instanceKeys: [keys.category],
167+
supportsFiltering: true,
168+
autoExpand: true,
169+
children: [
170+
NodeValidators.createForClassGroupingNode({
171+
autoExpand: true,
172+
children: [
173+
NodeValidators.createForInstanceNode({
174+
instanceKeys: [keys.parentElement],
175+
supportsFiltering: true,
176+
children: [
177+
NodeValidators.createForClassGroupingNode({
178+
children: [
179+
NodeValidators.createForInstanceNode({
180+
instanceKeys: [keys.childElement],
181+
supportsFiltering: true,
182+
children: false,
183+
}),
184+
],
185+
}),
186+
],
187+
}),
188+
],
189+
}),
190+
],
191+
}),
192+
],
193+
}),
194+
],
195+
});
196+
});
197+
103198
runTestCases(
104199
TreeFilteringTestCaseDefinition.create(
105200
"immediate Subject nodes",

packages/itwin/tree-widget/src/test/trees/models-tree/Utils.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,25 @@ interface CreateModelsTreeProviderProps {
2727
imodel: IModelConnection;
2828
filteredNodePaths?: HierarchyFilteringPath[];
2929
hierarchyConfig?: Partial<ModelsTreeHierarchyConfiguration>;
30+
idsCache?: ModelsTreeIdsCache;
31+
imodelAccess?: ReturnType<typeof createIModelAccess>;
3032
}
3133

3234
export function createModelsTreeProvider({
3335
imodel,
3436
filteredNodePaths,
3537
hierarchyConfig,
38+
imodelAccess,
39+
idsCache,
3640
}: CreateModelsTreeProviderProps): HierarchyProvider & { dispose: () => void; [Symbol.dispose]: () => void } {
3741
const config = { ...defaultHierarchyConfiguration, hideRootSubject: true, ...hierarchyConfig };
38-
const imodelAccess = createIModelAccess(imodel);
39-
const idsCache = new ModelsTreeIdsCache(imodelAccess, config);
42+
const createdImodelAccess = imodelAccess ?? createIModelAccess(imodel);
43+
const createdIdsCache = idsCache ?? new ModelsTreeIdsCache(createdImodelAccess, config);
4044
const provider = createIModelHierarchyProvider({
41-
imodelAccess,
45+
imodelAccess: createdImodelAccess,
4246
hierarchyDefinition: new ModelsTreeDefinition({
43-
imodelAccess,
44-
idsCache,
47+
imodelAccess: createdImodelAccess,
48+
idsCache: createdIdsCache,
4549
hierarchyConfig: config,
4650
}),
4751
...(filteredNodePaths
@@ -50,7 +54,9 @@ export function createModelsTreeProvider({
5054
});
5155
const dispose = () => {
5256
provider[Symbol.dispose]();
53-
idsCache[Symbol.dispose]();
57+
if (!idsCache) {
58+
createdIdsCache[Symbol.dispose]();
59+
}
5460
};
5561
return {
5662
hierarchyChanged: provider.hierarchyChanged,

packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ export class ModelsTreeDefinition implements HierarchyDefinition {
544544
];
545545
}
546546

547-
public static async createInstanceKeyPaths(props: ModelsTreeInstanceKeyPathsProps) {
547+
public static async createInstanceKeyPaths(props: ModelsTreeInstanceKeyPathsProps): Promise<HierarchyFilteringPath[]> {
548548
return lastValueFrom(
549549
defer(() => {
550550
if (ModelsTreeInstanceKeyPathsProps.isLabelProps(props)) {

0 commit comments

Comments
 (0)