Farmbot-Web-App/frontend/devices/__tests__/reducer_test.ts

173 lines
5.7 KiB
TypeScript

jest.mock("../../redux/store", () => ({ store: jest.fn() }));
import { botReducer, initialState } from "../reducer";
import { Actions } from "../../constants";
import { ControlPanelState, BotState } from "../interfaces";
import { defensiveClone } from "../../util";
import { stash } from "../../connectivity/data_consistency";
import { incomingStatus } from "../../connectivity/connect_device";
import { Vector3, uuid } from "farmbot";
import { now } from "../connectivity/qos";
const statusOf = (state: BotState) => {
return state.hardware.informational_settings.sync_status;
};
describe("botReducer", () => {
it("Starts / stops an update", () => {
const step1 = botReducer(initialState(), {
type: Actions.SETTING_UPDATE_START,
payload: undefined
});
expect(step1.isUpdating).toBe(true);
const step2 = botReducer(step1, {
type: Actions.SETTING_UPDATE_END,
payload: undefined
});
expect(step2.isUpdating).toBe(false);
});
it("changes step size", () => {
const state = botReducer(initialState(), {
type: Actions.CHANGE_STEP_SIZE,
payload: 23
});
expect(state.stepSize).toBe(23);
});
it("toggles control panel options", () => {
const payload: keyof ControlPanelState = "danger_zone";
const state = botReducer(initialState(), {
type: Actions.TOGGLE_CONTROL_PANEL_OPTION,
payload
});
expect(state.controlPanelState.danger_zone)
.toBe(!initialState().controlPanelState.danger_zone);
});
it("bulk toggles firmware control panel options", () => {
const state = botReducer(initialState(), {
type: Actions.BULK_TOGGLE_CONTROL_PANEL,
payload: { open: true, all: false }
});
const bulkToggable =
Object.entries(state.controlPanelState).filter(([k, _]) => ![
"power_and_reset", "farmbot_os", "farm_designer", "firmware",
].includes(k));
Object.values(bulkToggable).map(value => {
expect(value).toBeTruthy();
});
});
it("bulk toggles all control panel options", () => {
const state = botReducer(initialState(), {
type: Actions.BULK_TOGGLE_CONTROL_PANEL,
payload: { open: true, all: true }
});
Object.values(state.controlPanelState).map(value => {
expect(value).toBeTruthy();
});
});
it("fetches OS update info", () => {
const r = botReducer(initialState(), {
type: Actions.FETCH_OS_UPDATE_INFO_OK,
payload: { version: "1.2.3", commit: undefined }
}).currentOSVersion;
expect(r).toBe("1.2.3");
});
it("fetches beta OS update info", () => {
const r = botReducer(initialState(), {
type: Actions.FETCH_BETA_OS_UPDATE_INFO_OK,
payload: { version: "1.2.3", commit: undefined }
}).currentBetaOSVersion;
expect(r).toBe("1.2.3");
});
it("fetches min OS feature data", () => {
const r = botReducer(initialState(), {
type: Actions.FETCH_MIN_OS_FEATURE_INFO_OK,
payload: {}
}).minOsFeatureData;
expect(r).toEqual({});
});
it("fetches OS release notes", () => {
const r = botReducer(initialState(), {
type: Actions.FETCH_OS_RELEASE_NOTES_OK,
payload: "notes"
}).osReleaseNotes;
expect(r).toEqual("notes");
});
it("Handles status_v8 info", () => {
const n = () => Math.round(Math.random() * 1000);
const position: Vector3 = { x: n(), y: n(), z: n() };
const state = initialState();
state.hardware.informational_settings.sync_status = "synced";
const action = incomingStatus({ location_data: { position } });
const r = botReducer(state, action);
expect(r.hardware.location_data.position).toEqual(position);
});
it("resets hardware state when transitioning into maintenance mode.", () => {
const state = initialState();
const payload = defensiveClone(state.hardware);
payload.informational_settings.sync_status = "maintenance";
payload.location_data.position.x = -1;
payload.location_data.position.y = -1;
payload.location_data.position.z = -1;
const action = { type: Actions.LEGACY_BOT_CHANGE, payload };
// Make the starting state different than initialState();
const result = botReducer(state, action);
// Resets .hardware to initialState()
expect(result.hardware.location_data.position)
.toEqual(initialState().hardware.location_data.position);
expect(result.hardware.informational_settings.sync_status)
.toBe("maintenance");
});
it("stashes/unstashes sync status based on connectivity", () => {
const step1 = initialState();
step1.statusStash = "booting";
step1.hardware.informational_settings.sync_status = "synced";
const go = (direction: "up" | "down", one: BotState) => {
const id = uuid();
const action1 = { type: Actions.PING_START, payload: { id } };
const two = botReducer(one, action1);
const type_ = (direction == "up") ? Actions.PING_OK : Actions.PING_NO;
const action2 = { type: type_, payload: { id, at: now() } };
return botReducer(two, action2);
};
const step2 = go("down", step1);
expect(step2.statusStash).toBe(statusOf(step1));
expect(statusOf(step2)).toBeUndefined();
const step3 = go("down", step2);
expect(step3.statusStash).toBe(statusOf(step1));
expect(statusOf(step3)).toBeUndefined();
const step4 = go("up", step3);
expect(statusOf(step4)).toBe(step3.statusStash);
});
it("handles STASH_STATUS / _RESOURCE_NO", () => {
const step1 = initialState();
step1.statusStash = "booting";
step1.hardware.informational_settings.sync_status = "synced";
const step2 = botReducer(step1, stash());
expect(step2.statusStash).toBe(statusOf(step1));
const no = { type: Actions._RESOURCE_NO, payload: undefined };
const step3 = botReducer(step2, no);
expect(statusOf(step3)).toBe(step3.statusStash);
});
});