jest.mock("../../../history", () => ({ history: { push: jest.fn() }, getPathArray: () => "/app/designer/tools".split("/"), })); jest.mock("../../../api/crud", () => ({ edit: jest.fn(), save: jest.fn(), })); const mockDevice = { readPin: jest.fn(() => Promise.resolve()) }; jest.mock("../../../device", () => ({ getDevice: () => mockDevice })); import * as React from "react"; import { mount, shallow } from "enzyme"; import { RawTools as Tools, ToolsProps, mapStateToProps, ToolSlotInventoryItem, ToolSlotInventoryItemProps, } from "../index"; import { fakeTool, fakeToolSlot, fakeSensor, } from "../../../__test_support__/fake_state/resources"; import { history } from "../../../history"; import { fakeState } from "../../../__test_support__/fake_state"; import { buildResourceIndex, fakeDevice, } from "../../../__test_support__/resource_index_builder"; import { bot } from "../../../__test_support__/fake_state/bot"; import { error } from "../../../toast/toast"; import { Content, Actions } from "../../../constants"; import { edit, save } from "../../../api/crud"; import { ToolSelection } from "../tool_slot_edit_components"; describe("", () => { const fakeProps = (): ToolsProps => ({ tools: [], toolSlots: [], dispatch: jest.fn(), findTool: () => fakeTool(), device: fakeDevice(), sensors: [fakeSensor()], bot, hoveredToolSlot: undefined, firmwareHardware: undefined, isActive: jest.fn(), }); it("renders with no tools", () => { const wrapper = mount(); expect(wrapper.text()).toContain("Add a tool"); }); it("renders with tools", () => { const p = fakeProps(); p.tools = [fakeTool(), fakeTool(), fakeTool()]; p.tools[0].body.id = 1; p.tools[0].body.status = "inactive"; p.tools[0].body.name = undefined; p.tools[1].body.id = 2; p.tools[1].body.name = "my tool"; p.tools[2].body.id = 3; p.tools[2].body.name = "my tool"; p.toolSlots = [fakeToolSlot(), fakeToolSlot()]; p.toolSlots[0].body.tool_id = 2; p.toolSlots[0].body.x = 1; p.toolSlots[1].body.tool_id = 3; p.toolSlots[1].body.gantry_mounted = true; p.toolSlots[1].body.y = 2; const wrapper = mount(); [ "foo", "my tool", "unnamed", "(1, 0, 0)", "unknown", "(gantry, 2, 0)", ].map(string => expect(wrapper.text().toLowerCase()).toContain(string)); }); it("navigates to tool", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.tools[0].body.id = 1; p.tools[0].body.status = "inactive"; p.toolSlots = [fakeToolSlot()]; p.toolSlots[0].body.id = 2; p.toolSlots[0].body.tool_id = 3; const wrapper = mount(); wrapper.find(".tool-slot-search-item").first().simulate("click"); expect(history.push).toHaveBeenCalledWith("/app/designer/tool-slots/2"); wrapper.find(".tool-search-item").first().simulate("click"); expect(history.push).toHaveBeenCalledWith("/app/designer/tools/1"); }); it("hovers tool", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.tools[0].body.id = 1; p.toolSlots = [fakeToolSlot()]; p.toolSlots[0].body.id = 1; p.hoveredToolSlot = p.toolSlots[0].uuid; const wrapper = mount(); wrapper.find(".tool-slot-search-item").simulate("mouseEnter"); expect(p.dispatch).toHaveBeenCalledWith({ type: Actions.HOVER_TOOL_SLOT, payload: p.toolSlots[0].uuid }); wrapper.find(".tool-slot-search-item").simulate("mouseLeave"); expect(p.dispatch).toHaveBeenCalledWith({ type: Actions.HOVER_TOOL_SLOT, payload: undefined }); }); it("changes search term", () => { const p = fakeProps(); p.tools = [fakeTool(), fakeTool()]; p.tools[0].body.name = "tool 0"; p.tools[1].body.name = "tool 1"; const wrapper = shallow(); wrapper.find("input").first().simulate("change", { currentTarget: { value: "0" } }); expect(wrapper.state().searchTerm).toEqual("0"); }); it("filters tools", () => { const p = fakeProps(); p.tools = [fakeTool(), fakeTool()]; p.tools[0].body.name = "tool 0"; p.tools[1].body.name = "tool 1"; const wrapper = mount(); wrapper.setState({ searchTerm: "0" }); expect(wrapper.text()).not.toContain("tool 1"); }); it("changes mounted tool", () => { const p = fakeProps(); p.tools = [fakeTool()]; const wrapper = mount(); shallow(wrapper.instance().MountedToolInfo()).find(ToolSelection) .simulate("change", { tool_id: 123 }); expect(edit).toHaveBeenCalledWith(p.device, { mounted_tool_id: 123 }); expect(save).toHaveBeenCalledWith(p.device.uuid); }); it("displays tool verification result: disconnected", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.sensors[0].body.label = "tool verification"; p.sensors[0].body.pin = undefined; p.bot.hardware.pins = { "63": { value: 1, mode: 0 } }; const wrapper = mount(); expect(wrapper.text()).toContain("disconnected"); }); it("displays tool verification result: connected", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.sensors[0].body.label = "tool verification"; p.sensors[0].body.pin = 64; p.bot.hardware.pins = { "64": { value: 0, mode: 0 } }; const wrapper = mount(); expect(wrapper.text()).toContain("connected"); }); it("verifies tool attachment", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.bot.hardware.informational_settings.sync_status = "synced"; p.bot.connectivity.uptime["bot.mqtt"] = { state: "up", at: 0 }; const wrapper = mount(); expect(wrapper.text().toLowerCase()).toContain("mounted tool"); wrapper.find(".yellow").first().simulate("click"); expect(mockDevice.readPin).toHaveBeenCalledWith({ label: "pin63", pin_mode: 0, pin_number: 63 }); }); it("can't verify tool attachment when offline", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.bot.connectivity.uptime["bot.mqtt"] = undefined; const wrapper = mount(); wrapper.find(".yellow").first().simulate("click"); expect(mockDevice.readPin).not.toHaveBeenCalled(); expect(error).toHaveBeenCalledWith(Content.NOT_AVAILABLE_WHEN_OFFLINE); }); it("doesn't display mounted tool on express models", () => { const p = fakeProps(); p.firmwareHardware = "express_k10"; const wrapper = mount(); expect(wrapper.text().toLowerCase()).not.toContain("mounted tool"); }); it("displays tool as active", () => { const p = fakeProps(); p.tools = [fakeTool()]; p.isActive = () => true; p.device.body.mounted_tool_id = undefined; const wrapper = mount(); expect(wrapper.text().toLowerCase()).toContain("in slot"); }); it("displays tool as mounted", () => { const p = fakeProps(); const tool = fakeTool(); tool.body.id = 1; p.findTool = () => tool; p.tools = [tool]; p.device.body.mounted_tool_id = 1; const wrapper = mount(); expect(wrapper.find("p").last().text().toLowerCase()).toContain("mounted"); }); it("handles missing tools", () => { const p = fakeProps(); const tool = fakeTool(); tool.body.id = 1; p.findTool = () => undefined; p.tools = [tool]; p.device.body.mounted_tool_id = 1; const wrapper = mount(); expect(wrapper.find("p").last().text().toLowerCase()).not.toContain("mounted"); }); }); describe("", () => { const fakeProps = (): ToolSlotInventoryItemProps => ({ toolSlot: fakeToolSlot(), tools: [], hovered: false, dispatch: jest.fn(), isActive: jest.fn(), }); it("changes tool", () => { const p = fakeProps(); const wrapper = shallow(); wrapper.find(ToolSelection).simulate("change", { tool_id: 1 }); expect(edit).toHaveBeenCalledWith(p.toolSlot, { tool_id: 1 }); expect(save).toHaveBeenCalledWith(p.toolSlot.uuid); }); it("doesn't open tool slot", () => { const wrapper = shallow(); const e = { stopPropagation: jest.fn() }; wrapper.find(".tool-selection-wrapper").first().simulate("click", e); expect(e.stopPropagation).toHaveBeenCalled(); }); }); describe("mapStateToProps()", () => { it("returns props", () => { const state = fakeState(); const tool = fakeTool(); tool.body.id = 1; state.resources = buildResourceIndex([tool, fakeDevice()]); const props = mapStateToProps(state); expect(props.findTool(tool.body.id)).toEqual(tool); }); });