const mockDevice = { checkUpdates: jest.fn(() => Promise.resolve()), updateConfig: jest.fn(() => Promise.resolve()), }; jest.mock("../../../../device", () => ({ getDevice: () => mockDevice })); import * as React from "react"; import { mount } from "enzyme"; import { bot } from "../../../../__test_support__/fake_state/bot"; import { OsUpdateButton } from "../os_update_button"; import { OsUpdateButtonProps } from "../interfaces"; import { ShouldDisplay } from "../../../interfaces"; import { Content } from "../../../../constants"; import { ConfigurationName } from "farmbot"; const UPDATE_CHANNEL = "update_channel" as ConfigurationName; describe("", () => { beforeEach(() => { bot.currentOSVersion = "6.1.6"; bot.hardware.informational_settings.controller_version = "6.1.6"; (bot.hardware.configuration[UPDATE_CHANNEL] as string) = "stable"; }); const fakeProps = (): OsUpdateButtonProps => ({ bot, sourceFbosConfig: x => ({ value: bot.hardware.configuration[x], consistent: true }), botOnline: true, shouldDisplay: () => false, }); interface TestProps { installedVersion: string | undefined; installedCommit: string; availableVersion: string | undefined; availableBetaVersion: string | undefined; availableBetaCommit: string | undefined; onBeta: boolean | undefined; update_available?: boolean | undefined; shouldDisplay: ShouldDisplay; update_channel: string; } const defaultTestProps = (): TestProps => ({ installedVersion: "6.1.6", installedCommit: "", availableVersion: "6.1.6", availableBetaVersion: undefined, availableBetaCommit: undefined, onBeta: false, shouldDisplay: () => false, update_channel: "stable", }); interface Results { text: string; title: string | undefined; color: string; disabled: boolean; } const updateNeeded = (title: string | undefined): Results => ({ text: "UPDATE", title, color: "green", disabled: false, }); const upToDate = (title: string | undefined): Results => ({ text: "UP TO DATE", title, color: "gray", disabled: false, }); const cantConnect = (entity: string): Results => ({ text: `Can't connect to ${entity}`, title: undefined, color: "yellow", disabled: false, }); const tooOld = (): Results => ({ text: Content.TOO_OLD_TO_UPDATE, title: "6.1.6", color: "yellow", disabled: false, }); const updating = (progress: string): Results => ({ text: progress, title: undefined, color: "gray", disabled: true, }); const testButtonState = ( testProps: TestProps, expected: Results) => { const { installedVersion, installedCommit, onBeta, update_available, availableVersion, availableBetaVersion, availableBetaCommit, shouldDisplay, update_channel, } = testProps; bot.hardware.informational_settings.controller_version = installedVersion; bot.hardware.informational_settings.commit = installedCommit; bot.hardware.informational_settings.currently_on_beta = onBeta; bot.hardware.informational_settings.update_available = update_available || false; bot.currentOSVersion = availableVersion; bot.currentBetaOSVersion = availableBetaVersion; bot.currentBetaOSCommit = availableBetaCommit; (bot.hardware.configuration[UPDATE_CHANNEL] as string) = update_channel; const p = fakeProps(); p.shouldDisplay = shouldDisplay; const buttons = mount(); const osUpdateButton = buttons.find("button").first(); expect(osUpdateButton.text()).toBe(expected.text); expect(osUpdateButton.props().title).toBe(expected.title); expect(osUpdateButton.hasClass(expected.color)).toBe(true); expect((osUpdateButton.props().disabled)).toBe(expected.disabled); }; it("renders buttons: too old", () => { const testProps = defaultTestProps(); testProps.installedVersion = "5.0.0"; const expectedResults = tooOld(); testButtonState(testProps, expectedResults); }); it("renders buttons: not connected", () => { const testProps = defaultTestProps(); testProps.installedVersion = undefined; testProps.availableVersion = undefined; const expectedResults = cantConnect("bot"); testButtonState(testProps, expectedResults); }); it("renders buttons: connected to releases but not bot", () => { const testProps = defaultTestProps(); testProps.installedVersion = undefined; const expectedResults = cantConnect("bot"); expectedResults.title = "6.1.6"; testButtonState(testProps, expectedResults); }); it("renders buttons: no releases available", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableVersion = undefined; testProps.update_channel = "beta"; const expectedResults = cantConnect("release server"); testButtonState(testProps, expectedResults); }); it("renders buttons: only beta release available", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableVersion = undefined; testProps.availableBetaVersion = "6.1.7-beta"; testProps.update_channel = "beta"; const expectedResults = updateNeeded("6.1.7-beta"); testButtonState(testProps, expectedResults); }); it("renders buttons: no beta release available", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableBetaVersion = undefined; testProps.update_channel = "beta"; const expectedResults = upToDate("6.1.6"); testButtonState(testProps, expectedResults); }); it("up to date", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; const expectedResults = upToDate("6.1.6"); testButtonState(testProps, expectedResults); }); it("up to date: newer", () => { const testProps = defaultTestProps(); testProps.installedVersion = "7.0.0"; const expectedResults = upToDate("6.1.6"); testButtonState(testProps, expectedResults); }); it("update available", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.5"; const expectedResults = updateNeeded("6.1.6"); testButtonState(testProps, expectedResults); }); it("beta update available", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.5"; testProps.availableBetaVersion = "7.0.0-beta"; testProps.update_channel = "beta"; const expectedResults = updateNeeded("7.0.0-beta"); testButtonState(testProps, expectedResults); }); it("latest newer than beta update: latest installed", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableBetaVersion = "6.1.6-beta"; testProps.update_channel = "beta"; const expectedResults = upToDate("6.1.6"); testButtonState(testProps, expectedResults); }); it("latest newer than beta update: beta installed", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableBetaVersion = "6.1.6-beta"; testProps.update_channel = "beta"; testProps.onBeta = true; const expectedResults = updateNeeded("6.1.6"); testButtonState(testProps, expectedResults); }); it("latest newer than beta update: beta installed (beta disabled)", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.availableBetaVersion = "6.1.6-beta"; testProps.update_channel = "stable"; testProps.onBeta = true; const expectedResults = updateNeeded("6.1.6"); testButtonState(testProps, expectedResults); }); it("on latest beta update", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.7"; testProps.availableBetaVersion = "6.1.7-beta"; testProps.update_channel = "beta"; testProps.onBeta = true; const expectedResults = upToDate("6.1.7-beta"); testButtonState(testProps, expectedResults); }); it("on latest beta update: already has beta suffix", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.7-beta"; testProps.availableBetaVersion = "6.1.7-beta"; testProps.update_channel = "beta"; const expectedResults = upToDate("6.1.7-beta"); testButtonState(testProps, expectedResults); }); it("beta update has same numeric version: newer commit", () => { const testProps = defaultTestProps(); testProps.installedVersion = "7.0.0"; testProps.installedCommit = "old commit"; testProps.availableBetaVersion = "7.0.0-beta"; testProps.availableBetaCommit = "new commit"; testProps.update_channel = "beta"; testProps.onBeta = true; const expectedResults = updateNeeded("7.0.0-beta"); testButtonState(testProps, expectedResults); }); it("handles installed version newer than available (beta enabled)", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.7"; testProps.update_channel = "beta"; testProps.onBeta = false; testProps.availableBetaVersion = "6.1.7-beta"; const expectedResults = upToDate("6.1.7-beta"); testButtonState(testProps, expectedResults); }); it("handles FBOS update available override", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.update_available = true; const expectedResults = updateNeeded("6.1.6"); testButtonState(testProps, expectedResults); }); it("uses update_channel value", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.shouldDisplay = () => true; testProps.update_channel = "stable"; testProps.availableBetaVersion = "6.1.7-beta"; const expectedResults = upToDate("6.1.6"); testButtonState(testProps, expectedResults); }); it("uses update_channel value: beta", () => { const testProps = defaultTestProps(); testProps.installedVersion = "6.1.6"; testProps.shouldDisplay = () => true; testProps.update_channel = "beta"; testProps.availableBetaVersion = "6.1.7-beta"; const expectedResults = updateNeeded("6.1.7-beta"); testButtonState(testProps, expectedResults); }); it("compares release candidates: newer", () => { const testProps = defaultTestProps(); testProps.availableVersion = "6.1.5"; testProps.installedVersion = "6.1.6-rc1"; testProps.shouldDisplay = () => true; testProps.update_channel = "beta"; testProps.availableBetaVersion = "6.1.6-rc2"; const expectedResults = updateNeeded("6.1.6-rc2"); testButtonState(testProps, expectedResults); }); it("compares release candidates: older", () => { const testProps = defaultTestProps(); testProps.availableVersion = "6.1.5"; testProps.installedVersion = "6.1.6-rc2"; testProps.shouldDisplay = () => true; testProps.update_channel = "beta"; testProps.availableBetaVersion = "6.1.6-rc1"; const expectedResults = upToDate("6.1.6-rc1"); testButtonState(testProps, expectedResults); }); it("calls checkUpdates", () => { const buttons = mount(); const osUpdateButton = buttons.find("button").first(); osUpdateButton.simulate("click"); expect(mockDevice.checkUpdates).toHaveBeenCalledTimes(1); }); it("handles undefined jobs", () => { // tslint:disable-next-line:no-any bot.hardware.jobs = undefined as any; const buttons = mount(); const osUpdateButton = buttons.find("button").first(); expect(osUpdateButton.text()).toEqual("UP TO DATE"); }); it.each<[string, number]>([ ["300B", 300], ["29kB", 30000], ["3MB", 3e6], ])("shows bytes update progress: %s", (expected, progress) => { bot.hardware.jobs = { "FBOS_OTA": { status: "working", bytes: progress, unit: "bytes" } }; const buttons = mount(); const osUpdateButton = buttons.find("button").first(); expect(osUpdateButton.text()).toBe(expected); }); it("shows percent update progress: 10%", () => { bot.hardware.jobs = { "FBOS_OTA": { status: "working", percent: 10, unit: "percent" } }; const expectedResults = updating("10%"); expectedResults.title = "6.1.6"; testButtonState(defaultTestProps(), expectedResults); }); it("update success", () => { bot.hardware.jobs = { "FBOS_OTA": { status: "complete", percent: 100, unit: "percent" } }; testButtonState(defaultTestProps(), upToDate("6.1.6")); }); it("update failed", () => { bot.hardware.jobs = { "FBOS_OTA": { status: "error", percent: 10, unit: "percent" } }; const testProps = defaultTestProps(); testProps.installedVersion = "6.1.5"; testButtonState(testProps, updateNeeded("6.1.6")); }); it("is disabled", () => { bot.hardware.jobs = { "FBOS_OTA": { status: "working", percent: 10, unit: "percent" } }; const buttons = mount(); const osUpdateButton = buttons.find("button").first(); osUpdateButton.simulate("click"); expect(mockDevice.checkUpdates).not.toHaveBeenCalled(); }); });