bug fixes and tests

pull/449/head
gabrielburnworth 2017-09-08 11:38:46 -07:00
parent 4cf3f4fd2c
commit 89c10de58b
6 changed files with 193 additions and 35 deletions

View File

@ -0,0 +1,109 @@
jest.mock("fastclick", () => ({
attach: jest.fn(),
}));
import * as React from "react";
import { App, AppProps } from "../app";
import { mount } from "enzyme";
import { bot } from "../__test_support__/fake_state/bot";
import { fakeUser } from "../__test_support__/fake_state/resources";
import { createStore } from "redux";
import { reducers } from "../redux/root_reducer";
describe("<App />: Controls Pop-Up", () => {
function fakeProps(): AppProps {
return {
dispatch: jest.fn(),
loaded: [],
logs: [],
user: fakeUser(),
bot: bot
};
}
function controlsPopUp(page: string, exists: boolean) {
it(`doesn't render controls pop-up on ${page} page`, () => {
Object.defineProperty(location, "pathname", {
value: "/app/" + page, configurable: true
});
const wrapper = mount(<App {...fakeProps() } />,
{ context: { store: createStore(reducers) } });
if (exists) {
expect(wrapper.html()).toContain("controls-popup");
} else {
expect(wrapper.html()).not.toContain("controls-popup");
}
});
}
controlsPopUp("designer", true);
controlsPopUp("designer/plants", true);
controlsPopUp("controls", false);
controlsPopUp("device", true);
controlsPopUp("sequences", true);
controlsPopUp("sequences/for_regimens", true);
controlsPopUp("regimens", false);
controlsPopUp("tools", true);
controlsPopUp("farmware", true);
controlsPopUp("account", false);
});
describe.skip("<App />: Loading", () => {
function fakeProps(): AppProps {
return {
dispatch: jest.fn(),
loaded: [],
logs: [],
user: fakeUser(),
bot: bot
};
}
it("MUST_LOADs not loaded", () => {
const wrapper = mount(<App {...fakeProps() } />,
{ context: { store: createStore(reducers) } });
expect(wrapper.html()).toContain("spinner");
});
it("MUST_LOADs partially loaded", () => {
const p = fakeProps();
p.loaded = ["sequences"];
const wrapper = mount(<App {...p } />,
{ context: { store: createStore(reducers) } });
expect(wrapper.html()).toContain("spinner");
});
it("MUST_LOADs loaded", () => {
const p = fakeProps();
p.loaded = ["sequences", "regimens", "farm_events", "points"];
const wrapper = mount(<App {...p } />,
{ context: { store: createStore(reducers) } });
expect(wrapper.html()).not.toContain("spinner");
});
});
describe("<App />: NavBar", () => {
function fakeProps(): AppProps {
return {
dispatch: jest.fn(),
loaded: [],
logs: [],
user: fakeUser(),
bot: bot
};
}
it("displays links", () => {
const wrapper = mount(<App {...fakeProps() } />,
{ context: { store: createStore(reducers) } });
expect(wrapper.text())
.toContain("Farm DesignerControlsDeviceSequencesRegimensToolsFarmware");
});
it("displays ticker", () => {
const wrapper = mount(<App {...fakeProps() } />,
{ context: { store: createStore(reducers) } });
expect(wrapper.text()).toContain("No logs yet.");
});
});

View File

@ -1,9 +1,24 @@
jest.mock("../device", () => ({
devices: {
current: {
moveRelative: jest.fn(() => { return Promise.resolve(); }),
}
}
}));
import * as React from "react";
import { ControlsPopup } from "../controls_popup";
import { mount } from "enzyme";
import { devices } from "../device";
describe("<ControlsPopup />", () => {
const wrapper = mount(<ControlsPopup dispatch={jest.fn()} />);
beforeEach(function () {
jest.clearAllMocks();
});
const wrapper = mount(<ControlsPopup
dispatch={jest.fn()}
axisInversion={{ x: true, y: false, z: false }} />);
it("Has a false initial state", () => {
expect(wrapper.state("isOpen")).toBeFalsy();
@ -15,4 +30,32 @@ describe("<ControlsPopup />", () => {
expect(wrapper.state("isOpen")).toBeTruthy();
});
it("x axis is inverted", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const button = wrapper.find("button").first();
expect(button.props().title).toBe("move x axis");
button.simulate("click");
const args = mock.calls[0][0];
expect(args.x).toBe(100);
expect(args.y).toBe(0);
expect(args.z).toBe(0);
});
it("y axis is not inverted", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const button = wrapper.find("button").at(2);
expect(button.props().title).toBe("move y axis");
button.simulate("click");
const args = mock.calls[0][0];
expect(args.x).toBe(0);
expect(args.y).toBe(100);
expect(args.z).toBe(0);
});
it("disabled when closed", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
wrapper.setState({ isOpen: false });
[0, 1, 2, 3].map((i) => wrapper.find("button").at(i).simulate("click"));
expect(mock.calls.length).toBe(0);
});
});

View File

@ -21,7 +21,7 @@ fastClick.attach(document.body);
/** For the logger module */
init();
interface AppProps {
export interface AppProps {
dispatch: Function;
loaded: ResourceName[];
logs: Log[];
@ -76,6 +76,7 @@ export class App extends React.Component<AppProps, {}> {
render() {
const syncLoaded = this.isLoaded;
const currentPath = window.location.pathname;
return <div className="app">
<HotKeys dispatch={this.props.dispatch} />
<NavBar
@ -85,7 +86,12 @@ export class App extends React.Component<AppProps, {}> {
logs={this.props.logs} />
{!syncLoaded && <Spinner radius={33} strokeWidth={6} />}
{syncLoaded && this.props.children}
<ControlsPopup dispatch={this.props.dispatch} />
{!currentPath.startsWith("/app/controls") &&
!currentPath.startsWith("/app/account") &&
!currentPath.startsWith("/app/regimens") &&
<ControlsPopup
dispatch={this.props.dispatch}
axisInversion={this.props.bot.axis_inversion} />}
</div>;
}
}

View File

@ -1,6 +1,7 @@
import * as React from "react";
import { DirectionButton } from "./controls/direction_button";
import { Xyz } from "./devices/interfaces";
export interface State {
isOpen: boolean;
@ -9,6 +10,7 @@ export interface State {
export interface Props {
dispatch: Function;
axisInversion: Record<Xyz, boolean>;
}
export class ControlsPopup extends React.Component<Props, Partial<State>> {
@ -32,27 +34,27 @@ export class ControlsPopup extends React.Component<Props, Partial<State>> {
<DirectionButton
axis="x"
direction="right"
isInverted={false}
isInverted={this.props.axisInversion.x}
steps={this.state.stepSize}
disabled={false} />
disabled={!isOpen} />
<DirectionButton
axis="y"
direction="up"
isInverted={false}
isInverted={this.props.axisInversion.y}
steps={this.state.stepSize}
disabled={false} />
disabled={!isOpen} />
<DirectionButton
axis="y"
direction="down"
isInverted={false}
isInverted={this.props.axisInversion.y}
steps={this.state.stepSize}
disabled={false} />
disabled={!isOpen} />
<DirectionButton
axis="x"
direction="left"
isInverted={false}
isInverted={this.props.axisInversion.x}
steps={this.state.stepSize}
disabled={false} />
disabled={!isOpen} />
</div>
</div>
</div>;

View File

@ -6,6 +6,7 @@
max-width: 100%;
margin: auto;
max-height: 650px;
min-height: 200px;
}
.image-flipper-left {

View File

@ -30,13 +30,11 @@ describe("checkControllerUpdates()", function () {
jest.clearAllMocks();
});
it("calls checkUpdates", () => {
it("calls checkUpdates", async () => {
const { mock } = devices.current.checkUpdates as jest.Mock<{}>;
actions.checkControllerUpdates();
await actions.checkControllerUpdates();
expect(mock.calls.length).toEqual(1);
// TODO: It would be nice if this worked to check for sent toasts.
// See expectations for each test in comments below.
// expect(mockOk.mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
});
});
@ -45,11 +43,11 @@ describe("powerOff()", function () {
jest.clearAllMocks();
});
it("calls powerOff", () => {
it("calls powerOff", async () => {
const { mock } = devices.current.powerOff as jest.Mock<{}>;
actions.powerOff();
await actions.powerOff();
expect(mock.calls.length).toEqual(1);
// expect(mockOk.mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
});
});
@ -58,11 +56,11 @@ describe("reboot()", function () {
jest.clearAllMocks();
});
it("calls reboot", () => {
it("calls reboot", async () => {
const { mock } = devices.current.reboot as jest.Mock<{}>;
actions.reboot();
await actions.reboot();
expect(mock.calls.length).toEqual(1);
// expect(mockOk.mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
});
});
@ -105,13 +103,13 @@ describe("execSequence()", function () {
jest.clearAllMocks();
});
it("calls execSequence", () => {
it("calls execSequence", async () => {
const { mock } = devices.current.execSequence as jest.Mock<{}>;
const s = fakeSequence().body;
actions.execSequence(s);
await actions.execSequence(s);
expect(mock.calls.length).toEqual(1);
expect(mock.calls[0][0]).toEqual(s.id);
// expect(mockOk.mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
});
it("implodes when executing unsaved sequences", () => {
@ -132,7 +130,6 @@ describe("MCUFactoryReset()", function () {
const { mock } = devices.current.resetMCU as jest.Mock<{}>;
actions.MCUFactoryReset();
expect(mock.calls.length).toEqual(1);
// expect(mockOk.mock.calls.length).toEqual(1);
});
});
@ -141,12 +138,12 @@ describe("botConfigChange()", function () {
jest.clearAllMocks();
});
it("calls updateMcu", () => {
it("calls updateMcu", async () => {
const { mock } = devices.current.updateMcu as jest.Mock<{}>;
actions.botConfigChange("encoder_enabled_x", 0);
await actions.botConfigChange("encoder_enabled_x", 0);
expect(mock.calls.length).toEqual(1);
expect(mock.calls[0][0]).toEqual({ "encoder_enabled_x": 0 });
// expect(mockOk.mock.calls.length).toEqual(0);
expect(mockOk.mock.calls.length).toEqual(0);
});
});
@ -155,13 +152,13 @@ describe("pinToggle()", function () {
jest.clearAllMocks();
});
it("calls togglePin", () => {
it("calls togglePin", async () => {
const { mock } = devices.current.togglePin as jest.Mock<{}>;
actions.pinToggle(5);
await actions.pinToggle(5);
expect(mock.calls.length).toEqual(1);
const argList = mock.calls[0];
expect(argList[0].pin_number).toEqual(5);
// expect(mockOk.mock.calls.length).toEqual(0);
expect(mockOk.mock.calls.length).toEqual(0);
});
});
@ -170,14 +167,14 @@ describe("homeAll()", function () {
jest.clearAllMocks();
});
it("calls home", () => {
it("calls home", async () => {
const { mock } = devices.current.home as jest.Mock<{}>;
actions.homeAll(100);
await actions.homeAll(100);
expect(mock.calls.length).toEqual(1);
const argList = mock.calls[0];
expect(argList[0].axis).toEqual("all");
expect(argList[0].speed).toEqual(100);
// expect(mockOk.mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
});
});