UNPKG

@itwin/core-backend

Version:
674 lines • 32.3 kB
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) { if (value !== null && value !== void 0) { if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); var dispose, inner; if (async) { if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); dispose = value[Symbol.asyncDispose]; } if (dispose === void 0) { if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); dispose = value[Symbol.dispose]; if (async) inner = dispose; } if (typeof dispose !== "function") throw new TypeError("Object not disposable."); if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; env.stack.push({ value: value, dispose: dispose, async: async }); } else if (async) { env.stack.push({ async: true }); } return value; }; var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) { return function (env) { function fail(e) { env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; env.hasError = true; } var r, s = 0; function next() { while (r = env.stack.pop()) { try { if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); if (r.dispose) { var result = r.dispose.call(r.value); if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); } else s |= 1; } catch (e) { fail(e); } } if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); if (env.hasError) throw env.error; } return next(); }; })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; import * as path from "path"; import * as sinon from "sinon"; import { DbResult, Id64, Logger, LogLevel } from "@itwin/core-bentley"; import { ECDb, ECDbOpenMode, IModelJsFs, SqliteValueType } from "../../core-backend"; import { KnownTestLocations } from "../KnownTestLocations"; import { ECDbTestHelper } from "./ECDbTestHelper"; import { QueryOptionsBuilder } from "@itwin/core-common"; import { EntityClass, SchemaContext, SchemaJsonLocater, SchemaKey } from "@itwin/ecschema-metadata"; describe("ECDb", () => { const outDir = KnownTestLocations.outputDir; it("should be able to create a new ECDb", () => { const env_1 = { stack: [], error: void 0, hasError: false }; try { const ecdb = __addDisposableResource(env_1, ECDbTestHelper.createECDb(outDir, "create.ecdb"), false); assert.isTrue(ecdb.isOpen); } catch (e_1) { env_1.error = e_1; env_1.hasError = true; } finally { __disposeResources(env_1); } }); it("should be able to close an ECDb", () => { const ecdb = ECDbTestHelper.createECDb(outDir, "close.ecdb"); assert.isTrue(ecdb.isOpen); ecdb.closeDb(); assert.isFalse(ecdb.isOpen); }); it("should be able to open an ECDb", () => { const env_2 = { stack: [], error: void 0, hasError: false }; try { const fileName = "open.ecdb"; const ecdbPath = path.join(outDir, fileName); { const env_3 = { stack: [], error: void 0, hasError: false }; try { const testECDb = __addDisposableResource(env_3, ECDbTestHelper.createECDb(outDir, fileName), false); assert.isTrue(testECDb.isOpen); } catch (e_2) { env_3.error = e_2; env_3.hasError = true; } finally { __disposeResources(env_3); } } const ecdb = __addDisposableResource(env_2, new ECDb(), false); ecdb.openDb(ecdbPath, ECDbOpenMode.ReadWrite); assert.isTrue(ecdb.isOpen); } catch (e_3) { env_2.error = e_3; env_2.hasError = true; } finally { __disposeResources(env_2); } }); it("Open ECDb with upgrade option", () => { const fileName = "open.ecdb"; const ecdbPath = path.join(outDir, fileName); { const env_4 = { stack: [], error: void 0, hasError: false }; try { const testECDb = __addDisposableResource(env_4, ECDbTestHelper.createECDb(outDir, fileName), false); assert.isTrue(testECDb.isOpen); } catch (e_4) { env_4.error = e_4; env_4.hasError = true; } finally { __disposeResources(env_4); } } { const env_5 = { stack: [], error: void 0, hasError: false }; try { const ecdb = __addDisposableResource(env_5, new ECDb(), false); assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly)); } catch (e_5) { env_5.error = e_5; env_5.hasError = true; } finally { __disposeResources(env_5); } } { const env_6 = { stack: [], error: void 0, hasError: false }; try { const ecdb = __addDisposableResource(env_6, new ECDb(), false); assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.ReadWrite)); } catch (e_6) { env_6.error = e_6; env_6.hasError = true; } finally { __disposeResources(env_6); } } { const env_7 = { stack: [], error: void 0, hasError: false }; try { const ecdb = __addDisposableResource(env_7, new ECDb(), false); assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.FileUpgrade)); } catch (e_7) { env_7.error = e_7; env_7.hasError = true; } finally { __disposeResources(env_7); } } }); it("attach/detach newer profile version", async () => { const env_8 = { stack: [], error: void 0, hasError: false }; try { const fileName1 = "source_file.ecdb"; const ecdbPath1 = path.join(outDir, fileName1); const testECDb = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, fileName1, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1"> <ECEntityClass typeName="Person" modifier="Sealed"> <ECProperty propertyName="Name" typeName="string"/> <ECProperty propertyName="Age" typeName="int"/> </ECEntityClass> </ECSchema>`), false); assert.isTrue(testECDb.isOpen); // eslint-disable-next-line @typescript-eslint/no-deprecated testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => { const res = stmt.stepForInsert(); assert.equal(res.status, DbResult.BE_SQLITE_DONE); assert.isDefined(res.id); assert.isTrue(Id64.isValidId64(res.id)); return res.id; }); // override profile version to 55.0.0 which is currently not supported testECDb.withSqliteStatement(` UPDATE be_Prop SET StrData = '{"major":55,"minor":0,"sub1":0,"sub2":0}' WHERE Namespace = 'ec_Db' AND Name = 'SchemaVersion'`, (stmt) => { stmt.step(); }); testECDb.saveChanges(); const runDbListPragmaUsingStatement = (ecdb) => { // eslint-disable-next-line @typescript-eslint/no-deprecated return ecdb.withPreparedStatement("PRAGMA db_list", (stmt) => { const result = []; while (stmt.step() === DbResult.BE_SQLITE_ROW) { result.push(stmt.getRow()); } return result; }); }; const runDbListPragmaCCQ = async (ecdb) => { const reader = ecdb.createQueryReader("PRAGMA db_list"); const result = []; while (await reader.step()) { result.push(reader.current.toRow()); } return result; }; const testECDb0 = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, "file2.ecdb"), false); // following call will not fail but unknow ECDb profile will cause it to be attach as SQLite. testECDb0.attachDb(ecdbPath1, "source"); // eslint-disable-next-line @typescript-eslint/no-deprecated expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded."); expect(runDbListPragmaUsingStatement(testECDb0)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file2.ecdb"), profile: "ECDb" }, { sno: 1, alias: "source", fileName: path.join(outDir, "source_file.ecdb"), profile: "SQLite" } ]); testECDb0.detachDb("source"); expect(runDbListPragmaUsingStatement(testECDb0)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file2.ecdb"), profile: "ECDb" }, ]); // eslint-disable-next-line @typescript-eslint/no-deprecated expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded."); const testECDb1 = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, "file4.ecdb"), false); testECDb1.attachDb(ecdbPath1, "source"); const reader1 = testECDb1.createQueryReader("SELECT Name, Age FROM source.test.Person"); let expectThrow = false; try { await reader1.step(); } catch (err) { if (err instanceof Error) { assert.equal(err.message, "ECClass 'source.test.Person' does not exist or could not be loaded."); expectThrow = true; } } assert.isTrue(expectThrow); expect(await runDbListPragmaCCQ(testECDb1)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file4.ecdb"), profile: "ECDb" }, { sno: 1, alias: "source", fileName: path.join(outDir, "source_file.ecdb"), profile: "SQLite" } ]); testECDb1.detachDb("source"); expect(await runDbListPragmaCCQ(testECDb1)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file4.ecdb"), profile: "ECDb" }, ]); } catch (e_8) { env_8.error = e_8; env_8.hasError = true; } finally { __disposeResources(env_8); } }); it("attach/detach file & db_list pragma", async () => { const env_9 = { stack: [], error: void 0, hasError: false }; try { const fileName1 = "source_file.ecdb"; const ecdbPath1 = path.join(outDir, fileName1); const testECDb = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, fileName1, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1"> <ECEntityClass typeName="Person" modifier="Sealed"> <ECProperty propertyName="Name" typeName="string"/> <ECProperty propertyName="Age" typeName="int"/> </ECEntityClass> </ECSchema>`), false); assert.isTrue(testECDb.isOpen); // eslint-disable-next-line @typescript-eslint/no-deprecated testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => { const res = stmt.stepForInsert(); assert.equal(res.status, DbResult.BE_SQLITE_DONE); assert.isDefined(res.id); assert.isTrue(Id64.isValidId64(res.id)); return res.id; }); testECDb.saveChanges(); const runDbListPragma = (ecdb) => { // eslint-disable-next-line @typescript-eslint/no-deprecated return ecdb.withPreparedStatement("PRAGMA db_list", (stmt) => { const result = []; while (stmt.step() === DbResult.BE_SQLITE_ROW) { result.push(stmt.getRow()); } return result; }); }; const testECDb0 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file2.ecdb"), false); testECDb0.attachDb(ecdbPath1, "source"); // eslint-disable-next-line @typescript-eslint/no-deprecated testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", (stmt) => { assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); const row = stmt.getRow(); assert.equal(row.name, "Mary"); assert.equal(row.age, 45); }); expect(runDbListPragma(testECDb0)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file2.ecdb"), profile: "ECDb" }, { sno: 1, alias: "source", fileName: path.join(outDir, "source_file.ecdb"), profile: "ECDb" } ]); testECDb0.detachDb("source"); expect(runDbListPragma(testECDb0)).deep.equals([ { sno: 0, alias: "main", fileName: path.join(outDir, "file2.ecdb"), profile: "ECDb" }, ]); // eslint-disable-next-line @typescript-eslint/no-deprecated expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded."); const testECDb1 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file3.ecdb"), false); testECDb1.attachDb(ecdbPath1, "source"); const reader1 = testECDb1.createQueryReader("SELECT Name, Age FROM source.test.Person", undefined, new QueryOptionsBuilder().setUsePrimaryConnection(true).getOptions()); assert.equal(await reader1.step(), true); assert.equal(reader1.current.name, "Mary"); assert.equal(reader1.current.age, 45); testECDb1.detachDb("source"); const testECDb2 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file4.ecdb"), false); testECDb2.attachDb(ecdbPath1, "source"); const reader2 = testECDb2.createQueryReader("SELECT Name, Age FROM source.test.Person"); assert.equal(await reader2.step(), true); assert.equal(reader2.current.name, "Mary"); assert.equal(reader2.current.age, 45); testECDb2.detachDb("source"); const reader3 = testECDb2.createQueryReader("SELECT Name, Age FROM source.test.Person"); let expectThrow = false; try { await reader3.step(); } catch (err) { if (err instanceof Error) { assert.equal(err.message, "ECClass 'source.test.Person' does not exist or could not be loaded."); expectThrow = true; } } assert.isTrue(expectThrow); } catch (e_9) { env_9.error = e_9; env_9.hasError = true; } finally { __disposeResources(env_9); } }); it("should be able to import a schema", () => { const env_10 = { stack: [], error: void 0, hasError: false }; try { const fileName = "schemaimport.ecdb"; const ecdbPath = path.join(outDir, fileName); let id; { const env_11 = { stack: [], error: void 0, hasError: false }; try { const testECDb = __addDisposableResource(env_11, ECDbTestHelper.createECDb(outDir, fileName, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1"> <ECEntityClass typeName="Person" modifier="Sealed"> <ECProperty propertyName="Name" typeName="string"/> <ECProperty propertyName="Age" typeName="int"/> </ECEntityClass> </ECSchema>`), false); assert.isTrue(testECDb.isOpen); id = testECDb.withCachedWriteStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => { const res = stmt.stepForInsert(); assert.equal(res.status, DbResult.BE_SQLITE_DONE); assert.isDefined(res.id); assert.isTrue(Id64.isValidId64(res.id)); return res.id; }); testECDb.saveChanges(); } catch (e_10) { env_11.error = e_10; env_11.hasError = true; } finally { __disposeResources(env_11); } } const ecdb = __addDisposableResource(env_10, new ECDb(), false); ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly); assert.isTrue(ecdb.isOpen); // eslint-disable-next-line @typescript-eslint/no-deprecated ecdb.withPreparedStatement("SELECT Name, Age FROM test.Person WHERE ECInstanceId=?", (stmt) => { stmt.bindId(1, id); assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); const row = stmt.getRow(); assert.equal(row.name, "Mary"); assert.equal(row.age, 45); }); } catch (e_11) { env_10.error = e_11; env_10.hasError = true; } finally { __disposeResources(env_10); } }); it("should be able to get schema props", () => { const env_12 = { stack: [], error: void 0, hasError: false }; try { const fileName = "schema-props.ecdb"; const ecdbPath = path.join(outDir, fileName); { const env_13 = { stack: [], error: void 0, hasError: false }; try { const testECDb = __addDisposableResource(env_13, ECDbTestHelper.createECDb(outDir, fileName), false); assert.isTrue(testECDb.isOpen); } catch (e_12) { env_13.error = e_12; env_13.hasError = true; } finally { __disposeResources(env_13); } } const ecdb = __addDisposableResource(env_12, new ECDb(), false); ecdb.openDb(ecdbPath); const schema = ecdb.getSchemaProps("ECDbMeta"); assert.equal(schema.name, "ECDbMeta"); } catch (e_13) { env_12.error = e_13; env_12.hasError = true; } finally { __disposeResources(env_12); } }); it("Run plain SQL", () => { const env_14 = { stack: [], error: void 0, hasError: false }; try { const fileName = "plainseql.ecdb"; const ecdbPath = path.join(outDir, fileName); { const env_15 = { stack: [], error: void 0, hasError: false }; try { const testECDb = __addDisposableResource(env_15, ECDbTestHelper.createECDb(outDir, fileName), false); assert.isTrue(testECDb.isOpen); testECDb.withPreparedSqliteStatement("CREATE TABLE Test(Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Code INTEGER)", (stmt) => { assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => { stmt.bindValue(1, "Dummy 1"); stmt.bindValue(2, 100); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => { stmt.bindValues(["Dummy 2", 200]); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => { stmt.bindValue(":p1", "Dummy 3"); stmt.bindValue(":p2", 300); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => { stmt.bindValues({ ":p1": "Dummy 4", ":p2": 400 }); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); testECDb.saveChanges(); } catch (e_14) { env_15.error = e_14; env_15.hasError = true; } finally { __disposeResources(env_15); } } const ecdb = __addDisposableResource(env_14, new ECDb(), false); ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly); assert.isTrue(ecdb.isOpen); ecdb.withPreparedSqliteStatement("SELECT Id,Name,Code FROM Test ORDER BY Id", (stmt) => { for (let i = 1; i <= 4; i++) { assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); assert.equal(stmt.getColumnCount(), 3); const val0 = stmt.getValue(0); assert.equal(val0.columnName, "Id"); assert.equal(val0.type, SqliteValueType.Integer); assert.isFalse(val0.isNull); assert.equal(val0.getInteger(), i); const val1 = stmt.getValue(1); assert.equal(val1.columnName, "Name"); assert.equal(val1.type, SqliteValueType.String); assert.isFalse(val1.isNull); assert.equal(val1.getString(), `Dummy ${i}`); const val2 = stmt.getValue(2); assert.equal(val2.columnName, "Code"); assert.equal(val2.type, SqliteValueType.Integer); assert.isFalse(val2.isNull); assert.equal(val2.getInteger(), i * 100); const row = stmt.getRow(); assert.equal(row.id, i); assert.equal(row.name, `Dummy ${i}`); assert.equal(row.code, i * 100); } assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); } catch (e_15) { env_14.error = e_15; env_14.hasError = true; } finally { __disposeResources(env_14); } }); it("test unit labels in composite formats", () => { const ecdb = ECDbTestHelper.createECDb(outDir, "TestCompositeFormats.ecdb"); const xmlpathOriginal = path.join(outDir, "compositeFormats1.ecschema.xml"); IModelJsFs.writeFileSync(xmlpathOriginal, `<?xml version="1.0" encoding="utf-8" ?> <ECSchema schemaName="TestCompositeFormats" alias="tcf" version="1.0.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2"> <ECSchemaReference name="Units" version="01.00.00" alias="u" /> <Unit typeName="TestUnit" displayLabel="Test Unit" definition="u:M" numerator="1.0" phenomenon="u:LENGTH" unitSystem="u:METRIC" /> <Format typeName="TestFormat" displayLabel="TestFormat" roundFactor="0.3" type="Fractional" showSignOption="OnlyNegative" formatTraits="TrailZeroes|KeepSingleZero" precision="4" decimalSeparator="." thousandSeparator="," uomSeparator=" "> <Composite> <Unit>u:KM</Unit> <Unit label="m">TestUnit</Unit> <Unit label="">u:CM</Unit> <Unit label="mm">u:MM</Unit> </Composite> </Format> <KindOfQuantity typeName="TestKOQ2" description="Test KOQ2" displayLabel="TestKOQ2" persistenceUnit="u:M" presentationUnits="TestFormat" relativeError="10e-3" /> </ECSchema>`); ecdb.importSchema(xmlpathOriginal); ecdb.saveChanges(); const expectedLabels = [undefined, "m", "", "mm"]; let index = 0; // eslint-disable-next-line @typescript-eslint/no-deprecated ecdb.withStatement("select label from meta.FormatCompositeUnitDef where Format.Id=0x1", (stmt) => { for (let i = 1; i <= 4; i++) { assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); expect(stmt.getRow().label).to.eql(expectedLabels[index++]); } }); const xmlpathUpdated = path.join(outDir, "compositeFormats2.ecschema.xml"); IModelJsFs.writeFileSync(xmlpathUpdated, `<?xml version="1.0" encoding="utf-8" ?> <ECSchema schemaName="TestCompositeFormats" alias="tcf" version="1.0.1" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2"> <ECSchemaReference name="Units" version="01.00.00" alias="u" /> <Unit typeName="TestUnit" displayLabel="Test Unit" definition="u:M" numerator="1.0" phenomenon="u:LENGTH" unitSystem="u:METRIC" /> <Format typeName="TestFormat" displayLabel="TestFormat" roundFactor="0.3" type="Fractional" showSignOption="OnlyNegative" formatTraits="TrailZeroes|KeepSingleZero" precision="4" decimalSeparator="." thousandSeparator="," uomSeparator=" "> <Composite spacer="=" includeZero="False"> <Unit label="">u:KM</Unit> <Unit label="m">TestUnit</Unit> <Unit>u:CM</Unit> <Unit label="mm">u:MM</Unit> </Composite> </Format> <KindOfQuantity typeName="TestKOQ2" description="Test KOQ2" displayLabel="TestKOQ2" persistenceUnit="u:M" presentationUnits="TestFormat" relativeError="10e-3" /> </ECSchema>`); ecdb.importSchema(xmlpathUpdated); ecdb.saveChanges(); const expectedLabelsUpdated = ["", "m", undefined, "mm"]; index = 0; // eslint-disable-next-line @typescript-eslint/no-deprecated ecdb.withStatement("select label from meta.FormatCompositeUnitDef where Format.Id=0x1", (stmt) => { for (let i = 1; i <= 4; i++) { assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); expect(stmt.getRow().label).to.eql(expectedLabelsUpdated[index++]); } }); ecdb.closeDb(); }); it("should log warning but continue if new schema changes are observed without version bump", async () => { const ecdb = ECDbTestHelper.createECDb(outDir, "importSchemaNoVersionBump.ecdb"); const xmlpathOriginal = path.join(outDir, "importSchemaNoVersionBump1.ecschema.xml"); IModelJsFs.writeFileSync(xmlpathOriginal, `<?xml version="1.0" encoding="UTF-8"?> <ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2"> <ECEntityClass typeName="Person" modifier="Sealed"> <ECProperty propertyName="Name" typeName="string"/> <ECProperty propertyName="Age" typeName="int"/> </ECEntityClass> </ECSchema>`); ecdb.importSchema(xmlpathOriginal); ecdb.saveChanges(); const xmlpathUpdated = path.join(outDir, "importSchemaNoVersionBump2.ecschema.xml"); IModelJsFs.writeFileSync(xmlpathUpdated, `<?xml version="1.0" encoding="UTF-8"?> <ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2"> <ECEntityClass typeName="Person" modifier="Sealed"> <ECProperty propertyName="Name" typeName="string"/> <ECProperty propertyName="Age" typeName="int"/> <ECProperty propertyName="Height" typeName="int"/> </ECEntityClass> </ECSchema>`); let calledCategory = ""; let calledMessage = ""; const stubbedLogWarning = sinon.stub(Logger, "logWarning").callsFake((category, message) => { calledCategory = category; calledMessage = message; }); const prevLevel = Logger.getLevel("ECDb"); try { Logger.setLevel("ECDb", LogLevel.Warning); // We do not want this behavior (just logs a warning and proceeds), initially we intended to throw an error // We will wait for the next major change to make this a hard error expect(ecdb.importSchema(xmlpathUpdated)).to.not.throw; expect(calledCategory).to.equal("ECDb"); expect(calledMessage).to.equal("Schema 'Test' has changes but its version was not incremented. Proceeding with import, but this may lead to unexpected behavior."); stubbedLogWarning.restore(); } finally { if (prevLevel !== undefined) Logger.setLevel("ECDb", prevLevel); else delete Logger._categoryFilter.ECDb; } const context = new SchemaContext(); const locater = new SchemaJsonLocater((name) => ecdb.getSchemaProps(name)); context.addLocater(locater); const schema = await context.getSchema(new SchemaKey("Test", 1, 0, 0)); assert.isDefined(schema); const personClass = await schema.getItem("Person", EntityClass); assert.isDefined(personClass); const heightProp = personClass.getProperty("Height"); assert.isDefined(heightProp); ecdb.closeDb(); }); }); //# sourceMappingURL=ECDb.test.js.map