@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.
- package/CHANGELOG.md +11 -1
- package/lib/cjs/ClassRegistry.d.ts.map +1 -1
- package/lib/cjs/ClassRegistry.js +1 -2
- package/lib/cjs/ClassRegistry.js.map +1 -1
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +8 -3
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/ECSqlRowExecutor.d.ts +23 -10
- package/lib/cjs/ECSqlRowExecutor.d.ts.map +1 -1
- package/lib/cjs/ECSqlRowExecutor.js +77 -15
- package/lib/cjs/ECSqlRowExecutor.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +20 -8
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +83 -54
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IpcHost.d.ts +26 -0
- package/lib/cjs/IpcHost.d.ts.map +1 -1
- package/lib/cjs/IpcHost.js +68 -61
- package/lib/cjs/IpcHost.js.map +1 -1
- package/lib/cjs/Relationship.d.ts.map +1 -1
- package/lib/cjs/Relationship.js +13 -7
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/SQLiteDb.d.ts +43 -0
- package/lib/cjs/SQLiteDb.d.ts.map +1 -1
- package/lib/cjs/SQLiteDb.js +51 -0
- package/lib/cjs/SQLiteDb.js.map +1 -1
- package/lib/cjs/ViewStore.js +1 -1
- package/lib/cjs/ViewStore.js.map +1 -1
- package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts +23 -0
- package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
- package/lib/cjs/internal/ECSqlInstanceReshaper.js +125 -0
- package/lib/cjs/internal/ECSqlInstanceReshaper.js.map +1 -0
- package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
- package/lib/cjs/internal/annotations/fields.js +9 -4
- package/lib/cjs/internal/annotations/fields.js.map +1 -1
- package/lib/esm/ClassRegistry.d.ts.map +1 -1
- package/lib/esm/ClassRegistry.js +1 -2
- package/lib/esm/ClassRegistry.js.map +1 -1
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +9 -4
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/ECSqlRowExecutor.d.ts +23 -10
- package/lib/esm/ECSqlRowExecutor.d.ts.map +1 -1
- package/lib/esm/ECSqlRowExecutor.js +77 -16
- package/lib/esm/ECSqlRowExecutor.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +20 -8
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +85 -56
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/IpcHost.d.ts +26 -0
- package/lib/esm/IpcHost.d.ts.map +1 -1
- package/lib/esm/IpcHost.js +70 -63
- package/lib/esm/IpcHost.js.map +1 -1
- package/lib/esm/Relationship.d.ts.map +1 -1
- package/lib/esm/Relationship.js +13 -7
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/SQLiteDb.d.ts +43 -0
- package/lib/esm/SQLiteDb.d.ts.map +1 -1
- package/lib/esm/SQLiteDb.js +51 -0
- package/lib/esm/SQLiteDb.js.map +1 -1
- package/lib/esm/ViewStore.js +1 -1
- package/lib/esm/ViewStore.js.map +1 -1
- package/lib/esm/internal/ECSqlInstanceReshaper.d.ts +23 -0
- package/lib/esm/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
- package/lib/esm/internal/ECSqlInstanceReshaper.js +120 -0
- package/lib/esm/internal/ECSqlInstanceReshaper.js.map +1 -0
- package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
- package/lib/esm/internal/annotations/fields.js +9 -4
- package/lib/esm/internal/annotations/fields.js.map +1 -1
- package/lib/esm/test/IpcHost.test.js +232 -1
- package/lib/esm/test/IpcHost.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +139 -1
- package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
- package/lib/esm/test/imodel/IModel.test.js +20 -0
- package/lib/esm/test/imodel/IModel.test.js.map +1 -1
- package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts +2 -0
- package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts.map +1 -0
- package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js +289 -0
- package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js.map +1 -0
- package/lib/esm/test/schema/ClassRegistry.test.js +2 -2
- package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
- package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js +546 -0
- package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewLifecycle.test.js +2 -2
- package/lib/esm/test/schema/SchemaViewLifecycle.test.js.map +1 -1
- package/lib/esm/test/standalone/MergeConflict.test.js +1 -1
- package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
- package/lib/esm/test/standalone/SQLiteDb.test.d.ts +1 -1
- package/lib/esm/test/standalone/SQLiteDb.test.d.ts.map +1 -1
- package/lib/esm/test/standalone/SQLiteDb.test.js +93 -1
- package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
- package/lib/esm/test/standalone/ViewStoreDb.test.js +30 -0
- package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
- package/package.json +13 -13
|
@@ -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":"AAAA;;;+FAG+F;AAC/F,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,IAAI,EAAc,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AACjH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,yDAAyD;AAEzD,sGAAsG;AACtG,yGAAyG;AACzG,4GAA4G;AAC5G,kGAAkG;AAClG,wFAAwF;AACxF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,UAAU,GAAG,cAAc,CAAC;IAClC,MAAM,WAAW,GAAG,KAAK,CAAC;IAC1B,MAAM,UAAU,GAAG,uBAAuB,CAAC;IAE3C,IAAI,MAAkB,CAAC;IACvB,IAAI,UAAsB,CAAC;IAC3B,IAAI,UAAsB,CAAC;IAC3B,IAAI,QAAoB,CAAC;IACzB,IAAI,cAA0B,CAAC;IAE/B,MAAM,CAAC,KAAK,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG;8BACW,UAAU,YAAY,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+B7C,CAAC;QAEf,MAAM,YAAY,GAAG,eAAe,CAAC,iBAAiB,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;QAChG,MAAM,UAAU,GAAG,eAAe,CAAC,iBAAiB,CAAC,UAAU,EAAE,GAAG,UAAU,eAAe,CAAC,CAAC;QAC/F,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAE7C,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE,EAAE,CAAC,CAAC;QACtG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAEzC,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC;gBAC7B,aAAa,EAAE,GAAG,UAAU,kBAAkB;gBAC9C,KAAK,EAAE,MAAM,CAAC,YAAY;gBAC1B,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE;aACzB,CAAC,CAAC;YACH,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC;gBAC7B,aAAa,EAAE,GAAG,UAAU,kBAAkB;gBAC9C,KAAK,EAAE,MAAM,CAAC,YAAY;gBAC1B,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE;aACzB,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;YAE5C,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC;gBAC1B,aAAa,EAAE,GAAG,UAAU,iBAAiB;gBAC7C,OAAO,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE;gBAC3B,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;gBACvB,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;gBACzB,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;gBACxD,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;gBACpB,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;gBAC5D,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;aACpG,CAAC,CAAC;YACV,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YAE1C,cAAc,GAAG,GAAG,CAAC,kBAAkB,CAAC;gBACtC,aAAa,EAAE,GAAG,UAAU,2BAA2B;gBACvD,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,UAAU;gBACpB,KAAK,EAAE,WAAW;aACZ,CAAC,CAAC;YACV,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAE9C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,eAAe,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,oBAAoB,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qIAAqI,EAAE,GAAG,EAAE;QAC7I,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,iBAAiB,WAAW,8CAA8C,EAAE,CAAC,MAAM,EAAE,EAAE;YACxH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAE1D,gFAAgF;QAChF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QAEjE,yDAAyD;QACzD,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,iCAAiC,EAAE,CAAC,CAAC;QAExG,wDAAwD;QACxD,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAEnD,4DAA4D;QAC5D,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAErD,0GAA0G;QAC1G,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAEpF,yFAAyF;QACzF,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEhD,4FAA4F;QAC5F,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAExF,2EAA2E;QAC3E,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE;YACjC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7C,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;SACjD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0GAA0G,EAAE,GAAG,EAAE;QAClH,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,2BAA2B,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,iBAAiB,WAAW,8DAA8D,EAAE,CAAC,MAAM,EAAE,EAAE;YACxI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAEpH,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAE1D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,UAAU,2BAA2B,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,UAAU,kBAAkB,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,UAAU,kBAAkB,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;QAEvF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAE1D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iGAAiG,EAAE,GAAG,EAAE;QACzG,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,KAAK,CAAE,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,KAAK,CAAE,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,IAAI,CAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEtB,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,SAAS,CACd,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EACnF,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,UAAU,CAAE,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAChH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;QAC3F,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,CAAE,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;QAE1C,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,uBAAuB,WAAW,8CAA8C,EAAE,CAAC,MAAM,EAAE,EAAE;YAC9H,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,iCAAiC,EAAE,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0IAA0I,EAAE,GAAG,EAAE;QAClJ,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,CAAE,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,MAAM,mBAAmB,GAAG,YAAY,CAAC;QACzC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAClH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8GAA8G,EAAE,GAAG,EAAE;QACtH,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,CAAE,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACxG,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uHAAuH,EAAE,GAAG,EAAE;QAC/H,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,mBAAmB,GAAG,YAAY,CAAC;QACzC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACjH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0HAA0H,EAAE,GAAG,EAAE;QAClI,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,CAAE,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3B,mGAAmG;QACnG,qGAAqG;QACrG,mGAAmG;QACnG,kGAAkG;QAClG,8FAA8F;QAC9F,MAAM,QAAQ,GAAG,oBAAoB,CACnC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAC/G,WAAW,EACX,MAAM,CACP,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE;YACzB,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7C,EAAE;YACF,EAAE;YACF,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;SAC9C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4GAA4G,EAAE,GAAG,EAAE;QACpH,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAE,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE1B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACrF,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oHAAoH,EAAE,GAAG,EAAE;QAC5H,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,IAAI,aAAqB,CAAC;QAC1B,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC;gBAC/B,aAAa,EAAE,GAAG,UAAU,iBAAiB;gBAC7C,OAAO,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE;gBAC3B,MAAM,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;aACzC,CAAC,CAAC;QACZ,CAAC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,iBAAiB,WAAW,wCAAwC,EAAE,CAAC,MAAM,EAAE,EAAE;YAClH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,aAAc,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wGAAwG,EAAE,GAAG,EAAE;QAChH,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,IAAI,aAAqB,CAAC;QAC1B,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC;gBAC/B,aAAa,EAAE,GAAG,UAAU,iBAAiB;gBAC7C,OAAO,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE;gBAC3B,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;aACxC,CAAC,CAAC;QACZ,CAAC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,iBAAiB,WAAW,wCAAwC,EAAE,CAAC,MAAM,EAAE,EAAE;YAClH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,aAAc,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2FAA2F,EAAE,GAAG,EAAE;QACnG,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,6BAA6B,WAAW,8CAA8C,EAAE,CAAC,MAAM,EAAE,EAAE;YACpI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","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([
|