Minor merge conflict in package.json while merging `staging`

pull/1125/head
Rick Carlino 2019-02-15 14:55:39 -06:00
commit 63bf7b08c7
25 changed files with 285 additions and 185 deletions

View File

@ -42,4 +42,4 @@ jobs:
- run:
name: Check Coveralls coverage on staging
command: |
sudo docker-compose run -e CIRCLE_SHA1="$CIRCLE_SHA1" web rake coverage:run
sudo docker-compose run -e CIRCLE_SHA1="$CIRCLE_SHA1" -e CIRCLE_BRANCH="$CIRCLE_BRANCH" web rake coverage:run

View File

@ -1,20 +1,16 @@
class SendNervesHubInfoJob < ApplicationJob
WHOOPS = "SendNervesHubInfoJob Failure"
queue_as :default
def perform(device_id:, serial_number:, tags:)
device = Device.find(device_id)
DeviceSerialNumber.transaction do
device.update_attributes!(serial_number: serial_number)
resp_data = NervesHub.create_or_update(serial_number, tags)
certs = NervesHub.sign_device(resp_data.fetch(:identifier))
Transport.current.amqp_send(certs.to_json, device_id, "nerves_hub")
end
device = Device.find(device_id)
resp_data = NervesHub.create_or_update(serial_number, tags)
certs = NervesHub.sign_device(resp_data.fetch(:identifier))
Transport.current.amqp_send(certs.to_json, device_id, "nerves_hub")
rescue => error
Rollbar.error(WHOOPS, { error: error,
device_id: device_id,
serial_number: serial_number,
tags: tags, })
NervesHub.report_problem({ error: error,
device_id: device_id,
serial_number: serial_number,
tags: tags, })
raise error
end
end

View File

@ -298,4 +298,9 @@ private
def self.current_ca_file
@current_ca_file ||= (try_env_ca_file || try_file_ca_file || nil)
end
WHOOPS = "🚨 NervesHub Anomaly Detected! 🚨"
def self.report_problem(payload = {})
Rollbar.error(WHOOPS, payload)
end
end

View File

@ -32,7 +32,6 @@ class Device < ApplicationRecord
has_many :diagnostic_dumps, dependent: :destroy
has_many :fragments, dependent: :destroy
has_one :fbos_config, dependent: :destroy
has_one :device_serial_number, dependent: :destroy
has_many :in_use_tools
has_many :in_use_points
has_many :users

View File

@ -1,4 +0,0 @@
class DeviceSerialNumber < ApplicationRecord
belongs_to :device
# DO NOT USE THIS TABLE. IT IS DEPRECATED. DESTROY FEB 2019.
end

View File

@ -13,7 +13,15 @@ class FbosConfig < ApplicationRecord
def sync_nerves
serial = device.serial_number
return unless serial
unless serial
# This feature can be removed in May '19
# It is used to repair data damage on
# production during the initial nervehub
# deployment.
problem = "Device #{device.id} missing serial"
NervesHub.report_problem({ problem: problem })
return
end
self.delay.push_changes_to_nerves_hub(serial, update_channel)
end

View File

@ -10,7 +10,7 @@ module DeviceCerts
SendNervesHubInfoJob.perform_later(device_id: device.id,
serial_number: serial_number,
tags: tags)
return {}
return device.update_attributes!(serial_number: serial_number) && device
end
end
end

View File

@ -1,8 +1,16 @@
class DeprecateDeviceSerialNumberTable < ActiveRecord::Migration[5.2]
unless Kernel.const_defined?("DeviceSerialNumber")
# Shim so that legacy users don't crash when (up|down)grading
class DeviceSerialNumber
def self.preload(*x)
end
end
end
def change
DeviceSerialNumber.preload(:devices) do |x|
x.device
.update_attributes!(serial_number: x.serial_number)
x.device.update_attributes!(serial_number: x.serial_number)
end
end
end

View File

@ -0,0 +1,5 @@
class RemoveDeviceSerialNumberTable < ActiveRecord::Migration[5.2]
def change
drop_table :device_serial_numbers
end
end

View File

@ -14,7 +14,6 @@ if Rails.env == "development"
[
Sensor,
Peripheral,
DeviceSerialNumber,
Log,
PinBinding,
Point,

View File

@ -153,38 +153,6 @@ CREATE SEQUENCE public.delayed_jobs_id_seq
ALTER SEQUENCE public.delayed_jobs_id_seq OWNED BY public.delayed_jobs.id;
--
-- Name: device_serial_numbers; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.device_serial_numbers (
id bigint NOT NULL,
device_id bigint,
serial_number character varying(16) NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
--
-- Name: device_serial_numbers_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.device_serial_numbers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: device_serial_numbers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.device_serial_numbers_id_seq OWNED BY public.device_serial_numbers.id;
--
-- Name: devices; Type: TABLE; Schema: public; Owner: -
--
@ -385,8 +353,7 @@ CREATE TABLE public.farmware_installations (
url character varying,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
package character varying(80),
package_error character varying
package character varying(80)
);
@ -1580,13 +1547,6 @@ ALTER TABLE ONLY public.arg_sets ALTER COLUMN id SET DEFAULT nextval('public.arg
ALTER TABLE ONLY public.delayed_jobs ALTER COLUMN id SET DEFAULT nextval('public.delayed_jobs_id_seq'::regclass);
--
-- Name: device_serial_numbers id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.device_serial_numbers ALTER COLUMN id SET DEFAULT nextval('public.device_serial_numbers_id_seq'::regclass);
--
-- Name: devices id; Type: DEFAULT; Schema: public; Owner: -
--
@ -1850,14 +1810,6 @@ ALTER TABLE ONLY public.delayed_jobs
ADD CONSTRAINT delayed_jobs_pkey PRIMARY KEY (id);
--
-- Name: device_serial_numbers device_serial_numbers_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.device_serial_numbers
ADD CONSTRAINT device_serial_numbers_pkey PRIMARY KEY (id);
--
-- Name: devices devices_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -2151,13 +2103,6 @@ CREATE INDEX index_arg_sets_on_fragment_id ON public.arg_sets USING btree (fragm
CREATE INDEX index_arg_sets_on_node_id ON public.arg_sets USING btree (node_id);
--
-- Name: index_device_serial_numbers_on_device_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_device_serial_numbers_on_device_id ON public.device_serial_numbers USING btree (device_id);
--
-- Name: index_devices_on_mounted_tool_id; Type: INDEX; Schema: public; Owner: -
--
@ -2720,14 +2665,6 @@ ALTER TABLE ONLY public.edge_nodes
ADD CONSTRAINT fk_rails_c86213fd78 FOREIGN KEY (sequence_id) REFERENCES public.sequences(id);
--
-- Name: device_serial_numbers fk_rails_d052988096; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.device_serial_numbers
ADD CONSTRAINT fk_rails_d052988096 FOREIGN KEY (device_id) REFERENCES public.devices(id);
--
-- Name: points fk_rails_d6f3cdbe9a; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -2878,6 +2815,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20190103211708'),
('20190103213956'),
('20190108211419'),
('20190209133811');
('20190209133811'),
('20190212215842');

View File

@ -31,21 +31,23 @@ import { ready, storeToken } from "../actions";
import { setToken, didLogin } from "../../auth/actions";
import { Session } from "../../session";
import { auth } from "../../__test_support__/fake_state/token";
import { fakeState } from "../../__test_support__/fake_state";
describe("Actions", () => {
it("calls didLogin()", () => {
jest.resetAllMocks();
const dispatch = jest.fn();
const getState = jest.fn(() => mockState);
const thunk = ready();
thunk(dispatch, getState);
thunk(dispatch, fakeState);
expect(setToken).toHaveBeenCalled();
});
it("Calls Session.clear() when missing auth", () => {
jest.resetAllMocks();
const dispatch = jest.fn();
const getState = jest.fn(() => ({}));
const state = fakeState();
delete state.auth;
const getState = () => state;
const thunk = ready();
thunk(dispatch, getState);
expect(Session.clear).toHaveBeenCalled();

View File

@ -1,5 +1,6 @@
import { toggleWebAppBool } from "../actions";
import { BooleanSetting } from "../../session_keys";
import { fakeState } from "../../__test_support__/fake_state";
jest.mock("../../api/crud", () => {
return { save: jest.fn(), edit: jest.fn() };
@ -13,8 +14,7 @@ describe("toggleWebAppBool", () => {
it("toggles things", () => {
const action = toggleWebAppBool(BooleanSetting.show_first_party_farmware);
const dispatch = jest.fn();
const getState = jest.fn(() => ({ resources: { index: {} } }));
const kaboom = () => action(dispatch, getState);
const kaboom = () => action(dispatch, fakeState);
expect(kaboom).toThrowError("Toggled settings before app was loaded.");
});
});

View File

@ -1,7 +1,10 @@
import { toggleWebAppBool, getWebAppConfigValue, setWebAppConfigValue } from "../actions";
import {
toggleWebAppBool, getWebAppConfigValue, setWebAppConfigValue
} from "../actions";
import { BooleanSetting, NumericSetting } from "../../session_keys";
import { edit, save } from "../../api/crud";
import { fakeWebAppConfig } from "../../__test_support__/fake_state/resources";
import { fakeState } from "../../__test_support__/fake_state";
jest.mock("../../api/crud", () => {
return { save: jest.fn(), edit: jest.fn() };
@ -18,8 +21,7 @@ describe("toggleWebAppBool", () => {
it("toggles things", () => {
const action = toggleWebAppBool(BooleanSetting.show_first_party_farmware);
const dispatch = jest.fn();
const getState = jest.fn(() => ({ resources: { index: {} } }));
action(dispatch, getState);
action(dispatch, fakeState);
expect(edit).toHaveBeenCalledWith(mockConfig, {
show_first_party_farmware: true
});
@ -28,8 +30,7 @@ describe("toggleWebAppBool", () => {
});
describe("getWebAppConfigValue", () => {
const getState = jest.fn(() => ({ resources: { index: {} } }));
const getValue = getWebAppConfigValue(getState);
const getValue = getWebAppConfigValue(fakeState);
it("gets a boolean setting value", () => {
expect(getValue(BooleanSetting.show_first_party_farmware)).toEqual(false);
@ -41,10 +42,8 @@ describe("getWebAppConfigValue", () => {
});
describe("setWebAppConfigValue", () => {
const getState = jest.fn(() => ({ resources: { index: {} } }));
it("sets a numeric setting value", () => {
setWebAppConfigValue(NumericSetting.fun_log, 2)(jest.fn(), getState);
setWebAppConfigValue(NumericSetting.fun_log, 2)(jest.fn(), fakeState);
expect(edit).toHaveBeenCalledWith(mockConfig, { fun_log: 2 });
expect(save).toHaveBeenCalledWith(mockConfig.uuid);
});
@ -53,7 +52,7 @@ describe("setWebAppConfigValue", () => {
// tslint:disable-next-line:no-any
mockConfig = undefined as any;
const action = () => setWebAppConfigValue(NumericSetting.fun_log, 1)(
jest.fn(), getState);
jest.fn(), fakeState);
expect(action).toThrowError("Changed settings before app was loaded.");
});
});

View File

@ -222,7 +222,7 @@ describe("settingToggle()", () => {
window.alert = jest.fn();
const msg = "this is an alert.";
actions.settingToggle(
"param_mov_nr_retry", jest.fn(() => ({ value: "" })),
"param_mov_nr_retry", jest.fn(() => ({ value: 1, consistent: true })),
msg)(jest.fn(), fakeState);
expect(window.alert).toHaveBeenCalledWith(msg);
});

View File

@ -10,7 +10,7 @@ describe("onInit()", () => {
await onInit({}, jest.fn());
expect({}).toBeTruthy();
expect(render).toHaveBeenCalled();
const [calls] = (render as jest.Mock<{}>).mock.calls;
const [calls] = (render as jest.Mock).mock.calls;
expect(calls[0].type.name).toBe("PasswordReset");
done();
});

View File

@ -1,14 +1,64 @@
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"
REPO_URL = "https://api.github.com/repos/Farmbot/Farmbot-Web-App"
CURRENT_BRANCH = ENV.fetch("CIRCLE_BRANCH", "staging")
CURRENT_COMMIT = ENV.fetch("CIRCLE_SHA1", "")
CSS_SELECTOR = ".fraction"
FRACTION_DELIM = "/"
# Fetch JSON over HTTP. Rails probably already has a helper for this :shrug:
def open_json(url)
JSON.parse(open(url).read)
begin
JSON.parse(open(url).read)
rescue OpenURI::HTTPError => exception
puts exception.message
return {}
end
end
# Get pull request information from the GitHub API.
def fetch_pull_data()
if CURRENT_BRANCH.include? "/"
return open_json("#{REPO_URL}/pulls/#{CURRENT_BRANCH.split("/")[1]}")
end
return {}
end
# Determine the base branch of the current build.
def get_current_branch(pull_data)
pull_data.dig("base", "ref") || CURRENT_BRANCH
end
# Assemble the coverage data URL using the provided branch.
def coverage_url(branch)
commit = open_json("#{REPO_URL}/git/refs/heads/#{branch}").dig("object", "sha")
return "https://coveralls.io/builds/#{commit}.json"
end
# Fetch relevant remote coverage data.
def fetch_build_data(url)
build_data = open_json(url)
return {
branch: build_data["branch"],
commit: build_data["commit_sha"],
percent: build_data["covered_percent"]}
end
# <commit hash> on <username>:<branch>
def branch_info_string?(target, pull_data)
unless pull_data.dig(target, "sha").nil?
"#{pull_data.dig(target, "sha")} on #{pull_data.dig(target, "label")}"
end
end
# Print a coverage difference summary string.
def print_summary_text(build_percent, remote, pull_data)
diff = (build_percent - remote[:percent]).round(2)
direction = diff > 0 ? "increased" : "decreased"
description = diff == 0 ? "remained the same at" : "#{direction} (#{diff}%) to"
puts "Coverage #{description} #{build_percent.round(3)}%"\
" when pulling #{branch_info_string?("head", pull_data)}"\
" into #{branch_info_string?("base", pull_data) || remote[:branch]}."
end
def to_percent(pair)
@ -18,6 +68,7 @@ end
namespace :coverage do
desc "Coveralls stats stopped working :("
task run: :environment do
# Fetch current build coverage data from the HTML summary.
statements, branches, functions, lines = Nokogiri::HTML(open(COVERAGE_FILE_PATH))
.css(CSS_SELECTOR)
.map(&:text)
@ -30,41 +81,66 @@ namespace :coverage do
puts "Branches: #{to_percent(branches)}%"
puts "Functions: #{to_percent(functions)}%"
puts "Lines: #{to_percent(lines)}%"
puts
# Calculate an aggregate coverage percentage for the current build.
covered = lines.head + branches.head
total = lines.tail + branches.tail
build_percent = (covered / total) * 100
puts "Aggregate: #{build_percent.round(4)}%"
puts
latest_commit_staging = open_json(REPO_URL).dig("object", "sha")
puts "staging: #{latest_commit_staging}"
build_url = "https://coveralls.io/builds/#{latest_commit_staging}.json"
any_build_url = "https://coveralls.io/github/FarmBot/Farmbot-Web-App.json"
begin
staging_percent = open_json(build_url).fetch("covered_percent") ||
open_json(any_build_url).fetch("covered_percent")
rescue OpenURI::HTTPError => exception
puts exception.message
# Attempt to fetch remote build coverage data for the current branch.
pull_request_data = fetch_pull_data()
current_branch = get_current_branch(pull_request_data)
remote = fetch_build_data(coverage_url(current_branch))
if remote[:percent].nil? && CURRENT_COMMIT == remote[:commit]
puts "Coverage already calculated for #{remote[:branch]}."
puts "Using this build's data instead."
remote[:percent] = build_percent
end
if remote[:percent].nil? && current_branch != "staging"
puts "Error getting coveralls data for #{current_branch}."
puts "Attempting to use staging build coveralls data."
remote = fetch_build_data(coverage_url("staging"))
end
if remote[:percent].nil?
puts "Error getting coveralls data for staging."
puts "Attempting to use latest build coveralls data."
latest_cov_url = "https://coveralls.io/github/FarmBot/Farmbot-Web-App.json"
remote = fetch_build_data(latest_cov_url)
end
if remote[:percent].nil?
puts "Error getting coveralls data."
puts "Wait for staging build to finish and try again."
puts "If error continues, perhaps a blinky test failed the staging build."
staging_percent = 100
puts "Wait for build to finish and try again or check for build errors."
puts "Using 100 instead of nil for remote coverage value."
remote = {branch: "N/A", commit: "", percent: 100}
end
if CURRENT_COMMIT == latest_commit_staging
staging_percent = build_percent
end
# Adjust remote build data values for printing.
r = {
branch: (remote[:branch] + ' ' * 8)[0,8],
percent: remote[:percent].round(8),
commit: remote[:commit][0,8]}
diff = (build_percent - staging_percent)
# Calculate coverage difference between the current and previous build.
diff = (build_percent - remote[:percent])
pass = (diff > -THRESHOLD)
puts
puts "=" * 37
puts "COVERAGE RESULTS"
puts "This build: #{build_percent.round(8)}% #{CURRENT_COMMIT[0,8]}"
puts "Staging build: #{staging_percent.round(8)}% #{latest_commit_staging[0,8]}"
puts "This build: #{build_percent.round(8)}% #{CURRENT_COMMIT[0,8]}"
puts "#{r[:branch]} build: #{r[:percent]}% #{r[:commit]}"
puts "=" * 37
puts "Difference: #{diff.round(8)}%"
puts "Pass?: #{pass ? "yes" : "no"}"
puts "Difference: #{diff.round(8)}%"
puts "Pass? #{pass ? "yes" : "no"}"
puts
print_summary_text(build_percent, remote, pull_request_data)
exit pass ? 0 : 1

69
lib/tasks/fe.rake 100644
View File

@ -0,0 +1,69 @@
PACKAGE_JSON_FILE = "./package.json"
DEPS_KEY = "dependencies"
EXCLUDE = ["i18next", "@types/i18next"]
# Load package.json as JSON.
def load_package_json()
return JSON.parse(open(PACKAGE_JSON_FILE).read)
end
# Save JSON to package.json.
def save_package_json(json)
open(PACKAGE_JSON_FILE, "w") { |file|
file.write(JSON.pretty_generate(json))
file.puts
}
end
# Fetch latest versions for outdated dependencies.
def fetch_available_upgrades()
begin
latest_json = JSON.parse(`npm outdated --json`)
rescue JSON::ParserError => exception
latest_json = {}
end
latest_versions = {}
latest_json.each do |dep, data|
unless EXCLUDE.include?(dep) || data["latest"].nil?
latest_versions[dep] = data["latest"]
end
end
return latest_versions
end
# Install depdendency updates.
def install_updates
sh "sudo docker-compose run web npm install"
end
namespace :fe do
desc "Update frontend dependencies to the latest available."\
"This often causes breakage. Use only for development."
task update_deps: :environment do
puts "begin?"; if !user_typed?("developer"); puts "done."; exit end
available_upgrades = fetch_available_upgrades()
if available_upgrades.length > 0
max_key_length = available_upgrades.keys.max_by(&:length).length
package_json = load_package_json()
puts
puts "=" * 40
puts "#{PACKAGE_JSON_FILE} AVAILABLE UPDATES:"
available_upgrades.each do |dep, new_version|
current_version = package_json[DEPS_KEY][dep]
padding = ' ' * (max_key_length - dep.length)
puts " #{dep} #{padding} #{current_version} -> #{new_version}"
package_json[DEPS_KEY][dep] = new_version
end
puts "=" * 40
puts "Type 'save' to update #{PACKAGE_JSON_FILE}, enter to abort."
save_package_json(package_json) if user_typed?("save")
puts "Saved. Use 'sudo docker-compose run web npm install' to upgrade."
# install_updates if user_typed?("update")
else
puts "No updates available."
end
end
end

View File

@ -24,47 +24,48 @@
"author": "farmbot.io",
"license": "MIT",
"dependencies": {
"@blueprintjs/core": "3.10.0",
"@blueprintjs/datetime": "3.5.0",
"@blueprintjs/select": "3.4.0",
"@types/enzyme": "3.1.15",
"@types/jest": "23.3.12",
"@types/lodash": "4.14.120",
"@blueprintjs/core": "3.13.0",
"@blueprintjs/datetime": "3.7.1",
"@blueprintjs/select": "3.6.1",
"@types/enzyme": "3.1.18",
"@types/i18next": "12.1.0",
"@types/jest": "24.0.5",
"@types/lodash": "4.14.121",
"@types/markdown-it": "0.0.7",
"@types/moxios": "0.4.8",
"@types/node": "10.12.18",
"@types/node": "11.9.4",
"@types/promise-timeout": "1.3.0",
"@types/react": "16.7.18",
"@types/react-color": "2.14.0",
"@types/react-dom": "16.0.11",
"@types/react-redux": "6.0.12",
"@types/react": "16.8.3",
"@types/react-color": "2.14.1",
"@types/react-dom": "16.8.1",
"@types/react-redux": "7.0.1",
"axios": "0.18.0",
"boxed_value": "1.0.0",
"browser-speech": "1.1.1",
"coveralls": "3.0.2",
"enzyme": "3.8.0",
"enzyme-adapter-react-16": "1.7.1",
"enzyme-adapter-react-16": "1.9.1",
"farmbot": "7.0.0-rc7",
"farmbot-toastr": "1.0.3",
"i18next": "13.1.0",
"jest": "23.6.0",
"jest-cli": "23.6.0",
"i18next": "12.1.0",
"jest": "24.1.0",
"jest-cli": "24.1.0",
"lodash": "4.17.11",
"markdown-it": "8.4.2",
"markdown-it-emoji": "1.4.0",
"moment": "2.23.0",
"moment": "2.24.0",
"moxios": "0.4.0",
"parcel-bundler": "1.11.0",
"promise-timeout": "1.3.0",
"raf": "3.4.1",
"react": "16.7.0",
"react": "16.8.2",
"react-addons-test-utils": "15.6.2",
"react-color": "2.17.0",
"react-dom": "16.7.0",
"react-joyride": "2.0.2",
"react-dom": "16.8.2",
"react-joyride": "2.0.5",
"react-redux": "6.0.0",
"react-test-renderer": "16.7.0",
"react-transition-group": "2.5.2",
"react-test-renderer": "16.8.2",
"react-transition-group": "2.5.3",
"redux": "4.0.1",
"redux-immutable-state-invariant": "2.1.0",
"redux-thunk": "2.3.0",
@ -72,14 +73,14 @@
"takeme": "0.11.1",
"ts-jest": "23.10.5",
"ts-lint": "4.5.1",
"tslint": "5.12.0",
"typescript": "3.2.4",
"tslint": "5.12.1",
"typescript": "3.3.3",
"which": "1.3.1"
},
"devDependencies": {
"jest-skipped-reporter": "0.0.4",
"madge": "3.4.3",
"sass": "1.16.1"
"madge": "3.4.4",
"sass": "1.17.0"
},
"jest": {
"clearMocks": true,
@ -130,6 +131,8 @@
"lcov"
],
"coverageDirectory": "<rootDir>/coverage_fe",
"setupTestFrameworkScriptFile": "<rootDir>/frontend/__test_support__/customMatchers.js"
"setupFilesAfterEnv": [
"<rootDir>/frontend/__test_support__/customMatchers.js"
]
}
}

View File

@ -34,7 +34,6 @@ describe Api::DeviceCertsController do
post_args = ["/orgs/farmbot/devices/456/certificates/sign",
post_data,
{"Content-Type"=>"application/json"}]
old_count = DeviceSerialNumber.count
# Setup wiring ===========================================================
NervesHub.set_conn(conn)
@ -57,8 +56,8 @@ describe Api::DeviceCertsController do
post :create, body: payl.to_json, params: {format: :json}
end
expect(response.status).to eq(200)
expect(json).to eq({})
expect(DeviceSerialNumber.count).to eq(old_count)
expect(json).to be_kind_of(Hash)
expect(json.fetch(:id)).to eq(device.id)
end
end
end

View File

@ -1,6 +0,0 @@
FactoryBot.define do
factory :device_serial_number do
device { nil }
serial_number { raise "Stop using this model" }
end
end

View File

@ -1,17 +1,31 @@
require 'spec_helper'
require "spec_helper"
describe FbosConfig do
let(:device) { FactoryBot.create(:device) }
let(:config) { FbosConfig.create!(device: device) }
let(:device) { FactoryBot.create(:device) }
let(:config) { FbosConfig.create!(device: device) }
it 'triggers callbacks' do
conn = double("Create a cert", :ca_file= => nil,
:cert_store => nil,
:cert_store= => nil,
:use_ssl => nil,
:use_ssl= => nil,
:cert= => nil,
:key= => nil)
def fake_conn(desc)
double(desc, :ca_file= => nil,
:cert_store => nil,
:cert_store= => nil,
:use_ssl => nil,
:use_ssl= => nil,
:cert= => nil,
:key= => nil)
end
it "notifies us of broken production data" do
# Remove this test by May 2019.
config.device.update_attributes!(serial_number: nil)
conn = fake_conn("Report broke data")
NervesHub.set_conn(conn)
problem = "Device #{device.id} missing serial"
expect(NervesHub).to receive(:report_problem).with({ problem: problem })
config.sync_nerves
end
it "triggers callbacks" do
conn = fake_conn("Create a cert")
NervesHub.set_conn(conn)
url = "/orgs/farmbot/devices/#{device.serial_number}"
resp = StubResp.new("200", { "data" => { "tags": [] } }.to_json)

View File

@ -33,7 +33,7 @@ describe DeviceCerts::Create do
result = DeviceCerts::Create.run!(tags: tags,
device: device,
serial_number: ser)
expect(result).to eq({})
expect(result).to eq(device)
end
end
end

View File

@ -1,9 +0,0 @@
import i18n from "i18next";
declare module "i18next" {
export function init(options: i18n.InitOptions, callback?: i18n.Callback):
Promise<i18n.TranslationFunction>;
export const t: i18n.TranslationFunction;
export type InitOptions = i18n.InitOptions;
export type Callback = i18n.Callback;
}

1
typings/index.d.ts vendored
View File

@ -1,5 +1,4 @@
/// <reference path="react-redux.d.ts" />
/// <reference path="i18next.d.ts" />
/** This contains all of the global ENV vars passed from server => client.
* Previously was `process.env.XYZ`. */