@itwin/presentation-testing
Version:
Testing utilities for iTwin.js Presentation library
131 lines • 5.09 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Helpers
*/
import { join } from "path";
import { IModelHost } from "@itwin/core-backend";
import { Guid, Logger, LogLevel } from "@itwin/core-bentley";
import { IModelReadRpcInterface, RpcConfiguration, RpcDefaultConfiguration } from "@itwin/core-common";
import { IModelApp, NoRenderApp } from "@itwin/core-frontend";
import { HierarchyCacheMode, Presentation as PresentationBackend, PresentationBackendNativeLoggerCategory, } from "@itwin/presentation-backend";
import { PresentationRpcInterface } from "@itwin/presentation-common";
import { Presentation as PresentationFrontend } from "@itwin/presentation-frontend";
import { getTestOutputDir, setTestOutputDir } from "./FilenameUtils.js";
function initializeRpcInterfaces(interfaces) {
const config = class extends RpcDefaultConfiguration {
interfaces = () => interfaces;
};
for (const definition of interfaces) {
// eslint-disable-next-line @itwin/no-internal
RpcConfiguration.assign(definition, /* istanbul ignore next */ () => config);
}
const instance = RpcConfiguration.obtain(config);
try {
RpcConfiguration.initializeInterfaces(instance);
/* c8 ignore start */
}
catch {
// this may fail with "Error: RPC interface "xxx" is already initialized." because
// multiple different tests want to set up rpc interfaces
}
/* c8 ignore end */
}
let isInitialized = false;
// eslint-disable-next-line @typescript-eslint/no-deprecated
export { HierarchyCacheMode };
/**
* Initialize the framework for presentation testing. The function sets up backend,
* frontend and RPC communication between them.
*
* @see `terminate`
*
* @public
*/
export const initialize = async (props) => {
if (isInitialized) {
return;
}
if (!props) {
props = {};
}
Logger.initializeToConsole();
Logger.setLevelDefault(LogLevel.Warning);
Logger.setLevel("i18n", LogLevel.Error);
Logger.setLevel("SQLite", LogLevel.Error);
Logger.setLevel(PresentationBackendNativeLoggerCategory.ECObjects, LogLevel.Warning);
// set up rpc interfaces
initializeRpcInterfaces(props.rpcs ?? [IModelReadRpcInterface, PresentationRpcInterface]);
// init backend
// make sure backend gets assigned an id which puts its resources into a unique directory
props.backendProps = props.backendProps ?? {};
if (!props.backendProps.id) {
props.backendProps.id = `test-${Guid.createValue()}`;
}
await IModelHost.startup({
cacheDir: join(getTestOutputDir(), ".cache", `${process.pid}`),
...props.backendHostProps,
});
PresentationBackend.initialize(props.backendProps);
// init frontend
if (!props.frontendApp) {
props.frontendApp = NoRenderApp;
}
await props.frontendApp.startup(props.frontendAppOptions);
const defaultFrontendProps = {
presentation: {
activeLocale: IModelApp.localization.getLanguageList()[0],
},
};
await PresentationFrontend.initialize({ ...defaultFrontendProps, ...props.frontendProps });
setTestOutputDir(props.testOutputDir);
isInitialized = true;
};
/**
* Undoes the setup made by `initialize`.
* @param frontendApp IModelApp implementation
*
* @see `initialize`
*
* @public
*/
export const terminate = async (frontendApp = IModelApp) => {
if (!isInitialized) {
return;
}
// store directory that needs to be cleaned-up
let hierarchiesCacheDirectory;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const hierarchiesCacheConfig = PresentationBackend.initProps?.caching?.hierarchies;
// eslint-disable-next-line @typescript-eslint/no-deprecated
if (hierarchiesCacheConfig?.mode === HierarchyCacheMode.Disk) {
hierarchiesCacheDirectory = hierarchiesCacheConfig?.directory;
// eslint-disable-next-line @typescript-eslint/no-deprecated
}
else if (hierarchiesCacheConfig?.mode === HierarchyCacheMode.Hybrid) {
hierarchiesCacheDirectory = hierarchiesCacheConfig?.disk?.directory;
}
// terminate backend
PresentationBackend.terminate();
await IModelHost.shutdown();
if (hierarchiesCacheDirectory) {
const { sync: rimrafSync } = await import("rimraf");
rimrafSync(hierarchiesCacheDirectory);
}
// terminate frontend
PresentationFrontend.terminate();
await frontendApp.shutdown();
isInitialized = false;
};
/** @internal */
export function safeDispose(disposable) {
if ("dispose" in disposable) {
disposable.dispose();
}
else if (Symbol.dispose in disposable) {
disposable[Symbol.dispose]();
}
}
//# sourceMappingURL=Helpers.js.map