bug fixes
parent
d868625ba3
commit
2f0bd67222
|
@ -67,7 +67,7 @@ const peripheralItems = (resources: ResourceIndex): DropDownItem[] => {
|
|||
value: "" + peripheral.body.pin,
|
||||
headingId: PinGroupName.Peripheral
|
||||
}));
|
||||
return list.length ? [PERIPHERAL_HEADING, ...list] : [];
|
||||
return list.length ? [PERIPHERAL_HEADING(), ...list] : [];
|
||||
};
|
||||
|
||||
interface OnChangeProps {
|
||||
|
|
|
@ -29,6 +29,7 @@ describe("<Logs />", () => {
|
|||
dispatch: jest.fn(),
|
||||
sourceFbosConfig: jest.fn(),
|
||||
getConfigValue: x => mockStorj[x],
|
||||
shouldDisplay: () => false,
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
|
|
@ -9,24 +9,31 @@ const logTypes = MESSAGE_TYPES;
|
|||
|
||||
describe("<LogsFilterMenu />", () => {
|
||||
const fakeState: LogsState = {
|
||||
autoscroll: true, assertion: 1, success: 1, busy: 1, warn: 1,
|
||||
error: 1, info: 1, fun: 1, debug: 1
|
||||
autoscroll: true, success: 1, busy: 1, warn: 1,
|
||||
error: 1, info: 1, fun: 1, debug: 1, assertion: 1,
|
||||
};
|
||||
|
||||
const fakeProps = (): LogsFilterMenuProps => {
|
||||
return {
|
||||
toggle: jest.fn(),
|
||||
setFilterLevel: jest.fn(),
|
||||
state: fakeState,
|
||||
};
|
||||
};
|
||||
const fakeProps = (): LogsFilterMenuProps => ({
|
||||
toggle: jest.fn(),
|
||||
setFilterLevel: jest.fn(),
|
||||
state: fakeState,
|
||||
shouldDisplay: () => false,
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<LogsFilterMenu {...fakeProps()} />);
|
||||
logTypes.filter(x => x !== "assertion").map(string =>
|
||||
expect(wrapper.text().toLowerCase()).toContain(string.toLowerCase()));
|
||||
expect(wrapper.text().toLowerCase()).not.toContain("autoscroll");
|
||||
});
|
||||
|
||||
it("renders new types", () => {
|
||||
const p = fakeProps();
|
||||
p.shouldDisplay = () => true;
|
||||
const wrapper = mount(<LogsFilterMenu {...p} />);
|
||||
logTypes.map(string =>
|
||||
expect(wrapper.text().toLowerCase())
|
||||
.toContain(string.toLowerCase()));
|
||||
expect(wrapper.text()).not.toContain("autscroll");
|
||||
expect(wrapper.text().toLowerCase()).toContain(string.toLowerCase()));
|
||||
expect(wrapper.text().toLowerCase()).not.toContain("autoscroll");
|
||||
});
|
||||
|
||||
it("filters logs", () => {
|
||||
|
@ -36,7 +43,7 @@ describe("<LogsFilterMenu />", () => {
|
|||
p.toggle = (x) => () => toggle(x);
|
||||
p.setFilterLevel = (x) => () => setFilterLevel(x);
|
||||
const wrapper = mount(<LogsFilterMenu {...p} />);
|
||||
wrapper.find("button").at(3).simulate("click");
|
||||
wrapper.find("button").at(2).simulate("click");
|
||||
expect(toggle).toHaveBeenCalledWith(MessageType.success);
|
||||
});
|
||||
|
||||
|
@ -46,7 +53,7 @@ describe("<LogsFilterMenu />", () => {
|
|||
const wrapper = mount(<LogsFilterMenu {...fakeProps()} />);
|
||||
const toggles = wrapper.find("button");
|
||||
expect(toggles.last().hasClass("green")).toBeTruthy();
|
||||
expect(toggles.at(3).hasClass("red")).toBeTruthy();
|
||||
expect(toggles.at(2).hasClass("red")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("bulk toggles filter levels", () => {
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
import * as React from "react";
|
||||
import { LogsFilterMenuProps } from "../interfaces";
|
||||
import { Slider } from "@blueprintjs/core";
|
||||
|
||||
import { Filters } from "../interfaces";
|
||||
import { startCase } from "lodash";
|
||||
import { MESSAGE_TYPES } from "../../sequences/interfaces";
|
||||
import { MESSAGE_TYPES, MessageType } from "../../sequences/interfaces";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import { Feature } from "../../devices/interfaces";
|
||||
|
||||
const MENU_ORDER: string[] = [
|
||||
MessageType.success,
|
||||
MessageType.busy,
|
||||
MessageType.warn,
|
||||
MessageType.error,
|
||||
MessageType.info,
|
||||
MessageType.fun,
|
||||
MessageType.debug,
|
||||
MessageType.assertion,
|
||||
];
|
||||
|
||||
const REVERSE_MENU_ORDER = MENU_ORDER.slice().reverse();
|
||||
|
||||
/** Order the log filter sort menu, adding unknown types last. */
|
||||
const menuSort = (a: string, b: string) =>
|
||||
REVERSE_MENU_ORDER.indexOf(b) - REVERSE_MENU_ORDER.indexOf(a);
|
||||
|
||||
export const LogsFilterMenu = (props: LogsFilterMenuProps) => {
|
||||
/** Filter level 0: logs hidden. */
|
||||
|
@ -27,8 +44,10 @@ export const LogsFilterMenu = (props: LogsFilterMenuProps) => {
|
|||
{t("normal")}
|
||||
</button>
|
||||
</fieldset>
|
||||
{Object.keys(props.state)
|
||||
.filter(x => { if (!(x == "autoscroll")) { return x; } })
|
||||
{Object.keys(props.state).sort(menuSort)
|
||||
.filter(x => x !== "autoscroll")
|
||||
.filter(x =>
|
||||
props.shouldDisplay(Feature.assertion_block) || x !== "assertion")
|
||||
.map((logType: keyof Filters) => {
|
||||
return <fieldset key={logType}>
|
||||
<label>
|
||||
|
|
|
@ -110,6 +110,7 @@ export class Logs extends React.Component<LogsProps, Partial<LogsState>> {
|
|||
</button>
|
||||
<LogsFilterMenu
|
||||
toggle={this.toggle} state={this.state}
|
||||
shouldDisplay={this.props.shouldDisplay}
|
||||
setFilterLevel={this.setFilterLevel} />
|
||||
</Popover>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { TaggedLog, ConfigurationName, ALLOWED_MESSAGE_TYPES } from "farmbot";
|
||||
import { SourceFbosConfig } from "../devices/interfaces";
|
||||
import { SourceFbosConfig, ShouldDisplay } from "../devices/interfaces";
|
||||
import { GetWebAppConfigValue } from "../config_storage/actions";
|
||||
import { TimeSettings } from "../interfaces";
|
||||
|
||||
|
@ -9,6 +9,7 @@ export interface LogsProps {
|
|||
dispatch: Function;
|
||||
sourceFbosConfig: SourceFbosConfig;
|
||||
getConfigValue: GetWebAppConfigValue;
|
||||
shouldDisplay: ShouldDisplay;
|
||||
}
|
||||
|
||||
export type Filters = Record<ALLOWED_MESSAGE_TYPES, number>;
|
||||
|
@ -30,6 +31,7 @@ export interface LogsFilterMenuProps {
|
|||
toggle: (property: keyof LogsState) => ToggleEventHandler;
|
||||
state: LogsState;
|
||||
setFilterLevel: SetNumSetting;
|
||||
shouldDisplay: ShouldDisplay;
|
||||
}
|
||||
|
||||
export interface LogSettingProps {
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
import { Everything } from "../interfaces";
|
||||
import {
|
||||
selectAllLogs, maybeGetTimeSettings
|
||||
selectAllLogs, maybeGetTimeSettings, maybeGetDevice
|
||||
} from "../resources/selectors";
|
||||
import { LogsProps } from "./interfaces";
|
||||
import {
|
||||
sourceFbosConfigValue
|
||||
} from "../devices/components/source_config_value";
|
||||
import { validFbosConfig } from "../util";
|
||||
import {
|
||||
validFbosConfig, determineInstalledOsVersion,
|
||||
shouldDisplay as shouldDisplayFunc
|
||||
} from "../util";
|
||||
import { ResourceIndex } from "../resources/interfaces";
|
||||
import { TaggedLog } from "farmbot";
|
||||
import { getWebAppConfigValue } from "../config_storage/actions";
|
||||
import { getFbosConfig } from "../resources/getters";
|
||||
import { chain } from "lodash";
|
||||
import { DevSettings } from "../account/dev/dev_support";
|
||||
|
||||
/** Take the specified number of logs after sorting by time created. */
|
||||
export function takeSortedLogs(
|
||||
|
@ -28,11 +32,17 @@ export function mapStateToProps(props: Everything): LogsProps {
|
|||
const fbosConfig = validFbosConfig(getFbosConfig(props.resources.index));
|
||||
const sourceFbosConfig =
|
||||
sourceFbosConfigValue(fbosConfig, hardware.configuration);
|
||||
const installedOsVersion = determineInstalledOsVersion(
|
||||
props.bot, maybeGetDevice(props.resources.index));
|
||||
const fbosVersionOverride = DevSettings.overriddenFbosVersion();
|
||||
const shouldDisplay = shouldDisplayFunc(
|
||||
installedOsVersion, props.bot.minOsFeatureData, fbosVersionOverride);
|
||||
return {
|
||||
dispatch: props.dispatch,
|
||||
sourceFbosConfig,
|
||||
logs: takeSortedLogs(250, props.resources.index),
|
||||
timeSettings: maybeGetTimeSettings(props.resources.index),
|
||||
getConfigValue: getWebAppConfigValue(() => props),
|
||||
shouldDisplay,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -94,7 +94,8 @@ export enum MessageType {
|
|||
error = "error",
|
||||
info = "info",
|
||||
fun = "fun",
|
||||
debug = "debug"
|
||||
debug = "debug",
|
||||
assertion = "assertion",
|
||||
}
|
||||
|
||||
export const MESSAGE_TYPES = Object.keys(MessageType);
|
||||
|
|
|
@ -59,7 +59,7 @@ describe("Pin and Peripheral support files", () => {
|
|||
it("has a list of unnamed pins", () => {
|
||||
expect(pinDropdowns(n => n).length)
|
||||
.toBe(PIN_RANGE.length + 1); // 54 pins plus the header.
|
||||
expect(pinDropdowns(n => n)[0]).toBe(PIN_HEADING);
|
||||
expect(pinDropdowns(n => n)[0]).toEqual(PIN_HEADING());
|
||||
// Grab all uniq heading IDs- we expect only 1.
|
||||
const values = chain(pinDropdowns(n => n))
|
||||
.tail()
|
||||
|
@ -75,7 +75,7 @@ describe("Pin and Peripheral support files", () => {
|
|||
const ri = buildResourceIndex([p]);
|
||||
const result = peripheralsAsDropDowns(ri.index);
|
||||
expect(result.length).toEqual(2); // Heading + 1 peripheral
|
||||
expect(result[0]).toBe(PERIPHERAL_HEADING);
|
||||
expect(result[0]).toEqual(PERIPHERAL_HEADING());
|
||||
expect(result[1]).toEqual({
|
||||
label: p.body.label,
|
||||
headingId: PinGroupName.Peripheral,
|
||||
|
@ -89,7 +89,7 @@ describe("Pin and Peripheral support files", () => {
|
|||
const ri = buildResourceIndex([s]);
|
||||
const result = sensorsAsDropDowns(ri.index);
|
||||
expect(result.length).toEqual(2); // Heading + 1 sensor
|
||||
expect(result[0]).toBe(SENSOR_HEADING);
|
||||
expect(result[0]).toEqual(SENSOR_HEADING());
|
||||
expect(result[1]).toEqual({
|
||||
label: s.body.label,
|
||||
headingId: PinGroupName.Sensor,
|
||||
|
@ -101,8 +101,8 @@ describe("Pin and Peripheral support files", () => {
|
|||
const ri = buildResourceIndex([]);
|
||||
const sResult = sensorsAsDropDowns(ri.index);
|
||||
const pResult = peripheralsAsDropDowns(ri.index);
|
||||
expect(sResult).not.toContain(SENSOR_HEADING);
|
||||
expect(pResult).not.toContain(PERIPHERAL_HEADING);
|
||||
expect(sResult).not.toContain(SENSOR_HEADING());
|
||||
expect(pResult).not.toContain(PERIPHERAL_HEADING());
|
||||
});
|
||||
|
||||
it("Validates correctness of `pin_type` at runtime", () => {
|
||||
|
|
|
@ -35,16 +35,16 @@ const BOX_LED_LABELS: { [x: string]: string } = {
|
|||
[BoxLed.BoxLed4]: t("Box LED 4"),
|
||||
};
|
||||
|
||||
export const PERIPHERAL_HEADING: DropDownItem =
|
||||
export const PERIPHERAL_HEADING = (): DropDownItem =>
|
||||
({ heading: true, label: t("Peripherals"), value: 0, headingId: PinGroupName.Peripheral });
|
||||
|
||||
export const SENSOR_HEADING: DropDownItem =
|
||||
export const SENSOR_HEADING = (): DropDownItem =>
|
||||
({ heading: true, label: t("Sensors"), value: 0, headingId: PinGroupName.Sensor });
|
||||
|
||||
export const BOX_LED_HEADING: DropDownItem =
|
||||
export const BOX_LED_HEADING = (): DropDownItem =>
|
||||
({ heading: true, label: t("Box LEDs"), value: 0, headingId: PinGroupName.BoxLed });
|
||||
|
||||
export const PIN_HEADING: DropDownItem =
|
||||
export const PIN_HEADING = (): DropDownItem =>
|
||||
({ heading: true, label: t("Pins"), value: 0, headingId: PinGroupName.Pin });
|
||||
|
||||
/** Pass it the number X and it will generate a DropDownItem for `pin x`. */
|
||||
|
@ -79,17 +79,17 @@ const boxLed2DropDown =
|
|||
|
||||
export function peripheralsAsDropDowns(input: ResourceIndex): DropDownItem[] {
|
||||
const list = selectAllSavedPeripherals(input).map(peripheral2DropDown);
|
||||
return list.length ? [PERIPHERAL_HEADING, ...list] : [];
|
||||
return list.length ? [PERIPHERAL_HEADING(), ...list] : [];
|
||||
}
|
||||
|
||||
export function sensorsAsDropDowns(input: ResourceIndex): DropDownItem[] {
|
||||
const list = selectAllSavedSensors(input).map(sensor2DropDown);
|
||||
return list.length ? [SENSOR_HEADING, ...list] : [];
|
||||
return list.length ? [SENSOR_HEADING(), ...list] : [];
|
||||
}
|
||||
|
||||
export function boxLedsAsDropDowns(): DropDownItem[] {
|
||||
const list = Object.values(BoxLed).map(boxLed2DropDown);
|
||||
return [BOX_LED_HEADING, ...list];
|
||||
return [BOX_LED_HEADING(), ...list];
|
||||
}
|
||||
|
||||
/** Number of pins in an Arduino Mega */
|
||||
|
@ -97,7 +97,7 @@ export const PIN_RANGE = range(0, 70);
|
|||
|
||||
export function pinDropdowns(
|
||||
valueFormat: (n: number) => string | number): DropDownItem[] {
|
||||
return [PIN_HEADING, ...PIN_RANGE.map(pinNumber2DropDown(valueFormat))];
|
||||
return [PIN_HEADING(), ...PIN_RANGE.map(pinNumber2DropDown(valueFormat))];
|
||||
}
|
||||
|
||||
export const pinsAsDropDownsWritePin = (
|
||||
|
|
|
@ -13,7 +13,6 @@ describe("<TypePart/>", () => {
|
|||
.simulate("change", { value: "anything", label: "y" });
|
||||
expect(p.dispatch).toHaveBeenCalled();
|
||||
const calls = (p.dispatch as jest.Mock).mock.calls[0][0];
|
||||
console.log(calls);
|
||||
const { assertion_type } = calls.payload.update.body[1].args;
|
||||
expect(assertion_type).toEqual("anything");
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ export function SequencePart(props: AssertionStepProps) {
|
|||
return <span>
|
||||
<label>Recovery Sequence</label>
|
||||
<SequenceSelectBox
|
||||
key={JSON.stringify(props.currentStep)}
|
||||
onChange={onChange}
|
||||
resources={props.resources}
|
||||
sequenceId={sequenceId} />
|
||||
|
|
|
@ -16,6 +16,7 @@ export function TypePart(props: AssertionStepProps) {
|
|||
return <span>
|
||||
<label>If Test Fails</label>
|
||||
<FBSelect
|
||||
key={JSON.stringify(props.currentStep)}
|
||||
selectedItem={ASSERTION_TYPES[assertion_type]}
|
||||
onChange={(ddi) => {
|
||||
props.dispatch(editStep({
|
||||
|
|
Loading…
Reference in New Issue