@itwin/core-backend 5.12.0-dev.8 → 5.13.0-dev.1

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/lib/cjs/ClassRegistry.d.ts.map +1 -1
  3. package/lib/cjs/ClassRegistry.js +1 -2
  4. package/lib/cjs/ClassRegistry.js.map +1 -1
  5. package/lib/cjs/ECDb.d.ts.map +1 -1
  6. package/lib/cjs/ECDb.js +8 -3
  7. package/lib/cjs/ECDb.js.map +1 -1
  8. package/lib/cjs/ECSqlRowExecutor.d.ts +23 -10
  9. package/lib/cjs/ECSqlRowExecutor.d.ts.map +1 -1
  10. package/lib/cjs/ECSqlRowExecutor.js +77 -15
  11. package/lib/cjs/ECSqlRowExecutor.js.map +1 -1
  12. package/lib/cjs/IModelDb.d.ts +20 -8
  13. package/lib/cjs/IModelDb.d.ts.map +1 -1
  14. package/lib/cjs/IModelDb.js +83 -54
  15. package/lib/cjs/IModelDb.js.map +1 -1
  16. package/lib/cjs/IpcHost.d.ts +26 -0
  17. package/lib/cjs/IpcHost.d.ts.map +1 -1
  18. package/lib/cjs/IpcHost.js +68 -61
  19. package/lib/cjs/IpcHost.js.map +1 -1
  20. package/lib/cjs/Relationship.d.ts.map +1 -1
  21. package/lib/cjs/Relationship.js +13 -7
  22. package/lib/cjs/Relationship.js.map +1 -1
  23. package/lib/cjs/SQLiteDb.d.ts +43 -0
  24. package/lib/cjs/SQLiteDb.d.ts.map +1 -1
  25. package/lib/cjs/SQLiteDb.js +51 -0
  26. package/lib/cjs/SQLiteDb.js.map +1 -1
  27. package/lib/cjs/ViewStore.js +1 -1
  28. package/lib/cjs/ViewStore.js.map +1 -1
  29. package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts +23 -0
  30. package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
  31. package/lib/cjs/internal/ECSqlInstanceReshaper.js +125 -0
  32. package/lib/cjs/internal/ECSqlInstanceReshaper.js.map +1 -0
  33. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
  34. package/lib/cjs/internal/annotations/fields.js +9 -4
  35. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  36. package/lib/esm/ClassRegistry.d.ts.map +1 -1
  37. package/lib/esm/ClassRegistry.js +1 -2
  38. package/lib/esm/ClassRegistry.js.map +1 -1
  39. package/lib/esm/ECDb.d.ts.map +1 -1
  40. package/lib/esm/ECDb.js +9 -4
  41. package/lib/esm/ECDb.js.map +1 -1
  42. package/lib/esm/ECSqlRowExecutor.d.ts +23 -10
  43. package/lib/esm/ECSqlRowExecutor.d.ts.map +1 -1
  44. package/lib/esm/ECSqlRowExecutor.js +77 -16
  45. package/lib/esm/ECSqlRowExecutor.js.map +1 -1
  46. package/lib/esm/IModelDb.d.ts +20 -8
  47. package/lib/esm/IModelDb.d.ts.map +1 -1
  48. package/lib/esm/IModelDb.js +85 -56
  49. package/lib/esm/IModelDb.js.map +1 -1
  50. package/lib/esm/IpcHost.d.ts +26 -0
  51. package/lib/esm/IpcHost.d.ts.map +1 -1
  52. package/lib/esm/IpcHost.js +70 -63
  53. package/lib/esm/IpcHost.js.map +1 -1
  54. package/lib/esm/Relationship.d.ts.map +1 -1
  55. package/lib/esm/Relationship.js +13 -7
  56. package/lib/esm/Relationship.js.map +1 -1
  57. package/lib/esm/SQLiteDb.d.ts +43 -0
  58. package/lib/esm/SQLiteDb.d.ts.map +1 -1
  59. package/lib/esm/SQLiteDb.js +51 -0
  60. package/lib/esm/SQLiteDb.js.map +1 -1
  61. package/lib/esm/ViewStore.js +1 -1
  62. package/lib/esm/ViewStore.js.map +1 -1
  63. package/lib/esm/internal/ECSqlInstanceReshaper.d.ts +23 -0
  64. package/lib/esm/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
  65. package/lib/esm/internal/ECSqlInstanceReshaper.js +120 -0
  66. package/lib/esm/internal/ECSqlInstanceReshaper.js.map +1 -0
  67. package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
  68. package/lib/esm/internal/annotations/fields.js +9 -4
  69. package/lib/esm/internal/annotations/fields.js.map +1 -1
  70. package/lib/esm/test/IpcHost.test.js +232 -1
  71. package/lib/esm/test/IpcHost.test.js.map +1 -1
  72. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +139 -1
  73. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
  74. package/lib/esm/test/imodel/IModel.test.js +20 -0
  75. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  76. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts +2 -0
  77. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts.map +1 -0
  78. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js +289 -0
  79. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js.map +1 -0
  80. package/lib/esm/test/schema/ClassRegistry.test.js +2 -2
  81. package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
  82. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts +2 -0
  83. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts.map +1 -0
  84. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js +546 -0
  85. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js.map +1 -0
  86. package/lib/esm/test/schema/SchemaViewLifecycle.test.js +2 -2
  87. package/lib/esm/test/schema/SchemaViewLifecycle.test.js.map +1 -1
  88. package/lib/esm/test/standalone/MergeConflict.test.js +1 -1
  89. package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
  90. package/lib/esm/test/standalone/SQLiteDb.test.d.ts +1 -1
  91. package/lib/esm/test/standalone/SQLiteDb.test.d.ts.map +1 -1
  92. package/lib/esm/test/standalone/SQLiteDb.test.js +93 -1
  93. package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
  94. package/lib/esm/test/standalone/ViewStoreDb.test.js +30 -0
  95. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  96. package/package.json +13 -13
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ECSqlInstanceReshaper.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ECSqlInstanceReshaper.test.d.ts","sourceRoot":"","sources":["../../../../src/test/internal/ECSqlInstanceReshaper.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,289 @@
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 { assert, expect } from "chai";
6
+ import { Id64 } from "@itwin/core-bentley";
7
+ import { Code, IModel, QueryBinder, QueryRowFormat } from "@itwin/core-common";
8
+ import { withEditTxn } from "../../EditTxn";
9
+ import { getRuntimeClass, reshapeInstanceRow, reshapePropertyValue } from "../../internal/ECSqlInstanceReshaper";
10
+ import { IModelJsFs, SnapshotDb } from "../../core-backend";
11
+ import { IModelTestUtils } from "../IModelTestUtils";
12
+ /* eslint-disable @typescript-eslint/naming-convention */
13
+ // Direct unit tests for the ECSqlInstanceReshaper helper, which reshapes rows/values queried with the
14
+ // non-deprecated QueryRowFormat.UseECSqlPropertyNames row format back into the legacy shape historically
15
+ // produced by the deprecated QueryRowFormat.UseJsPropertyNames row format. These call the helper's exported
16
+ // functions directly against real ECSQL rows, rather than only exercising them indirectly through
17
+ // ElementAspect/Relationship/annotation field call sites (which are covered elsewhere).
18
+ describe("ECSqlInstanceReshaper", () => {
19
+ const schemaName = "ReshaperTest";
20
+ const schemaAlias = "rst";
21
+ const subDirName = "ECSqlInstanceReshaper";
22
+ let iModel;
23
+ let element1Id;
24
+ let element2Id;
25
+ let aspectId;
26
+ let relationshipId;
27
+ before(async () => {
28
+ const schema = `<?xml version="1.0" encoding="UTF-8"?>
29
+ <ECSchema schemaName="${schemaName}" alias="${schemaAlias}" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
30
+ <ECSchemaReference name="BisCore" version="01.00.04" alias="bis"/>
31
+ <ECStructClass typeName="PointStruct" modifier="None">
32
+ <ECProperty propertyName="Label" typeName="string"/>
33
+ <ECProperty propertyName="P3d" typeName="point3d"/>
34
+ </ECStructClass>
35
+ <ECEntityClass typeName="ReshaperElement" modifier="None">
36
+ <BaseClass>bis:DefinitionElement</BaseClass>
37
+ </ECEntityClass>
38
+ <ECEntityClass typeName="ReshaperAspect" modifier="None">
39
+ <BaseClass>bis:ElementUniqueAspect</BaseClass>
40
+ <ECProperty propertyName="P2d" typeName="point2d"/>
41
+ <ECProperty propertyName="P3d" typeName="point3d"/>
42
+ <ECStructProperty propertyName="St" typeName="PointStruct"/>
43
+ <ECArrayProperty propertyName="ArrayI" typeName="int" minOccurs="0" maxOccurs="unbounded"/>
44
+ <ECArrayProperty propertyName="ArrayP3d" typeName="point3d" minOccurs="0" maxOccurs="unbounded"/>
45
+ <ECStructArrayProperty propertyName="ArraySt" typeName="PointStruct" minOccurs="0" maxOccurs="unbounded"/>
46
+ </ECEntityClass>
47
+ <ECRelationshipClass typeName="ReshaperRelatesToElement" strength="referencing" modifier="Sealed">
48
+ <BaseClass>bis:ElementRefersToElements</BaseClass>
49
+ <Source multiplicity="(0..*)" roleLabel="refers to" polymorphic="true">
50
+ <Class class="ReshaperElement"/>
51
+ </Source>
52
+ <Target multiplicity="(0..*)" roleLabel="is referenced by" polymorphic="true">
53
+ <Class class="ReshaperElement"/>
54
+ </Target>
55
+ <ECProperty propertyName="Label" typeName="string"/>
56
+ </ECRelationshipClass>
57
+ <ECEnumeration typeName="ReshaperNotAClass" backingTypeName="int" isStrict="true">
58
+ <ECEnumerator name="Value0" value="0"/>
59
+ </ECEnumeration>
60
+ </ECSchema>`;
61
+ const testFileName = IModelTestUtils.prepareOutputFile(subDirName, "ECSqlInstanceReshaper.bim");
62
+ const schemaPath = IModelTestUtils.prepareOutputFile(subDirName, `${schemaName}.01.00.00.xml`);
63
+ IModelJsFs.writeFileSync(schemaPath, schema);
64
+ iModel = SnapshotDb.createEmpty(testFileName, { rootSubject: { name: "ECSqlInstanceReshaperTest" } });
65
+ await iModel.importSchemas([schemaPath]);
66
+ withEditTxn(iModel, (txn) => {
67
+ element1Id = txn.insertElement({
68
+ classFullName: `${schemaName}:ReshaperElement`,
69
+ model: IModel.dictionaryId,
70
+ code: Code.createEmpty(),
71
+ });
72
+ element2Id = txn.insertElement({
73
+ classFullName: `${schemaName}:ReshaperElement`,
74
+ model: IModel.dictionaryId,
75
+ code: Code.createEmpty(),
76
+ });
77
+ assert.isTrue(Id64.isValidId64(element1Id));
78
+ assert.isTrue(Id64.isValidId64(element2Id));
79
+ aspectId = txn.insertAspect({
80
+ classFullName: `${schemaName}:ReshaperAspect`,
81
+ element: { id: element1Id },
82
+ p2d: { x: 100, y: 200 },
83
+ p3d: { x: 1, y: 2, z: 3 },
84
+ st: { label: "struct-label", p3d: { x: 4, y: 5, z: 6 } },
85
+ arrayI: [10, 20, 30],
86
+ arrayP3d: [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }],
87
+ arraySt: [{ label: "arr-0", p3d: { x: 7, y: 8, z: 9 } }, { label: "arr-1", p3d: { x: 10, y: 11, z: 12 } }],
88
+ });
89
+ assert.isTrue(Id64.isValidId64(aspectId));
90
+ relationshipId = txn.insertRelationship({
91
+ classFullName: `${schemaName}:ReshaperRelatesToElement`,
92
+ sourceId: element1Id,
93
+ targetId: element2Id,
94
+ label: "rel-label",
95
+ });
96
+ assert.isTrue(Id64.isValidId64(relationshipId));
97
+ });
98
+ });
99
+ after(() => {
100
+ iModel.close();
101
+ });
102
+ it("getRuntimeClass resolves a runtime class by full class name and throws for unknown classes", () => {
103
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
104
+ assert.equal(ecClass.name, "ReshaperAspect");
105
+ assert.equal(ecClass.schema.name, schemaName);
106
+ assert.throws(() => getRuntimeClass(iModel, `${schemaName}:DoesNotExist`), /Class not found/);
107
+ });
108
+ it("getRuntimeClass throws when the resolved schema item exists but isn't a class", () => {
109
+ assert.throws(() => getRuntimeClass(iModel, `${schemaName}:ReshaperNotAClass`), /Class not found/);
110
+ });
111
+ it("reshapeInstanceRow reshapes an ElementAspect row: system properties, points, struct, primitive array, point array, and struct array", () => {
112
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
113
+ const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {
114
+ assert.isTrue(reader.step());
115
+ return reader.current.toRow();
116
+ }, new QueryBinder().bindId("aspectId", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
117
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
118
+ // system properties: ECInstanceId -> id, ECClassId -> className (dot-separated)
119
+ assert.equal(reshaped.id, aspectId);
120
+ assert.equal(reshaped.className, `${schemaName}.ReshaperAspect`);
121
+ // inherited navigation property from ElementUniqueAspect
122
+ assert.deepEqual(reshaped.element, { id: element1Id, relClassName: "BisCore.ElementOwnsUniqueAspect" });
123
+ // point2d property: first letter lowercased, X/Y -> x/y
124
+ assert.deepEqual(reshaped.p2d, { x: 100, y: 200 });
125
+ // point3d property: first letter lowercased, X/Y/Z -> x/y/z
126
+ assert.deepEqual(reshaped.p3d, { x: 1, y: 2, z: 3 });
127
+ // struct property: first letter lowercased, and its members recursively reshaped (including nested point)
128
+ assert.deepEqual(reshaped.st, { label: "struct-label", p3d: { x: 4, y: 5, z: 6 } });
129
+ // primitive (non-point) array: values pass through unchanged, only the key is lowercased
130
+ assert.deepEqual(reshaped.arrayI, [10, 20, 30]);
131
+ // point3d array: each scalar element reshaped like a standalone point, not just key-renamed
132
+ assert.deepEqual(reshaped.arrayP3d, [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }]);
133
+ // struct array: each element recursively reshaped like a standalone struct
134
+ assert.deepEqual(reshaped.arraySt, [
135
+ { label: "arr-0", p3d: { x: 7, y: 8, z: 9 } },
136
+ { label: "arr-1", p3d: { x: 10, y: 11, z: 12 } },
137
+ ]);
138
+ });
139
+ it("reshapeInstanceRow reshapes a Relationship row: source/target system properties and a primitive property", () => {
140
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperRelatesToElement`);
141
+ const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperRelatesToElement WHERE ECInstanceId=:relationshipId`, (reader) => {
142
+ assert.isTrue(reader.step());
143
+ return reader.current.toRow();
144
+ }, new QueryBinder().bindId("relationshipId", relationshipId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
145
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
146
+ assert.equal(reshaped.id, relationshipId);
147
+ assert.equal(reshaped.className, `${schemaName}.ReshaperRelatesToElement`);
148
+ assert.equal(reshaped.sourceId, element1Id);
149
+ assert.equal(reshaped.sourceClassName, `${schemaName}.ReshaperElement`);
150
+ assert.equal(reshaped.targetId, element2Id);
151
+ assert.equal(reshaped.targetClassName, `${schemaName}.ReshaperElement`);
152
+ assert.equal(reshaped.label, "rel-label");
153
+ });
154
+ it("reshapeInstanceRow omits null/undefined members instead of propagating them", () => {
155
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
156
+ const row = { ECInstanceId: aspectId, P3d: null, St: undefined, ArrayI: [10, 20, 30] };
157
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
158
+ assert.equal(reshaped.id, aspectId);
159
+ assert.isUndefined(reshaped.p3d);
160
+ assert.isUndefined(reshaped.st);
161
+ assert.deepEqual(reshaped.arrayI, [10, 20, 30]);
162
+ });
163
+ it("reshapePropertyValue reshapes a single Point2d, Point3d, and struct property value in isolation", () => {
164
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
165
+ const p2dProp = ecClass.getPropertySync("P2d");
166
+ const p3dProp = ecClass.getPropertySync("P3d");
167
+ const stProp = ecClass.getPropertySync("St");
168
+ assert.exists(p2dProp);
169
+ assert.exists(p3dProp);
170
+ assert.exists(stProp);
171
+ assert.deepEqual(reshapePropertyValue({ X: 100, Y: 200 }, p2dProp, iModel), { x: 100, y: 200 });
172
+ assert.deepEqual(reshapePropertyValue({ X: 1, Y: 2, Z: 3 }, p3dProp, iModel), { x: 1, y: 2, z: 3 });
173
+ assert.deepEqual(reshapePropertyValue({ Label: "hello", P3d: { X: 1, Y: 2, Z: 3 } }, stProp, iModel), { label: "hello", p3d: { x: 1, y: 2, z: 3 } });
174
+ });
175
+ it("reshapePropertyValue reshapes an array of Point3d scalars, not just a key rename", () => {
176
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
177
+ const arrayP3dProp = ecClass.getPropertySync("ArrayP3d");
178
+ assert.exists(arrayP3dProp);
179
+ assert.isTrue(arrayP3dProp.isArray());
180
+ const reshaped = reshapePropertyValue([{ X: 13, Y: 14, Z: 15 }, { X: 16, Y: 17, Z: 18 }], arrayP3dProp, iModel);
181
+ assert.deepEqual(reshaped, [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }]);
182
+ });
183
+ it("reshapePropertyValue reshapes a navigation property value into {id, relClassName}", () => {
184
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
185
+ const elementProp = ecClass.getPropertySync("Element");
186
+ assert.exists(elementProp);
187
+ assert.isTrue(elementProp.isNavigation());
188
+ const row = iModel.withQueryReader(`SELECT Element FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {
189
+ assert.isTrue(reader.step());
190
+ return reader.current.toRow();
191
+ }, new QueryBinder().bindId("aspectId", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
192
+ const reshaped = reshapePropertyValue(row.Element, elementProp, iModel);
193
+ expect(reshaped).to.deep.equal({ id: element1Id, relClassName: "BisCore.ElementOwnsUniqueAspect" });
194
+ });
195
+ it("reshapePropertyValue falls back to the raw classId instead of throwing when a navigation property's relationship class can't be resolved", () => {
196
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
197
+ const elementProp = ecClass.getPropertySync("Element");
198
+ assert.exists(elementProp);
199
+ const unresolvableClassId = "0xdeadbeef";
200
+ const reshaped = reshapePropertyValue({ Id: element1Id, RelECClassId: unresolvableClassId }, elementProp, iModel);
201
+ assert.deepEqual(reshaped, { id: element1Id, relClassName: unresolvableClassId });
202
+ });
203
+ it("reshapePropertyValue omits relClassName entirely when a navigation property's relationship class Id is unset", () => {
204
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
205
+ const elementProp = ecClass.getPropertySync("Element");
206
+ assert.exists(elementProp);
207
+ const reshaped = reshapePropertyValue({ Id: element1Id, RelECClassId: undefined }, elementProp, iModel);
208
+ assert.deepEqual(reshaped, { id: element1Id });
209
+ assert.isFalse("relClassName" in reshaped);
210
+ });
211
+ it("reshapeInstanceRow falls back to the raw classId instead of throwing when a system ECClassId column can't be resolved", () => {
212
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
213
+ const unresolvableClassId = "0xdeadbeef";
214
+ const reshaped = reshapeInstanceRow({ ECInstanceId: aspectId, ECClassId: unresolvableClassId }, ecClass, iModel);
215
+ assert.equal(reshaped.id, aspectId);
216
+ assert.equal(reshaped.className, unresolvableClassId);
217
+ });
218
+ it("reshapePropertyValue preserves a null/undefined struct-array element as an empty object, matching the native row adaptor", () => {
219
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
220
+ const arrayStProp = ecClass.getPropertySync("ArraySt");
221
+ assert.exists(arrayStProp);
222
+ // A null struct-array element is rendered by the native row adaptor as an empty object placeholder
223
+ // (unlike primitive arrays, where null elements are dropped entirely), preserving the array's length
224
+ // and the positions of surrounding elements. The underlying query reader already normalizes a null
225
+ // struct-array element to `{}` before it reaches the reshaper, but the reshaper is also exercised
226
+ // directly here against raw `null`/`undefined` inputs to keep it robust regardless of caller.
227
+ const reshaped = reshapePropertyValue([{ Label: "arr-0", P3d: { X: 1, Y: 2, Z: 3 } }, null, undefined, { Label: "arr-3", P3d: { X: 4, Y: 5, Z: 6 } }], arrayStProp, iModel);
228
+ assert.deepEqual(reshaped, [
229
+ { label: "arr-0", p3d: { x: 1, y: 2, z: 3 } },
230
+ {},
231
+ {},
232
+ { label: "arr-3", p3d: { x: 4, y: 5, z: 6 } },
233
+ ]);
234
+ });
235
+ it("reshapePropertyValue drops null/undefined elements from a primitive array, matching the native row adaptor", () => {
236
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
237
+ const arrayIProp = ecClass.getPropertySync("ArrayI");
238
+ assert.exists(arrayIProp);
239
+ const reshaped = reshapePropertyValue([10, null, undefined, 30], arrayIProp, iModel);
240
+ assert.deepEqual(reshaped, [10, 30]);
241
+ });
242
+ it("reshapeInstanceRow reshapes a row containing null array elements without throwing, matching the native row adaptor", () => {
243
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
244
+ let probeAspectId;
245
+ withEditTxn(iModel, (txn) => {
246
+ probeAspectId = txn.insertAspect({
247
+ classFullName: `${schemaName}:ReshaperAspect`,
248
+ element: { id: element1Id },
249
+ arrayI: [10, null, 30],
250
+ arraySt: [{ label: "a" }, null, { label: "c" }],
251
+ });
252
+ });
253
+ const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:id`, (reader) => {
254
+ assert.isTrue(reader.step());
255
+ return reader.current.toRow();
256
+ }, new QueryBinder().bindId("id", probeAspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
257
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
258
+ assert.deepEqual(reshaped.arrayI, [10, 30]);
259
+ assert.deepEqual(reshaped.arraySt, [{ label: "a" }, {}, { label: "c" }]);
260
+ });
261
+ it("reshapeInstanceRow omits a null struct member from a real queried row, matching the native row adaptor", () => {
262
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
263
+ let probeAspectId;
264
+ withEditTxn(iModel, (txn) => {
265
+ probeAspectId = txn.insertAspect({
266
+ classFullName: `${schemaName}:ReshaperAspect`,
267
+ element: { id: element1Id },
268
+ st: { label: null, p3d: { x: 1, y: 2, z: 3 } },
269
+ });
270
+ });
271
+ const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:id`, (reader) => {
272
+ assert.isTrue(reader.step());
273
+ return reader.current.toRow();
274
+ }, new QueryBinder().bindId("id", probeAspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
275
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
276
+ assert.isFalse("label" in reshaped.st);
277
+ assert.deepEqual(reshaped.st.p3d, { x: 1, y: 2, z: 3 });
278
+ });
279
+ it("reshapeInstanceRow passes through an aliased/computed column with only its key lowercased", () => {
280
+ const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);
281
+ const row = iModel.withQueryReader(`SELECT *, 1+1 AS Foo FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {
282
+ assert.isTrue(reader.step());
283
+ return reader.current.toRow();
284
+ }, new QueryBinder().bindId("aspectId", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
285
+ const reshaped = reshapeInstanceRow(row, ecClass, iModel);
286
+ assert.equal(reshaped.foo, 2);
287
+ });
288
+ });
289
+ //# sourceMappingURL=ECSqlInstanceReshaper.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ECSqlInstanceReshaper.test.js","sourceRoot":"","sources":["../../../../src/test/internal/ECSqlInstanceReshaper.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport { assert, expect } from \"chai\";\nimport { Id64, Id64String } from \"@itwin/core-bentley\";\nimport { Code, IModel, QueryBinder, QueryRowFormat } from \"@itwin/core-common\";\nimport { withEditTxn } from \"../../EditTxn\";\nimport { getRuntimeClass, reshapeInstanceRow, reshapePropertyValue } from \"../../internal/ECSqlInstanceReshaper\";\nimport { IModelJsFs, SnapshotDb } from \"../../core-backend\";\nimport { IModelTestUtils } from \"../IModelTestUtils\";\n\n/* eslint-disable @typescript-eslint/naming-convention */\n\n// Direct unit tests for the ECSqlInstanceReshaper helper, which reshapes rows/values queried with the\n// non-deprecated QueryRowFormat.UseECSqlPropertyNames row format back into the legacy shape historically\n// produced by the deprecated QueryRowFormat.UseJsPropertyNames row format. These call the helper's exported\n// functions directly against real ECSQL rows, rather than only exercising them indirectly through\n// ElementAspect/Relationship/annotation field call sites (which are covered elsewhere).\ndescribe(\"ECSqlInstanceReshaper\", () => {\n const schemaName = \"ReshaperTest\";\n const schemaAlias = \"rst\";\n const subDirName = \"ECSqlInstanceReshaper\";\n\n let iModel: SnapshotDb;\n let element1Id: Id64String;\n let element2Id: Id64String;\n let aspectId: Id64String;\n let relationshipId: Id64String;\n\n before(async () => {\n const schema = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <ECSchema schemaName=\"${schemaName}\" alias=\"${schemaAlias}\" version=\"01.00.00\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.3.2\">\n <ECSchemaReference name=\"BisCore\" version=\"01.00.04\" alias=\"bis\"/>\n <ECStructClass typeName=\"PointStruct\" modifier=\"None\">\n <ECProperty propertyName=\"Label\" typeName=\"string\"/>\n <ECProperty propertyName=\"P3d\" typeName=\"point3d\"/>\n </ECStructClass>\n <ECEntityClass typeName=\"ReshaperElement\" modifier=\"None\">\n <BaseClass>bis:DefinitionElement</BaseClass>\n </ECEntityClass>\n <ECEntityClass typeName=\"ReshaperAspect\" modifier=\"None\">\n <BaseClass>bis:ElementUniqueAspect</BaseClass>\n <ECProperty propertyName=\"P2d\" typeName=\"point2d\"/>\n <ECProperty propertyName=\"P3d\" typeName=\"point3d\"/>\n <ECStructProperty propertyName=\"St\" typeName=\"PointStruct\"/>\n <ECArrayProperty propertyName=\"ArrayI\" typeName=\"int\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n <ECArrayProperty propertyName=\"ArrayP3d\" typeName=\"point3d\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n <ECStructArrayProperty propertyName=\"ArraySt\" typeName=\"PointStruct\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </ECEntityClass>\n <ECRelationshipClass typeName=\"ReshaperRelatesToElement\" strength=\"referencing\" modifier=\"Sealed\">\n <BaseClass>bis:ElementRefersToElements</BaseClass>\n <Source multiplicity=\"(0..*)\" roleLabel=\"refers to\" polymorphic=\"true\">\n <Class class=\"ReshaperElement\"/>\n </Source>\n <Target multiplicity=\"(0..*)\" roleLabel=\"is referenced by\" polymorphic=\"true\">\n <Class class=\"ReshaperElement\"/>\n </Target>\n <ECProperty propertyName=\"Label\" typeName=\"string\"/>\n </ECRelationshipClass>\n <ECEnumeration typeName=\"ReshaperNotAClass\" backingTypeName=\"int\" isStrict=\"true\">\n <ECEnumerator name=\"Value0\" value=\"0\"/>\n </ECEnumeration>\n </ECSchema>`;\n\n const testFileName = IModelTestUtils.prepareOutputFile(subDirName, \"ECSqlInstanceReshaper.bim\");\n const schemaPath = IModelTestUtils.prepareOutputFile(subDirName, `${schemaName}.01.00.00.xml`);\n IModelJsFs.writeFileSync(schemaPath, schema);\n\n iModel = SnapshotDb.createEmpty(testFileName, { rootSubject: { name: \"ECSqlInstanceReshaperTest\" } });\n await iModel.importSchemas([schemaPath]);\n\n withEditTxn(iModel, (txn) => {\n element1Id = txn.insertElement({\n classFullName: `${schemaName}:ReshaperElement`,\n model: IModel.dictionaryId,\n code: Code.createEmpty(),\n });\n element2Id = txn.insertElement({\n classFullName: `${schemaName}:ReshaperElement`,\n model: IModel.dictionaryId,\n code: Code.createEmpty(),\n });\n assert.isTrue(Id64.isValidId64(element1Id));\n assert.isTrue(Id64.isValidId64(element2Id));\n\n aspectId = txn.insertAspect({\n classFullName: `${schemaName}:ReshaperAspect`,\n element: { id: element1Id },\n p2d: { x: 100, y: 200 },\n p3d: { x: 1, y: 2, z: 3 },\n st: { label: \"struct-label\", p3d: { x: 4, y: 5, z: 6 } },\n arrayI: [10, 20, 30],\n arrayP3d: [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }],\n arraySt: [{ label: \"arr-0\", p3d: { x: 7, y: 8, z: 9 } }, { label: \"arr-1\", p3d: { x: 10, y: 11, z: 12 } }],\n } as any);\n assert.isTrue(Id64.isValidId64(aspectId));\n\n relationshipId = txn.insertRelationship({\n classFullName: `${schemaName}:ReshaperRelatesToElement`,\n sourceId: element1Id,\n targetId: element2Id,\n label: \"rel-label\",\n } as any);\n assert.isTrue(Id64.isValidId64(relationshipId));\n });\n });\n\n after(() => {\n iModel.close();\n });\n\n it(\"getRuntimeClass resolves a runtime class by full class name and throws for unknown classes\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n assert.equal(ecClass.name, \"ReshaperAspect\");\n assert.equal(ecClass.schema.name, schemaName);\n\n assert.throws(() => getRuntimeClass(iModel, `${schemaName}:DoesNotExist`), /Class not found/);\n });\n\n it(\"getRuntimeClass throws when the resolved schema item exists but isn't a class\", () => {\n assert.throws(() => getRuntimeClass(iModel, `${schemaName}:ReshaperNotAClass`), /Class not found/);\n });\n\n it(\"reshapeInstanceRow reshapes an ElementAspect row: system properties, points, struct, primitive array, point array, and struct array\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"aspectId\", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n\n // system properties: ECInstanceId -> id, ECClassId -> className (dot-separated)\n assert.equal(reshaped.id, aspectId);\n assert.equal(reshaped.className, `${schemaName}.ReshaperAspect`);\n\n // inherited navigation property from ElementUniqueAspect\n assert.deepEqual(reshaped.element, { id: element1Id, relClassName: \"BisCore.ElementOwnsUniqueAspect\" });\n\n // point2d property: first letter lowercased, X/Y -> x/y\n assert.deepEqual(reshaped.p2d, { x: 100, y: 200 });\n\n // point3d property: first letter lowercased, X/Y/Z -> x/y/z\n assert.deepEqual(reshaped.p3d, { x: 1, y: 2, z: 3 });\n\n // struct property: first letter lowercased, and its members recursively reshaped (including nested point)\n assert.deepEqual(reshaped.st, { label: \"struct-label\", p3d: { x: 4, y: 5, z: 6 } });\n\n // primitive (non-point) array: values pass through unchanged, only the key is lowercased\n assert.deepEqual(reshaped.arrayI, [10, 20, 30]);\n\n // point3d array: each scalar element reshaped like a standalone point, not just key-renamed\n assert.deepEqual(reshaped.arrayP3d, [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }]);\n\n // struct array: each element recursively reshaped like a standalone struct\n assert.deepEqual(reshaped.arraySt, [\n { label: \"arr-0\", p3d: { x: 7, y: 8, z: 9 } },\n { label: \"arr-1\", p3d: { x: 10, y: 11, z: 12 } },\n ]);\n });\n\n it(\"reshapeInstanceRow reshapes a Relationship row: source/target system properties and a primitive property\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperRelatesToElement`);\n const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperRelatesToElement WHERE ECInstanceId=:relationshipId`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"relationshipId\", relationshipId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n\n assert.equal(reshaped.id, relationshipId);\n assert.equal(reshaped.className, `${schemaName}.ReshaperRelatesToElement`);\n assert.equal(reshaped.sourceId, element1Id);\n assert.equal(reshaped.sourceClassName, `${schemaName}.ReshaperElement`);\n assert.equal(reshaped.targetId, element2Id);\n assert.equal(reshaped.targetClassName, `${schemaName}.ReshaperElement`);\n assert.equal(reshaped.label, \"rel-label\");\n });\n\n it(\"reshapeInstanceRow omits null/undefined members instead of propagating them\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const row = { ECInstanceId: aspectId, P3d: null, St: undefined, ArrayI: [10, 20, 30] };\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n\n assert.equal(reshaped.id, aspectId);\n assert.isUndefined(reshaped.p3d);\n assert.isUndefined(reshaped.st);\n assert.deepEqual(reshaped.arrayI, [10, 20, 30]);\n });\n\n it(\"reshapePropertyValue reshapes a single Point2d, Point3d, and struct property value in isolation\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const p2dProp = ecClass.getPropertySync(\"P2d\")!;\n const p3dProp = ecClass.getPropertySync(\"P3d\")!;\n const stProp = ecClass.getPropertySync(\"St\")!;\n assert.exists(p2dProp);\n assert.exists(p3dProp);\n assert.exists(stProp);\n\n assert.deepEqual(reshapePropertyValue({ X: 100, Y: 200 }, p2dProp, iModel), { x: 100, y: 200 });\n assert.deepEqual(reshapePropertyValue({ X: 1, Y: 2, Z: 3 }, p3dProp, iModel), { x: 1, y: 2, z: 3 });\n assert.deepEqual(\n reshapePropertyValue({ Label: \"hello\", P3d: { X: 1, Y: 2, Z: 3 } }, stProp, iModel),\n { label: \"hello\", p3d: { x: 1, y: 2, z: 3 } },\n );\n });\n\n it(\"reshapePropertyValue reshapes an array of Point3d scalars, not just a key rename\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const arrayP3dProp = ecClass.getPropertySync(\"ArrayP3d\")!;\n assert.exists(arrayP3dProp);\n assert.isTrue(arrayP3dProp.isArray());\n\n const reshaped = reshapePropertyValue([{ X: 13, Y: 14, Z: 15 }, { X: 16, Y: 17, Z: 18 }], arrayP3dProp, iModel);\n assert.deepEqual(reshaped, [{ x: 13, y: 14, z: 15 }, { x: 16, y: 17, z: 18 }]);\n });\n\n it(\"reshapePropertyValue reshapes a navigation property value into {id, relClassName}\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const elementProp = ecClass.getPropertySync(\"Element\")!;\n assert.exists(elementProp);\n assert.isTrue(elementProp.isNavigation());\n\n const row = iModel.withQueryReader(`SELECT Element FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"aspectId\", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapePropertyValue(row.Element, elementProp, iModel);\n expect(reshaped).to.deep.equal({ id: element1Id, relClassName: \"BisCore.ElementOwnsUniqueAspect\" });\n });\n\n it(\"reshapePropertyValue falls back to the raw classId instead of throwing when a navigation property's relationship class can't be resolved\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const elementProp = ecClass.getPropertySync(\"Element\")!;\n assert.exists(elementProp);\n\n const unresolvableClassId = \"0xdeadbeef\";\n const reshaped = reshapePropertyValue({ Id: element1Id, RelECClassId: unresolvableClassId }, elementProp, iModel);\n assert.deepEqual(reshaped, { id: element1Id, relClassName: unresolvableClassId });\n });\n\n it(\"reshapePropertyValue omits relClassName entirely when a navigation property's relationship class Id is unset\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const elementProp = ecClass.getPropertySync(\"Element\")!;\n assert.exists(elementProp);\n\n const reshaped = reshapePropertyValue({ Id: element1Id, RelECClassId: undefined }, elementProp, iModel);\n assert.deepEqual(reshaped, { id: element1Id });\n assert.isFalse(\"relClassName\" in reshaped);\n });\n\n it(\"reshapeInstanceRow falls back to the raw classId instead of throwing when a system ECClassId column can't be resolved\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const unresolvableClassId = \"0xdeadbeef\";\n const reshaped = reshapeInstanceRow({ ECInstanceId: aspectId, ECClassId: unresolvableClassId }, ecClass, iModel);\n assert.equal(reshaped.id, aspectId);\n assert.equal(reshaped.className, unresolvableClassId);\n });\n\n it(\"reshapePropertyValue preserves a null/undefined struct-array element as an empty object, matching the native row adaptor\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const arrayStProp = ecClass.getPropertySync(\"ArraySt\")!;\n assert.exists(arrayStProp);\n\n // A null struct-array element is rendered by the native row adaptor as an empty object placeholder\n // (unlike primitive arrays, where null elements are dropped entirely), preserving the array's length\n // and the positions of surrounding elements. The underlying query reader already normalizes a null\n // struct-array element to `{}` before it reaches the reshaper, but the reshaper is also exercised\n // directly here against raw `null`/`undefined` inputs to keep it robust regardless of caller.\n const reshaped = reshapePropertyValue(\n [{ Label: \"arr-0\", P3d: { X: 1, Y: 2, Z: 3 } }, null, undefined, { Label: \"arr-3\", P3d: { X: 4, Y: 5, Z: 6 } }],\n arrayStProp,\n iModel,\n );\n assert.deepEqual(reshaped, [\n { label: \"arr-0\", p3d: { x: 1, y: 2, z: 3 } },\n {},\n {},\n { label: \"arr-3\", p3d: { x: 4, y: 5, z: 6 } },\n ]);\n });\n\n it(\"reshapePropertyValue drops null/undefined elements from a primitive array, matching the native row adaptor\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const arrayIProp = ecClass.getPropertySync(\"ArrayI\")!;\n assert.exists(arrayIProp);\n\n const reshaped = reshapePropertyValue([10, null, undefined, 30], arrayIProp, iModel);\n assert.deepEqual(reshaped, [10, 30]);\n });\n\n it(\"reshapeInstanceRow reshapes a row containing null array elements without throwing, matching the native row adaptor\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n let probeAspectId: string;\n withEditTxn(iModel, (txn) => {\n probeAspectId = txn.insertAspect({\n classFullName: `${schemaName}:ReshaperAspect`,\n element: { id: element1Id },\n arrayI: [10, null, 30],\n arraySt: [{ label: \"a\" }, null, { label: \"c\" }],\n } as any);\n });\n const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:id`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"id\", probeAspectId!), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n assert.deepEqual(reshaped.arrayI, [10, 30]);\n assert.deepEqual(reshaped.arraySt, [{ label: \"a\" }, {}, { label: \"c\" }]);\n });\n\n it(\"reshapeInstanceRow omits a null struct member from a real queried row, matching the native row adaptor\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n let probeAspectId: string;\n withEditTxn(iModel, (txn) => {\n probeAspectId = txn.insertAspect({\n classFullName: `${schemaName}:ReshaperAspect`,\n element: { id: element1Id },\n st: { label: null, p3d: { x: 1, y: 2, z: 3 } },\n } as any);\n });\n const row = iModel.withQueryReader(`SELECT * FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:id`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"id\", probeAspectId!), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n assert.isFalse(\"label\" in reshaped.st);\n assert.deepEqual(reshaped.st.p3d, { x: 1, y: 2, z: 3 });\n });\n\n it(\"reshapeInstanceRow passes through an aliased/computed column with only its key lowercased\", () => {\n const ecClass = getRuntimeClass(iModel, `${schemaName}:ReshaperAspect`);\n const row = iModel.withQueryReader(`SELECT *, 1+1 AS Foo FROM ${schemaAlias}.ReshaperAspect WHERE ECInstanceId=:aspectId`, (reader) => {\n assert.isTrue(reader.step());\n return reader.current.toRow();\n }, new QueryBinder().bindId(\"aspectId\", aspectId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });\n\n const reshaped = reshapeInstanceRow(row, ecClass, iModel);\n assert.equal(reshaped.foo, 2);\n });\n});\n"]}
@@ -377,7 +377,7 @@ describe("Class Registry - generated classes", () => {
377
377
  relClassName: "TestGeneratedClasses:ElemRel",
378
378
  },
379
379
  });
380
- // eslint-disable-next-line @typescript-eslint/dot-notation
380
+ // eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/unbound-method -- The method is asserted but never invoked.
381
381
  assert.isDefined(GeneratedTestElementWithNavProp.prototype["collectReferenceIds"]);
382
382
  expect([...elemWithNavProp.getReferenceIds()]).to.have.members([
383
383
  EntityReferences.fromEntityType(elemWithNavProp.model, ConcreteEntityTypes.Model),
@@ -561,7 +561,7 @@ describe("Class Registry - generated classes", () => {
561
561
  relClassName: "TestGeneratedClasses:DerivedElemRel",
562
562
  },
563
563
  });
564
- // eslint-disable-next-line @typescript-eslint/dot-notation
564
+ // eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/unbound-method -- The method is asserted but never invoked.
565
565
  assert.isDefined(ActualDerivedWithNavProp.prototype["collectReferenceIds"]);
566
566
  // This demonstrates that if a non-generated class has a registered non-biscore base, it will not get a generated impl,
567
567
  expect([...derivedElemWithNavProp.getReferenceIds()]).to.have.members([