Skip to content

Commit

Permalink
[components + fullstack tests]: warning fixes (#799)
Browse files Browse the repository at this point in the history
* initial test fixes

* style fixes

* docs update

* adjustments
  • Loading branch information
MartynasStrazdas authored Dec 17, 2024
1 parent 4fcda0f commit dc3d68b
Show file tree
Hide file tree
Showing 23 changed files with 134 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@
},
"terminal.integrated.env.windows": {
"NODE_ENV": "development"
}
},
"terminal.integrated.scrollback": 5000,
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ describe("Learning snippets", () => {
});

it("handles errors", async function () {
// stub console log to avoid ErrorBoundary warning in console
const consoleStub = sinon.stub(console, "error").callsFake(() => {});
if (Number.parseInt(PresentationRpcInterface.interfaceVersion.split(".")[0], 10) < 4) {
// property grid started supporting error boundaries since [email protected]
this.skip();
Expand Down Expand Up @@ -87,6 +89,7 @@ describe("Learning snippets", () => {
// re-render the component, ensure we now get an error
rerender(<MyPropertyGrid imodel={imodel} elementKey={{ ...elementKey }} />);
await ensureHasError(container, "Network error");
consoleStub.restore();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ describe("Presentation filter builder value renderer", () => {
},
];

const { baseElement, getByRole, user } = render(
const { baseElement, findByRole, user } = render(
<PresentationFilterBuilderValueRenderer
property={testProperty}
onChange={() => {}}
Expand All @@ -146,7 +146,7 @@ describe("Presentation filter builder value renderer", () => {
);

// trigger loadTargets function
const combobox = await waitFor(() => getByRole("combobox"));
const combobox = await findByRole("combobox");
await user.click(combobox);
await waitFor(async () => {
expect(queryByText(baseElement, "Value1")).to.not.be.null;
Expand Down Expand Up @@ -249,7 +249,7 @@ describe("Presentation filter builder value renderer", () => {
},
];

const { baseElement, getByRole, user } = render(
const { baseElement, findByRole, user } = render(
<PresentationFilterBuilderValueRenderer
property={testProperty}
onChange={() => {}}
Expand All @@ -261,7 +261,7 @@ describe("Presentation filter builder value renderer", () => {
);

// trigger loadTargets function
const combobox = await waitFor(() => getByRole("combobox"));
const combobox = await findByRole("combobox");
await user.click(combobox);
await waitFor(async () => {
expect(queryByText(baseElement, "Value1")).to.not.be.null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ describe("Learning snippets", () => {
});

it("handles errors", async function () {
// stub console log to avoid ErrorBoundary warning in console
const consoleStub = sinon.stub(console, "error").callsFake(() => {});
// __PUBLISH_EXTRACT_START__ Presentation.Components.Table.ErrorHandling
/** Props for `MyTable` and `MyProtectedTable` components */
interface MyTableProps {
Expand Down Expand Up @@ -133,6 +135,7 @@ describe("Learning snippets", () => {
// re-render the component, ensure we now get an error
rerender(<MyTable imodel={imodel} keys={new KeySet([modelKey])} />);
await ensureHasError(container, "Network error");
consoleStub.restore();
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ describe("Learning snippets", () => {
});

it("handles errors", async function () {
// stub console log to avoid expected network error in console
const consoleStub = sinon.stub(console, "error").callsFake(() => {});
// __PUBLISH_EXTRACT_START__ Presentation.Components.Tree.ErrorHandling
function MyTree(props: { imodel: IModelConnection }) {
const state = usePresentationTreeState({
Expand Down Expand Up @@ -98,6 +100,7 @@ describe("Learning snippets", () => {
expect(() => getNodeByLabel(container, `My Model A`)).to.throw();
expect(() => getNodeByLabel(container, `My Model B`)).to.throw();
expect(getByText("Èrrór ¢rëätíñg thë hìérärçhý lévêl")).is.not.null;
consoleStub.restore();
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { expect } from "chai";
import { insertPhysicalElement, insertPhysicalModelWithPartition, insertSpatialCategory } from "presentation-test-utilities";
import { useState } from "react";
import sinon from "sinon";
import { SelectionMode, TreeRendererProps, UiComponents } from "@itwin/components-react";
import { IModelApp, IModelConnection } from "@itwin/core-frontend";
import { PresentationRpcInterface, Ruleset } from "@itwin/presentation-common";
Expand All @@ -31,6 +32,8 @@ describe("Learning snippets", () => {
});

it("limits hierarchy level size", async function () {
// stub console log to avoid hierarchy limit warning in console
const consoleStub = sinon.stub(console, "log").callsFake(() => {});
if (Number.parseInt(PresentationRpcInterface.interfaceVersion.split(".")[0], 10) < 4) {
// hierarchy level size limiting requires core libraries at least @4.0
this.skip();
Expand Down Expand Up @@ -98,6 +101,7 @@ describe("Learning snippets", () => {
expect(() => getNodeByLabel(container, `B element ${i + 1}`)).to.throw();
}
await waitFor(() => expect(getByText(`thèré ârë möré îtëms thâñ älløwèd límît õf ${hierarchyLevelSizeLimit}`, { exact: false })).is.not.null);
consoleStub.restore();
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ describe("TreeDataProvider", async () => {
});

it("creates error node when requesting root nodes with invalid paging", async () => {
// stub console log to avoid expected error in console
const consoleStub = sinon.stub(console, "error").callsFake(() => {});
provider.pagingSize = 5;
const nodes = await provider.getNodes(undefined, { start: 1, size: 5 });
if (nodes.length === 1) {
Expand All @@ -102,6 +104,7 @@ describe("TreeDataProvider", async () => {
// [email protected] returns an empty list in case of invalid page options
expect(nodes).to.be.empty;
}
consoleStub.restore();
});

it("returns child nodes count", async () => {
Expand All @@ -124,6 +127,8 @@ describe("TreeDataProvider", async () => {
});

it("returns error node when requesting child nodes with invalid paging", async () => {
// stub console log to avoid expected error in console
const consoleStub = sinon.stub(console, "error").callsFake(() => {});
const rootNodes = await provider.getNodes();
provider.pagingSize = 5;
const nodes = await provider.getNodes(rootNodes[0], { start: 1, size: 5 });
Expand All @@ -135,6 +140,7 @@ describe("TreeDataProvider", async () => {
// [email protected] returns an empty list in case of invalid page options
expect(nodes).to.be.empty;
}
consoleStub.restore();
});

it("requests backend only once to get first page", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe("Hierarchies React", () => {
type TreeProps = ComponentPropsWithoutRef<typeof Tree<RenderedTreeNode>>;
type TreeRendererProps = Props<typeof TreeRenderer>;

function MyTreeRenderer(props: TreeRendererProps) {
function MyTreeRenderer({ rootNodes }: TreeRendererProps) {
const nodeRenderer = useCallback<TreeProps["nodeRenderer"]>((nodeProps) => {
return <TreeNodeRenderer {...nodeProps} onFilterClick={() => {}} expandNode={() => {}} />;
}, []);
Expand All @@ -147,7 +147,7 @@ describe("Hierarchies React", () => {

return (
<LocalizationContextProvider localizedStrings={localizedStrings}>
<Tree<RenderedTreeNode> {...props} data={props.rootNodes} nodeRenderer={nodeRenderer} getNode={getNode} />
<Tree<RenderedTreeNode> data={rootNodes} nodeRenderer={nodeRenderer} getNode={getNode} enableVirtualization={true} />
</LocalizationContextProvider>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe("Hierarchies React", () => {

const { getByText } = render(<MyTreeComponentInternal imodelAccess={createIModelAccess(iModel)} />);

expect(getByText("No data to display")).to.not.be.null;
await waitFor(() => expect(getByText("No data to display")).to.not.be.null);
});
});
});
Expand Down
15 changes: 9 additions & 6 deletions apps/full-stack-tests/src/unified-selection/HiliteSet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import { expect } from "chai";
import * as fs from "fs";
import path from "path";
import {
getDefaultSubcategoryKey,
Expand All @@ -28,6 +27,7 @@ import { ECSchemaRpcImpl } from "@itwin/ecschema-rpcinterface-impl";
import { buildTestIModel, initialize, terminate } from "@itwin/presentation-testing";
import { createHiliteSetProvider, SelectableInstanceKey, Selectables } from "@itwin/unified-selection";
import { createIModelAccess } from "../hierarchies/Utils.js";
import { getSchemaFromPackage } from "./getSchema.js";

describe("HiliteSet", () => {
let iModel: IModelConnection;
Expand Down Expand Up @@ -201,6 +201,8 @@ describe("HiliteSet", () => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
iModel = await buildTestIModel(this, async (builder) => {
const modelKey = insertPhysicalModelWithPartition({ builder, codeValue: "test model" });
const schema = await getSchemaFromPackage("functional-schema", "Functional.ecschema.xml");
await builder.importSchema(schema);
const categoryKey = insertSpatialCategory({ builder, codeValue: "test category" });
assemblyKey = insertPhysicalElement({ builder, userLabel: "element 1", modelId: modelKey.id, categoryId: categoryKey.id });
const element2 = insertPhysicalElement({
Expand Down Expand Up @@ -236,6 +238,8 @@ describe("HiliteSet", () => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
iModel = await buildTestIModel(this, async (builder) => {
const modelKey = insertPhysicalModelWithPartition({ builder, codeValue: "test model" });
const schema = await getSchemaFromPackage("functional-schema", "Functional.ecschema.xml");
await builder.importSchema(schema);
const categoryKey = insertSpatialCategory({ builder, codeValue: "test category" });
elementKey = insertPhysicalElement({ builder, userLabel: "element", modelId: modelKey.id, categoryId: categoryKey.id });
});
Expand All @@ -252,6 +256,8 @@ describe("HiliteSet", () => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
iModel = await buildTestIModel(this, async (builder) => {
const modelKey = insertPhysicalModelWithPartition({ builder, codeValue: "test model" });
const schema = await getSchemaFromPackage("functional-schema", "Functional.ecschema.xml");
await builder.importSchema(schema);
const categoryKey = insertSpatialCategory({ builder, codeValue: "test category" });
elementKeys = [
insertPhysicalElement({ builder, userLabel: "element", modelId: modelKey.id, categoryId: categoryKey.id }),
Expand All @@ -271,11 +277,6 @@ describe("HiliteSet", () => {
});

describe("Functional element", () => {
async function getSchemaFromPackage(packageName: string, schemaFileName: string): Promise<string> {
const schemaFile = path.join(import.meta.dirname, "..", "..", "node_modules", "@bentley", packageName, schemaFileName);
return fs.readFileSync(schemaFile, "utf8");
}

it("hilites functional element related physical elements", async function () {
let functionalElement: SelectableInstanceKey;
let physicalElement: SelectableInstanceKey;
Expand Down Expand Up @@ -378,6 +379,8 @@ describe("HiliteSet", () => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
iModel = await buildTestIModel(this, async (builder) => {
const groupModel = insertGroupInformationModelWithPartition({ builder, codeValue: "group information model" });
const schema = await getSchemaFromPackage("functional-schema", "Functional.ecschema.xml");
await builder.importSchema(schema);
const physicalModelKey = insertPhysicalModelWithPartition({ builder, codeValue: "test physical model" });
const categoryKey = insertSpatialCategory({ builder, codeValue: "test category" });
groupInformationElement = insertGroupInformationElement({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import { expect } from "chai";
import * as fs from "fs";
import path from "path";
import {
insertDrawingCategory,
Expand All @@ -24,6 +23,7 @@ import { createECSqlQueryExecutor } from "@itwin/presentation-core-interop";
import { Props } from "@itwin/presentation-shared";
import { buildTestIModel, initialize, terminate } from "@itwin/presentation-testing";
import { computeSelection, SelectableInstanceKey } from "@itwin/unified-selection";
import { getSchemaFromPackage } from "./getSchema.js";

describe("SelectionScope", () => {
let iModel: IModelConnection;
Expand All @@ -43,11 +43,6 @@ describe("SelectionScope", () => {
await terminate();
});

async function getSchemaFromPackage(packageName: string, schemaFileName: string): Promise<string> {
const schemaFile = path.join(import.meta.dirname, "..", "..", "node_modules", "@bentley", packageName, schemaFileName);
return fs.readFileSync(schemaFile, "utf8");
}

async function getSelection(keys: string[], scope: Props<typeof computeSelection>["scope"]): Promise<SelectableInstanceKey[]> {
const selectables: SelectableInstanceKey[] = [];
for await (const selectable of computeSelection({ queryExecutor: createECSqlQueryExecutor(iModel), elementIds: keys, scope })) {
Expand Down
12 changes: 12 additions & 0 deletions apps/full-stack-tests/src/unified-selection/getSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/

import * as fs from "fs";
import path from "path";

export async function getSchemaFromPackage(packageName: string, schemaFileName: string): Promise<string> {
const schemaFile = path.join(import.meta.dirname, "..", "..", "node_modules", "@bentley", packageName, schemaFileName);
return fs.readFileSync(schemaFile, "utf8");
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface UniquePropertyValuesSelectorProps {
export function UniquePropertyValuesSelector(props: UniquePropertyValuesSelectorProps) {
const { imodel, descriptor, property, onChange, value, descriptorInputKeys, selectedClasses } = props;
const [field, setField] = useState<Field | undefined>(() => findField(descriptor, getInstanceFilterFieldName(property)));
const [searchInput, setSearchInput] = useState<string>();
const [searchInput, setSearchInput] = useState<string>("");
const selectedValues = useMemo(() => getUniqueValueFromProperty(value)?.map((val) => val.displayValue), [value]);
const ruleset = useUniquePropertyValuesRuleset(descriptor.ruleset, field, descriptorInputKeys, selectedClasses);
const { selectOptions, loadedOptions, isLoading } = useUniquePropertyValuesLoader({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useState } from "react";
import { ArrayValue, PropertyRecord, PropertyValueFormat } from "@itwin/appui-abstract";
import { NonPrimitivePropertyRenderer, PropertyValueRendererManager } from "@itwin/components-react";
import { Orientation } from "@itwin/core-react";
import { Anchor, Modal } from "@itwin/itwinui-react";
import { Anchor, Modal, ModalContent } from "@itwin/itwinui-react";

/**
* Props for [[TableCellRenderer]] component.
Expand Down Expand Up @@ -74,6 +74,7 @@ function NonPrimitiveCellRenderer(props: NonPrimitiveCellRendererProps) {
const { record, dialogLabel, buttonLabel, uniqueKey } = props;
const [isOpen, setIsOpen] = useState(false);

// modal window when opened causes findDOMNode warning https://github.com/iTwin/iTwinUI/issues/2199
return (
<>
<Anchor
Expand All @@ -84,9 +85,11 @@ function NonPrimitiveCellRenderer(props: NonPrimitiveCellRendererProps) {
{buttonLabel}
</Anchor>
<Modal isOpen={isOpen} title={dialogLabel} onClose={/* c8 ignore next */ () => setIsOpen(false)} className="presentation-components-non-primitive-value">
{/* Can't change our import to `components-react`, because it was added there in a version later than our peer dependency */}
{/* eslint-disable-next-line @typescript-eslint/no-deprecated */}
<NonPrimitivePropertyRenderer uniqueKey={uniqueKey} propertyRecord={record} orientation={Orientation.Horizontal} />
<ModalContent>
{/* Can't change our import to `components-react`, because it was added there in a version later than our peer dependency */}
{/* eslint-disable-next-line @typescript-eslint/no-deprecated */}
<NonPrimitivePropertyRenderer uniqueKey={uniqueKey} propertyRecord={record} orientation={Orientation.Horizontal} />
</ModalContent>
</Modal>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ describe("PresentationInstanceFilterDialog", () => {

it("throws error when filter is missing presentation metadata", async () => {
const fromComponentsPropertyFilterStub = sinon.stub(PresentationInstanceFilter, "fromComponentsPropertyFilter").throws(new Error("Some Error"));
// stub console log to avoid expected error in console
const consoleErrorStub = sinon.stub(console, "error").callsFake(() => {});
const spy = sinon.spy();
const { baseElement, user } = render(<PresentationInstanceFilterDialog imodel={imodel} propertiesSource={propertiesSource} onApply={spy} isOpen={true} />, {
addThemeProvider: true,
Expand All @@ -350,6 +352,7 @@ describe("PresentationInstanceFilterDialog", () => {

await waitFor(() => expect(queryByText(baseElement, "general.error")).to.not.be.null);
fromComponentsPropertyFilterStub.restore();
consoleErrorStub.restore();
});

it("renders custom title", async () => {
Expand Down Expand Up @@ -383,6 +386,8 @@ describe("PresentationInstanceFilterDialog", () => {
});

it("renders error boundary if error is thrown", async () => {
// stub console log to avoid expected error in console
const consoleErrorStub = sinon.stub(console, "error").callsFake(() => {});
const propertiesSourceGetter = () => {
throw new Error("Cannot load descriptor");
};
Expand All @@ -392,6 +397,7 @@ describe("PresentationInstanceFilterDialog", () => {
);

await waitFor(() => expect(queryByText(baseElement, "general.error")).to.not.be.null);
consoleErrorStub.restore();
});

it("renders with lazy-loaded descriptor", async () => {
Expand Down
Loading

0 comments on commit dc3d68b

Please sign in to comment.