|
5 | 5 |
|
6 | 6 | import { expect } from "chai";
|
7 | 7 | import sinon from "sinon";
|
8 |
| -import { IModel, IModelReadRpcInterface } from "@itwin/core-common"; |
9 |
| -import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common"; |
10 |
| -import { ECSchemaRpcImpl } from "@itwin/ecschema-rpcinterface-impl"; |
11 |
| -import { PresentationRpcInterface } from "@itwin/presentation-common"; |
12 | 8 | import { createECSqlQueryExecutor } from "@itwin/presentation-core-interop";
|
13 | 9 | import { createLimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
|
14 |
| -import { HierarchyCacheMode, initialize as initializePresentationTesting, terminate as terminatePresentationTesting } from "@itwin/presentation-testing"; |
15 | 10 | import { ModelsTreeIdsCache } from "../../../../tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js";
|
16 | 11 | import { defaultHierarchyConfiguration } from "../../../../tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js";
|
17 |
| -import { buildIModel, insertPhysicalElement, insertPhysicalModelWithPartition, insertSpatialCategory } from "../../../IModelUtils.js"; |
18 |
| -import { createIModelAccess, createIModelMock } from "../../Common.js"; |
19 |
| - |
20 |
| -import type { IModelConnection } from "@itwin/core-frontend"; |
| 12 | +import { createIModelMock } from "../../Common.js"; |
21 | 13 |
|
22 | 14 | describe("ModelsTreeIdsCache", () => {
|
23 |
| - describe("#unit", () => { |
24 |
| - function createIdsCache(queryHandler: (query: string) => any[]) { |
25 |
| - const iModel = createIModelMock(queryHandler); |
26 |
| - return new ModelsTreeIdsCache(createLimitingECSqlQueryExecutor(createECSqlQueryExecutor(iModel), "unbounded"), defaultHierarchyConfiguration); |
27 |
| - } |
28 |
| - |
29 |
| - it("caches category element count", async () => { |
30 |
| - const modelId = "0x1"; |
31 |
| - const categoryId = "0x2"; |
32 |
| - const elementIds = ["0x10", "0x20", "0x30"]; |
33 |
| - const stub = sinon.fake((query: string) => { |
34 |
| - if (query.includes(`WHERE Parent.Id IS NULL AND (Model.Id = ${modelId} AND Category.Id IN (${categoryId}))`)) { |
35 |
| - return [{ modelId, categoryId, elementsCount: elementIds.length }]; |
36 |
| - } |
37 |
| - throw new Error(`Unexpected query: ${query}`); |
38 |
| - }); |
39 |
| - using cache = createIdsCache(stub); |
40 |
| - await expect(cache.getCategoryElementsCount(modelId, categoryId)).to.eventually.eq(elementIds.length); |
41 |
| - expect(stub).to.have.callCount(1); |
42 |
| - await expect(cache.getCategoryElementsCount(modelId, categoryId)).to.eventually.eq(elementIds.length); |
43 |
| - expect(stub).to.have.callCount(1); |
44 |
| - }); |
45 |
| - }); |
46 |
| - |
47 |
| - describe("#integration", () => { |
48 |
| - before(async () => { |
49 |
| - await initializePresentationTesting({ |
50 |
| - backendProps: { |
51 |
| - caching: { |
52 |
| - hierarchies: { |
53 |
| - mode: HierarchyCacheMode.Memory, |
54 |
| - }, |
55 |
| - }, |
56 |
| - }, |
57 |
| - rpcs: [IModelReadRpcInterface, PresentationRpcInterface, ECSchemaRpcInterface], |
58 |
| - }); |
59 |
| - // eslint-disable-next-line @itwin/no-internal |
60 |
| - ECSchemaRpcImpl.register(); |
61 |
| - }); |
62 |
| - |
63 |
| - after(async () => { |
64 |
| - await terminatePresentationTesting(); |
65 |
| - }); |
66 |
| - |
67 |
| - function createIdsCache(props: { imodel: IModelConnection }) { |
68 |
| - const idsCache = new ModelsTreeIdsCache(createIModelAccess(props.imodel), defaultHierarchyConfiguration); |
69 |
| - return idsCache; |
70 |
| - } |
71 |
| - |
72 |
| - it("Does not throw with many requests to `idsCache.getCategoryElementsCount`", async function () { |
73 |
| - await using buildIModelResult = await buildIModel(this, async (builder) => { |
74 |
| - const categoryId = insertSpatialCategory({ builder, codeValue: "category" }).id; |
75 |
| - const modelId = insertPhysicalModelWithPartition({ builder, partitionParentId: IModel.rootSubjectId, codeValue: "1" }).id; |
76 |
| - insertPhysicalElement({ builder, modelId, categoryId }); |
77 |
| - return { categoryId, modelId }; |
78 |
| - }); |
79 |
| - |
80 |
| - const { imodel, ...keys } = buildIModelResult; |
81 |
| - using idsCache = createIdsCache({ imodel }); |
82 |
| - const promiseToAwait = idsCache.getCategoryElementsCount(keys.modelId, keys.categoryId); |
83 |
| - for (let i = 0; i < 5000; ++i) { |
84 |
| - void idsCache.getCategoryElementsCount(`0x${i}`, `0x${i}`); |
| 15 | + function createIdsCache(queryHandler: (query: string) => any[]) { |
| 16 | + const iModel = createIModelMock(queryHandler); |
| 17 | + return new ModelsTreeIdsCache(createLimitingECSqlQueryExecutor(createECSqlQueryExecutor(iModel), "unbounded"), defaultHierarchyConfiguration); |
| 18 | + } |
| 19 | + |
| 20 | + it("caches category element count", async () => { |
| 21 | + const modelId = "0x1"; |
| 22 | + const categoryId = "0x2"; |
| 23 | + const elementIds = ["0x10", "0x20", "0x30"]; |
| 24 | + const stub = sinon.fake((query: string) => { |
| 25 | + if (query.includes(`WHERE Parent.Id IS NULL AND (Model.Id = ${modelId} AND Category.Id IN (${categoryId}))`)) { |
| 26 | + return [{ modelId, categoryId, elementsCount: elementIds.length }]; |
85 | 27 | }
|
86 |
| - await promiseToAwait; |
| 28 | + throw new Error(`Unexpected query: ${query}`); |
87 | 29 | });
|
| 30 | + using cache = createIdsCache(stub); |
| 31 | + await expect(cache.getCategoryElementsCount(modelId, categoryId)).to.eventually.eq(elementIds.length); |
| 32 | + expect(stub).to.have.callCount(1); |
| 33 | + await expect(cache.getCategoryElementsCount(modelId, categoryId)).to.eventually.eq(elementIds.length); |
| 34 | + expect(stub).to.have.callCount(1); |
88 | 35 | });
|
89 | 36 | });
|
0 commit comments