commit
dcb12a89c9
|
@ -130,7 +130,7 @@ module CeleryScriptSettingsBag
|
|||
defn: [n(:execute), n(:nothing)],
|
||||
},
|
||||
data_value: {
|
||||
defn: ANY_VAR_TOKENIZED,
|
||||
defn: ANY_VAR_TOKENIZED + [n(:point_group), n(:every_point)],
|
||||
},
|
||||
default_value: {
|
||||
defn: ANY_VAR_TOKENIZED,
|
||||
|
@ -270,6 +270,9 @@ module CeleryScriptSettingsBag
|
|||
lua: {
|
||||
defn: [v(:string)],
|
||||
},
|
||||
every_point_type: {
|
||||
defn: [e(:PointType)],
|
||||
},
|
||||
}.map do |(name, conf)|
|
||||
blk = conf[:blk]
|
||||
defn = conf.fetch(:defn)
|
||||
|
@ -514,6 +517,18 @@ module CeleryScriptSettingsBag
|
|||
check_resource_type(n, resource_type, resource_id, Device.current)
|
||||
end,
|
||||
},
|
||||
point_group: {
|
||||
args: [:resource_id],
|
||||
tags: [:data, :list_like],
|
||||
blk: ->(n) do
|
||||
resource_id = n.args.fetch(:resource_id).value
|
||||
check_resource_type(n, "PointGroup", resource_id, Device.current)
|
||||
end,
|
||||
},
|
||||
every_point: {
|
||||
args: [:every_point_type],
|
||||
tags: [:data, :list_like],
|
||||
},
|
||||
}.map { |(name, list)| Corpus.node(name, **list) }
|
||||
|
||||
HASH = Corpus.as_json
|
||||
|
@ -535,6 +550,8 @@ module CeleryScriptSettingsBag
|
|||
# the current_device.
|
||||
# For convenience, we try to set it here, defaulting to 0
|
||||
node.args[:resource_id].instance_variable_set("@value", owner.id)
|
||||
when "PointGroup"
|
||||
no_resource(node, PointGroup, resource_id) unless PointGroup.exists?(resource_id)
|
||||
when *ALLOWED_RESOURCE_TYPE.without("Device")
|
||||
klass = Kernel.const_get(resource_type)
|
||||
resource_ok = klass.exists?(resource_id)
|
||||
|
|
|
@ -10,6 +10,8 @@ module Devices
|
|||
string :name
|
||||
string :timezone
|
||||
time :last_saw_mq
|
||||
time :last_ota
|
||||
time :last_ota_checkup
|
||||
integer :mounted_tool_id, nils: true
|
||||
end
|
||||
|
||||
|
|
|
@ -2,5 +2,5 @@ class DeviceSerializer < ApplicationSerializer
|
|||
attributes :fbos_version, :last_saw_api, :last_saw_mq,
|
||||
:mounted_tool_id, :name, :serial_number,
|
||||
:throttled_at, :throttled_until, :timezone,
|
||||
:tz_offset_hrs
|
||||
:tz_offset_hrs, :last_ota, :last_ota_checkup
|
||||
end
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
class RenameDeviceLastOtaChecktoLastOtaCheckup < ActiveRecord::Migration[5.2]
|
||||
safety_assured
|
||||
|
||||
def change
|
||||
rename_column :devices, :last_ota_check, :last_ota_checkup
|
||||
end
|
||||
end
|
|
@ -277,7 +277,7 @@ CREATE TABLE public.devices (
|
|||
serial_number character varying(32),
|
||||
mqtt_rate_limit_email_sent_at timestamp without time zone,
|
||||
last_ota timestamp without time zone,
|
||||
last_ota_check timestamp without time zone
|
||||
last_ota_checkup timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
|
@ -3274,6 +3274,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20190804194135'),
|
||||
('20190804194154'),
|
||||
('20190823164837'),
|
||||
('20190918185359');
|
||||
('20190918185359'),
|
||||
('20190924190539');
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ import {
|
|||
TaggedPointGroup,
|
||||
} from "farmbot";
|
||||
import { fakeResource } from "../fake_resource";
|
||||
import { ExecutableType, PinBindingType } from "farmbot/dist/resources/api_resources";
|
||||
import {
|
||||
ExecutableType, PinBindingType
|
||||
} from "farmbot/dist/resources/api_resources";
|
||||
import { FirmwareConfig } from "farmbot/dist/resources/configs/firmware";
|
||||
import { MessageType } from "../../sequences/interfaces";
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "";
|
||||
jest.mock("../history", () => ({
|
||||
getPathArray: jest.fn(() => mockPath.split("/")),
|
||||
|
@ -7,7 +5,7 @@ jest.mock("../history", () => ({
|
|||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { App, AppProps, mapStateToProps } from "../app";
|
||||
import { RawApp as App, AppProps, mapStateToProps } from "../app";
|
||||
import { mount } from "enzyme";
|
||||
import { bot } from "../__test_support__/fake_state/bot";
|
||||
import {
|
||||
|
@ -25,27 +23,25 @@ import { fakePings } from "../__test_support__/fake_state/pings";
|
|||
const FULLY_LOADED: ResourceName[] = [
|
||||
"Sequence", "Regimen", "FarmEvent", "Point", "Tool", "Device"];
|
||||
|
||||
const fakeProps = (): AppProps => {
|
||||
return {
|
||||
timeSettings: fakeTimeSettings(),
|
||||
dispatch: jest.fn(),
|
||||
loaded: [],
|
||||
logs: [],
|
||||
user: fakeUser(),
|
||||
bot: bot,
|
||||
consistent: true,
|
||||
axisInversion: { x: false, y: false, z: false },
|
||||
firmwareConfig: undefined,
|
||||
xySwap: false,
|
||||
animate: false,
|
||||
getConfigValue: jest.fn(),
|
||||
tour: undefined,
|
||||
resources: buildResourceIndex().index,
|
||||
autoSync: false,
|
||||
alertCount: 0,
|
||||
pings: fakePings()
|
||||
};
|
||||
};
|
||||
const fakeProps = (): AppProps => ({
|
||||
timeSettings: fakeTimeSettings(),
|
||||
dispatch: jest.fn(),
|
||||
loaded: [],
|
||||
logs: [],
|
||||
user: fakeUser(),
|
||||
bot: bot,
|
||||
consistent: true,
|
||||
axisInversion: { x: false, y: false, z: false },
|
||||
firmwareConfig: undefined,
|
||||
xySwap: false,
|
||||
animate: false,
|
||||
getConfigValue: jest.fn(),
|
||||
tour: undefined,
|
||||
resources: buildResourceIndex().index,
|
||||
autoSync: false,
|
||||
alertCount: 0,
|
||||
pings: fakePings()
|
||||
});
|
||||
|
||||
describe("<App />: Controls Pop-Up", () => {
|
||||
function controlsPopUp(page: string, exists: boolean) {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
jest.mock("../labs/labs_features", () => ({ LabsFeatures: () => <div /> }));
|
||||
|
||||
import * as React from "react";
|
||||
import { fakeState } from "../../__test_support__/fake_state";
|
||||
import { mapStateToProps } from "../state_to_props";
|
||||
import { shallow, mount } from "enzyme";
|
||||
import { Account } from "../index";
|
||||
import { RawAccount as Account } from "../index";
|
||||
import { edit } from "../../api/crud";
|
||||
|
||||
describe("<Account />", () => {
|
||||
|
|
|
@ -4,12 +4,15 @@ const mock = {
|
|||
}
|
||||
};
|
||||
|
||||
jest.mock("axios",
|
||||
() => ({ post: jest.fn(() => Promise.resolve(mock.response)) }));
|
||||
jest.mock("axios", () => ({
|
||||
post: jest.fn(() => Promise.resolve(mock.response))
|
||||
}));
|
||||
|
||||
import { API } from "../../api";
|
||||
import { Content } from "../../constants";
|
||||
import { requestAccountExport, generateFilename } from "../request_account_export";
|
||||
import {
|
||||
requestAccountExport, generateFilename
|
||||
} from "../request_account_export";
|
||||
import { success } from "../../toast/toast";
|
||||
import axios from "axios";
|
||||
import { fakeDevice } from "../../__test_support__/resource_index_builder";
|
||||
|
@ -32,7 +35,8 @@ describe("requestAccountExport", () => {
|
|||
expect(success).toHaveBeenCalledWith(Content.EXPORT_SENT);
|
||||
});
|
||||
|
||||
it("downloads the data synchronously (when API has no email support)", async () => {
|
||||
it("downloads the data synchronously (when API has no email support)", async (
|
||||
) => {
|
||||
mock.response.data = {};
|
||||
window.URL = window.URL || ({} as typeof window.URL);
|
||||
window.URL.createObjectURL = jest.fn();
|
||||
|
|
|
@ -18,7 +18,8 @@ export function ExportAccountPanel(props: { onClick: () => void }) {
|
|||
</label>
|
||||
</Col>
|
||||
<Col xs={4}>
|
||||
<button onClick={props.onClick} className="green fb-button" type="button" >
|
||||
<button className="green fb-button" type="button"
|
||||
onClick={props.onClick}>
|
||||
{t("Export")}
|
||||
</button>
|
||||
</Col>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import {
|
||||
BlurableInput, Widget, WidgetHeader, WidgetBody, SaveBtn
|
||||
} from "../../ui/index";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { API } from "../api";
|
||||
import { Content } from "../constants";
|
||||
import { success } from "../toast/toast";
|
||||
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { DeviceAccountSettings } from "farmbot/dist/resources/api_resources";
|
||||
import { t } from "../i18next_wrapper";
|
||||
|
|
|
@ -17,7 +17,6 @@ import { ResourceIndex } from "../resources/interfaces";
|
|||
import { SequenceBodyItem } from "farmbot/dist";
|
||||
import { Actions } from "../constants";
|
||||
import { maybeStartTracking } from "./maybe_start_tracking";
|
||||
|
||||
import { newTaggedResource } from "../sync/actions";
|
||||
import { arrayUnwrap } from "../resources/util";
|
||||
import { findByUuid } from "../resources/reducer_support";
|
||||
|
|
|
@ -21,7 +21,10 @@ jest.mock("../../redux/store", () => {
|
|||
|
||||
jest.mock("../auto_sync_handle_inbound", () => ({ handleInbound: jest.fn() }));
|
||||
|
||||
import { dispatchNetworkUp, dispatchNetworkDown, dispatchQosStart, networkUptimeThrottleStats } from "../index";
|
||||
import {
|
||||
dispatchNetworkUp, dispatchNetworkDown, dispatchQosStart,
|
||||
networkUptimeThrottleStats,
|
||||
} from "../index";
|
||||
import { networkUp, networkDown } from "../actions";
|
||||
import { GetState } from "../../redux/interfaces";
|
||||
import { autoSync, routeMqttData } from "../auto_sync";
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { GetState } from "../redux/interfaces";
|
||||
import { maybeDetermineUuid } from "../resources/selectors";
|
||||
import {
|
||||
TaggedResource,
|
||||
SpecialStatus
|
||||
} from "farmbot";
|
||||
import { TaggedResource, SpecialStatus } from "farmbot";
|
||||
import { overwrite, init } from "../api/crud";
|
||||
import { handleInbound } from "./auto_sync_handle_inbound";
|
||||
import { SyncPayload, MqttDataResult, Reason, UpdateMqttData } from "./interfaces";
|
||||
import {
|
||||
SyncPayload, MqttDataResult, Reason, UpdateMqttData
|
||||
} from "./interfaces";
|
||||
import { outstandingRequests } from "./data_consistency";
|
||||
import { newTaggedResource } from "../sync/actions";
|
||||
|
||||
|
@ -16,7 +15,8 @@ export function decodeBinary(payload: Buffer): SyncPayload {
|
|||
|
||||
const SKIP_THESE = ["DeviceSerialNumber"]; // Only FBOS Cares about this one.
|
||||
|
||||
export function routeMqttData(chan: string, payload: Buffer): MqttDataResult<TaggedResource> {
|
||||
export function routeMqttData(chan: string, payload: Buffer):
|
||||
MqttDataResult<TaggedResource> {
|
||||
/** Skip irrelevant messages: only resource auto-sync messages are desired.
|
||||
* eg, `bot/device_#/sync/Resource/#` */
|
||||
if (!(chan.split("/")[2] == "sync")) { return { status: "SKIP" }; }
|
||||
|
@ -37,7 +37,8 @@ export function routeMqttData(chan: string, payload: Buffer): MqttDataResult<Tag
|
|||
}
|
||||
}
|
||||
|
||||
export function asTaggedResource(data: UpdateMqttData<TaggedResource>): TaggedResource {
|
||||
export function asTaggedResource(data: UpdateMqttData<TaggedResource>):
|
||||
TaggedResource {
|
||||
return newTaggedResource(data.kind, data.body)[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,9 @@ export const HACKY_FLAGS = {
|
|||
export const incomingLegacyStatus = (statusMessage: HardwareState) =>
|
||||
({ type: Actions.LEGACY_BOT_CHANGE, payload: statusMessage });
|
||||
|
||||
export const incomingStatus =
|
||||
(payload: DeepPartial<HardwareState>) => ({ type: Actions.STATUS_UPDATE, payload });
|
||||
export const incomingStatus = (payload: DeepPartial<HardwareState>) => ({
|
||||
type: Actions.STATUS_UPDATE, payload
|
||||
});
|
||||
|
||||
/** Determine if an incoming log has a certain channel. If it is, execute the
|
||||
* supplied callback. */
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { Controls } from "../controls";
|
||||
import { RawControls as Controls } from "../controls";
|
||||
import { bot } from "../../__test_support__/fake_state/bot";
|
||||
import {
|
||||
fakePeripheral, fakeWebcamFeed, fakeSensor
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Row, Col } from "../ui/index";
|
||||
import { AxisDisplayGroupProps } from "./interfaces";
|
||||
import { isNumber } from "lodash";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { AxisInputBox } from "./axis_input_box";
|
||||
|
||||
import { Row, Col } from "../ui/index";
|
||||
import { AxisInputBoxGroupProps, AxisInputBoxGroupState } from "./interfaces";
|
||||
import { isNumber } from "lodash";
|
||||
|
@ -59,7 +58,7 @@ export class AxisInputBoxGroup extends
|
|||
onClick={this.clicked}
|
||||
disabled={this.props.disabled || false}
|
||||
title={t("Move to chosen location")}
|
||||
className="full-width green go fb-button" >
|
||||
className="full-width green go fb-button">
|
||||
{t("GO")}
|
||||
</button>
|
||||
</Col>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Row, Col } from "../../ui";
|
||||
import { BotLocationData } from "../../devices/interfaces";
|
||||
import { moveAbs } from "../../devices/actions";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { McuParams } from "farmbot";
|
||||
import { BotPosition } from "../../devices/interfaces";
|
||||
import { changeStepSize } from "../../devices/actions";
|
||||
|
|
|
@ -3,8 +3,9 @@ import { Xyz, LocationName, Dictionary } from "farmbot";
|
|||
import moment from "moment";
|
||||
import { BotLocationData, BotPosition } from "../../devices/interfaces";
|
||||
import { trim } from "../../util";
|
||||
|
||||
import { cloneDeep, max, get, isNumber, isEqual, takeRight, ceil, range } from "lodash";
|
||||
import {
|
||||
cloneDeep, max, get, isNumber, isEqual, takeRight, ceil, range
|
||||
} from "lodash";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
||||
const HEIGHT = 50;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { BooleanSetting } from "../../session_keys";
|
||||
import { ToggleButton } from "../toggle_button";
|
||||
import { ToggleWebAppBool, GetWebAppBool } from "./interfaces";
|
||||
|
@ -7,16 +6,17 @@ import { BooleanConfigKey } from "farmbot/dist/resources/configs/web_app";
|
|||
import { DevSettings } from "../../account/dev/dev_support";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
||||
export const moveWidgetSetting = (toggle: ToggleWebAppBool, getValue: GetWebAppBool) =>
|
||||
({ label, setting }: { label: string, setting: BooleanConfigKey }) =>
|
||||
<fieldset>
|
||||
<label>
|
||||
{t(label)}
|
||||
</label>
|
||||
<ToggleButton
|
||||
toggleAction={toggle(BooleanSetting[setting])}
|
||||
toggleValue={getValue(setting)} />
|
||||
</fieldset>;
|
||||
export const moveWidgetSetting =
|
||||
(toggle: ToggleWebAppBool, getValue: GetWebAppBool) =>
|
||||
({ label, setting }: { label: string, setting: BooleanConfigKey }) =>
|
||||
<fieldset>
|
||||
<label>
|
||||
{t(label)}
|
||||
</label>
|
||||
<ToggleButton
|
||||
toggleAction={toggle(BooleanSetting[setting])}
|
||||
toggleValue={getValue(setting)} />
|
||||
</fieldset>;
|
||||
|
||||
export const MoveWidgetSettingsMenu = ({ toggle, getValue }: {
|
||||
toggle: ToggleWebAppBool,
|
||||
|
|
|
@ -89,4 +89,4 @@ export const DeleteButton = (props: DeleteButtonProps) =>
|
|||
props.dispatch(destroy(props.uuid))
|
||||
.then(props.onDestroy || (() => { }))}>
|
||||
{props.children || <i className="fa fa-times" />}
|
||||
</button >;
|
||||
</button>;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ToggleButtonProps } from "./interfaces";
|
||||
import { t } from "../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -3,18 +3,26 @@ import { fakeWebcamFeed } from "../../../__test_support__/fake_state/resources";
|
|||
import { mount } from "enzyme";
|
||||
import { Show, IndexIndicator } from "../show";
|
||||
import { props } from "../test_helpers";
|
||||
import { PLACEHOLDER_FARMBOT } from "../../../farmware/images/image_flipper";
|
||||
|
||||
describe("<Show/>", () => {
|
||||
const feed1 = fakeWebcamFeed();
|
||||
const feed2 = fakeWebcamFeed();
|
||||
const p = props([feed1, feed2]);
|
||||
|
||||
it("Renders feed title", () => {
|
||||
const feed1 = fakeWebcamFeed();
|
||||
const feed2 = fakeWebcamFeed();
|
||||
const p = props([feed1, feed2]);
|
||||
const el = mount(<Show {...p} />);
|
||||
expect(el.text()).toContain(feed1.body.name);
|
||||
el.find(".image-flipper-right").first().simulate("click");
|
||||
el.render();
|
||||
expect(el.text()).toContain(feed2.body.name);
|
||||
});
|
||||
|
||||
it("returns a PLACEHOLDER_FEED", () => {
|
||||
const comp = new Show(p);
|
||||
const result = comp.getMessage("http://geocities.com/" + PLACEHOLDER_FARMBOT);
|
||||
expect(result).toEqual("Click the edit button to add or edit a feed URL.");
|
||||
});
|
||||
});
|
||||
|
||||
describe("<IndexIndicator/>", () => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Widget, WidgetHeader, WidgetBody } from "../../ui/index";
|
||||
|
||||
import { ToolTips } from "../../constants";
|
||||
import { WebcamPanelProps } from "./interfaces";
|
||||
import { KeyValEditRow } from "../key_val_edit_row";
|
||||
|
|
|
@ -5,7 +5,6 @@ import { WebcamPanelProps } from "./interfaces";
|
|||
import { TaggedWebcamFeed, SpecialStatus } from "farmbot";
|
||||
import { edit, save, destroy, init } from "../../api/crud";
|
||||
import { error } from "../../toast/toast";
|
||||
|
||||
import { WebcamFeed } from "farmbot/dist/resources/api_resources";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Widget, WidgetHeader, FallbackImg, WidgetBody } from "../../ui/index";
|
||||
|
||||
import { ToolTips } from "../../constants";
|
||||
import { WebcamPanelProps } from "./interfaces";
|
||||
import { PLACEHOLDER_FARMBOT } from "../../farmware/images/image_flipper";
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
import * as React from "react";
|
||||
import { shallow, render } from "enzyme";
|
||||
import { Devices } from "../devices";
|
||||
import { RawDevices as Devices } from "../devices";
|
||||
import { Props } from "../interfaces";
|
||||
import { auth } from "../../__test_support__/fake_state/token";
|
||||
import { bot } from "../../__test_support__/fake_state/bot";
|
||||
|
|
|
@ -400,5 +400,6 @@ export function changeStepSize(integer: number) {
|
|||
}
|
||||
|
||||
export function badVersion() {
|
||||
info(t("You are running an old version of FarmBot OS."), t("Please Update"), "red");
|
||||
info(t("You are running an old version of FarmBot OS."),
|
||||
t("Please Update"), "red");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
let mockReleaseNoteData = {};
|
||||
jest.mock("axios", () => ({
|
||||
get: jest.fn(() => Promise.resolve(mockReleaseNoteData))
|
||||
|
@ -9,6 +8,10 @@ jest.mock("../../../api/crud", () => ({
|
|||
save: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../fbos_settings/boot_sequence_selector", () => ({
|
||||
BootSequenceSelector: () => <div />
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { FarmbotOsSettings } from "../farmbot_os_settings";
|
||||
import { mount, shallow } from "enzyme";
|
||||
|
@ -19,14 +22,6 @@ import axios from "axios";
|
|||
import { fakeTimeSettings } from "../../../__test_support__/fake_time_settings";
|
||||
import { edit } from "../../../api/crud";
|
||||
|
||||
jest.mock("react-redux", () => ({
|
||||
connect: jest.fn(() => {
|
||||
return () => {
|
||||
return () => "";
|
||||
};
|
||||
})
|
||||
}));
|
||||
|
||||
describe("<FarmbotOsSettings />", () => {
|
||||
beforeEach(() => {
|
||||
window.alert = jest.fn();
|
||||
|
@ -87,5 +82,4 @@ describe("<FarmbotOsSettings />", () => {
|
|||
.simulate("change", { currentTarget: { value: newName } });
|
||||
expect(edit).toHaveBeenCalledWith(p.deviceAccount, { name: newName });
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
jest.mock("../../actions", () => ({
|
||||
settingToggle: jest.fn()
|
||||
}));
|
||||
jest.mock("../../actions", () => ({ settingToggle: jest.fn() }));
|
||||
|
||||
import * as React from "react";
|
||||
import { PinGuardMCUInputGroup } from "../pin_guard_input_group";
|
||||
|
@ -8,7 +6,9 @@ import { mount } from "enzyme";
|
|||
import { PinGuardMCUInputGroupProps } from "../interfaces";
|
||||
import { bot } from "../../../__test_support__/fake_state/bot";
|
||||
import { settingToggle } from "../../actions";
|
||||
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
|
||||
describe("<PinGuardMCUInputGroup/>", () => {
|
||||
const fakeProps = (): PinGuardMCUInputGroupProps => {
|
||||
|
|
|
@ -15,9 +15,10 @@ interface AxisStatus {
|
|||
* If neither of these are enabled, FarmBot can do some pretty dangerous things,
|
||||
* such as smashing tools and ramming into tool bays.
|
||||
*
|
||||
* This function returns a 2 dimensional array describing whether or not a particular
|
||||
* axis has at least one of the precautions in place. Useful for checking if it is safe
|
||||
* to proceed with certain actions that could damage the bot.
|
||||
* This function returns a 2 dimensional array describing whether or not
|
||||
* a particular axis has at least one of the precautions in place.
|
||||
* Useful for checking if it is safe to proceed with certain actions that
|
||||
* could damage the bot.
|
||||
*/
|
||||
export function axisTrackingStatus(h: McuParams): AxisStatus[] {
|
||||
const stats = enabledAxisMap(h);
|
||||
|
|
|
@ -20,7 +20,9 @@ export class DiagnosticDumpRow extends React.Component<Props, {}> {
|
|||
render() {
|
||||
return <Row>
|
||||
<Col xsOffset={3} xs={8}>
|
||||
{t("Report {{ticket}} (Saved {{age}})", { ticket: this.ticket, age: this.age })}
|
||||
{t("Report {{ticket}} (Saved {{age}})", {
|
||||
ticket: this.ticket, age: this.age
|
||||
})}
|
||||
</Col>
|
||||
<Col xs={1}>
|
||||
<button
|
||||
|
@ -30,6 +32,6 @@ export class DiagnosticDumpRow extends React.Component<Props, {}> {
|
|||
<i className="fa fa-times" />
|
||||
</button>
|
||||
</Col>
|
||||
</Row >;
|
||||
</Row>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import * as React from "react";
|
||||
import axios from "axios";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import { FarmbotOsProps, FarmbotOsState } from "../interfaces";
|
||||
import { Widget, WidgetHeader, WidgetBody, Row, Col } from "../../ui";
|
||||
import { save, edit } from "../../api/crud";
|
||||
|
@ -14,8 +16,6 @@ import { AutoSyncRow } from "./fbos_settings/auto_sync_row";
|
|||
import { isUndefined } from "lodash";
|
||||
import { PowerAndReset } from "./fbos_settings/power_and_reset";
|
||||
import { SendDiagnosticReport } from "./send_diagnostic_report";
|
||||
import axios from "axios";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
import { BootSequenceSelector } from "./fbos_settings/boot_sequence_selector";
|
||||
|
||||
export enum ColWidth {
|
||||
|
@ -70,11 +70,7 @@ export class FarmbotOsSettings
|
|||
|
||||
maybeWarnTz = () => {
|
||||
const wrongTZ = timezoneMismatch(this.props.deviceAccount.body.timezone);
|
||||
if (wrongTZ) {
|
||||
return t(Content.DIFFERENT_TZ_WARNING);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return wrongTZ ? t(Content.DIFFERENT_TZ_WARNING) : "";
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -173,6 +173,36 @@ describe("<FbosDetails/>", () => {
|
|||
const wrapper = mount(<FbosDetails {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("voltage");
|
||||
});
|
||||
|
||||
it("displays cpu usage", () => {
|
||||
const p = fakeProps();
|
||||
// tslint:disable-next-line:no-any
|
||||
(p.botInfoSettings as any).cpu_usage = 10;
|
||||
const wrapper = mount(<FbosDetails {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("cpu usage: 10%");
|
||||
});
|
||||
|
||||
it("displays ip address", () => {
|
||||
const p = fakeProps();
|
||||
p.botInfoSettings.private_ip = "192.168.0.100";
|
||||
const wrapper = mount(<FbosDetails {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("ip address");
|
||||
});
|
||||
|
||||
it("displays last OTA check date", () => {
|
||||
const p = fakeProps();
|
||||
p.deviceAccount.body.last_ota_checkup = "2018-01-11T20:20:38.362Z";
|
||||
const wrapper = mount(<FbosDetails {...p} />);
|
||||
expect(wrapper.text().toLowerCase())
|
||||
.toContain("last checked for updates: january");
|
||||
});
|
||||
|
||||
it("displays last OTA date", () => {
|
||||
const p = fakeProps();
|
||||
p.deviceAccount.body.last_ota = "2018-02-11T20:20:38.362Z";
|
||||
const wrapper = mount(<FbosDetails {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("last updated: february");
|
||||
});
|
||||
});
|
||||
|
||||
describe("betaReleaseOptIn()", () => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col } from "../../../ui/index";
|
||||
|
||||
import { ToggleButton } from "../../../controls/toggle_button";
|
||||
import { Content } from "../../../constants";
|
||||
import { updateConfig } from "../../actions";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col } from "../../../ui/index";
|
||||
|
||||
import { ColWidth } from "../farmbot_os_settings";
|
||||
import { ToggleButton } from "../../../controls/toggle_button";
|
||||
import { updateConfig } from "../../actions";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col, BlurableInput } from "../../../ui/index";
|
||||
|
||||
import { success, error } from "../../../toast/toast";
|
||||
import { getDevice } from "../../../device";
|
||||
import { transferOwnership } from "../../transfer_ownership/transfer_ownership";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col } from "../../../ui/index";
|
||||
|
||||
import { Content } from "../../../constants";
|
||||
import { factoryReset, updateConfig } from "../../actions";
|
||||
import { ToggleButton } from "../../../controls/toggle_button";
|
||||
|
@ -75,6 +74,6 @@ export function FactoryResetRow(props: FactoryResetRowProps) {
|
|||
disabled={!!disableFactoryReset.value}
|
||||
sourceFbosConfig={sourceFbosConfig} />
|
||||
</Col>
|
||||
</Row >
|
||||
</div >;
|
||||
</Row>
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -61,5 +61,5 @@ export function FarmbotOsRow(props: FarmbotOsRowProps) {
|
|||
shouldDisplay={props.shouldDisplay}
|
||||
botOnline={botOnline} />
|
||||
</Col>
|
||||
</Row >;
|
||||
</Row>;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col } from "../../../ui";
|
||||
|
||||
import { ColWidth } from "../farmbot_os_settings";
|
||||
import { t } from "../../../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as React from "react";
|
|||
import { Saucer } from "../../../ui/index";
|
||||
import { ToggleButton } from "../../../controls/toggle_button";
|
||||
import { updateConfig } from "../../actions";
|
||||
import { last, isNumber } from "lodash";
|
||||
import { last, isNumber, isString } from "lodash";
|
||||
import { Content } from "../../../constants";
|
||||
import { FbosDetailsProps } from "./interfaces";
|
||||
import { SourceFbosConfig, ShouldDisplay, Feature } from "../../interfaces";
|
||||
|
@ -10,6 +10,9 @@ import { ConfigurationName } from "farmbot";
|
|||
import { t } from "../../../i18next_wrapper";
|
||||
import { LastSeen } from "./last_seen_row";
|
||||
import { Popover } from "@blueprintjs/core";
|
||||
import moment from "moment";
|
||||
import { timeFormatString } from "../../../util";
|
||||
import { TimeSettings } from "../../../interfaces";
|
||||
|
||||
/** Return an indicator color for the given temperature (C). */
|
||||
export const colorFromTemp = (temp: number | undefined): string => {
|
||||
|
@ -258,14 +261,21 @@ const BetaReleaseOptInButton = (
|
|||
</fieldset>;
|
||||
};
|
||||
|
||||
/** Format datetime string for display. */
|
||||
const reformatDatetime = (datetime: string, timeSettings: TimeSettings) =>
|
||||
moment(datetime)
|
||||
.utcOffset(timeSettings.utcOffset)
|
||||
.format(`MMMM D, ${timeFormatString(timeSettings)}`);
|
||||
|
||||
/** Current technical information about FarmBot OS running on the device. */
|
||||
export function FbosDetails(props: FbosDetailsProps) {
|
||||
const {
|
||||
env, commit, target, node_name, firmware_version, firmware_commit,
|
||||
soc_temp, wifi_level, uptime, memory_usage, disk_usage, throttled,
|
||||
wifi_level_percent,
|
||||
wifi_level_percent, cpu_usage, private_ip,
|
||||
// tslint:disable-next-line:no-any
|
||||
} = props.botInfoSettings as any;
|
||||
const { last_ota, last_ota_checkup } = props.deviceAccount.body;
|
||||
|
||||
return <div>
|
||||
<LastSeen
|
||||
|
@ -277,6 +287,8 @@ export function FbosDetails(props: FbosDetailsProps) {
|
|||
<CommitDisplay title={t("Commit")} repo={"farmbot_os"} commit={commit} />
|
||||
<p><b>{t("Target")}: </b>{target}</p>
|
||||
<p><b>{t("Node name")}: </b>{last((node_name || "").split("@"))}</p>
|
||||
<p><b>{t("Device ID")}: </b>{props.deviceAccount.body.id}</p>
|
||||
{isString(private_ip) && <p><b>{t("Local IP address")}: </b>{private_ip}</p>}
|
||||
<p><b>{t("Firmware")}: </b>{firmware_version}</p>
|
||||
<CommitDisplay title={t("Firmware commit")}
|
||||
repo={"farmbot-arduino-firmware"} commit={firmware_commit} />
|
||||
|
@ -284,6 +296,7 @@ export function FbosDetails(props: FbosDetailsProps) {
|
|||
{isNumber(memory_usage) &&
|
||||
<p><b>{t("Memory usage")}: </b>{memory_usage}MB</p>}
|
||||
{isNumber(disk_usage) && <p><b>{t("Disk usage")}: </b>{disk_usage}%</p>}
|
||||
{isNumber(cpu_usage) && <p><b>{t("CPU usage")}: </b>{cpu_usage}%</p>}
|
||||
<ChipTemperatureDisplay chip={target} temperature={soc_temp} />
|
||||
<WiFiStrengthDisplay
|
||||
wifiStrength={wifi_level} wifiStrengthPercent={wifi_level_percent} />
|
||||
|
@ -292,5 +305,9 @@ export function FbosDetails(props: FbosDetailsProps) {
|
|||
dispatch={props.dispatch}
|
||||
shouldDisplay={props.shouldDisplay}
|
||||
sourceFbosConfig={props.sourceFbosConfig} />
|
||||
{last_ota_checkup && <p><b>{t("Last checked for updates")}: </b>
|
||||
{reformatDatetime(last_ota_checkup, props.timeSettings)}</p>}
|
||||
{last_ota && <p><b>{t("Last updated")}: </b>
|
||||
{reformatDatetime(last_ota, props.timeSettings)}</p>}
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { JobProgress, ConfigurationName } from "farmbot/dist";
|
||||
import { SemverResult, semverCompare } from "../../../util";
|
||||
import { OsUpdateButtonProps } from "./interfaces";
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Collapse, Popover, Position } from "@blueprintjs/core";
|
|||
import { FactoryResetRow } from "./factory_reset_row";
|
||||
import { PowerAndResetProps } from "./interfaces";
|
||||
import { ChangeOwnershipForm } from "./change_ownership_form";
|
||||
|
||||
import { Feature } from "../../interfaces";
|
||||
import { FbosButtonRow } from "./fbos_button_row";
|
||||
import { Content } from "../../../constants";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { DangerZoneProps } from "../interfaces";
|
||||
import { Row, Col } from "../../../ui/index";
|
||||
import { Header } from "./header";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { McuParams, Encoder, McuParamName } from "farmbot/dist";
|
||||
|
||||
import { FBSelect, DropDownItem } from "../../../ui/index";
|
||||
import { t } from "../../../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Row, Col } from "../../../ui/index";
|
||||
import { t } from "../../../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export function ZeroButton(props: { axis: Axis; disabled: boolean; }) {
|
|||
return <button
|
||||
className="fb-button yellow"
|
||||
disabled={disabled}
|
||||
onClick={() => zero(axis)} >
|
||||
onClick={() => zero(axis)}>
|
||||
{t("zero {{axis}}", { axis })}
|
||||
</button>;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export function LockableButton({ onClick, disabled, children }: Props) {
|
|||
return <button
|
||||
className={"fb-button " + className}
|
||||
disabled={disabled}
|
||||
onClick={() => disabled ? "" : onClick()} >
|
||||
onClick={() => disabled ? "" : onClick()}>
|
||||
{children}
|
||||
</button>;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col } from "../../ui";
|
||||
import { ColWidth } from "./farmbot_os_settings";
|
||||
|
||||
import { Collapse } from "@blueprintjs/core";
|
||||
import { Header } from "./hardware_settings/header";
|
||||
import { ShouldDisplay, Feature } from "../interfaces";
|
||||
|
|
|
@ -34,7 +34,9 @@ export function botToAPI(stat: string | undefined,
|
|||
from: "FarmBot",
|
||||
to: "Web App",
|
||||
connectionStatus,
|
||||
children: stat ? t("Last message seen ") + `${ago(new Date(stat).getTime())}.` : NOT_SEEN
|
||||
children: stat
|
||||
? t("Last message seen ") + `${ago(new Date(stat).getTime())}.`
|
||||
: NOT_SEEN
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ export class PinBindingInputGroup
|
|||
<button
|
||||
className="fb-button green"
|
||||
type="button"
|
||||
onClick={this.bindPin} >
|
||||
onClick={this.bindPin}>
|
||||
{t("BIND")}
|
||||
</button>
|
||||
</Col>
|
||||
|
|
|
@ -83,7 +83,7 @@ export const PinBindings = (props: PinBindingsProps) => {
|
|||
<Popover
|
||||
position={Position.RIGHT_TOP}
|
||||
interactionKind={PopoverInteractionKind.HOVER}
|
||||
popoverClassName={"help"} >
|
||||
popoverClassName={"help"}>
|
||||
<i className="fa fa-exclamation-triangle" />
|
||||
<div>
|
||||
{t(ToolTips.PIN_BINDING_WARNING)}
|
||||
|
|
|
@ -36,7 +36,7 @@ export class DropArea extends React.Component<DropAreaProps, DropAreaState> {
|
|||
}}
|
||||
onDragOver={this.dragOver}
|
||||
onDrop={this.drop}
|
||||
style={{ minHeight: "2rem" }} >
|
||||
style={{ minHeight: "2rem" }}>
|
||||
{this.props.children}
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export const NULL_DRAGGER_ID = 0xCAFEF00D;
|
|||
* Example usage:
|
||||
*
|
||||
* <button draggable={true}
|
||||
* onDragStart={stepDragEventHandler(dispatch, step, "optnl-stuff")} >
|
||||
* onDragStart={stepDragEventHandler(dispatch, step, "optnl-stuff")}>
|
||||
* Drag this!
|
||||
* </button>
|
||||
* */
|
||||
|
@ -36,7 +36,7 @@ export function StepDragger({ dispatch,
|
|||
onDragStart={stepDragEventHandler(dispatch,
|
||||
step,
|
||||
intent,
|
||||
draggerId)} >
|
||||
draggerId)}>
|
||||
{children}
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Widget, WidgetHeader, WidgetBody } from "../ui";
|
||||
import { t } from "../i18next_wrapper";
|
||||
|
||||
|
|
|
@ -1,36 +1,24 @@
|
|||
|
||||
jest.mock("../../api/crud", () => {
|
||||
return { overwrite: jest.fn() };
|
||||
});
|
||||
|
||||
jest.mock("../point_groups/group_detail", () => {
|
||||
return {
|
||||
fetchGroupFromUrl: jest.fn(() => mockGroup)
|
||||
};
|
||||
});
|
||||
jest.mock("../point_groups/group_detail", () => ({
|
||||
fetchGroupFromUrl: jest.fn(() => mockGroup)
|
||||
}));
|
||||
|
||||
jest.mock("../../api/crud", () => ({
|
||||
overwrite: jest.fn(),
|
||||
edit: jest.fn()
|
||||
edit: jest.fn(),
|
||||
}));
|
||||
|
||||
let mockMode = "none";
|
||||
jest.mock("../map/util", () => ({ getMode: jest.fn(() => mockMode) }));
|
||||
|
||||
jest.mock("../map/util", () => {
|
||||
return {
|
||||
getMode: jest.fn(() => mockMode)
|
||||
};
|
||||
});
|
||||
|
||||
import { fakePlant, fakePointGroup } from "../../__test_support__/fake_state/resources";
|
||||
import {
|
||||
fakePlant, fakePointGroup
|
||||
} from "../../__test_support__/fake_state/resources";
|
||||
import { fakeState } from "../../__test_support__/fake_state";
|
||||
import { GetState } from "../../redux/interfaces";
|
||||
import { clickMapPlant, selectPlant, toggleHoveredPlant } from "../actions";
|
||||
import {
|
||||
clickMapPlant,
|
||||
selectPlant,
|
||||
toggleHoveredPlant
|
||||
} from "../actions";
|
||||
import { buildResourceIndex } from "../../__test_support__/resource_index_builder";
|
||||
buildResourceIndex
|
||||
} from "../../__test_support__/resource_index_builder";
|
||||
import { overwrite } from "../../api/crud";
|
||||
|
||||
const mockGroup = fakePointGroup();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "/app/designer/plants";
|
||||
jest.mock("../../history", () => ({
|
||||
history: { getCurrentLocation: jest.fn(() => ({ pathname: mockPath })) },
|
||||
|
@ -11,8 +9,10 @@ jest.mock("../../api/crud", () => ({
|
|||
save: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../plants/plant_inventory", () => ({ Plants: () => <div /> }));
|
||||
|
||||
import * as React from "react";
|
||||
import { RawFarmDesigner } from "../index";
|
||||
import { RawFarmDesigner as FarmDesigner } from "../index";
|
||||
import { mount } from "enzyme";
|
||||
import { Props } from "../interfaces";
|
||||
import { GardenMapLegendProps } from "../map/interfaces";
|
||||
|
@ -22,48 +22,47 @@ import {
|
|||
} from "../../__test_support__/fake_state/resources";
|
||||
import { fakeDesignerState } from "../../__test_support__/fake_designer_state";
|
||||
import { fakeTimeSettings } from "../../__test_support__/fake_time_settings";
|
||||
import { buildResourceIndex } from "../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../__test_support__/resource_index_builder";
|
||||
import { fakeState } from "../../__test_support__/fake_state";
|
||||
import { edit } from "../../api/crud";
|
||||
import { BooleanSetting } from "../../session_keys";
|
||||
|
||||
describe("<RawFarmDesigner/>", () => {
|
||||
function fakeProps(): Props {
|
||||
|
||||
return {
|
||||
dispatch: jest.fn(),
|
||||
selectedPlant: undefined,
|
||||
designer: fakeDesignerState(),
|
||||
hoveredPlant: undefined,
|
||||
points: [],
|
||||
plants: [],
|
||||
toolSlots: [],
|
||||
crops: [],
|
||||
botLocationData: {
|
||||
position: { x: undefined, y: undefined, z: undefined },
|
||||
scaled_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
raw_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
},
|
||||
botMcuParams: bot.hardware.mcu_params,
|
||||
stepsPerMmXY: { x: undefined, y: undefined },
|
||||
peripherals: [],
|
||||
eStopStatus: false,
|
||||
latestImages: [],
|
||||
cameraCalibrationData: {
|
||||
scale: undefined, rotation: undefined,
|
||||
offset: { x: undefined, y: undefined },
|
||||
origin: undefined,
|
||||
calibrationZ: undefined
|
||||
},
|
||||
timeSettings: fakeTimeSettings(),
|
||||
getConfigValue: jest.fn(),
|
||||
sensorReadings: [],
|
||||
sensors: [],
|
||||
};
|
||||
}
|
||||
describe("<FarmDesigner/>", () => {
|
||||
const fakeProps = (): Props => ({
|
||||
dispatch: jest.fn(),
|
||||
selectedPlant: undefined,
|
||||
designer: fakeDesignerState(),
|
||||
hoveredPlant: undefined,
|
||||
points: [],
|
||||
plants: [],
|
||||
toolSlots: [],
|
||||
crops: [],
|
||||
botLocationData: {
|
||||
position: { x: undefined, y: undefined, z: undefined },
|
||||
scaled_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
raw_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
},
|
||||
botMcuParams: bot.hardware.mcu_params,
|
||||
stepsPerMmXY: { x: undefined, y: undefined },
|
||||
peripherals: [],
|
||||
eStopStatus: false,
|
||||
latestImages: [],
|
||||
cameraCalibrationData: {
|
||||
scale: undefined, rotation: undefined,
|
||||
offset: { x: undefined, y: undefined },
|
||||
origin: undefined,
|
||||
calibrationZ: undefined
|
||||
},
|
||||
timeSettings: fakeTimeSettings(),
|
||||
getConfigValue: jest.fn(),
|
||||
sensorReadings: [],
|
||||
sensors: [],
|
||||
});
|
||||
|
||||
it("loads default map settings", () => {
|
||||
const wrapper = mount(<RawFarmDesigner {...fakeProps()} />);
|
||||
const wrapper = mount(<FarmDesigner {...fakeProps()} />);
|
||||
const legendProps =
|
||||
wrapper.find("GardenMapLegend").props() as GardenMapLegendProps;
|
||||
expect(legendProps.legendMenuOpen).toBeFalsy();
|
||||
|
@ -86,7 +85,7 @@ describe("<RawFarmDesigner/>", () => {
|
|||
image1.body.created_at = "2001-01-03T00:00:00.000Z";
|
||||
image2.body.created_at = "2001-01-01T00:00:00.000Z";
|
||||
p.latestImages = [image1, image2];
|
||||
const wrapper = mount(<RawFarmDesigner {...p} />);
|
||||
const wrapper = mount(<FarmDesigner {...p} />);
|
||||
const legendProps =
|
||||
wrapper.find("GardenMapLegend").props() as GardenMapLegendProps;
|
||||
expect(legendProps.imageAgeInfo)
|
||||
|
@ -95,28 +94,34 @@ describe("<RawFarmDesigner/>", () => {
|
|||
|
||||
it("renders nav titles", () => {
|
||||
mockPath = "/app/designer/plants";
|
||||
const wrapper = mount(<RawFarmDesigner {...fakeProps()} />);
|
||||
const wrapper = mount(<FarmDesigner {...fakeProps()} />);
|
||||
["Map", "Plants", "Events"].map(string =>
|
||||
expect(wrapper.text()).toContain(string));
|
||||
expect(wrapper.find(".panel-nav").first().hasClass("hidden")).toBeTruthy();
|
||||
expect(wrapper.find(".farm-designer-panels").hasClass("panel-open")).toBeTruthy();
|
||||
expect(wrapper.find(".farm-designer-map").hasClass("panel-open")).toBeTruthy();
|
||||
expect(wrapper.find(".panel-nav").first().hasClass("hidden"))
|
||||
.toBeTruthy();
|
||||
expect(wrapper.find(".farm-designer-panels").hasClass("panel-open"))
|
||||
.toBeTruthy();
|
||||
expect(wrapper.find(".farm-designer-map").hasClass("panel-open"))
|
||||
.toBeTruthy();
|
||||
});
|
||||
|
||||
it("hides panel", () => {
|
||||
mockPath = "/app/designer";
|
||||
const wrapper = mount(<RawFarmDesigner {...fakeProps()} />);
|
||||
const wrapper = mount(<FarmDesigner {...fakeProps()} />);
|
||||
["Map", "Plants", "Events"].map(string =>
|
||||
expect(wrapper.text()).toContain(string));
|
||||
expect(wrapper.find(".panel-nav").first().hasClass("hidden")).toBeFalsy();
|
||||
expect(wrapper.find(".farm-designer-panels").hasClass("panel-open")).toBeFalsy();
|
||||
expect(wrapper.find(".farm-designer-map").hasClass("panel-open")).toBeFalsy();
|
||||
expect(wrapper.find(".panel-nav").first().hasClass("hidden"))
|
||||
.toBeFalsy();
|
||||
expect(wrapper.find(".farm-designer-panels").hasClass("panel-open"))
|
||||
.toBeFalsy();
|
||||
expect(wrapper.find(".farm-designer-map").hasClass("panel-open"))
|
||||
.toBeFalsy();
|
||||
});
|
||||
|
||||
it("renders saved garden indicator", () => {
|
||||
const p = fakeProps();
|
||||
p.designer.openedSavedGarden = "SavedGardenUuid";
|
||||
const wrapper = mount(<RawFarmDesigner {...p} />);
|
||||
const wrapper = mount(<FarmDesigner {...p} />);
|
||||
expect(wrapper.text().toLowerCase()).toContain("viewing saved garden");
|
||||
});
|
||||
|
||||
|
@ -126,8 +131,10 @@ describe("<RawFarmDesigner/>", () => {
|
|||
const dispatch = jest.fn();
|
||||
state.resources = buildResourceIndex([fakeWebAppConfig()]);
|
||||
p.dispatch = jest.fn(x => x(dispatch, () => state));
|
||||
const wrapper = mount<RawFarmDesigner>(<RawFarmDesigner {...p} />);
|
||||
const wrapper = mount<FarmDesigner>(<FarmDesigner {...p} />);
|
||||
wrapper.instance().toggle(BooleanSetting.show_plants)();
|
||||
expect(edit).toHaveBeenCalledWith(expect.any(Object), { bot_origin_quadrant: 2 });
|
||||
expect(edit).toHaveBeenCalledWith(expect.any(Object), {
|
||||
bot_origin_quadrant: 2
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
const mockDevice = { moveAbsolute: jest.fn(() => Promise.resolve()) };
|
||||
jest.mock("../../device", () => ({ getDevice: () => mockDevice }));
|
||||
|
||||
|
@ -12,8 +10,8 @@ jest.mock("../../history", () => ({
|
|||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import {
|
||||
MoveTo, MoveToProps, MoveToForm, MoveToFormProps, MoveModeLink, chooseLocation,
|
||||
mapStateToProps
|
||||
RawMoveTo as MoveTo, MoveToProps, MoveToForm, MoveToFormProps,
|
||||
MoveModeLink, chooseLocation, mapStateToProps,
|
||||
} from "../move_to";
|
||||
import { history } from "../../history";
|
||||
import { Actions } from "../../constants";
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../config_storage/actions", () => ({
|
||||
getWebAppConfigValue: jest.fn(x => { x(); return jest.fn(() => true); }),
|
||||
setWebAppConfigValue: jest.fn(),
|
||||
|
@ -8,7 +6,8 @@ jest.mock("../../config_storage/actions", () => ({
|
|||
import * as React from "react";
|
||||
import { mount, ReactWrapper } from "enzyme";
|
||||
import {
|
||||
RawDesignerSettings, DesignerSettingsProps, mapStateToProps
|
||||
RawDesignerSettings as DesignerSettings, DesignerSettingsProps,
|
||||
mapStateToProps,
|
||||
} from "../settings";
|
||||
import { fakeState } from "../../__test_support__/fake_state";
|
||||
import { BooleanSetting, NumericSetting } from "../../session_keys";
|
||||
|
@ -22,14 +21,14 @@ const getSetting =
|
|||
return setting;
|
||||
};
|
||||
|
||||
describe("<RawDesignerSettings />", () => {
|
||||
describe("<DesignerSettings />", () => {
|
||||
const fakeProps = (): DesignerSettingsProps => ({
|
||||
dispatch: jest.fn(),
|
||||
getConfigValue: jest.fn(),
|
||||
});
|
||||
|
||||
it("renders settings", () => {
|
||||
const wrapper = mount(<RawDesignerSettings {...fakeProps()} />);
|
||||
const wrapper = mount(<DesignerSettings {...fakeProps()} />);
|
||||
expect(wrapper.text()).toContain("size");
|
||||
const settings = wrapper.find(".designer-setting");
|
||||
expect(settings.length).toEqual(7);
|
||||
|
@ -38,13 +37,13 @@ describe("<RawDesignerSettings />", () => {
|
|||
it("renders defaultOn setting", () => {
|
||||
const p = fakeProps();
|
||||
p.getConfigValue = () => undefined;
|
||||
const wrapper = mount(<RawDesignerSettings {...p} />);
|
||||
const wrapper = mount(<DesignerSettings {...p} />);
|
||||
const confirmDeletion = getSetting(wrapper, 6, "confirm plant");
|
||||
expect(confirmDeletion.find("button").text()).toEqual("on");
|
||||
});
|
||||
|
||||
it("toggles setting", () => {
|
||||
const wrapper = mount(<RawDesignerSettings {...fakeProps()} />);
|
||||
const wrapper = mount(<DesignerSettings {...fakeProps()} />);
|
||||
const trailSetting = getSetting(wrapper, 1, "trail");
|
||||
trailSetting.find("button").simulate("click");
|
||||
expect(setWebAppConfigValue)
|
||||
|
@ -54,7 +53,7 @@ describe("<RawDesignerSettings />", () => {
|
|||
it("changes origin", () => {
|
||||
const p = fakeProps();
|
||||
p.getConfigValue = () => 2;
|
||||
const wrapper = mount(<RawDesignerSettings {...p} />);
|
||||
const wrapper = mount(<DesignerSettings {...p} />);
|
||||
const originSetting = getSetting(wrapper, 5, "origin");
|
||||
originSetting.find("div").last().simulate("click");
|
||||
expect(setWebAppConfigValue).toHaveBeenCalledWith(
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../history", () => ({ history: { push: jest.fn() } }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { AddFarmEvent } from "../add_farm_event";
|
||||
import { RawAddFarmEvent as AddFarmEvent } from "../add_farm_event";
|
||||
import { AddEditFarmEventProps } from "../../interfaces";
|
||||
import {
|
||||
fakeFarmEvent, fakeSequence, fakeRegimen
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
jest.mock("react-redux", () => ({
|
||||
connect: jest.fn(() => (x: {}) => x)
|
||||
}));
|
||||
|
||||
jest.mock("../../../history", () => ({
|
||||
history: {
|
||||
push: jest.fn()
|
||||
}
|
||||
history: { push: jest.fn() }
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { EditFarmEvent } from "../edit_farm_event";
|
||||
import { RawEditFarmEvent as EditFarmEvent } from "../edit_farm_event";
|
||||
import { AddEditFarmEventProps } from "../../interfaces";
|
||||
import {
|
||||
fakeFarmEvent, fakeSequence
|
||||
|
|
|
@ -2,12 +2,13 @@ import { Regimen } from "../../../regimens/interfaces";
|
|||
import { Sequence } from "../../../sequences/interfaces";
|
||||
import { FarmEvent } from "farmbot/dist/resources/api_resources";
|
||||
|
||||
/** Would it be better to make a fully formed farm event? Join regimen, sequence, etc. */
|
||||
/** Make a fully formed farm event: join regimen, sequence, etc. */
|
||||
|
||||
/** STEP 1: Extract querying of data and formatting of data into two
|
||||
* sep. function. This function will join `executable` on `farm_event`. */
|
||||
|
||||
export type FarmEventWithExecutable = FarmEventWithRegimen | FarmEventWithSequence;
|
||||
export type FarmEventWithExecutable =
|
||||
FarmEventWithRegimen | FarmEventWithSequence;
|
||||
|
||||
/** Takes a farm event and merges it with its sequence object. */
|
||||
export interface FarmEventWithSequence extends FarmEvent {
|
||||
|
|
|
@ -27,9 +27,8 @@ export function joinFarmEventsToExecutable(
|
|||
executable_type: body.executable_type,
|
||||
executable: executable1.body
|
||||
};
|
||||
} else {
|
||||
throw new Error("Bad executable ID (sequence): " + id);
|
||||
}
|
||||
break;
|
||||
case "Regimen":
|
||||
const executable2 = regimenById[id];
|
||||
if (executable2) {
|
||||
|
@ -38,12 +37,9 @@ export function joinFarmEventsToExecutable(
|
|||
executable_type: body.executable_type,
|
||||
executable: executable2.body
|
||||
};
|
||||
} else {
|
||||
throw new Error("Bad executable ID (regimen): " + id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error("Farmevent had no ID");
|
||||
}
|
||||
throw new Error("Impossible?");
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ import {
|
|||
maybeGetTimeSettings,
|
||||
} from "../../resources/selectors";
|
||||
import { ResourceIndex } from "../../resources/interfaces";
|
||||
import { FarmEventWithRegimen, FarmEventWithSequence } from "./calendar/interfaces";
|
||||
import {
|
||||
FarmEventWithRegimen, FarmEventWithSequence
|
||||
} from "./calendar/interfaces";
|
||||
import { scheduleForFarmEvent } from "./calendar/scheduler";
|
||||
import { last } from "lodash";
|
||||
import { RegimenItem } from "../../regimens/interfaces";
|
||||
|
@ -63,7 +65,8 @@ export const nextRegItemTimes =
|
|||
&& time.isSameOrAfter(moment(startTime)));
|
||||
};
|
||||
|
||||
export let regimenCalendarAdder = (index: ResourceIndex, timeSettings: TimeSettings) =>
|
||||
export let regimenCalendarAdder = (
|
||||
index: ResourceIndex, timeSettings: TimeSettings) =>
|
||||
(f: FarmEventWithRegimen, c: Calendar, now = moment()) => {
|
||||
const { regimen_items } = f.executable;
|
||||
const gracePeriod = itemGracePeriod(now);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { timezoneMismatch } from "../../devices/timezones/guess_timezone";
|
||||
import { Content } from "../../constants";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { transformXY } from "../util";
|
||||
import { MapTransformProps, BotSize } from "../interfaces";
|
||||
import { random, range, some, clamp, sample } from "lodash";
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "";
|
||||
jest.mock("../../../history", () => ({
|
||||
history: { push: jest.fn() },
|
||||
|
@ -8,7 +6,7 @@ jest.mock("../../../history", () => ({
|
|||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { AddPlant, AddPlantProps } from "../add_plant";
|
||||
import { RawAddPlant as AddPlant, AddPlantProps } from "../add_plant";
|
||||
import { history } from "../../../history";
|
||||
import {
|
||||
fakeCropLiveSearchResult
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
jest.mock("react-redux", () => ({
|
||||
connect: jest.fn(() => (x: {}) => x)
|
||||
}));
|
||||
|
||||
jest.mock("../../../api/crud", () => ({
|
||||
initSave: jest.fn()
|
||||
}));
|
||||
jest.mock("../../../api/crud", () => ({ initSave: jest.fn() }));
|
||||
|
||||
jest.mock("../../../farmware/weed_detector/actions", () => ({
|
||||
deletePoints: jest.fn()
|
||||
|
@ -49,14 +43,12 @@ describe("mapStateToProps", () => {
|
|||
});
|
||||
|
||||
describe("<CreatePoints />", () => {
|
||||
const fakeProps = (): CreatePointsProps => {
|
||||
return {
|
||||
dispatch: jest.fn(),
|
||||
currentPoint: undefined,
|
||||
deviceY: 1.23,
|
||||
deviceX: 3.21
|
||||
};
|
||||
};
|
||||
const fakeProps = (): CreatePointsProps => ({
|
||||
dispatch: jest.fn(),
|
||||
currentPoint: undefined,
|
||||
deviceY: 1.23,
|
||||
deviceX: 3.21
|
||||
});
|
||||
|
||||
const fakeInstance = () => {
|
||||
const props = fakeProps();
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
jest.mock("react-redux", () => ({
|
||||
connect: jest.fn(() => (x: {}) => x)
|
||||
}));
|
||||
|
||||
jest.mock("lodash", () => ({
|
||||
debounce: jest.fn(x => x),
|
||||
trim: jest.fn(x => x),
|
||||
|
@ -14,7 +10,7 @@ jest.mock("lodash", () => ({
|
|||
jest.mock("../../../history", () => ({ history: { push: jest.fn() } }));
|
||||
|
||||
import * as React from "react";
|
||||
import { CropCatalog } from "../crop_catalog";
|
||||
import { RawCropCatalog as CropCatalog } from "../crop_catalog";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { CropCatalogProps } from "../../interfaces";
|
||||
import { Actions } from "../../../constants";
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "";
|
||||
jest.mock("../../../history", () => ({
|
||||
getPathArray: jest.fn(() => { return mockPath.split("/"); }),
|
||||
history: { push: jest.fn() }
|
||||
}));
|
||||
|
||||
jest.mock("../../../api/crud", () => ({
|
||||
initSave: jest.fn()
|
||||
}));
|
||||
jest.mock("../../../api/crud", () => ({ initSave: jest.fn() }));
|
||||
|
||||
jest.mock("../../actions", () => ({
|
||||
unselectPlant: jest.fn(() => jest.fn()),
|
||||
|
@ -16,7 +12,7 @@ jest.mock("../../actions", () => ({
|
|||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { CropInfo, searchForCurrentCrop } from "../crop_info";
|
||||
import { RawCropInfo as CropInfo, searchForCurrentCrop } from "../crop_info";
|
||||
import { mount } from "enzyme";
|
||||
import { CropInfoProps } from "../../interfaces";
|
||||
import { initSave } from "../../../api/crud";
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "/app/designer/plants/1";
|
||||
jest.mock("../../../history", () => ({
|
||||
getPathArray: jest.fn(() => mockPath.split("/")),
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
import * as React from "react";
|
||||
import { RawPlants, PlantInventoryProps } from "../plant_inventory";
|
||||
import { RawPlants as Plants, PlantInventoryProps } from "../plant_inventory";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { fakePlant } from "../../../__test_support__/fake_state/resources";
|
||||
|
||||
|
@ -13,7 +11,7 @@ describe("<PlantInventory />", () => {
|
|||
});
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<RawPlants {...fakeProps()} />);
|
||||
const wrapper = mount(<Plants {...fakeProps()} />);
|
||||
["Map",
|
||||
"Plants",
|
||||
"Events",
|
||||
|
@ -25,13 +23,13 @@ describe("<PlantInventory />", () => {
|
|||
});
|
||||
|
||||
it("has link to crops", () => {
|
||||
const wrapper = mount(<RawPlants {...fakeProps()} />);
|
||||
const wrapper = mount(<Plants {...fakeProps()} />);
|
||||
expect(wrapper.html()).toContain("fa-plus");
|
||||
expect(wrapper.html()).toContain("/app/designer/plants/crop_search");
|
||||
});
|
||||
|
||||
it("updates search term", () => {
|
||||
const wrapper = shallow<RawPlants>(<RawPlants {...fakeProps()} />);
|
||||
const wrapper = shallow<Plants>(<Plants {...fakeProps()} />);
|
||||
expect(wrapper.state().searchTerm).toEqual("");
|
||||
wrapper.find("input").first().simulate("change",
|
||||
{ currentTarget: { value: "mint" } });
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "/app/designer/points/1";
|
||||
jest.mock("../../../history", () => ({
|
||||
getPathArray: jest.fn(() => mockPath.split("/")),
|
||||
|
@ -7,17 +5,20 @@ jest.mock("../../../history", () => ({
|
|||
}));
|
||||
|
||||
const mockMoveAbs = jest.fn();
|
||||
|
||||
jest.mock("../../../device", () => {
|
||||
return { getDevice: () => ({ moveAbsolute: mockMoveAbs }) };
|
||||
});
|
||||
jest.mock("../../../device", () => ({
|
||||
getDevice: () => ({ moveAbsolute: mockMoveAbs })
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { EditPoint, EditPointProps, mapStateToProps, moveToPoint } from "../point_info";
|
||||
import {
|
||||
RawEditPoint as EditPoint, EditPointProps, mapStateToProps, moveToPoint
|
||||
} from "../point_info";
|
||||
import { fakePoint } from "../../../__test_support__/fake_state/resources";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { getDevice } from "../../../device";
|
||||
|
||||
describe("<EditPoint />", () => {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../history", () => ({
|
||||
push: jest.fn(),
|
||||
getPathArray: () => [],
|
||||
|
@ -7,7 +5,7 @@ jest.mock("../../../history", () => ({
|
|||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { RawPoints, PointsProps } from "../point_inventory";
|
||||
import { RawPoints as Points, PointsProps } from "../point_inventory";
|
||||
import { fakePoint } from "../../../__test_support__/fake_state/resources";
|
||||
import { push } from "../../../history";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
|
@ -16,21 +14,21 @@ import {
|
|||
} from "../../../__test_support__/resource_index_builder";
|
||||
import { mapStateToProps } from "../point_inventory";
|
||||
|
||||
describe("<RawPoints> />", () => {
|
||||
describe("<Points> />", () => {
|
||||
const fakeProps = (): PointsProps => ({
|
||||
points: [],
|
||||
dispatch: jest.fn(),
|
||||
});
|
||||
|
||||
it("renders no points", () => {
|
||||
const wrapper = mount(<RawPoints {...fakeProps()} />);
|
||||
const wrapper = mount(<Points {...fakeProps()} />);
|
||||
expect(wrapper.text()).toContain("No points yet.");
|
||||
});
|
||||
|
||||
it("renders points", () => {
|
||||
const p = fakeProps();
|
||||
p.points = [fakePoint()];
|
||||
const wrapper = mount(<RawPoints {...p} />);
|
||||
const wrapper = mount(<Points {...p} />);
|
||||
expect(wrapper.text()).toContain("Point 1");
|
||||
});
|
||||
|
||||
|
@ -38,7 +36,7 @@ describe("<RawPoints> />", () => {
|
|||
const p = fakeProps();
|
||||
p.points = [fakePoint()];
|
||||
p.points[0].body.id = 1;
|
||||
const wrapper = mount(<RawPoints {...p} />);
|
||||
const wrapper = mount(<Points {...p} />);
|
||||
wrapper.find(".point-search-item").first().simulate("click");
|
||||
expect(push).toHaveBeenCalledWith("/app/designer/points/1");
|
||||
});
|
||||
|
@ -48,7 +46,7 @@ describe("<RawPoints> />", () => {
|
|||
p.points = [fakePoint(), fakePoint()];
|
||||
p.points[0].body.name = "point 0";
|
||||
p.points[1].body.name = "point 1";
|
||||
const wrapper = shallow<RawPoints>(<RawPoints {...p} />);
|
||||
const wrapper = shallow<Points>(<Points {...p} />);
|
||||
wrapper.find("input").first().simulate("change",
|
||||
{ currentTarget: { value: "0" } });
|
||||
expect(wrapper.state().searchTerm).toEqual("0");
|
||||
|
@ -59,7 +57,7 @@ describe("<RawPoints> />", () => {
|
|||
p.points = [fakePoint(), fakePoint()];
|
||||
p.points[0].body.name = "point 0";
|
||||
p.points[1].body.name = "point 1";
|
||||
const wrapper = mount(<RawPoints {...p} />);
|
||||
const wrapper = mount(<Points {...p} />);
|
||||
wrapper.setState({ searchTerm: "0" });
|
||||
expect(wrapper.text()).not.toContain("point 1");
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
let mockPath = "";
|
||||
jest.mock("../../../history", () => ({
|
||||
history: { push: jest.fn() },
|
||||
|
@ -17,7 +15,9 @@ jest.mock("../../point_groups/actions", () => ({ createGroup: jest.fn() }));
|
|||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { SelectPlants, SelectPlantsProps } from "../select_plants";
|
||||
import {
|
||||
RawSelectPlants as SelectPlants, SelectPlantsProps
|
||||
} from "../select_plants";
|
||||
import { fakePlant } from "../../../__test_support__/fake_state/resources";
|
||||
import { Actions } from "../../../constants";
|
||||
import { clickButton } from "../../../__test_support__/helpers";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from "react";
|
||||
import { Everything } from "../../interfaces";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { history } from "../../history";
|
||||
import { svgToUrl } from "../../open_farm/icons";
|
||||
import { CropLiveSearchResult, OpenfarmSearch } from "../interfaces";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from "react";
|
||||
import { Everything } from "../../interfaces";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { OpenFarmResults } from "./openfarm_search_results";
|
||||
import { CropCatalogProps } from "../interfaces";
|
||||
import { OFSearch } from "../util";
|
||||
|
|
|
@ -170,7 +170,7 @@ const EditOnOpenFarm = ({ slug }: { slug: string }) =>
|
|||
<div className="edit-on-openfarm">
|
||||
<span>{t("Edit on")} </span>
|
||||
<a href={OpenFarm.browsingCropUrl + slug} target="_blank"
|
||||
title={t("Open OpenFarm.cc in a new tab")} >
|
||||
title={t("Open OpenFarm.cc in a new tab")}>
|
||||
{"OpenFarm"}
|
||||
</a>
|
||||
</div>;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { PlantInventoryItem } from "./plant_inventory_item";
|
||||
import { Everything } from "../../interfaces";
|
||||
import { Panel, DesignerNavTabs } from "../panel_header";
|
||||
|
|
|
@ -157,7 +157,7 @@ const DeleteButtons = (props: DeleteButtonsProps) =>
|
|||
<button
|
||||
className="fb-button gray no-float"
|
||||
style={{ marginRight: "10px" }}
|
||||
onClick={() => history.push("/app/designer/plants/select")} >
|
||||
onClick={() => history.push("/app/designer/plants/select")}>
|
||||
{t("Delete multiple")}
|
||||
</button>
|
||||
</div>;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
const mockId = 123;
|
||||
|
||||
jest.mock("../../../history", () => {
|
||||
return {
|
||||
getPathArray: jest.fn(() => [mockId])
|
||||
};
|
||||
});
|
||||
jest.mock("../../../history", () => ({
|
||||
getPathArray: jest.fn(() => [mockId])
|
||||
}));
|
||||
|
||||
import { fetchGroupFromUrl } from "../group_detail";
|
||||
import { fakePointGroup } from "../../../__test_support__/fake_state/resources";
|
||||
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
|
||||
describe("fetchGroupFromUrl", () => {
|
||||
it("fetches a group from URL", () => {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../history", () => ({
|
||||
getPathArray: jest.fn(() => ["L", "O", "L"]),
|
||||
history: { push: jest.fn() }
|
||||
|
@ -7,11 +5,15 @@ jest.mock("../../../history", () => ({
|
|||
|
||||
import React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { RawGroupListPanel as GroupListPanel, GroupListPanelProps, mapStateToProps } from "../group_list_panel";
|
||||
import {
|
||||
RawGroupListPanel as GroupListPanel, GroupListPanelProps, mapStateToProps
|
||||
} from "../group_list_panel";
|
||||
import { fakePointGroup } from "../../../__test_support__/fake_state/resources";
|
||||
import { history } from "../../../history";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
|
||||
describe("<GroupListPanel />", () => {
|
||||
const fakeProps = (): GroupListPanelProps => {
|
||||
|
|
|
@ -53,8 +53,8 @@ export const LittleIcon =
|
|||
</span>;
|
||||
};
|
||||
|
||||
export class GroupDetailActive extends React.Component<GroupDetailActiveProps, State> {
|
||||
|
||||
export class GroupDetailActive
|
||||
extends React.Component<GroupDetailActiveProps, State> {
|
||||
state: State = { icons: {} };
|
||||
|
||||
update = ({ currentTarget }: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
|
@ -126,7 +126,9 @@ export class GroupDetailActive extends React.Component<GroupDetailActiveProps, S
|
|||
<input
|
||||
defaultValue={this.name}
|
||||
onChange={this.update} />
|
||||
<label>{t("GROUP MEMBERS ({{count}})", { count: this.icons.length })}</label>
|
||||
<label>
|
||||
{t("GROUP MEMBERS ({{count}})", { count: this.icons.length })}
|
||||
</label>
|
||||
<p>
|
||||
{t("Click plants in map to add or remove.")}
|
||||
</p>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../actions", () => ({
|
||||
snapshotGarden: jest.fn(),
|
||||
applyGarden: jest.fn(),
|
||||
|
@ -25,7 +23,8 @@ jest.mock("../../../account/dev/dev_support", () => ({
|
|||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import {
|
||||
SavedGardens, mapStateToProps, SavedGardensLink, SavedGardenHUD, savedGardenOpen
|
||||
RawSavedGardens as SavedGardens, mapStateToProps, SavedGardensLink,
|
||||
SavedGardenHUD, savedGardenOpen,
|
||||
} from "../saved_gardens";
|
||||
import { clickButton } from "../../../__test_support__/helpers";
|
||||
import {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { snapshotGarden, newSavedGarden, copySavedGarden } from "./actions";
|
||||
import { TaggedPlantTemplate, TaggedSavedGarden } from "farmbot";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { CropLiveSearchResult } from "./interfaces";
|
||||
|
||||
import { DEFAULT_ICON } from "../open_farm/icons";
|
||||
import { startCase, find } from "lodash";
|
||||
import { t } from "../i18next_wrapper";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../api/crud", () => ({ initSave: jest.fn() }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { RawAddTool as AddTool, AddToolProps, mapStateToProps } from "../add_tool";
|
||||
import {
|
||||
RawAddTool as AddTool, AddToolProps, mapStateToProps
|
||||
} from "../add_tool";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { SaveBtn } from "../../../ui";
|
||||
import { initSave } from "../../../api/crud";
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../api/crud", () => ({ edit: jest.fn() }));
|
||||
|
||||
jest.mock("../../../history", () => ({
|
||||
|
@ -9,7 +7,9 @@ jest.mock("../../../history", () => ({
|
|||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { RawEditTool as EditTool, EditToolProps, mapStateToProps } from "../edit_tool";
|
||||
import {
|
||||
RawEditTool as EditTool, EditToolProps, mapStateToProps
|
||||
} from "../edit_tool";
|
||||
import { fakeTool } from "../../../__test_support__/fake_state/resources";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
jest.mock("../../../history", () => ({
|
||||
history: { push: jest.fn() },
|
||||
getPathArray: () => "/app/designer/tools".split("/"),
|
||||
|
@ -13,7 +11,9 @@ import {
|
|||
} from "../../../__test_support__/fake_state/resources";
|
||||
import { history } from "../../../history";
|
||||
import { fakeState } from "../../../__test_support__/fake_state";
|
||||
import { buildResourceIndex } from "../../../__test_support__/resource_index_builder";
|
||||
import {
|
||||
buildResourceIndex
|
||||
} from "../../../__test_support__/resource_index_builder";
|
||||
|
||||
describe("<Tools />", () => {
|
||||
const fakeProps = (): ToolsProps => ({
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
|
||||
const mockDevice = { execScript: jest.fn(() => Promise.resolve({})) };
|
||||
jest.mock("../../device", () => ({ getDevice: () => mockDevice }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { FarmwarePage, BasicFarmwarePage } from "../index";
|
||||
import { RawFarmwarePage as FarmwarePage, BasicFarmwarePage } from "../index";
|
||||
import { FarmwareProps } from "../../devices/interfaces";
|
||||
import {
|
||||
fakeFarmware, fakeFarmwares
|
||||
|
|
|
@ -36,7 +36,7 @@ export class CameraCalibration extends
|
|||
lockOpen={process.env.NODE_ENV !== "production"}>
|
||||
<button
|
||||
onClick={this.props.dispatch(calibrate)}
|
||||
className="fb-button green" >
|
||||
className="fb-button green">
|
||||
{t("Calibrate")}
|
||||
</button>
|
||||
</MustBeOnline>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Col, BlurableInput } from "../ui/index";
|
||||
|
||||
import { Pair, FarmwareConfig } from "farmbot";
|
||||
import { getDevice } from "../device";
|
||||
import {
|
||||
|
@ -25,7 +24,8 @@ export function getConfigEnvName(farmwareName: string, configName: string) {
|
|||
}
|
||||
|
||||
/** Farmware description and version info for help text contents. */
|
||||
export function farmwareHelpText(farmware: FarmwareManifestInfo | undefined): string {
|
||||
export function farmwareHelpText(farmware: FarmwareManifestInfo | undefined):
|
||||
string {
|
||||
if (farmware) {
|
||||
const description = farmware.meta.description;
|
||||
const versionString = " (version: " + farmware.meta.version + ")";
|
||||
|
|
|
@ -37,7 +37,7 @@ const farmwareListItem = (dispatch: Function, current: string | undefined) =>
|
|||
to={`/app/farmware/${urlFriendly(farmwareName)}`}
|
||||
key={farmwareName}
|
||||
onClick={click}>
|
||||
<div className={`farmware-list-items ${selected}`} >
|
||||
<div className={`farmware-list-items ${selected}`}>
|
||||
<p>{displayName}</p>
|
||||
</div>
|
||||
</Link>;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ImageFlipperProps, ImageFlipperState } from "./interfaces";
|
||||
import { Content } from "../../constants";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
|
|
@ -2,19 +2,13 @@ const mockDevice = {
|
|||
execScript: jest.fn(() => Promise.resolve()),
|
||||
setUserEnv: jest.fn(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
jest.mock("../../../device", () => ({
|
||||
getDevice: () => {
|
||||
return mockDevice;
|
||||
}
|
||||
}));
|
||||
jest.mock("react-redux", () => ({ connect: jest.fn(() => (x: {}) => x) }));
|
||||
jest.mock("../../../device", () => ({ getDevice: () => mockDevice }));
|
||||
|
||||
jest.mock("../../images/actions", () => ({ selectImage: jest.fn() }));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { RawWeedDetector as WeedDetector, namespace } from "../index";
|
||||
import { WeedDetector, namespace } from "../index";
|
||||
import { FarmwareProps } from "../../../devices/interfaces";
|
||||
import { API } from "../../../api";
|
||||
import { selectImage } from "../../images/actions";
|
||||
|
|
|
@ -26,7 +26,8 @@ export class WeedDetectorConfig extends React.Component<SettingsMenuProps, {}> {
|
|||
<BlurableInput type="number"
|
||||
id={conf}
|
||||
value={"" + envGet(conf, this.props.values)}
|
||||
onCommit={e => this.props.onChange(conf, parseFloat(e.currentTarget.value))}
|
||||
onCommit={e =>
|
||||
this.props.onChange(conf, parseFloat(e.currentTarget.value))}
|
||||
placeholder={label} />
|
||||
</div>;
|
||||
};
|
||||
|
@ -54,10 +55,12 @@ export class WeedDetectorConfig extends React.Component<SettingsMenuProps, {}> {
|
|||
<input
|
||||
type="checkbox"
|
||||
id="invert_hue_selection"
|
||||
checked={!!envGet("CAMERA_CALIBRATION_invert_hue_selection", this.props.values)}
|
||||
onChange={e => this.props.onChange("CAMERA_CALIBRATION_invert_hue_selection",
|
||||
e.currentTarget.checked ?
|
||||
SPECIAL_VALUES.TRUE : SPECIAL_VALUES.FALSE)} />
|
||||
checked={!!envGet("CAMERA_CALIBRATION_invert_hue_selection",
|
||||
this.props.values)}
|
||||
onChange={e =>
|
||||
this.props.onChange("CAMERA_CALIBRATION_invert_hue_selection",
|
||||
e.currentTarget.checked ?
|
||||
SPECIAL_VALUES.TRUE : SPECIAL_VALUES.FALSE)} />
|
||||
</div>
|
||||
<this.NumberBox
|
||||
conf={"CAMERA_CALIBRATION_calibration_object_separation"}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { DropDownItem } from "../../ui/index";
|
||||
import { SPECIAL_VALUES } from "./remote_env/constants";
|
||||
import { t } from "../../i18next_wrapper";
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue