Merge pull request #1035 from gabrielburnworth/staging

FarmwareInstallations basics
pull/1040/head
Rick Carlino 2018-11-06 07:57:45 -06:00 committed by GitHub
commit 61b340bf58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 88 additions and 18 deletions

View File

@ -1,10 +1,8 @@
COVERAGE_FILE_PATH = [
ENV.fetch("CIRCLE_WORKING_DIRECTORY", "./coverage_fe"),
"index.html"
].join("/")
COVERAGE_FILE_PATH = "./coverage_fe/index.html"
THRESHOLD = 0.001
REPO_URL = "https://api.github.com/repos/Farmbot/Farmbot-Web-App/git"\
"/refs/heads/staging"
CURRENT_COMMIT = ENV.fetch("CIRCLE_SHA1", "")
CSS_SELECTOR = ".fraction"
FRACTION_DELIM = "/"
@ -22,23 +20,29 @@ namespace :coverage do
.map { |x| x.split(FRACTION_DELIM).map(&:to_f) }
.map { |x| Pair.new(*x) }
numerator = lines.head + branches.head
denominator = lines.tail + branches.tail
build_percent = (numerator / denominator) * 100
covered = lines.head + branches.head
total = lines.tail + branches.tail
build_percent = (covered / total) * 100
latest_commit_staging = open_json(REPO_URL).dig("object", "sha")
build_url = "https://coveralls.io/builds/#{latest_commit_staging}.json"
staging_percent = open_json(build_url).fetch("covered_percent")
begin
staging_percent = open_json(build_url).fetch("covered_percent")
rescue OpenURI::HTTPError => exception
puts exception.message
puts "Error getting coveralls data. Wait for build to finish and try again."
staging_percent = 100
end
diff = (build_percent - staging_percent)
pass = (diff > -THRESHOLD)
puts "=" * 37
puts "COVERAGE RESULTS"
puts "This build: #{build_percent}"
puts "Staging build: #{staging_percent}"
puts "This build: #{build_percent.round(8)} #{CURRENT_COMMIT[0,7]}"
puts "Staging build: #{staging_percent.round(8)} #{latest_commit_staging[0,7]}"
puts "=" * 37
puts "Difference: #{diff}"
puts "Difference: #{diff.round(8)}"
puts "Pass?: #{pass ? "yes" : "no"}"
exit pass ? 0 : 1

View File

@ -23,6 +23,7 @@ import {
TaggedPlantTemplate,
TaggedToolSlotPointer,
TaggedFarmwareEnv,
TaggedFarmwareInstallation,
} from "farmbot";
import { fakeResource } from "../fake_resource";
import { ExecutableType, PinBindingType } from "farmbot/dist/resources/api_resources";
@ -411,3 +412,9 @@ export function fakeFarmwareEnv(): TaggedFarmwareEnv {
value: "fake_FarmwareEnv_value"
});
}
export function fakeFarmwareInstallation(): TaggedFarmwareInstallation {
return fakeResource("FarmwareInstallation", {
url: "https://"
});
}

View File

@ -13,7 +13,7 @@ describe("API", () => {
[API.current.farmwareEnvPath, BASE + "/api/farmware_envs/"],
[API.current.plantTemplatePath, BASE + "/api/plant_templates/"],
[API.current.diagnosticDumpsPath, BASE + "/api/diagnostic_dumps/"],
[API.current.farmwareInstallationPath, BASE + "/api/farmware_installations"],
[API.current.farmwareInstallationPath, BASE + "/api/farmware_installations/"],
].map(x => expect(x[0]).toEqual(x[1]));
});

View File

@ -151,7 +151,7 @@ export class API {
get diagnosticDumpsPath() { return `${this.baseUrl}/api/diagnostic_dumps/`; }
/** /api/farmware_installations/:id */
get farmwareInstallationPath() {
return `${this.baseUrl}/api/farmware_installations`;
return `${this.baseUrl}/api/farmware_installations/`;
}
get syncPatch() { return `${this.baseUrl}/api/device/sync/`; }
}

View File

@ -235,6 +235,7 @@ export function urlFor(tag: ResourceName) {
SavedGarden: API.current.savedGardensPath,
PlantTemplate: API.current.plantTemplatePath,
FarmwareEnv: API.current.farmwareEnvPath,
FarmwareInstallation: API.current.farmwareInstallationPath,
};
const url = OPTIONS[tag];
if (url) {

View File

@ -7,7 +7,8 @@ import {
TaggedDevice,
TaggedSensor,
TaggedDiagnosticDump,
TaggedUser
TaggedUser,
TaggedFarmwareInstallation
} from "farmbot";
import { ResourceIndex } from "../resources/interfaces";
import { WD_ENV } from "../farmware/weed_detector/remote_env/interfaces";
@ -221,6 +222,7 @@ export interface FarmwareProps {
currentFarmware: string | undefined;
shouldDisplay: ShouldDisplay;
saveFarmwareEnv: SaveFarmwareEnv;
taggedFarmwareInstallations: TaggedFarmwareInstallation[];
}
export interface HardwareSettingsProps {

View File

@ -19,6 +19,9 @@ describe("<FarmwareInfo />", () => {
farmware: fakeFarmware(),
showFirstParty: false,
firstPartyFarmwareNames: [],
dispatch: jest.fn(),
installations: [],
shouldDisplay: () => false,
};
};
@ -64,12 +67,32 @@ describe("<FarmwareInfo />", () => {
expect(mockDevice.updateFarmware).toHaveBeenCalledWith("My Fake Farmware");
});
it("doesn't update Farmware", () => {
const p = fakeProps();
p.farmware = fakeFarmware();
// tslint:disable-next-line:no-any
p.farmware.name = undefined as any;
const wrapper = mount(<FarmwareInfo {...p} />);
clickButton(wrapper, 0, "Update");
expect(mockDevice.updateFarmware).not.toHaveBeenCalled();
});
it("removes Farmware", () => {
const wrapper = mount(<FarmwareInfo {...fakeProps()} />);
clickButton(wrapper, 1, "Remove");
expect(mockDevice.removeFarmware).toHaveBeenCalledWith("My Fake Farmware");
});
it("removes Farmware", () => {
const p = fakeProps();
p.farmware = fakeFarmware();
// tslint:disable-next-line:no-any
p.farmware.name = undefined as any;
const wrapper = mount(<FarmwareInfo {...p} />);
clickButton(wrapper, 1, "Remove");
expect(mockDevice.removeFarmware).not.toHaveBeenCalled();
});
it("doesn't remove 1st-party Farmware", () => {
const p = fakeProps();
p.farmware = fakeFarmware();

View File

@ -22,6 +22,7 @@ describe("<FarmwareList />", () => {
showFirstParty: false,
firstPartyFarmwareNames: [],
shouldDisplay: () => false,
installations: [],
};
};

View File

@ -41,6 +41,7 @@ describe("<FarmwarePage />", () => {
currentFarmware: undefined,
shouldDisplay: () => false,
saveFarmwareEnv: jest.fn(),
taggedFarmwareInstallations: [],
};
};

View File

@ -2,7 +2,7 @@
import { farmwareReducer } from "../reducer";
import { FarmwareState } from "../interfaces";
import { Actions } from "../../constants";
import { fakeImage } from "../../__test_support__/fake_state/resources";
import { fakeImage, fakeFarmwareInstallation } from "../../__test_support__/fake_state/resources";
describe("farmwareReducer", () => {
const fakeState = (): FarmwareState => {
@ -60,6 +60,17 @@ describe("farmwareReducer", () => {
expect(newState.currentImage).toBe(image.uuid);
});
it("doesn't set the current image via INIT_RESOURCE for non-image", () => {
const nonimage = fakeFarmwareInstallation();
const oldState = fakeState();
const newState = farmwareReducer(oldState, {
type: Actions.INIT_RESOURCE,
payload: nonimage
});
expect(oldState.currentImage).toEqual(newState.currentImage);
expect(newState.currentImage).toBeUndefined();
});
it("sets 1st party farmware list", () => {
const FARMWARE_NAMES = ["1stPartyOne", "1stPartyTwo"];
const oldState = fakeState();

View File

@ -1,14 +1,18 @@
import * as React from "react";
import { t } from "i18next";
import { FarmwareManifest } from "farmbot";
import { FarmwareManifest, TaggedFarmwareInstallation } from "farmbot";
import { getDevice } from "../device";
import { commandErr } from "../devices/actions";
import { Content } from "../constants";
import { ShouldDisplay } from "../devices/interfaces";
export interface FarmwareInfoProps {
dispatch: Function;
farmware: FarmwareManifest | undefined;
showFirstParty: boolean;
firstPartyFarmwareNames: string[];
installations: TaggedFarmwareInstallation[];
shouldDisplay: ShouldDisplay;
}
export function FarmwareInfo(props: FarmwareInfoProps) {

View File

@ -10,6 +10,7 @@ import { every, Dictionary } from "lodash";
import { Popover, Position } from "@blueprintjs/core";
import { Link } from "../link";
import { ShouldDisplay } from "../devices/interfaces";
import { TaggedFarmwareInstallation } from "farmbot";
const DISPLAY_NAMES: Dictionary<string> = {
"Photos": t("Photos"),
@ -47,6 +48,7 @@ export interface FarmwareListProps {
showFirstParty: boolean;
firstPartyFarmwareNames: string[];
shouldDisplay: ShouldDisplay;
installations: TaggedFarmwareInstallation[];
}
interface FarmwareListState {

View File

@ -161,6 +161,7 @@ export class FarmwarePage extends React.Component<FarmwareProps, {}> {
dispatch={this.props.dispatch}
shouldDisplay={this.props.shouldDisplay}
farmwares={this.props.farmwares}
installations={this.props.taggedFarmwareInstallations}
firstPartyFarmwareNames={this.props.firstPartyFarmwareNames}
showFirstParty={!!this.props.webAppConfig.show_first_party_farmware} />
</LeftPanel>
@ -180,7 +181,10 @@ export class FarmwarePage extends React.Component<FarmwareProps, {}> {
helpText={ToolTips.FARMWARE_INFO}
show={!!farmware}>
<FarmwareInfo
dispatch={this.props.dispatch}
farmware={farmware}
installations={this.props.taggedFarmwareInstallations}
shouldDisplay={this.props.shouldDisplay}
firstPartyFarmwareNames={this.props.firstPartyFarmwareNames}
showFirstParty={!!this.props.webAppConfig.show_first_party_farmware} />
</RightPanel>

View File

@ -2,11 +2,13 @@ import { Everything } from "../interfaces";
import {
selectAllImages, maybeGetTimeOffset, maybeGetDevice
} from "../resources/selectors";
import { FarmwareProps, Feature, SaveFarmwareEnv, UserEnv } from "../devices/interfaces";
import {
FarmwareProps, Feature, SaveFarmwareEnv, UserEnv
} from "../devices/interfaces";
import { prepopulateEnv } from "./weed_detector/remote_env/selectors";
import * as _ from "lodash";
import {
getWebAppConfig, selectAllFarmwareEnvs
getWebAppConfig, selectAllFarmwareEnvs, selectAllFarmwareInstallations
} from "../resources/selectors_by_kind";
import {
determineInstalledOsVersion,
@ -61,6 +63,9 @@ export function mapStateToProps(props: Everything): FarmwareProps {
? reduceFarmwareEnv(props.resources.index)
: props.bot.hardware.user_env;
const taggedFarmwareInstallations =
selectAllFarmwareInstallations(props.resources.index);
return {
timeOffset: maybeGetTimeOffset(props.resources.index),
currentFarmware,
@ -76,5 +81,6 @@ export function mapStateToProps(props: Everything): FarmwareProps {
firstPartyFarmwareNames,
shouldDisplay,
saveFarmwareEnv: saveOrEditFarmwareEnv(props.resources.index),
taggedFarmwareInstallations,
};
}

View File

@ -41,6 +41,7 @@ describe("<WeedDetector />", () => {
currentFarmware: undefined,
shouldDisplay: () => false,
saveFarmwareEnv: jest.fn(),
taggedFarmwareInstallations: [],
});
it("renders", () => {

View File

@ -23,6 +23,7 @@ import {
TaggedSavedGarden,
TaggedPlantTemplate,
TaggedFarmwareEnv,
TaggedFarmwareInstallation,
} from "farmbot";
import {
isTaggedResource,
@ -99,6 +100,8 @@ export const selectAllDiagnosticDumps =
(i: ResourceIndex) => findAll<TaggedDiagnosticDump>(i, "DiagnosticDump");
export const selectAllFarmwareEnvs =
(i: ResourceIndex) => findAll<TaggedFarmwareEnv>(i, "FarmwareEnv");
export const selectAllFarmwareInstallations = (i: ResourceIndex) =>
findAll<TaggedFarmwareInstallation>(i, "FarmwareInstallation");
export const selectAllRegimens = (i: ResourceIndex) =>
findAll<TaggedRegimen>(i, "Regimen");
export const selectAllSensors = (i: ResourceIndex) => findAll<TaggedSensor>(i, "Sensor");