Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/ui/components/TooltipWrapper/tooltipWrapper.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ jest.mock("clipboard-copy", () => {
});
(copyToClipboard as jest.Mock).mockImplementation(() => Promise.resolve());

jest.mock("../../widgets/tooltip", () => {
return {
resolveTooltip: jest.fn((props: any) => props.resolvedTooltip)
};
});

let wrapper: ReactWrapper;
let wrappedElement: ReactWrapper;

Expand All @@ -25,7 +19,7 @@ beforeEach((): void => {
<TooltipWrapper
pvName="pv"
// eslint-disable-next-line no-template-curly-in-string
resolvedTooltip="${pvName}"
tooltip="${pvName}"
connected={true}
value={vstring("hello")}
>
Expand All @@ -48,7 +42,7 @@ describe("TooltipWrapper", (): void => {
});

test("it renders text", (): void => {
expect(wrappedElement.childAt(0).text()).toEqual("Testing Tooltip Wrapper");
expect(wrappedElement.text()).toEqual("Testing Tooltip Wrapper");
});

// How do we test the popover content? It renders on the
Expand Down
6 changes: 3 additions & 3 deletions src/ui/components/TooltipWrapper/tooltipWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const TooltipWrapper = (props: {
value?: VType;
children: ReactNode;
style?: object;
resolvedTooltip?: string;
tooltip?: string;
}): JSX.Element => {
const [popoverOpen, setPopoverOpen] = useState(false);
const { pvName, style = {} } = props;
Expand Down Expand Up @@ -48,12 +48,12 @@ export const TooltipWrapper = (props: {

/* The following elements were separated from the popover element
for clarity and performance

In particular, the popover position was found to be causing inefficient
renders when it was previously in a list of preferred positions, i.e ["top"]
rather than "top". As we only have one preferred position, this works
fine for us. If you change it, be sure to measure the performance impact.

The other functions and objects were separated as good practice to
prevent React seeing them as new functions/objects on renders which
can often be an issue with anonymous functions/object
Expand Down
7 changes: 4 additions & 3 deletions src/ui/hooks/useRules.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from "react";
import { useSelector } from "react-redux";
import { Rule, useRules, RuleProps } from "./useRules";
import { Rule, useRules } from "./useRules";
import { shallow } from "enzyme";
import { vdouble } from "../../types/vtypes/vtypes";
import { AnyProps } from "../widgets/widgetProps";

// Mock useSubscription.
jest.mock("./useSubscription", (): object => {
Expand All @@ -23,8 +24,8 @@ jest.mock("react-redux", (): object => {
PV1: [{ value: vdouble(2), connected: true, readonly: false }, "PV1"]
};
});
const RuleTester = (props: RuleProps): JSX.Element => {
const ruleProps = useRules(props);
const RuleTester = (props: { id: string; rules: Rule[] }): JSX.Element => {
const ruleProps = useRules(props as AnyProps);
return <div>{ruleProps.text}</div>;
};

Expand Down
15 changes: 5 additions & 10 deletions src/ui/hooks/useRules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import log from "loglevel";

import { useSubscription } from "./useSubscription";
Expand All @@ -7,6 +6,7 @@ import { MacroMap, CsState } from "../../redux/csState";

import { evaluate } from "mathjs";
import { PvArrayResults, pvStateSelector, pvStateComparator } from "./utils";
import { AnyProps } from "../widgets/widgetProps";

export interface Rule {
condition: string;
Expand All @@ -16,13 +16,8 @@ export interface Rule {
prop: string;
}

export interface RuleProps extends React.PropsWithChildren<any> {
id: string;
rules?: Rule[];
}

export function useRules(props: RuleProps): RuleProps {
const newProps: RuleProps = { ...props };
export function useRules(props: AnyProps): AnyProps {
const newProps: AnyProps = { ...props };
const rules = props.rules === undefined ? [] : props.rules;
let pvs: string[] = [];
for (const rule of rules) {
Expand All @@ -49,8 +44,8 @@ export function useRules(props: RuleProps): RuleProps {
condition = condition.replace(name, pvState.value.getValue());
try {
const state = evaluate(condition);
const styleValue = state ? trueState : falseState;
newProps[prop] = styleValue;
const updatedValue = state ? trueState : falseState;
newProps[prop] = updatedValue;
} catch (error) {
log.warn(`Failed to evaluate rule ${condition}: ${error}`);
}
Expand Down
5 changes: 3 additions & 2 deletions src/ui/widgets/ActionButton/actionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useContext } from "react";
import { WidgetActions, executeActions } from "../widgetActions";
import { PVComponent, PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVComponent, PVWidgetPropType } from "../widgetProps";
import classes from "./actionButton.module.css";
import { useHistory } from "react-router-dom";
import { registerWidget } from "../register";
Expand Down Expand Up @@ -80,6 +81,6 @@ export const ActionButtonWidget = (

export const ActionButton = (
props: InferWidgetProps<typeof ActionButtonProps>
): JSX.Element => <PVWidget baseWidget={ActionButtonWidget} {...props} />;
): JSX.Element => <Widget baseWidget={ActionButtonWidget} {...props} />;

registerWidget(ActionButton, ActionButtonProps, "actionbutton");
3 changes: 2 additions & 1 deletion src/ui/widgets/Display/display.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { ChoicePropOpt, ChildrenPropOpt, InferWidgetProps } from "../propTypes";

Expand Down
3 changes: 2 additions & 1 deletion src/ui/widgets/DynamicPage/dynamicPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { useContext } from "react";
import log from "loglevel";
import { Route, RouteComponentProps } from "react-router-dom";

import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { ActionButton } from "../ActionButton/actionButton";
import { CLOSE_PAGE } from "../widgetActions";
import { registerWidget } from "../register";
Expand Down
2 changes: 1 addition & 1 deletion src/ui/widgets/EmbeddedDisplay/embeddedDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
widgetDescriptionToComponent
} from "../createComponent";
import { MacroMap } from "../../../redux/csState";
import { WidgetPropType } from "../widget";
import { WidgetPropType } from "../widgetProps";
import { bobToWidgets } from "./bobUtils";
import { opiToWidgets } from "./opiUtils";
import { registerWidget } from "../register";
Expand Down
3 changes: 2 additions & 1 deletion src/ui/widgets/FlexContainer/flexContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";

import classes from "./flexContainer.module.css";
import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { ChildrenPropOpt, ChoicePropOpt, InferWidgetProps } from "../propTypes";

Expand Down
3 changes: 2 additions & 1 deletion src/ui/widgets/GroupingContainer/groupingContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { StringProp, ChildrenPropOpt, InferWidgetProps } from "../propTypes";

Expand Down
3 changes: 2 additions & 1 deletion src/ui/widgets/Image/image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { CSSProperties, useContext } from "react";

import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import {
InferWidgetProps,
StringProp,
Expand Down
5 changes: 3 additions & 2 deletions src/ui/widgets/Input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import React, { useState } from "react";
import classes from "./input.module.css";
import { writePv } from "../../hooks/useSubscription";
import { vtypeToString, stringToVtype } from "../../../types/vtypes/utils";
import { PVInputComponent, PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVInputComponent, PVWidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { InferWidgetProps } from "../propTypes";

Expand Down Expand Up @@ -87,6 +88,6 @@ export const SmartInputComponent = (props: PVInputComponent): JSX.Element => {

export const Input = (
props: InferWidgetProps<typeof PVWidgetPropType>
): JSX.Element => <PVWidget baseWidget={SmartInputComponent} {...props} />;
): JSX.Element => <Widget baseWidget={SmartInputComponent} {...props} />;

registerWidget(Input, PVWidgetPropType, "input");
3 changes: 2 additions & 1 deletion src/ui/widgets/Label/label.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";

import classes from "./label.module.css";
import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { BoolPropOpt, StringOrNumProp, InferWidgetProps } from "../propTypes";

Expand Down
5 changes: 3 additions & 2 deletions src/ui/widgets/MenuButton/menuButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { writePv } from "../../hooks/useSubscription";

import { VType, VEnum } from "../../../types/vtypes/vtypes";
import { vtypeToString, stringToVtype } from "../../../types/vtypes/utils";
import { PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVWidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { InferWidgetProps } from "../propTypes";

Expand Down Expand Up @@ -100,6 +101,6 @@ export const SmartMenuButton = (props: {

export const MenuButton = (
props: InferWidgetProps<typeof PVWidgetPropType>
): JSX.Element => <PVWidget baseWidget={SmartMenuButton} {...props} />;
): JSX.Element => <Widget baseWidget={SmartMenuButton} {...props} />;

registerWidget(MenuButton, PVWidgetPropType, "menubutton");
5 changes: 3 additions & 2 deletions src/ui/widgets/ProgressBar/progressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React from "react";

import classes from "./progressBar.module.css";
import { vtypeOrUndefinedToNumber } from "../../../types/vtypes/utils";
import { PVComponent, PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVComponent, PVWidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import {
FloatPropOpt,
Expand Down Expand Up @@ -87,6 +88,6 @@ const ProgressBarWidgetProps = {

export const ProgressBar = (
props: InferWidgetProps<typeof ProgressBarWidgetProps>
): JSX.Element => <PVWidget baseWidget={ProgressBarComponent} {...props} />;
): JSX.Element => <Widget baseWidget={ProgressBarComponent} {...props} />;

registerWidget(ProgressBar, ProgressBarWidgetProps, "progressbar");
5 changes: 3 additions & 2 deletions src/ui/widgets/Readback/readback.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import { PVComponent, PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVComponent, PVWidgetPropType } from "../widgetProps";

import classes from "./readback.module.css";
import { alarmOf, AlarmSeverity } from "../../../types/vtypes/alarm";
Expand Down Expand Up @@ -77,6 +78,6 @@ const ReadbackWidgetProps = {

export const Readback = (
props: InferWidgetProps<typeof ReadbackWidgetProps>
): JSX.Element => <PVWidget baseWidget={ReadbackComponent} {...props} />;
): JSX.Element => <Widget baseWidget={ReadbackComponent} {...props} />;

registerWidget(Readback, ReadbackWidgetProps, "readback");
3 changes: 2 additions & 1 deletion src/ui/widgets/Shape/shape.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { Component, Widget, WidgetPropType } from "../widget";
import { Widget } from "../widget";
import { Component, WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import { BoolPropOpt, StringPropOpt, InferWidgetProps } from "../propTypes";

Expand Down
5 changes: 3 additions & 2 deletions src/ui/widgets/SlideControl/slideControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
ProgressBarProps
} from "../ProgressBar/progressBar";
import { writePv } from "../../hooks/useSubscription";
import { PVInputComponent, PVWidget, PVWidgetPropType } from "../widget";
import { Widget } from "../widget";
import { PVInputComponent, PVWidgetPropType } from "../widgetProps";
import { InferWidgetProps } from "../propTypes";
import { registerWidget } from "../register";

Expand Down Expand Up @@ -104,6 +105,6 @@ const SlideControlWidgetProps = {

export const SlideControl = (
props: InferWidgetProps<typeof SlideControlWidgetProps>
): JSX.Element => <PVWidget baseWidget={SlideControlComponent} {...props} />;
): JSX.Element => <Widget baseWidget={SlideControlComponent} {...props} />;

registerWidget(SlideControl, SlideControlWidgetProps, "slidecontrol");
37 changes: 20 additions & 17 deletions src/ui/widgets/widget.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from "react";
import { mount } from "enzyme";

import { Widget, PVWidget } from "./widget";
import { Widget, ConnectingComponent } from "./widget";
import { LabelComponent } from "./Label/label";
import { MacroProps } from "../hooks/useMacros";
import { vdouble } from "../../types/vtypes/vtypes";
import { useConnection } from "../hooks/useConnection";
import { RuleProps } from "../hooks/useRules";
import { TooltipWrapper } from "../components/TooltipWrapper/tooltipWrapper";
import { AnyProps } from "./widgetProps";

// Mock the useMacros hook as otherwise we'd have to provide
// a store for it to use.
Expand All @@ -19,7 +19,7 @@ jest.mock("../hooks/useMacros", (): object => {
// Mock useRules.
jest.mock("../hooks/useRules", (): object => {
return {
useRules: (props: RuleProps): RuleProps => props
useRules: (props: AnyProps): AnyProps => props
};
});
// Slightly elaborate mocking of useConnection.
Expand Down Expand Up @@ -52,31 +52,34 @@ describe("<Widget />", (): void => {
test("it has one child all the way down", (): void => {
// Widget
expect(component.children()).toHaveLength(1);
// TooltipWrapper
// ConnectingComponent
const c1 = component.childAt(0);
expect(c1.type()).toEqual(TooltipWrapper);
expect(c1.type()).toEqual(ConnectingComponent);
expect(c1.children()).toHaveLength(1);
// div child of TooltipWrapper
// TooltipWrapper
const c2 = c1.childAt(0);
expect(c2.children()).toHaveLength(1);
expect(c2.type()).toEqual("div");
// TestLabel
expect(c2.type()).toEqual(TooltipWrapper);
// div child of TooltipWrapper
const c3 = c2.childAt(0);
expect(c3.type()).toEqual(TestLabel);
expect(c3.type()).toEqual("div");
expect(c3.children()).toHaveLength(1);
// LabelComponent
// TestLabel
const c4 = c3.childAt(0);
expect(c4.type()).toEqual(LabelComponent);
// Finally the Label div
expect(c4.type()).toEqual(TestLabel);
// LabelComponent
const c5 = c4.childAt(0);
expect(c5.type()).toEqual("div");
expect(c5.type()).toEqual(LabelComponent);
// Finally the Label div
const c6 = c5.childAt(0);
expect(c6.type()).toEqual("div");
// No further children
expect(c5.text()).toEqual("Test");
expect(c6.text()).toEqual("Test");
});

test("it has TooltipWrapper", (): void => {
const component = mount(
<PVWidget
<Widget
pvName="pv"
baseWidget={TestLabel}
containerStyling={{ position: "relative" }}
Expand All @@ -92,7 +95,7 @@ describe("<Widget />", (): void => {

test("it has alarmborder", (): void => {
const component = mount(
<PVWidget
<Widget
pvName="pv"
baseWidget={TestLabel}
containerStyling={{ position: "relative" }}
Expand All @@ -109,7 +112,7 @@ describe("<Widget />", (): void => {

test("it has alarmborder and TooltipWrapper", (): void => {
const component = mount(
<PVWidget
<Widget
pvName="pv"
baseWidget={TestLabel}
containerStyling={{ position: "relative" }}
Expand Down
Loading