From e29c42afa2814916e1275ae69846186d1f9576f8 Mon Sep 17 00:00:00 2001 From: James Kerr Date: Thu, 9 Aug 2018 16:53:04 -0700 Subject: [PATCH] Removed old code and fixed tests --- README.md | 18 +++ package.json | 7 +- src/js/.eslintrc.yml | 4 +- src/js/actions/boomd.js | 2 +- src/js/actions/fetchMainSearch.js | 2 +- src/js/actions/fetchNextPage.js | 2 +- src/js/actions/logDetails.js | 2 +- src/js/actions/mainSearch.js | 2 +- src/js/actions/spaces.js | 2 +- src/js/{treehouse => boom}/outMessages.js | 0 src/js/reducers/index.test.js | 3 +- src/js/reducers/searchBar.js | 1 - src/js/treehouse/Api.js | 148 ---------------------- src/js/treehouse/Api.test.js | 59 --------- src/js/treehouse/Connection.js | 106 ---------------- src/js/treehouse/Connection.test.js | 114 ----------------- 16 files changed, 33 insertions(+), 439 deletions(-) rename src/js/{treehouse => boom}/outMessages.js (100%) delete mode 100644 src/js/treehouse/Api.js delete mode 100644 src/js/treehouse/Api.test.js delete mode 100644 src/js/treehouse/Connection.js delete mode 100644 src/js/treehouse/Connection.test.js diff --git a/README.md b/README.md index 602b39847a..ce985c1a9e 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,24 @@ npx jest --watch +## Code Style + +This project uses eslint and prettier for style consistency. + +Run the linter: + +``` +npm run lint +``` + +Run the code formatter: + +``` +npm run format +``` + + + ## Release ``` diff --git a/package.json b/package.json index c3cc4b2d93..2ede8af25f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "author": "Looky Labs, Inc.", "scripts": { "start": "npm-run-all -p electron watch:*", - "test": "jest src/js", + "test": "jest --roots src/js", + "pretest": "npm run lint", "electron": "electron .", "release": "electron-packager . Looky --out releases --overwrite --icon dist/static/looky.smaller.icns", "prerelease": "npm run build", @@ -20,7 +21,9 @@ "watch:js": "npm run build:js -- --watch", "watch:css": "npm run build:css -- --watch", "watch:static": "npm run build:static -- --watch", - "watch:reload": "livereload dist" + "watch:reload": "livereload dist", + "lint": "eslint src", + "format": "prettier" }, "jest": { "notify": true, diff --git a/src/js/.eslintrc.yml b/src/js/.eslintrc.yml index 99edb0e26e..af8f08b5ad 100644 --- a/src/js/.eslintrc.yml +++ b/src/js/.eslintrc.yml @@ -1,11 +1,11 @@ parserOptions: - ecmaVersion: 6 + ecmaVersion: 2018 ecmaFeatures: jsx: true - experimentalObjectRestSpread: true sourceType: "module" env: + node: true browser: true jest: true es6: true diff --git a/src/js/actions/boomd.js b/src/js/actions/boomd.js index 7789e3996b..dec5d684ee 100644 --- a/src/js/actions/boomd.js +++ b/src/js/actions/boomd.js @@ -21,7 +21,7 @@ export const connectBoomd = () => (dispatch, getState, api) => { dispatch(setBoomdError("Incorrect user and pass combination.")) else dispatch(connectedBoomd()) }) - .catch(res => { + .catch(_res => { dispatch(setBoomdError("No server running at that host and port.")) }) } diff --git a/src/js/actions/fetchMainSearch.js b/src/js/actions/fetchMainSearch.js index c8a210bc27..9f2724875e 100644 --- a/src/js/actions/fetchMainSearch.js +++ b/src/js/actions/fetchMainSearch.js @@ -1,6 +1,6 @@ import * as actions from "." import * as selectors from "../selectors" -import * as outMessages from "../treehouse/outMessages" +import * as outMessages from "../boom/outMessages" import eventsReceiver from "../receivers/eventsReceiver" import countByTimeReceiver from "../receivers/countByTimeReceiver" import analyticsReceiver from "../receivers/analyticsReceiver" diff --git a/src/js/actions/fetchNextPage.js b/src/js/actions/fetchNextPage.js index e229884153..9c9b061a21 100644 --- a/src/js/actions/fetchNextPage.js +++ b/src/js/actions/fetchNextPage.js @@ -1,6 +1,6 @@ import * as actions from "." import * as selectors from "../selectors/index" -import outMessages from "../treehouse/outMessages" +import outMessages from "../boom/outMessages" import eventsReceiver from "../receivers/eventsReceiver" export function fetchMainSearchPage() { diff --git a/src/js/actions/logDetails.js b/src/js/actions/logDetails.js index 5df9e7a704..788b0b9208 100644 --- a/src/js/actions/logDetails.js +++ b/src/js/actions/logDetails.js @@ -1,5 +1,5 @@ import * as actions from "." -import * as outMessages from "../treehouse/outMessages" +import * as outMessages from "../boom/outMessages" import {getCurrentSpace} from "../reducers/spaces" import * as selectors from "../selectors" diff --git a/src/js/actions/mainSearch.js b/src/js/actions/mainSearch.js index fea25668b8..66eab0b4c4 100644 --- a/src/js/actions/mainSearch.js +++ b/src/js/actions/mainSearch.js @@ -1,5 +1,5 @@ import {getCurrentSpace} from "../reducers/spaces" -import * as outMessages from "../treehouse/outMessages" +import * as outMessages from "../boom/outMessages" import uniq from "lodash/uniq" export function requestMainSearch({saveToHistory, query}) { diff --git a/src/js/actions/spaces.js b/src/js/actions/spaces.js index 864dcf96d1..42075fc6ca 100644 --- a/src/js/actions/spaces.js +++ b/src/js/actions/spaces.js @@ -1,4 +1,4 @@ -import * as outMessages from "../treehouse/outMessages" +import * as outMessages from "../boom/outMessages" export function fetchSpaceInfo(name) { return (dispatch, getState, api) => { diff --git a/src/js/treehouse/outMessages.js b/src/js/boom/outMessages.js similarity index 100% rename from src/js/treehouse/outMessages.js rename to src/js/boom/outMessages.js diff --git a/src/js/reducers/index.test.js b/src/js/reducers/index.test.js index cda4ccc610..7226426df8 100644 --- a/src/js/reducers/index.test.js +++ b/src/js/reducers/index.test.js @@ -3,11 +3,12 @@ import reducer from "." test("NEW_BRO_SCHEMA", () => { const newState = reducer(undefined, { type: "NEW_BRO_SCHEMA", + spaceName: "default", id: "1", descriptor: ["...schema stuff"] }) expect(newState.broSchemas).toEqual({ - 1: ["...schema stuff"] + "default.1": ["...schema stuff"] }) }) diff --git a/src/js/reducers/searchBar.js b/src/js/reducers/searchBar.js index 077c448f65..a41359faa4 100644 --- a/src/js/reducers/searchBar.js +++ b/src/js/reducers/searchBar.js @@ -3,7 +3,6 @@ import isNumber from "lodash/isNumber" import trim from "lodash/trim" import {changeProgramTimeWindow} from "../changeProgramTimeWindow" import {createSelector} from "reselect" -import compact from "lodash/compact" export const initialState = { current: "", diff --git a/src/js/treehouse/Api.js b/src/js/treehouse/Api.js deleted file mode 100644 index 0bcac4d9f3..0000000000 --- a/src/js/treehouse/Api.js +++ /dev/null @@ -1,148 +0,0 @@ -import shortid from "shortid" -import Connection from "./Connection" - -export default class Api { - constructor({conn = new Connection()} = {}) { - this.messageTracker = new MessageTracker() - this.conn = conn - this.onConnectCallback = () => {} - this.onDisconnectCallback = () => {} - this.registerCallbacks() - } - - registerCallbacks() { - this.conn.onOpen(this.onConnectCallback) - this.conn.onClose(this.onDisconnectCallback) - this.conn.onError(this.onError.bind(this)) - this.conn.onMessage(this.onMessage.bind(this)) - } - - connect({host, port, _user, _pass}) { - this.conn = new Connection({ - sessionUrl: `${host}:${port}/session` - }) - this.registerCallbacks() - try { - this.conn.connect() - } catch (e) { - this.onDisconnectCallback(e) - } - } - - onConnect(callback) { - this.onConnectCallback = callback - } - - onDisconnect(callback) { - this.onDisconnectCallback = callback - } - - send(payload) { - const id = this.newId() - const message = new ApiMessageHandler(payload) - - this.messageTracker.register(id, message) - setTimeout(() => this.conn.send({...payload, eid: id})) - - return message - } - - onMessage(messageEvent) { - const {eid, payload} = JSON.parse(messageEvent.data) - const handler = this.messageTracker.lookup(eid) - - if (handler) { - handler.receive(payload) - - if (handler.isDone()) { - this.messageTracker.unregister(eid) - } - } else { - console.warn("Unhandled message", eid, payload) - } - } - - onError(error) { - console.error(error) - } - - pendingRequests() { - return this.messageTracker.getMap() - } - - newId() { - return shortid.generate() - } -} - -class MessageTracker { - constructor() { - this.map = {} - } - - getMap() { - return this.map - } - - register(id, message) { - this.map[id] = message - } - - lookup(key) { - return this.map[key] - } - - unregister(key) { - delete this.map[key] - } -} - -class ApiMessageHandler { - constructor(request) { - this.request = request - this.pending = 0 - this.channelCallbacks = {} - this.doneCallbacks = [] - this.eachCallbacks = [] - this.errorCallbacks = [] - } - - each(callback) { - this.eachCallbacks.push(callback) - return this - } - - channel(id, callback) { - this.channelCallbacks[id] = callback - this.pending += 1 - return this - } - - done(callback) { - this.doneCallbacks.push(callback) - return this - } - - isDone() { - return this.pending === 0 - } - - receive(payload) { - this.eachCallbacks.forEach(cb => cb(payload)) - - if ("channel_id" in payload) { - if (payload.type === "SearchEnd") { - this.pending -= 1 - } - this.channelCallback(payload.channel_id, payload) - } - - if (this.isDone()) { - this.doneCallbacks.forEach(cb => cb(payload)) - } - } - - channelCallback(id, payload) { - if (id in this.channelCallbacks) this.channelCallbacks[id](payload) - } -} diff --git a/src/js/treehouse/Api.test.js b/src/js/treehouse/Api.test.js deleted file mode 100644 index cb65be7bd5..0000000000 --- a/src/js/treehouse/Api.test.js +++ /dev/null @@ -1,59 +0,0 @@ -import Connection from "./Connection" -import MockWebSocket from "../mocks/MockWebSocket" -import Api from "./Api" - -let api - -beforeEach(() => { - let conn = new Connection({transport: MockWebSocket}) - conn.connect() - conn.socket.mockOpen() - api = new Api({conn}) -}) - -test("using channel callbacks", () => { - const channel0 = jest.fn() - const channel1 = jest.fn() - - api - .send({data: "Marco"}) - .channel(0, channel0) - .channel(1, channel1) - - const messageId = Object.keys(api.pendingRequests())[0] - const response = { - eid: messageId, - payload: {type: "SearchResult", channel_id: 0} - } - - api.conn.socket.mockMessage({data: JSON.stringify(response)}) - - expect(channel0).toHaveBeenCalled() - expect(channel1).not.toHaveBeenCalled() -}) - -test("using the done callback", () => { - const channel1 = jest.fn() - const complete = jest.fn() - const request = {data: "Marco"} - - api - .send(request) - .channel(1, channel1) - .done(complete) - - const messageId = Object.keys(api.pendingRequests())[0] - const response = { - eid: messageId, - payload: {type: "SearchEnd", looky: "here", channel_id: 1} - } - - api.conn.socket.mockMessage({data: JSON.stringify(response)}) - - expect(channel1).toHaveBeenCalledWith({ - looky: "here", - channel_id: 1, - type: "SearchEnd" - }) - expect(complete).toHaveBeenCalled() -}) diff --git a/src/js/treehouse/Connection.js b/src/js/treehouse/Connection.js deleted file mode 100644 index ba6e5aef1b..0000000000 --- a/src/js/treehouse/Connection.js +++ /dev/null @@ -1,106 +0,0 @@ -export default class Connection { - constructor(opts = {}) { - this.sessionUrl = opts.sessionUrl - this.sendBuffer = [] - this.transport = opts.transport || WebSocket - this.reconnectTimer = new Timer(() => this.connect()) - this.callbacks = {open: [], error: [], message: [], close: []} - } - - connect() { - if (this.socket) this.socket.close() - - this.socket = new this.transport(`ws://${this.sessionUrl}`) - this.socket.onopen = () => this.onSocketOpen() - this.socket.onerror = error => this.onSocketError(error) - this.socket.onmessage = message => this.onSocketMessage(message) - this.socket.onclose = () => this.onSocketClose() - } - - disconnect() { - if (this.socket) this.socket.close() - } - - onOpen(callback) { - this.callbacks.open.push(callback) - } - - onError(callback) { - this.callbacks.error.push(callback) - } - - onMessage(callback) { - this.callbacks.message.push(callback) - } - - onClose(callback) { - this.callbacks.close.push(callback) - } - - send(payload) { - if (this.isConnected()) { - this.socket.send(JSON.stringify(payload)) - } else { - this.sendBuffer.push(payload) - } - } - - // Private Interface Below - - isConnected() { - if (!this.socket) return false - else return this.socket.readyState === WebSocket.OPEN - } - - onSocketOpen() { - this.reconnectTimer.clear() - this.callbacks.open.forEach(callback => callback()) - this.flushSendBuffer() - } - - onSocketError(error) { - this.callbacks.error.forEach(callback => callback(error)) - } - - onSocketMessage(message) { - this.callbacks.message.forEach(callback => callback(message)) - } - - onSocketClose() { - this.callbacks.close.forEach(callback => callback()) - this.socket = null - this.reconnectTimer.scheduleAttempt() - } - - flushSendBuffer() { - while (this.isConnected() && this.sendBuffer.length > 0) { - this.send(this.sendBuffer.shift()) - } - } -} - -class Timer { - constructor(callback, delayFunc) { - this.delayFunc = - delayFunc || (tries => [1000, 2000, 3000][tries - 1] || 4000) - this.callback = callback - this.timeoutId = null - this.tries = 0 - } - - scheduleAttempt() { - const nextTry = this.tries + 1 - const delay = this.delayFunc(nextTry) - clearTimeout(this.timeoutId) - - this.timeoutId = setTimeout(() => { - this.tries = nextTry - this.callback() - }, delay) - } - - clear() { - this.tries = 0 - clearTimeout(this.timeoutId) - } -} diff --git a/src/js/treehouse/Connection.test.js b/src/js/treehouse/Connection.test.js deleted file mode 100644 index 64ce34d664..0000000000 --- a/src/js/treehouse/Connection.test.js +++ /dev/null @@ -1,114 +0,0 @@ -import Connection from "./Connection" -import MockWebSocket from "../mocks/MockWebSocket" - -test("onOpen callback", () => { - let conn = new Connection({transport: MockWebSocket}) - let called = false - conn.onOpen(() => (called = true)) - - conn.connect() - conn.socket.mockOpen() - - expect(called).toBe(true) -}) - -test("onError Callback", () => { - let conn = new Connection({transport: MockWebSocket}) - let error = null - conn.onError(err => (error = err)) - - conn.connect() - conn.socket.mockError("bad bad bad") - - expect(error).toBe("bad bad bad") -}) - -test("onMessage callback", () => { - let conn = new Connection({transport: MockWebSocket}) - let message = null - conn.onMessage(msg => (message = msg)) - - conn.connect() - conn.socket.mockMessage("hello world") - - expect(message).toBe("hello world") -}) - -test("onClose callback", () => { - let conn = new Connection({transport: MockWebSocket}) - let called = false - conn.onClose(() => (called = true)) - - conn.connect() - conn.socket.mockClose() - - expect(called).toBe(true) -}) - -test("isConnected when no socket instance", () => { - let conn = new Connection({transport: MockWebSocket}) - - expect(conn.isConnected()).toBe(false) -}) - -test("isConnected when still connecting", () => { - let conn = new Connection({transport: MockWebSocket}) - - conn.connect() - - expect(conn.isConnected()).toBe(false) -}) - -test("isConnected when socket is connected", () => { - let conn = new Connection({transport: MockWebSocket}) - - conn.connect() - conn.socket.mockOpen() - - expect(conn.isConnected()).toBe(true) -}) - -test("isConnected when socket is closed", () => { - let conn = new Connection({transport: MockWebSocket}) - conn.connect() - conn.socket.mockOpen() - expect(conn.isConnected()).toBe(true) - - conn.socket.mockClose() - - expect(conn.isConnected()).toBe(false) -}) - -test("buffers messages until connected", () => { - let conn = new Connection({transport: MockWebSocket}) - conn.connect() - conn.send({james: "kerr"}) - conn.send({matt: "nibecker"}) - expect(conn.socket.sentMessages.length).toBe(0) - - conn.socket.mockOpen() - - expect(conn.socket.sentMessages).toEqual([ - {james: "kerr"}, - {matt: "nibecker"} - ]) -}) - -test("retries to connect if failed", () => { - let conn = new Connection({transport: MockWebSocket}) - conn.connect() - expect(conn.reconnectTimer.timeoutId).toBe(null) - - conn.socket.mockClose() - expect(conn.reconnectTimer.timeoutId).toEqual(expect.any(Number)) -}) - -test("the reconnect timer calls connect", () => { - let conn = new Connection({transport: MockWebSocket}) - let called = false - conn.connect = () => (called = true) - - conn.reconnectTimer.callback() - - expect(called).toBe(true) -})