diff --git a/package.json b/package.json index 1d0dc08..e554992 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,13 @@ "github-api": "^3.0.0", "hls": "0.0.1", "hls.js": "^0.7.9", + "husky": "^0.14.3", "int64-buffer": "^0.1.9", "js-cookie": "^2.1.4", "left-pad": "^1.1.3", + "lint-staged": "^6.0.0", "moment": "^2.18.1", + "prettier": "^1.9.2", "prop-types": "^15.5.10", "raven-js": "^3.16.0", "react": "^16.2.0", @@ -57,6 +60,13 @@ "build": "react-app-rewired build", "test": "react-app-rewired test --env=jsdom", "sass": - "scss src/index.scss:src/index.css; sass --watch src/index.scss:src/index.css" + "scss src/index.scss:src/index.css; sass --watch src/index.scss:src/index.css", + "precommit": "lint-staged" + }, + "lint-staged": { + "*.{js,jsx}": ["prettier --parser flow --write", "git add"], + "*.json": ["prettier --parser json --write", "git add"], + "*.{graphql,gql}": ["prettier --parser graphql --write", "git add"], + "*.{md,markdown}": ["prettier --parser markdown --write", "git add"] } } diff --git a/src/__tests__/can/dbc.mutate.js b/src/__tests__/can/dbc.mutate.js index 2d16273..0874206 100644 --- a/src/__tests__/can/dbc.mutate.js +++ b/src/__tests__/can/dbc.mutate.js @@ -1,25 +1,27 @@ -global.__JEST__ = 1 -import DBC from '../../models/can/dbc'; -import Signal from '../../models/can/signal'; +global.__JEST__ = 1; +import DBC from "../../models/can/dbc"; +import Signal from "../../models/can/signal"; -test('setting signals should create a message', () => { - const dbc = new DBC(); - dbc.setSignals(100, {'My Signal': new Signal({name: 'My Signal'})}); +test("setting signals should create a message", () => { + const dbc = new DBC(); + dbc.setSignals(100, { "My Signal": new Signal({ name: "My Signal" }) }); - expect(dbc.messages.has(100)).toBe(true); + expect(dbc.messages.has(100)).toBe(true); }); -test('setting signals should update DBC.boardUnits', () => { - const dbc = new DBC(); - dbc.setSignals(100, {'My Signal': new Signal({name: 'My Signal', receiver: ['NEO']})}); +test("setting signals should update DBC.boardUnits", () => { + const dbc = new DBC(); + dbc.setSignals(100, { + "My Signal": new Signal({ name: "My Signal", receiver: ["NEO"] }) + }); - expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0); + expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0); }); -test('adding a signal should update DBC.boardUnits', () => { - const dbc = new DBC(); - dbc.createFrame(100); - dbc.addSignal(100, new Signal({name: 'My Signal', receiver: ['NEO']})); +test("adding a signal should update DBC.boardUnits", () => { + const dbc = new DBC(); + dbc.createFrame(100); + dbc.addSignal(100, new Signal({ name: "My Signal", receiver: ["NEO"] })); - expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0); -}); \ No newline at end of file + expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0); +}); diff --git a/src/__tests__/can/dbc.parse.test.js b/src/__tests__/can/dbc.parse.test.js index 62f8c7a..2521cfd 100644 --- a/src/__tests__/can/dbc.parse.test.js +++ b/src/__tests__/can/dbc.parse.test.js @@ -1,7 +1,7 @@ -global.__JEST__ = 1 -import DBC, {swapOrder} from '../../models/can/dbc'; -import Signal from '../../models/can/signal'; -import Bitarray from '../../models/bitarray'; +global.__JEST__ = 1; +import DBC, { swapOrder } from "../../models/can/dbc"; +import Signal from "../../models/can/signal"; +import Bitarray from "../../models/bitarray"; const DBC_MESSAGE_DEF = `BO_ 228 STEERING_CONTROL: 5 ADAS SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS @@ -63,7 +63,7 @@ BO_ 228 STEERING_CONTROL: 5 ADAS CM_ SG_ 228 STEER_TORQUE "steer torque is the amount of torque in Nm applied";`; - const DBC_SIGNAL_WITH_MULTI_LINE_COMMENT = ` +const DBC_SIGNAL_WITH_MULTI_LINE_COMMENT = ` BO_ 228 STEERING_CONTROL: 5 ADAS SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS @@ -137,136 +137,148 @@ VAL_TABLE_ DI_speedUnits 1 "DI_SPEED_KPH" 0 "DI_SPEED_MPH" ; `; const steerTorqueSignal = new Signal({ - name: 'STEER_TORQUE', - startBit: 7, - size: 16, - isLittleEndian: false, - isSigned: true, - factor: 1, - offset: 0, - min: -3840, - max: 3840, - receiver: ['EPS'], - unit: ""}); - -test('DBC parses steering control message', () => { - const dbcParsed = new DBC(DBC_MESSAGE_DEF); - const {signals} = dbcParsed.messages.get(228); - - expect(Object.keys(signals).length).toBe(6); - expect(signals['STEER_TORQUE'].equals(steerTorqueSignal)).toBe(true); + name: "STEER_TORQUE", + startBit: 7, + size: 16, + isLittleEndian: false, + isSigned: true, + factor: 1, + offset: 0, + min: -3840, + max: 3840, + receiver: ["EPS"], + unit: "" }); -test('DBC parses signal comment', () => { - const dbcParsed = new DBC(DBC_SIGNAL_WITH_COMMENT); - const {signals} = dbcParsed.messages.get(228); +test("DBC parses steering control message", () => { + const dbcParsed = new DBC(DBC_MESSAGE_DEF); + const { signals } = dbcParsed.messages.get(228); - expect(signals.STEER_TORQUE.comment).toEqual("steer torque is the amount of torque in Nm applied"); + expect(Object.keys(signals).length).toBe(6); + expect(signals["STEER_TORQUE"].equals(steerTorqueSignal)).toBe(true); }); -test('DBC parses multi-line signal comment', () => { - const dbcParsed = new DBC(DBC_SIGNAL_WITH_MULTI_LINE_COMMENT); - const {signals} = dbcParsed.messages.get(228); +test("DBC parses signal comment", () => { + const dbcParsed = new DBC(DBC_SIGNAL_WITH_COMMENT); + const { signals } = dbcParsed.messages.get(228); - expect(signals.STEER_TORQUE.comment).toEqual("steer torque is the\namount of torque in Nm applied"); + expect(signals.STEER_TORQUE.comment).toEqual( + "steer torque is the amount of torque in Nm applied" + ); }); -test('DBC parses message comment', () => { - const dbcParsed = new DBC(DBC_MESSAGE_WITH_COMMENT); - const msg = dbcParsed.messages.get(228); +test("DBC parses multi-line signal comment", () => { + const dbcParsed = new DBC(DBC_SIGNAL_WITH_MULTI_LINE_COMMENT); + const { signals } = dbcParsed.messages.get(228); - expect(msg.comment).toEqual("this message contains steer torque information"); + expect(signals.STEER_TORQUE.comment).toEqual( + "steer torque is the\namount of torque in Nm applied" + ); }); -test('DBC parses multi-line message comment', () => { - const dbcParsed = new DBC(DBC_MESSAGE_WITH_MULTI_LINE_COMMENT); - const msg = dbcParsed.messages.get(228); +test("DBC parses message comment", () => { + const dbcParsed = new DBC(DBC_MESSAGE_WITH_COMMENT); + const msg = dbcParsed.messages.get(228); - expect(msg.comment).toEqual("this message contains\nsteer torque information"); + expect(msg.comment).toEqual("this message contains steer torque information"); }); -test('DBC parses board unit names', () => { - const dbcParsed = new DBC(DBC_BOARD_UNITS); - expect(dbcParsed.boardUnits[0].name).toEqual("first_board_unit"); - expect(dbcParsed.boardUnits[1].name).toEqual("second_board_unit"); +test("DBC parses multi-line message comment", () => { + const dbcParsed = new DBC(DBC_MESSAGE_WITH_MULTI_LINE_COMMENT); + const msg = dbcParsed.messages.get(228); + + expect(msg.comment).toEqual( + "this message contains\nsteer torque information" + ); }); -test('DBC parses board unit comments', () => { - const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT); - expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit comment"); +test("DBC parses board unit names", () => { + const dbcParsed = new DBC(DBC_BOARD_UNITS); + expect(dbcParsed.boardUnits[0].name).toEqual("first_board_unit"); + expect(dbcParsed.boardUnits[1].name).toEqual("second_board_unit"); }); -test('DBC parses multi-line board unit comments', () => { - const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT_LINES); - expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit\ncomment"); +test("DBC parses board unit comments", () => { + const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT); + expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit comment"); }); -test('DBC parses signal value descriptions', () => { - const dbcParsed = new DBC(DBC_SIGNALS_WITH_VAL); - const {signals} = dbcParsed.messages.get(228); - - const expectedTorqueRequestVals = new Map([['1', 'requesting torque'], - ['0', 'not requesting torque']]); - expect(signals.STEER_TORQUE_REQUEST.valueDescriptions).toEqual(expectedTorqueRequestVals); +test("DBC parses multi-line board unit comments", () => { + const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT_LINES); + expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit\ncomment"); }); -test('DBC parses value tables', () => { - const dbcParsed = new DBC(DBC_VALUE_TABLE); - const stateTableEntries = [['4', "DI_STATE_ENABLE"], - ['3', "DI_STATE_FAULT"], - ['2', "DI_STATE_CLEAR_FAULT"], - ['1', "DI_STATE_STANDBY"], - ['0', "DI_STATE_PREAUTH"]] - const stateTable = new Map(stateTableEntries); - const speedUnitsEntries = [['1',"DI_SPEED_KPH"], - ['0',"DI_SPEED_MPH"]] - const speedUnitsTable = new Map(speedUnitsEntries); +test("DBC parses signal value descriptions", () => { + const dbcParsed = new DBC(DBC_SIGNALS_WITH_VAL); + const { signals } = dbcParsed.messages.get(228); - const valueTableEntries = Array.from(dbcParsed.valueTables.entries()); - expect(valueTableEntries[0]).toEqual(['DI_state', stateTable]); - expect(valueTableEntries[1]).toEqual(['DI_speedUnits', speedUnitsTable]); + const expectedTorqueRequestVals = new Map([ + ["1", "requesting torque"], + ["0", "not requesting torque"] + ]); + expect(signals.STEER_TORQUE_REQUEST.valueDescriptions).toEqual( + expectedTorqueRequestVals + ); }); -test('swapOrder properly converts little endian to big endian', () => { - const littleEndianHex = 'e2d62a0bd0d3b5e5'; - const bigEndianHex = 'e5b5d3d00b2ad6e2'; +test("DBC parses value tables", () => { + const dbcParsed = new DBC(DBC_VALUE_TABLE); + const stateTableEntries = [ + ["4", "DI_STATE_ENABLE"], + ["3", "DI_STATE_FAULT"], + ["2", "DI_STATE_CLEAR_FAULT"], + ["1", "DI_STATE_STANDBY"], + ["0", "DI_STATE_PREAUTH"] + ]; + const stateTable = new Map(stateTableEntries); + const speedUnitsEntries = [["1", "DI_SPEED_KPH"], ["0", "DI_SPEED_MPH"]]; + const speedUnitsTable = new Map(speedUnitsEntries); - const littleEndianHexSwapped = swapOrder(littleEndianHex, 16, 2); - - expect(littleEndianHexSwapped == bigEndianHex).toBe(true); + const valueTableEntries = Array.from(dbcParsed.valueTables.entries()); + expect(valueTableEntries[0]).toEqual(["DI_state", stateTable]); + expect(valueTableEntries[1]).toEqual(["DI_speedUnits", speedUnitsTable]); }); -test('int32 parser produces correct value for steer torque signal', () => { - const dbc = new DBC(DBC_MESSAGE_DEF); +test("swapOrder properly converts little endian to big endian", () => { + const littleEndianHex = "e2d62a0bd0d3b5e5"; + const bigEndianHex = "e5b5d3d00b2ad6e2"; - const hex = 'e2d62a0bd0d3b5e5'; - const buffer = Buffer.from(hex, 'hex'); - const bufferSwapped = Buffer.from(buffer).swap64(); + const littleEndianHexSwapped = swapOrder(littleEndianHex, 16, 2); - const bitArr = Bitarray.fromBytes(buffer); - const bitsSwapped = Bitarray.fromBytes(bufferSwapped); - const value = dbc.valueForInt32Signal(steerTorqueSignal, bitArr, bitsSwapped); - - expect(value).toBe(-7466); + expect(littleEndianHexSwapped == bigEndianHex).toBe(true); }); -test('int64 parser produces correct value for steer torque signal', () => { - const dbc = new DBC(DBC_MESSAGE_DEF); +test("int32 parser produces correct value for steer torque signal", () => { + const dbc = new DBC(DBC_MESSAGE_DEF); - const hex = 'e2d62a0bd0d3b5e5'; - const value = dbc.valueForInt64Signal(steerTorqueSignal, hex); + const hex = "e2d62a0bd0d3b5e5"; + const buffer = Buffer.from(hex, "hex"); + const bufferSwapped = Buffer.from(buffer).swap64(); - expect(value).toBe(-7466); + const bitArr = Bitarray.fromBytes(buffer); + const bitsSwapped = Bitarray.fromBytes(bufferSwapped); + const value = dbc.valueForInt32Signal(steerTorqueSignal, bitArr, bitsSwapped); + + expect(value).toBe(-7466); +}); + +test("int64 parser produces correct value for steer torque signal", () => { + const dbc = new DBC(DBC_MESSAGE_DEF); + + const hex = "e2d62a0bd0d3b5e5"; + const value = dbc.valueForInt64Signal(steerTorqueSignal, hex); + + expect(value).toBe(-7466); }); function dbcInt32SignalValue(dbc, signalSpec, hex) { - const buffer = Buffer.from(hex, 'hex'); - const bufferSwapped = Buffer.from(buffer).swap64(); + const buffer = Buffer.from(hex, "hex"); + const bufferSwapped = Buffer.from(buffer).swap64(); - const bits = Bitarray.fromBytes(buffer); - const bitsSwapped = Bitarray.fromBytes(bufferSwapped); + const bits = Bitarray.fromBytes(buffer); + const bitsSwapped = Bitarray.fromBytes(bufferSwapped); - return dbc.valueForInt32Signal(signalSpec, bits, bitsSwapped); + return dbc.valueForInt32Signal(signalSpec, bits, bitsSwapped); } const DBC_BINARY_LE_SIGNAL = ` @@ -274,56 +286,53 @@ BO_ 768 NEW_MSG_1: 8 XXX SG_ NEW_SIGNAL_1 : 37|1@1+ (1,0) [0|1] "" XXX `; -test('int32 parsers produces correct value for binary little endian signal', () => { - const dbc = new DBC(DBC_BINARY_LE_SIGNAL) - const signalSpec = dbc.messages.get(768).signals['NEW_SIGNAL_1']; +test("int32 parsers produces correct value for binary little endian signal", () => { + const dbc = new DBC(DBC_BINARY_LE_SIGNAL); + const signalSpec = dbc.messages.get(768).signals["NEW_SIGNAL_1"]; - const hexDataSet = '0000000020000000'; - const hexDataNotSet = '0000000000000000'; + const hexDataSet = "0000000020000000"; + const hexDataNotSet = "0000000000000000"; + const setValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSet); + const notSetValue = dbcInt32SignalValue(dbc, signalSpec, hexDataNotSet); - const setValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSet); - const notSetValue = dbcInt32SignalValue(dbc, signalSpec, hexDataNotSet); - - expect(setValue).toEqual(1); - expect(notSetValue).toEqual(0); + expect(setValue).toEqual(1); + expect(notSetValue).toEqual(0); }); const DBC_TWO_BIT_LE_SIGNAL = ` BO_ 768 NEW_MSG_1: 8 XXX SG_ NEW_SIGNAL_1 : 35|2@1+ (1,0) [0|3] "" XXX `; -test('int32 parser produces correct value for 2-bit little endian signal spanning words', () => { - const dbc = new DBC(DBC_TWO_BIT_LE_SIGNAL); - const signalSpec = dbc.messages.get(768).signals['NEW_SIGNAL_1']; +test("int32 parser produces correct value for 2-bit little endian signal spanning words", () => { + const dbc = new DBC(DBC_TWO_BIT_LE_SIGNAL); + const signalSpec = dbc.messages.get(768).signals["NEW_SIGNAL_1"]; - const hexData = '00000001f8000000'; + const hexData = "00000001f8000000"; - const value = dbcInt32SignalValue(dbc, signalSpec, hexData); - expect(value).toEqual(3); + const value = dbcInt32SignalValue(dbc, signalSpec, hexData); + expect(value).toEqual(3); }); const DBC_FOUR_BIT_LE_SIGNAL = ` BO_ 768 NEW_MSG_1: 8 XXX SG_ NEW_SIGNAL_1 : 6|4@1+ (1,0) [0|15] "" XXX `; -test('int32 parser produces correct value for 4-bit little endian signal', () => { - const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL); - const signalSpec = dbc.messages.get(768).signals['NEW_SIGNAL_1']; +test("int32 parser produces correct value for 4-bit little endian signal", () => { + const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL); + const signalSpec = dbc.messages.get(768).signals["NEW_SIGNAL_1"]; - // this data is symmetric, the data bits are 1111 - const hexDataSymmetric = 'f00f000000000000'; - const symValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSymmetric); - expect(symValue).toEqual(15); + // this data is symmetric, the data bits are 1111 + const hexDataSymmetric = "f00f000000000000"; + const symValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSymmetric); + expect(symValue).toEqual(15); - // this data is asymmetric, the data bits are 1101 - const hexDataAsymmetric = 'f002000000000000'; - const aSymValue = dbcInt32SignalValue(dbc, signalSpec, hexDataAsymmetric); - expect(aSymValue).toEqual(11); + // this data is asymmetric, the data bits are 1101 + const hexDataAsymmetric = "f002000000000000"; + const aSymValue = dbcInt32SignalValue(dbc, signalSpec, hexDataAsymmetric); + expect(aSymValue).toEqual(11); }); - - const DBC_CHFFR_METRIC_COMMENT = ` BO_ 37 STEERING_CONTROL: 8 XXX SG_ STEER_ANGLE : 6|4@1+ (1,0) [0|15] "" XXX @@ -331,10 +340,12 @@ BO_ 37 STEERING_CONTROL: 8 XXX CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180"; `; -test('dbc parser parses top-level comment with chffr metric', () => { - const dbc = new DBC(DBC_CHFFR_METRIC_COMMENT); - const { comments } = dbc; +test("dbc parser parses top-level comment with chffr metric", () => { + const dbc = new DBC(DBC_CHFFR_METRIC_COMMENT); + const { comments } = dbc; - expect(comments.length).toEqual(1); - expect(comments[0]).toEqual("CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180"); -}) \ No newline at end of file + expect(comments.length).toEqual(1); + expect(comments[0]).toEqual( + "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180" + ); +}); diff --git a/src/__tests__/can/dbc.write.test.js b/src/__tests__/can/dbc.write.test.js index a64bd83..f70dcc3 100644 --- a/src/__tests__/can/dbc.write.test.js +++ b/src/__tests__/can/dbc.write.test.js @@ -1,17 +1,17 @@ -global.__JEST__ = 1 -import DBC, {swapOrder} from '../../models/can/dbc'; -import { ACURA_DBC } from '../res/acura-dbc'; -import { CRV_DBC } from '../res/crv-dbc'; -import { TESLA_DBC } from '../res/tesla-dbc'; +global.__JEST__ = 1; +import DBC, { swapOrder } from "../../models/can/dbc"; +import { ACURA_DBC } from "../res/acura-dbc"; +import { CRV_DBC } from "../res/crv-dbc"; +import { TESLA_DBC } from "../res/tesla-dbc"; -test('DBC.text() for acura DBC should be equivalent to its original text', () => { - const dbc = new DBC(ACURA_DBC); +test("DBC.text() for acura DBC should be equivalent to its original text", () => { + const dbc = new DBC(ACURA_DBC); - expect(dbc.text()).toBe(ACURA_DBC); + expect(dbc.text()).toBe(ACURA_DBC); }); -test('DBC.text() for crv DBC should be equivalent to its original text', () => { - const dbc = new DBC(CRV_DBC); +test("DBC.text() for crv DBC should be equivalent to its original text", () => { + const dbc = new DBC(CRV_DBC); - expect(dbc.text()).toBe(CRV_DBC); + expect(dbc.text()).toBe(CRV_DBC); }); diff --git a/src/__tests__/can/entries.test.js b/src/__tests__/can/entries.test.js index b054289..33913e1 100644 --- a/src/__tests__/can/entries.test.js +++ b/src/__tests__/can/entries.test.js @@ -1,9 +1,17 @@ -import Entries from '../../models/can/entries'; +import Entries from "../../models/can/entries"; -test('segment index low is inclusive and index high is exclusive', () => { - const entries = [{time: 1.0}, {time: 3.45}, {time: 3.65}, {time: 5.55}]; - const [segmentIdxLow, segmentIdxHi] = Entries.findSegmentIndices(entries, [3.45, 5.55]); +test("segment index low is inclusive and index high is exclusive", () => { + const entries = [ + { time: 1.0 }, + { time: 3.45 }, + { time: 3.65 }, + { time: 5.55 } + ]; + const [segmentIdxLow, segmentIdxHi] = Entries.findSegmentIndices(entries, [ + 3.45, + 5.55 + ]); - expect(segmentIdxLow).toBe(1); - expect(segmentIdxHi).toBe(entries.length - 1); -}) + expect(segmentIdxLow).toBe(1); + expect(segmentIdxHi).toBe(entries.length - 1); +}); diff --git a/src/__tests__/can/frame.test.js b/src/__tests__/can/frame.test.js index 0fa6e36..7c102b5 100644 --- a/src/__tests__/can/frame.test.js +++ b/src/__tests__/can/frame.test.js @@ -1,8 +1,13 @@ -import Frame from '../../models/can/frame'; +import Frame from "../../models/can/frame"; const FRAME_HEADER = "BO_ 255 SOME_FRAME: 5 ADAS"; -test('Frame.header() returns spec compliant representation', () => { - const frame = new Frame({name: 'SOME_FRAME', id: 255, size: 5, transmitters: ['ADAS']}); - expect(frame.header()).toEqual(FRAME_HEADER); +test("Frame.header() returns spec compliant representation", () => { + const frame = new Frame({ + name: "SOME_FRAME", + id: 255, + size: 5, + transmitters: ["ADAS"] + }); + expect(frame.header()).toEqual(FRAME_HEADER); }); diff --git a/src/__tests__/can/signal.test.js b/src/__tests__/can/signal.test.js index 00ff3f3..fb7dd3d 100644 --- a/src/__tests__/can/signal.test.js +++ b/src/__tests__/can/signal.test.js @@ -1,77 +1,104 @@ -import Signal from '../../models/can/signal'; +import Signal from "../../models/can/signal"; const someSignalParams = { - name: 'STEER_TORQUE', - startBit: 7, - size: 16, - isLittleEndian: false, - isSigned: true, - factor: 1, - offset: 0, - min: -3840, - max: 3840, - unit: ""}; + name: "STEER_TORQUE", + startBit: 7, + size: 16, + isLittleEndian: false, + isSigned: true, + factor: 1, + offset: 0, + min: -3840, + max: 3840, + unit: "" +}; const someOtherSignalParams = { - name: 'DIFFERENT_NAME', - startBit: 0, + name: "DIFFERENT_NAME", + startBit: 0, + size: 16, + isLittleEndian: false, + isSigned: true, + factor: 1, + offset: 0, + min: -3840, + max: 3840, + unit: "" +}; + +test("Signal.equals returns true for signals with identical properties", () => { + const someSignal = new Signal(someSignalParams); + const someEquivalentSignal = new Signal(someSignalParams); + expect(someSignal.equals(someEquivalentSignal)).toBe(true); +}); + +test("Signal.equals returns false for signals with different properties", () => { + const someSignal = new Signal(someSignalParams); + const differentSignal = new Signal(someOtherSignalParams); + expect(someSignal.equals(differentSignal)).toBe(false); +}); + +test("Signal.bitDescription returns proper description for a little endian signal", () => { + const littleEndianSignal = new Signal({ + name: "little endian signal", + startBit: 20, + size: 4, + isLittleEndian: true + }); + + expect(littleEndianSignal.bitDescription(20).bitNumber).toBe(0); + expect(littleEndianSignal.bitDescription(21).bitNumber).toBe(1); + expect(littleEndianSignal.bitDescription(22).bitNumber).toBe(2); + expect(littleEndianSignal.bitDescription(23).bitNumber).toBe(3); +}); + +test("Signal.bitDescription returns proper description for a big endian signal", () => { + const bigEndianSignal = new Signal({ + name: "big endian signal", + startBit: 7, size: 16, - isLittleEndian: false, - isSigned: true, - factor: 1, - offset: 0, - min: -3840, - max: 3840, - unit: ""}; + isLittleEndian: false + }); -test('Signal.equals returns true for signals with identical properties', () => { - const someSignal = new Signal(someSignalParams); - const someEquivalentSignal = new Signal(someSignalParams); - expect(someSignal.equals(someEquivalentSignal)).toBe(true); + const bitFifteenDescription = { + bitNumber: 8, + isLsb: false, + isMsb: false, + range: [0, 15] + }; + const bitZeroDescription = { + bitNumber: 7, + isLsb: false, + isMsb: false, + range: [0, 15] + }; + const bitEightDescription = { + bitNumber: 15, + isLsb: true, + isMsb: false, + range: [0, 15] + }; + const bitSevenDescription = { + bitNumber: 0, + isLsb: false, + isMsb: true, + range: [0, 15] + }; + + expect(bigEndianSignal.bitDescription(15)).toEqual(bitFifteenDescription); + expect(bigEndianSignal.bitDescription(0)).toEqual(bitZeroDescription); + expect(bigEndianSignal.bitDescription(8)).toEqual(bitEightDescription); + expect(bigEndianSignal.bitDescription(7)).toEqual(bitSevenDescription); }); -test('Signal.equals returns false for signals with different properties', () => { - const someSignal = new Signal(someSignalParams); - const differentSignal = new Signal(someOtherSignalParams); - expect(someSignal.equals(differentSignal)).toBe(false); -}); - -test('Signal.bitDescription returns proper description for a little endian signal', () => { - const littleEndianSignal = new Signal({name: 'little endian signal', - startBit: 20, - size: 4, - isLittleEndian: true}); - - expect(littleEndianSignal.bitDescription(20).bitNumber).toBe(0); - expect(littleEndianSignal.bitDescription(21).bitNumber).toBe(1); - expect(littleEndianSignal.bitDescription(22).bitNumber).toBe(2); - expect(littleEndianSignal.bitDescription(23).bitNumber).toBe(3); -}); - -test('Signal.bitDescription returns proper description for a big endian signal', () => { - const bigEndianSignal = new Signal({name: 'big endian signal', - startBit: 7, - size: 16, - isLittleEndian: false}); - - const bitFifteenDescription = {bitNumber: 8, isLsb: false, isMsb: false, range: [0,15]}; - const bitZeroDescription = {bitNumber: 7, isLsb: false, isMsb: false, range: [0,15]}; - const bitEightDescription = {bitNumber: 15, isLsb: true, isMsb: false, range: [0,15]}; - const bitSevenDescription = {bitNumber: 0, isLsb: false, isMsb: true, range: [0,15]}; - - expect(bigEndianSignal.bitDescription(15)).toEqual(bitFifteenDescription); - expect(bigEndianSignal.bitDescription(0)).toEqual(bitZeroDescription); - expect(bigEndianSignal.bitDescription(8)).toEqual(bitEightDescription); - expect(bigEndianSignal.bitDescription(7)).toEqual(bitSevenDescription); -}); - - -test('Signal.bitDescription returns null for bit index that is not in its range', () => { - const someSignal = new Signal({name: 'some signal', - startBit: 20, - size: 4, - isLittleEndian: false}); - - expect(someSignal.bitDescription(21)).toBe(null); - expect(someSignal.bitDescription(16)).toBe(null); +test("Signal.bitDescription returns null for bit index that is not in its range", () => { + const someSignal = new Signal({ + name: "some signal", + startBit: 20, + size: 4, + isLittleEndian: false + }); + + expect(someSignal.bitDescription(21)).toBe(null); + expect(someSignal.bitDescription(16)).toBe(null); }); diff --git a/src/__tests__/components/AddSignals.test.js b/src/__tests__/components/AddSignals.test.js index 57e9b79..7fea64b 100644 --- a/src/__tests__/components/AddSignals.test.js +++ b/src/__tests__/components/AddSignals.test.js @@ -5,10 +5,10 @@ note: 'right' and 'left' in test descriptions refer to the sides of the bit matrix as displayed to the user. */ -import AddSignals from '../../components/AddSignals'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; -import {StyleSheetTestUtils} from 'aphrodite'; +import AddSignals from "../../components/AddSignals"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; +import { StyleSheetTestUtils } from "aphrodite"; // Prevents style injection from firing after test finishes // and jsdom is torn down. @@ -22,286 +22,332 @@ afterEach(() => { // signal creation function createAddSignals(signals) { - if(signals === undefined) { - signals = {}; - } - const message = {signals, - address: 0, - entries: [ - {relTime: 0, - hexData: '0000000000000000'} - ]}; + if (signals === undefined) { + signals = {}; + } + const message = { + signals, + address: 0, + entries: [ + { + relTime: 0, + hexData: "0000000000000000" + } + ] + }; - const component = shallow( {}} />); + const component = shallow( + {}} + /> + ); - return component; + return component; } -test('double clicking adds a signal', () => { - const component = createAddSignals(); +test("double clicking adds a signal", () => { + const component = createAddSignals(); - const firstBit = component.find('.bit').first(); + const firstBit = component.find(".bit").first(); - firstBit.simulate('dblclick'); - const newSignal = Object.values(component.state('signals'))[0]; + firstBit.simulate("dblclick"); + const newSignal = Object.values(component.state("signals"))[0]; - expect(newSignal).toBeDefined(); - expect(newSignal.size).toBe(1); + expect(newSignal).toBeDefined(); + expect(newSignal.size).toBe(1); }); -test('dragging right to left across a byte creates a little endian signal', () => { - const component = createAddSignals(); - const leftBitInByte = component.find('.bit').first(); - const rightBitInByte = component.find('.bit').at(7); - rightBitInByte.simulate('mousedown'); - leftBitInByte.simulate('mouseup'); +test("dragging right to left across a byte creates a little endian signal", () => { + const component = createAddSignals(); + const leftBitInByte = component.find(".bit").first(); + const rightBitInByte = component.find(".bit").at(7); + rightBitInByte.simulate("mousedown"); + leftBitInByte.simulate("mouseup"); - const newSignal = Object.values(component.state('signals'))[0]; - expect(newSignal).toBeDefined(); - expect(newSignal.size).toBe(8); - expect(newSignal.isLittleEndian).toBe(true); - expect(newSignal.startBit).toBe(0); + const newSignal = Object.values(component.state("signals"))[0]; + expect(newSignal).toBeDefined(); + expect(newSignal.size).toBe(8); + expect(newSignal.isLittleEndian).toBe(true); + expect(newSignal.startBit).toBe(0); }); -test('dragging left to right across a byte creates a big endian signal', () => { - const component = createAddSignals(); - const leftBitInByte = component.find('.bit').first(); - const rightBitInByte = component.find('.bit').at(7); - leftBitInByte.simulate('mousedown'); - rightBitInByte.simulate('mouseup'); +test("dragging left to right across a byte creates a big endian signal", () => { + const component = createAddSignals(); + const leftBitInByte = component.find(".bit").first(); + const rightBitInByte = component.find(".bit").at(7); + leftBitInByte.simulate("mousedown"); + rightBitInByte.simulate("mouseup"); - const newSignal = Object.values(component.state('signals'))[0]; - expect(newSignal).toBeDefined(); - expect(newSignal.size).toBe(8); - expect(newSignal.isLittleEndian).toBe(false); - expect(newSignal.startBit).toBe(7); + const newSignal = Object.values(component.state("signals"))[0]; + expect(newSignal).toBeDefined(); + expect(newSignal.size).toBe(8); + expect(newSignal.isLittleEndian).toBe(false); + expect(newSignal.startBit).toBe(7); }); -test('dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes', () => { - const component = createAddSignals(); - const leftBitInByte = component.find('.bit').first(); - const rightBitInByte = component.find('.bit').at(15); - leftBitInByte.simulate('mousedown'); - rightBitInByte.simulate('mouseup'); +test("dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes", () => { + const component = createAddSignals(); + const leftBitInByte = component.find(".bit").first(); + const rightBitInByte = component.find(".bit").at(15); + leftBitInByte.simulate("mousedown"); + rightBitInByte.simulate("mouseup"); - const newSignal = Object.values(component.state('signals'))[0]; - expect(newSignal).toBeDefined(); - expect(newSignal.size).toBe(16); - expect(newSignal.isLittleEndian).toBe(false); - expect(newSignal.startBit).toBe(7); + const newSignal = Object.values(component.state("signals"))[0]; + expect(newSignal).toBeDefined(); + expect(newSignal.size).toBe(16); + expect(newSignal.isLittleEndian).toBe(false); + expect(newSignal.startBit).toBe(7); }); -test('dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes', () => { - const component = createAddSignals(); - const leftBitInByteOne = component.find('.bit').at(8); // left of byte 1 - const rightBitInByteZero = component.find('.bit').at(7); // right of byte 0 +test("dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes", () => { + const component = createAddSignals(); + const leftBitInByteOne = component.find(".bit").at(8); // left of byte 1 + const rightBitInByteZero = component.find(".bit").at(7); // right of byte 0 - rightBitInByteZero.simulate('mousedown'); - leftBitInByteOne.simulate('mouseup'); + rightBitInByteZero.simulate("mousedown"); + leftBitInByteOne.simulate("mouseup"); - const newSignal = Object.values(component.state('signals'))[0]; - expect(newSignal).toBeDefined(); - expect(newSignal.size).toBe(16); - expect(newSignal.isLittleEndian).toBe(true); - expect(newSignal.startBit).toBe(0); + const newSignal = Object.values(component.state("signals"))[0]; + expect(newSignal).toBeDefined(); + expect(newSignal.size).toBe(16); + expect(newSignal.isLittleEndian).toBe(true); + expect(newSignal.startBit).toBe(0); }); -test('dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes', () => { - const component = createAddSignals(); - const leftBitInByteOne = component.find('.bit').at(8); - const rightBitInByteZero = component.find('.bit').at(7); +test("dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes", () => { + const component = createAddSignals(); + const leftBitInByteOne = component.find(".bit").at(8); + const rightBitInByteZero = component.find(".bit").at(7); - leftBitInByteOne.simulate('mousedown'); - rightBitInByteZero.simulate('mouseup'); + leftBitInByteOne.simulate("mousedown"); + rightBitInByteZero.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(16); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(0); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(16); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(0); }); -test('dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes', () => { - const component = createAddSignals(); - const leftBitInByteZero = component.find('.bit').at(0); - const rightBitInByteOne = component.find('.bit').at(15); +test("dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes", () => { + const component = createAddSignals(); + const leftBitInByteZero = component.find(".bit").at(0); + const rightBitInByteOne = component.find(".bit").at(15); - rightBitInByteOne.simulate('mousedown'); - leftBitInByteZero.simulate('mouseup'); + rightBitInByteOne.simulate("mousedown"); + leftBitInByteZero.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(16); - expect(signal.isLittleEndian).toBe(false); - expect(signal.startBit).toBe(7); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(16); + expect(signal.isLittleEndian).toBe(false); + expect(signal.startBit).toBe(7); }); // signal mutation -test('dragging a one-bit big-endian signal to the right should extend it to the right of the byte', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 7, size: 1, isLittleEndian: false}); +test("dragging a one-bit big-endian signal to the right should extend it to the right of the byte", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 7, size: 1, isLittleEndian: false }); - const signalBit = component.find('.bit').at(0); - signalBit.simulate('mousedown'); - for(let i = 1; i < 8; i++) { - component.find('.bit').at(i).simulate('mouseenter'); - } - const bitAtRightOfFirstByte = component.find('.bit').at(7); - bitAtRightOfFirstByte.simulate('mouseup'); + const signalBit = component.find(".bit").at(0); + signalBit.simulate("mousedown"); + for (let i = 1; i < 8; i++) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + const bitAtRightOfFirstByte = component.find(".bit").at(7); + bitAtRightOfFirstByte.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(false); - expect(signal.startBit).toBe(7); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(false); + expect(signal.startBit).toBe(7); }); -test('dragging a one-bit little-endian signal to the right should extend it to the right of the byte', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 7, size: 1, isLittleEndian: true}); +test("dragging a one-bit little-endian signal to the right should extend it to the right of the byte", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 7, size: 1, isLittleEndian: true }); - const signalBit = component.find('.bit').at(0); - signalBit.simulate('mousedown'); - for(let i = 1; i < 8; i++) { - component.find('.bit').at(i).simulate('mouseenter'); - } - const bitAtRightOfFirstByte = component.find('.bit').at(7); - bitAtRightOfFirstByte.simulate('mouseup'); + const signalBit = component.find(".bit").at(0); + signalBit.simulate("mousedown"); + for (let i = 1; i < 8; i++) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + const bitAtRightOfFirstByte = component.find(".bit").at(7); + bitAtRightOfFirstByte.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(0); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(0); }); -test('dragging a one-bit big-endian signal to the left should extend it to the left of the byte', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 0, size: 1, isLittleEndian: false}); +test("dragging a one-bit big-endian signal to the left should extend it to the left of the byte", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 0, size: 1, isLittleEndian: false }); - const signalBit = component.find('.bit').at(7); - signalBit.simulate('mousedown'); - for(let i = 6; i > -1; i--) { - component.find('.bit').at(i).simulate('mouseenter'); - } - const bitAtRightOfFirstByte = component.find('.bit').at(0); - bitAtRightOfFirstByte.simulate('mouseup'); + const signalBit = component.find(".bit").at(7); + signalBit.simulate("mousedown"); + for (let i = 6; i > -1; i--) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + const bitAtRightOfFirstByte = component.find(".bit").at(0); + bitAtRightOfFirstByte.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(false); - expect(signal.startBit).toBe(7); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(false); + expect(signal.startBit).toBe(7); }); -test('extending a two-bit big-endian signal by its LSB should extend it to the right of the byte', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 7, size: 2, isLittleEndian: false}); +test("extending a two-bit big-endian signal by its LSB should extend it to the right of the byte", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 7, size: 2, isLittleEndian: false }); - const lsb = component.find('.bit').at(1); - lsb.simulate('mousedown'); - for(let i = 0; i < 8; i++) { - component.find('.bit').at(i).simulate('mouseenter'); - } - const bitAtRightOfFirstByte = component.find('.bit').at(7); - bitAtRightOfFirstByte.simulate('mouseup'); + const lsb = component.find(".bit").at(1); + lsb.simulate("mousedown"); + for (let i = 0; i < 8; i++) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + const bitAtRightOfFirstByte = component.find(".bit").at(7); + bitAtRightOfFirstByte.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(false); - expect(signal.startBit).toBe(7); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(false); + expect(signal.startBit).toBe(7); }); -test('a two-bit little-endian signal should extend by its LSB to the end of the byte', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 6, size: 2, isLittleEndian: true}); +test("a two-bit little-endian signal should extend by its LSB to the end of the byte", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 6, size: 2, isLittleEndian: true }); - const lsb = component.find('.bit').at(1); - lsb.simulate('mousedown'); - for(let i = 0; i < 8; i++) { - component.find('.bit').at(i).simulate('mouseenter'); - } - const bitAtRightOfFirstByte = component.find('.bit').at(7); - bitAtRightOfFirstByte.simulate('mouseup'); + const lsb = component.find(".bit").at(1); + lsb.simulate("mousedown"); + for (let i = 0; i < 8; i++) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + const bitAtRightOfFirstByte = component.find(".bit").at(7); + bitAtRightOfFirstByte.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(0); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(0); }); -test('dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 0, size: 8, isLittleEndian: true}); +test("dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 0, size: 8, isLittleEndian: true }); - const lsb = component.find('.bit').at(7); - lsb.simulate('mousedown'); + const lsb = component.find(".bit").at(7); + lsb.simulate("mousedown"); - const bitPastMsb = component.find('.bit').at(15); - bitPastMsb.simulate('mouseenter'); - bitPastMsb.simulate('mouseup'); + const bitPastMsb = component.find(".bit").at(15); + bitPastMsb.simulate("mouseenter"); + bitPastMsb.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(0); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(0); }); -test('dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 7, size: 8, isLittleEndian: false}); +test("dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 7, size: 8, isLittleEndian: false }); - const lsb = component.find('.bit').at(7); - lsb.simulate('mousedown'); - for(let i = 6; i > 0; i--) { - component.find('.bit').at(i).simulate('mouseenter'); - } - component.find('.bit').at(1).simulate('mouseup'); + const lsb = component.find(".bit").at(7); + lsb.simulate("mousedown"); + for (let i = 6; i > 0; i--) { + component + .find(".bit") + .at(i) + .simulate("mouseenter"); + } + component + .find(".bit") + .at(1) + .simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(2); - expect(signal.isLittleEndian).toBe(false); - expect(signal.startBit).toBe(7); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(2); + expect(signal.isLittleEndian).toBe(false); + expect(signal.startBit).toBe(7); }); -test('a big endian signal spanning one byte should switch to little endian preserving its bit coverage', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 0, size: 8, isLittleEndian: true}); +test("a big endian signal spanning one byte should switch to little endian preserving its bit coverage", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 0, size: 8, isLittleEndian: true }); - const lsb = component.find('.bit').at(7); - lsb.simulate('mousedown'); + const lsb = component.find(".bit").at(7); + lsb.simulate("mousedown"); - const bitPastMsb = component.find('.bit').at(15); - bitPastMsb.simulate('mouseenter'); - bitPastMsb.simulate('mouseup'); + const bitPastMsb = component.find(".bit").at(15); + bitPastMsb.simulate("mouseenter"); + bitPastMsb.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(8); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(0); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(8); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(0); }); -test('dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal', () => { - const component = createAddSignals(); - component.instance().createSignal({startBit: 14, size: 2, isLittleEndian: true}); +test("dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal", () => { + const component = createAddSignals(); + component + .instance() + .createSignal({ startBit: 14, size: 2, isLittleEndian: true }); - const msb = component.find('.bit').at(8); - msb.simulate('mousedown'); - const bitOutOfBounds = component.find('.bit').at(0); - bitOutOfBounds.simulate('mouseenter'); - bitOutOfBounds.simulate('mouseup'); + const msb = component.find(".bit").at(8); + msb.simulate("mousedown"); + const bitOutOfBounds = component.find(".bit").at(0); + bitOutOfBounds.simulate("mouseenter"); + bitOutOfBounds.simulate("mouseup"); - const signal = Object.values(component.state('signals'))[0]; - expect(signal).toBeDefined(); - expect(signal.size).toBe(2); - expect(signal.isLittleEndian).toBe(true); - expect(signal.startBit).toBe(14); + const signal = Object.values(component.state("signals"))[0]; + expect(signal).toBeDefined(); + expect(signal.size).toBe(2); + expect(signal.isLittleEndian).toBe(true); + expect(signal.startBit).toBe(14); }); diff --git a/src/__tests__/components/CanExplorer.test.js b/src/__tests__/components/CanExplorer.test.js index a6658a0..cf80ea9 100644 --- a/src/__tests__/components/CanExplorer.test.js +++ b/src/__tests__/components/CanExplorer.test.js @@ -1,9 +1,9 @@ -global.__JEST__ = 1 -import CanExplorer from '../../CanExplorer'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; -import {StyleSheetTestUtils} from 'aphrodite'; +global.__JEST__ = 1; +import CanExplorer from "../../CanExplorer"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; +import { StyleSheetTestUtils } from "aphrodite"; -test('CanExplorer renders', () => { - const canExplorer = shallow(); -}); \ No newline at end of file +test("CanExplorer renders", () => { + const canExplorer = shallow(); +}); diff --git a/src/__tests__/components/CanGraph.test.js b/src/__tests__/components/CanGraph.test.js index bb89922..b4308de 100644 --- a/src/__tests__/components/CanGraph.test.js +++ b/src/__tests__/components/CanGraph.test.js @@ -1,29 +1,31 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import CanGraph from '../../components/CanGraph'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import CanGraph from "../../components/CanGraph"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('CanGraph successfully mounts with minimal default props', () => { - const component = shallow( {}} - unplot={() => {}} - messages={{}} - messageId={null} - messageName={null} - signalSpec={null} - onSegmentChanged={() => {}} - segment={[]} - data={[]} - onRelativeTimeClick={() => {}} - currentTime={0} - onDragStart={() => {}} - onDragEnd={() => {}} - container={null} - dragPos={null} - canReceiveGraphDrop={false} - plottedSignals={[]} - live={true} - />); - expect(component.exists()).toBe(true); +test("CanGraph successfully mounts with minimal default props", () => { + const component = shallow( + {}} + unplot={() => {}} + messages={{}} + messageId={null} + messageName={null} + signalSpec={null} + onSegmentChanged={() => {}} + segment={[]} + data={[]} + onRelativeTimeClick={() => {}} + currentTime={0} + onDragStart={() => {}} + onDragEnd={() => {}} + container={null} + dragPos={null} + canReceiveGraphDrop={false} + plottedSignals={[]} + live={true} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/CanGraphList.test.js b/src/__tests__/components/CanGraphList.test.js index 9190701..76a3b03 100644 --- a/src/__tests__/components/CanGraphList.test.js +++ b/src/__tests__/components/CanGraphList.test.js @@ -1,20 +1,23 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import CanGraphList from '../../components/CanGraphList'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import CanGraphList from "../../components/CanGraphList"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('CanGraphList successfully mounts with minimal default props', () => { - const component = shallow( {}} - seekTime={0} - onSegmentChanged={() => {}} - onSignalUnplotPressed={() => {}} - segment={[]} - mergePlots={() => {}} - live={true} />); - expect(component.exists()).toBe(true); +test("CanGraphList successfully mounts with minimal default props", () => { + const component = shallow( + {}} + seekTime={0} + onSegmentChanged={() => {}} + onSignalUnplotPressed={() => {}} + segment={[]} + mergePlots={() => {}} + live={true} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/CanLog.test.js b/src/__tests__/components/CanLog.test.js index ad1b8c1..b976336 100644 --- a/src/__tests__/components/CanLog.test.js +++ b/src/__tests__/components/CanLog.test.js @@ -1,18 +1,21 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import CanLog from '../../components/CanLog'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import CanLog from "../../components/CanLog"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('CanLog successfully mounts with minimal default props', () => { - const component = shallow( {}} - onSignalUnplotPressed={() => {}} - showAddSignal={() => {}} - onMessageExpanded={() => {}} />); - expect(component.exists()).toBe(true); +test("CanLog successfully mounts with minimal default props", () => { + const component = shallow( + {}} + onSignalUnplotPressed={() => {}} + showAddSignal={() => {}} + onMessageExpanded={() => {}} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/DbcUpload.test.js b/src/__tests__/components/DbcUpload.test.js index 828ed26..b78b05d 100644 --- a/src/__tests__/components/DbcUpload.test.js +++ b/src/__tests__/components/DbcUpload.test.js @@ -1,10 +1,10 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import DbcUpload from '../../components/DbcUpload'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import DbcUpload from "../../components/DbcUpload"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('DbcUpload successfully mounts with minimal default props', () => { - const component = shallow(); - expect(component.exists()).toBe(true); +test("DbcUpload successfully mounts with minimal default props", () => { + const component = shallow(); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/EditMessageModal.test.js b/src/__tests__/components/EditMessageModal.test.js index 183aa2c..71a2789 100644 --- a/src/__tests__/components/EditMessageModal.test.js +++ b/src/__tests__/components/EditMessageModal.test.js @@ -1,20 +1,22 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import EditMessageModal from '../../components/EditMessageModal'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; -import DbcUtils from '../../utils/dbc'; -import DBC from '../../models/can/dbc'; +import EditMessageModal from "../../components/EditMessageModal"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; +import DbcUtils from "../../utils/dbc"; +import DBC from "../../models/can/dbc"; -test('EditMessageModal successfully mounts with minimal default props', () => { - const dbc = new DBC(); - const frame = dbc.createFrame(0); - const message = DbcUtils.createMessageSpec(dbc, 0, '0', 1); +test("EditMessageModal successfully mounts with minimal default props", () => { + const dbc = new DBC(); + const frame = dbc.createFrame(0); + const message = DbcUtils.createMessageSpec(dbc, 0, "0", 1); - const component = shallow( {}} - handleSave={() => {}} - message={message} - />); - expect(component.exists()).toBe(true); + const component = shallow( + {}} + handleSave={() => {}} + message={message} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/Explorer.test.js b/src/__tests__/components/Explorer.test.js index a267a1d..032e70f 100644 --- a/src/__tests__/components/Explorer.test.js +++ b/src/__tests__/components/Explorer.test.js @@ -1,30 +1,32 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import Explorer from '../../components/Explorer'; -import React from 'react'; -import Moment from 'moment'; -import { shallow, mount, render } from 'enzyme'; +import Explorer from "../../components/Explorer"; +import React from "react"; +import Moment from "moment"; +import { shallow, mount, render } from "enzyme"; -test('Explorer successfully mounts with minimal default props', () => { - const component = shallow( {}} - onSeek={() => {}} - onUserSeek={() => {}} - canFrameOffset={0} - firstCanTime={0} - seekTime={0} - seekIndex={0} - currentParts={[0,0]} - partsLoaded={0} - autoplay={true} - showEditMessageModal={() => {}} - onPartChange={() => {}} - routeStartTime={Moment()} - partsCount={0} - />); - expect(component.exists()).toBe(true); +test("Explorer successfully mounts with minimal default props", () => { + const component = shallow( + {}} + onSeek={() => {}} + onUserSeek={() => {}} + canFrameOffset={0} + firstCanTime={0} + seekTime={0} + seekIndex={0} + currentParts={[0, 0]} + partsLoaded={0} + autoplay={true} + showEditMessageModal={() => {}} + onPartChange={() => {}} + routeStartTime={Moment()} + partsCount={0} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/GithubDbcList.test.js b/src/__tests__/components/GithubDbcList.test.js index 91edffe..88d1320 100644 --- a/src/__tests__/components/GithubDbcList.test.js +++ b/src/__tests__/components/GithubDbcList.test.js @@ -1,17 +1,20 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import GithubDbcList from '../../components/GithubDbcList'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import GithubDbcList from "../../components/GithubDbcList"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -import OpenDbc from '../../api/OpenDbc'; +import OpenDbc from "../../api/OpenDbc"; -test('GithubDbcList successfully mounts with minimal default props', () => { - const openDbcClient = new OpenDbc(null); +test("GithubDbcList successfully mounts with minimal default props", () => { + const openDbcClient = new OpenDbc(null); - const component = shallow( {} } - repo="commaai/opendbc" - openDbcClient={ openDbcClient } />); - expect(component.exists()).toBe(true); + const component = shallow( + {}} + repo="commaai/opendbc" + openDbcClient={openDbcClient} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/HLS.test.js b/src/__tests__/components/HLS.test.js index 83126dd..f548f82 100644 --- a/src/__tests__/components/HLS.test.js +++ b/src/__tests__/components/HLS.test.js @@ -1,23 +1,26 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import HLS from '../../components/HLS'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import HLS from "../../components/HLS"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('HLS successfully mounts with minimal default props', () => { - const component = shallow( {}} - playing={false} - onClick={() => {}} - onLoadStart={() => {}} - onLoadEnd={() => {}} - onUserSeek={() => {}} - onPlaySeek={() => {}} - segmentProgress={() => {}} - shouldRestart={false} - onRestart={() => {}} />); - expect(component.exists()).toBe(true); +test("HLS successfully mounts with minimal default props", () => { + const component = shallow( + {}} + playing={false} + onClick={() => {}} + onLoadStart={() => {}} + onLoadEnd={() => {}} + onUserSeek={() => {}} + onPlaySeek={() => {}} + segmentProgress={() => {}} + shouldRestart={false} + onRestart={() => {}} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/LoadDbcModal.test.js b/src/__tests__/components/LoadDbcModal.test.js index d1db5c4..133f72e 100644 --- a/src/__tests__/components/LoadDbcModal.test.js +++ b/src/__tests__/components/LoadDbcModal.test.js @@ -1,18 +1,20 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -import LoadDbcModal from '../../components/LoadDbcModal'; -import OpenDbc from '../../api/OpenDbc'; +import LoadDbcModal from "../../components/LoadDbcModal"; +import OpenDbc from "../../api/OpenDbc"; -test('LoadDbcModal successfully mounts with minimal default props', () => { - const openDbcClient = new OpenDbc(null); - const component = shallow( {}} - handleClose={() => {}} - openDbcClient={openDbcClient} - loginWithGithub={

Login with github

} - />); - expect(component.exists()).toBe(true); +test("LoadDbcModal successfully mounts with minimal default props", () => { + const openDbcClient = new OpenDbc(null); + const component = shallow( + {}} + handleClose={() => {}} + openDbcClient={openDbcClient} + loginWithGithub={

Login with github

} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/LoadingBar.test.js b/src/__tests__/components/LoadingBar.test.js index bd1e878..4a58de2 100644 --- a/src/__tests__/components/LoadingBar.test.js +++ b/src/__tests__/components/LoadingBar.test.js @@ -1,10 +1,10 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import LoadingBar from '../../components/LoadingBar'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import LoadingBar from "../../components/LoadingBar"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('LoadingBar successfully mounts with minimal default props', () => { - const component = shallow(); - expect(component.exists()).toBe(true); +test("LoadingBar successfully mounts with minimal default props", () => { + const component = shallow(); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/MessageBytes.test.js b/src/__tests__/components/MessageBytes.test.js index 82e91a4..be86161 100644 --- a/src/__tests__/components/MessageBytes.test.js +++ b/src/__tests__/components/MessageBytes.test.js @@ -1,17 +1,16 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -import MessageBytes from '../../components/MessageBytes'; -import DbcUtils from '../../utils/dbc'; -import DBC from '../../models/can/dbc'; +import MessageBytes from "../../components/MessageBytes"; +import DbcUtils from "../../utils/dbc"; +import DBC from "../../models/can/dbc"; -test('MessageBytes successfully mounts with minimal default props', () => { - const message = DbcUtils.createMessageSpec(new DBC(), 0, '0', 1); - const component = shallow(); - expect(component.exists()).toBe(true); +test("MessageBytes successfully mounts with minimal default props", () => { + const message = DbcUtils.createMessageSpec(new DBC(), 0, "0", 1); + const component = shallow( + + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/Meta.test.js b/src/__tests__/components/Meta.test.js index 8b199bd..3b099d4 100644 --- a/src/__tests__/components/Meta.test.js +++ b/src/__tests__/components/Meta.test.js @@ -1,30 +1,33 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import Meta from '../../components/Meta'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import Meta from "../../components/Meta"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('Meta successfully mounts with minimal default props', () => { - const component = shallow( {}} - showEditMessageModal={() => {}} - currentParts={[]} - onMessageSelected={() => {}} - onMessageUnselected={() => {}} - showLoadDbc={() => {}} - showSaveDbc={() => {}} - dbcFilename={null} - dbcLastSaved={null} - dongleId={null} - name={null} - route={null} - seekTime={0} - seekIndex={0} - maxByteStateChangeCount={0} - isDemo={false} - live={true} - />); - expect(component.exists()).toBe(true); +test("Meta successfully mounts with minimal default props", () => { + const component = shallow( + {}} + showEditMessageModal={() => {}} + currentParts={[]} + onMessageSelected={() => {}} + onMessageUnselected={() => {}} + showLoadDbc={() => {}} + showSaveDbc={() => {}} + dbcFilename={null} + dbcLastSaved={null} + dongleId={null} + name={null} + route={null} + seekTime={0} + seekIndex={0} + maxByteStateChangeCount={0} + isDemo={false} + live={true} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/Modal.test.js b/src/__tests__/components/Modal.test.js index d391b72..ddb702e 100644 --- a/src/__tests__/components/Modal.test.js +++ b/src/__tests__/components/Modal.test.js @@ -1,10 +1,10 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import Modal from '../../components/Modal'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import Modal from "../../components/Modal"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('Modal successfully mounts with minimal default props', () => { - const component = shallow(); - expect(component.exists()).toBe(true); +test("Modal successfully mounts with minimal default props", () => { + const component = shallow(); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/PartSelector.test.js b/src/__tests__/components/PartSelector.test.js index 7314dcc..bc1776e 100644 --- a/src/__tests__/components/PartSelector.test.js +++ b/src/__tests__/components/PartSelector.test.js @@ -1,12 +1,12 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import PartSelector from '../../components/PartSelector'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import PartSelector from "../../components/PartSelector"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('PartSelector successfully mounts with minimal default props', () => { - const component = shallow( {} } - partsCount={ 0 } />); - expect(component.exists()).toBe(true); +test("PartSelector successfully mounts with minimal default props", () => { + const component = shallow( + {}} partsCount={0} /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/PlayButton.test.js b/src/__tests__/components/PlayButton.test.js index 8d98d29..d154953 100644 --- a/src/__tests__/components/PlayButton.test.js +++ b/src/__tests__/components/PlayButton.test.js @@ -1,10 +1,10 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import PlayButton from '../../components/PlayButton'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import PlayButton from "../../components/PlayButton"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('PlayButton successfully mounts with minimal default props', () => { - const component = shallow(); - expect(component.exists()).toBe(true); +test("PlayButton successfully mounts with minimal default props", () => { + const component = shallow(); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/RouteSeeker.test.js b/src/__tests__/components/RouteSeeker.test.js index 2d4d7bf..a10a1d9 100644 --- a/src/__tests__/components/RouteSeeker.test.js +++ b/src/__tests__/components/RouteSeeker.test.js @@ -1,21 +1,24 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import RouteSeeker from '../../components/RouteSeeker'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import RouteSeeker from "../../components/RouteSeeker"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('RouteSeeker successfully mounts with minimal default props', () => { - const component = shallow( {}} - secondsLoaded={0} - segmentIndices={[]} - onUserSeek={() => {}} - onPlaySeek={() => {}} - videoElement={null} - onPlay={() => {}} - onPause={() => {}} - playing={false} - ratioTime={() => {}} />); - expect(component.exists()).toBe(true); +test("RouteSeeker successfully mounts with minimal default props", () => { + const component = shallow( + {}} + secondsLoaded={0} + segmentIndices={[]} + onUserSeek={() => {}} + onPlaySeek={() => {}} + videoElement={null} + onPlay={() => {}} + onPause={() => {}} + playing={false} + ratioTime={() => {}} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/RouteVideoSync.test.js b/src/__tests__/components/RouteVideoSync.test.js index dda367f..11c240a 100644 --- a/src/__tests__/components/RouteVideoSync.test.js +++ b/src/__tests__/components/RouteVideoSync.test.js @@ -1,9 +1,9 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import RouteVideoSync from '../../components/RouteVideoSync'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; -import {StyleSheetTestUtils} from 'aphrodite'; +import RouteVideoSync from "../../components/RouteVideoSync"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; +import { StyleSheetTestUtils } from "aphrodite"; // Prevents style injection from firing after test finishes // and jsdom is torn down. @@ -14,22 +14,25 @@ afterEach(() => { StyleSheetTestUtils.clearBufferAndResumeStyleInjection(); }); -test('RouteVideoSync successfully mounts with minimal default props', () => { - const component = shallow( {}} - onPlaySeek={() => {}} - onUserSeek={() => {}} - onPlay={() => {}} - onPause={() => {}} - userSeekTime={0} />); - expect(component.exists()).toBe(true); +test("RouteVideoSync successfully mounts with minimal default props", () => { + const component = shallow( + {}} + onPlaySeek={() => {}} + onUserSeek={() => {}} + onPlay={() => {}} + onPause={() => {}} + userSeekTime={0} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/SaveDbcModal.test.js b/src/__tests__/components/SaveDbcModal.test.js index 93380d2..e7fd737 100644 --- a/src/__tests__/components/SaveDbcModal.test.js +++ b/src/__tests__/components/SaveDbcModal.test.js @@ -1,23 +1,25 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -import SaveDbcModal from '../../components/SaveDbcModal'; -import OpenDbc from '../../api/OpenDbc'; -import DBC from '../../models/can/dbc'; +import SaveDbcModal from "../../components/SaveDbcModal"; +import OpenDbc from "../../api/OpenDbc"; +import DBC from "../../models/can/dbc"; -test('SaveDbcModal successfully mounts with minimal default props', () => { - const openDbcClient = new OpenDbc(null); - const dbc = new DBC(); - const component = shallow( {}} - handleClose={() => {}} - openDbcClient={openDbcClient} - hasGithubAuth={false} - loginWithGithub={

Login with github

} - />); - expect(component.exists()).toBe(true); +test("SaveDbcModal successfully mounts with minimal default props", () => { + const openDbcClient = new OpenDbc(null); + const dbc = new DBC(); + const component = shallow( + {}} + handleClose={() => {}} + openDbcClient={openDbcClient} + hasGithubAuth={false} + loginWithGithub={

Login with github

} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/SignalLegend.test.js b/src/__tests__/components/SignalLegend.test.js index 7390a63..edbb196 100644 --- a/src/__tests__/components/SignalLegend.test.js +++ b/src/__tests__/components/SignalLegend.test.js @@ -1,21 +1,23 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import SignalLegend from '../../components/SignalLegend'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; +import SignalLegend from "../../components/SignalLegend"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; -test('SignalLegend successfully mounts with minimal default props', () => { - const component = shallow( {}} - onSignalHoverEnd={() => {}} - onTentativeSignalChange={() => {}} - onSignalChange={() => {}} - onSignalRemove={() => {}} - onSignalPlotChange={() => {}} - plottedSignals={[]} - />); - expect(component.exists()).toBe(true); +test("SignalLegend successfully mounts with minimal default props", () => { + const component = shallow( + {}} + onSignalHoverEnd={() => {}} + onTentativeSignalChange={() => {}} + onSignalChange={() => {}} + onSignalRemove={() => {}} + onSignalPlotChange={() => {}} + plottedSignals={[]} + /> + ); + expect(component.exists()).toBe(true); }); diff --git a/src/__tests__/components/SignalLegendEntry.test.js b/src/__tests__/components/SignalLegendEntry.test.js index bd7bc74..8cca970 100644 --- a/src/__tests__/components/SignalLegendEntry.test.js +++ b/src/__tests__/components/SignalLegendEntry.test.js @@ -1,8 +1,8 @@ -import SignalLegendEntry from '../../components/SignalLegendEntry'; -import Signal from '../../models/can/signal'; -import React from 'react'; -import { shallow, mount, render } from 'enzyme'; -import {StyleSheetTestUtils} from 'aphrodite'; +import SignalLegendEntry from "../../components/SignalLegendEntry"; +import Signal from "../../models/can/signal"; +import React from "react"; +import { shallow, mount, render } from "enzyme"; +import { StyleSheetTestUtils } from "aphrodite"; // Prevents style injection from firing after test finishes // and jsdom is torn down. @@ -14,100 +14,122 @@ afterEach(() => { }); function createSignalLegendEntry(props) { - let signal = props.signal, - onSignalChange = props.onSignalChange, - onTentativeSignalChange = props.onTentativeSignalChange; - if(signal === undefined) { - signal = new Signal({name: 'NEW_SIGNAL'}); - } - if(onSignalChange === undefined) { - onSignalChange = () => {}; - } - if(onTentativeSignalChange === undefined) { - onTentativeSignalChange = () => {}; - } + let signal = props.signal, + onSignalChange = props.onSignalChange, + onTentativeSignalChange = props.onTentativeSignalChange; + if (signal === undefined) { + signal = new Signal({ name: "NEW_SIGNAL" }); + } + if (onSignalChange === undefined) { + onSignalChange = () => {}; + } + if (onTentativeSignalChange === undefined) { + onTentativeSignalChange = () => {}; + } - return shallow(); + return shallow( + + ); } -test('a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => { - const signal = new Signal({name: 'signal', - startBit: 0, - size: 8, - isLittleEndian: true}); +test("a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => { + const signal = new Signal({ + name: "signal", + startBit: 0, + size: 8, + isLittleEndian: true + }); - const component = createSignalLegendEntry({signal}); - const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName('isLittleEndian'); - component.instance().updateField(endiannessFieldSpec, false); + const component = createSignalLegendEntry({ signal }); + const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName( + "isLittleEndian" + ); + component.instance().updateField(endiannessFieldSpec, false); - const signalEdited = component.state('signalEdited'); - expect(signalEdited.isLittleEndian).toBe(false); - expect(signalEdited.startBit).toBe(7); - expect(signalEdited.size).toBe(8); + const signalEdited = component.state("signalEdited"); + expect(signalEdited.isLittleEndian).toBe(false); + expect(signalEdited.startBit).toBe(7); + expect(signalEdited.size).toBe(8); }); -test('a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage', () => { - const signal = new Signal({name: 'signal', - startBit: 7, - size: 8, - isLittleEndian: false}); - const component = createSignalLegendEntry({signal}); - const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName('isLittleEndian'); - component.instance().updateField(endiannessFieldSpec, true); +test("a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage", () => { + const signal = new Signal({ + name: "signal", + startBit: 7, + size: 8, + isLittleEndian: false + }); + const component = createSignalLegendEntry({ signal }); + const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName( + "isLittleEndian" + ); + component.instance().updateField(endiannessFieldSpec, true); - const signalEdited = component.state('signalEdited'); - expect(signalEdited.isLittleEndian).toBe(true); - expect(signalEdited.startBit).toBe(0); - expect(signalEdited.size).toBe(8); + const signalEdited = component.state("signalEdited"); + expect(signalEdited.isLittleEndian).toBe(true); + expect(signalEdited.startBit).toBe(0); + expect(signalEdited.size).toBe(8); }); test("a big endian signal spanning one and a half bytes should adjust its startBit switching to little endian, preserving the first byte's coverage", () => { - const signal = new Signal({name: 'signal', - startBit: 7, - size: 12, - isLittleEndian: false}); + const signal = new Signal({ + name: "signal", + startBit: 7, + size: 12, + isLittleEndian: false + }); - const component = createSignalLegendEntry({signal}); - const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName('isLittleEndian'); - component.instance().updateField(endiannessFieldSpec, true); + const component = createSignalLegendEntry({ signal }); + const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName( + "isLittleEndian" + ); + component.instance().updateField(endiannessFieldSpec, true); - const signalEdited = component.state('signalEdited'); - expect(signalEdited.isLittleEndian).toBe(true); - expect(signalEdited.startBit).toBe(0); - expect(signalEdited.size).toBe(12); + const signalEdited = component.state("signalEdited"); + expect(signalEdited.isLittleEndian).toBe(true); + expect(signalEdited.startBit).toBe(0); + expect(signalEdited.size).toBe(12); }); -test('a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => { - const signal = new Signal({name: 'signal', - startBit: 13, - size: 3, - isLittleEndian: true}); - const component = createSignalLegendEntry({signal}); - const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName('isLittleEndian'); - component.instance().updateField(endiannessFieldSpec, false); +test("a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => { + const signal = new Signal({ + name: "signal", + startBit: 13, + size: 3, + isLittleEndian: true + }); + const component = createSignalLegendEntry({ signal }); + const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName( + "isLittleEndian" + ); + component.instance().updateField(endiannessFieldSpec, false); - const signalEdited = component.state('signalEdited'); - expect(signalEdited.isLittleEndian).toBe(false); - expect(signalEdited.startBit).toBe(15); - expect(signalEdited.size).toBe(3); + const signalEdited = component.state("signalEdited"); + expect(signalEdited.isLittleEndian).toBe(false); + expect(signalEdited.startBit).toBe(15); + expect(signalEdited.size).toBe(3); }); -test('a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage', () => { - const signal = new Signal({name: 'signal', - startBit: 15, - size: 3, - isLittleEndian: false}); - const component = createSignalLegendEntry({signal}); - const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName('isLittleEndian'); - component.instance().updateField(endiannessFieldSpec, true); +test("a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage", () => { + const signal = new Signal({ + name: "signal", + startBit: 15, + size: 3, + isLittleEndian: false + }); + const component = createSignalLegendEntry({ signal }); + const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName( + "isLittleEndian" + ); + component.instance().updateField(endiannessFieldSpec, true); - const signalEdited = component.state('signalEdited'); - expect(signalEdited.isLittleEndian).toBe(true); - expect(signalEdited.startBit).toBe(13); - expect(signalEdited.size).toBe(3); -}); \ No newline at end of file + const signalEdited = component.state("signalEdited"); + expect(signalEdited.isLittleEndian).toBe(true); + expect(signalEdited.startBit).toBe(13); + expect(signalEdited.size).toBe(3); +}); diff --git a/src/__tests__/models/graph-data.test.js b/src/__tests__/models/graph-data.test.js index 602bdd4..3dbf5e2 100644 --- a/src/__tests__/models/graph-data.test.js +++ b/src/__tests__/models/graph-data.test.js @@ -1,38 +1,45 @@ // appendNewGraphData(plottedSignals, graphData, messages) { global.__JEST__ = 1; -import GraphData from '../../models/graph-data'; -import Signal from '../../models/can/signal'; -import DBC from '../../models/can/dbc'; -import DbcUtils from '../../utils/dbc'; +import GraphData from "../../models/graph-data"; +import Signal from "../../models/can/signal"; +import DBC from "../../models/can/dbc"; +import DbcUtils from "../../utils/dbc"; function appendMockGraphData(existingGraphData, entryCount = 1) { - const dbc = new DBC(); - const signal = new Signal({name: 'NEW_SIGNAL_1'}); - dbc.setSignals(0, {[signal.name]: signal}); - const message = DbcUtils.createMessageSpec(dbc, 0, '0', 0); - // time, relTime, data, byteStateChangeTimes) { - message.entries = Array(entryCount).fill(DbcUtils.createMessageEntry(dbc, 0, 0, 0, Buffer.alloc(8), [])); - const messages = {[message.id]: message}; + const dbc = new DBC(); + const signal = new Signal({ name: "NEW_SIGNAL_1" }); + dbc.setSignals(0, { [signal.name]: signal }); + const message = DbcUtils.createMessageSpec(dbc, 0, "0", 0); + // time, relTime, data, byteStateChangeTimes) { + message.entries = Array(entryCount).fill( + DbcUtils.createMessageEntry(dbc, 0, 0, 0, Buffer.alloc(8), []) + ); + const messages = { [message.id]: message }; - const plottedSignals = [[{signalUid: signal.uid, messageId: '0'}]]; + const plottedSignals = [[{ signalUid: signal.uid, messageId: "0" }]]; - return GraphData.appendNewGraphData(plottedSignals, existingGraphData, messages, 0); + return GraphData.appendNewGraphData( + plottedSignals, + existingGraphData, + messages, + 0 + ); } -test('GraphData.appendNewGraphData adds messages to empty GraphData array', () => { - const graphData = appendMockGraphData([[]]); - expect(graphData.length).toEqual(1); // 1 plot - expect(graphData[0].length).toEqual(1); // 1 message entry - expect(graphData[0][0].x).toEqual(0); // message entry X value corresponds to provided time in createMessageEntry +test("GraphData.appendNewGraphData adds messages to empty GraphData array", () => { + const graphData = appendMockGraphData([[]]); + expect(graphData.length).toEqual(1); // 1 plot + expect(graphData[0].length).toEqual(1); // 1 message entry + expect(graphData[0][0].x).toEqual(0); // message entry X value corresponds to provided time in createMessageEntry }); -test('GraphData.appendNewGraphData does not change graph data when entries are unchanged', () => { - let graphData = [[]]; - for(let i = 0; i < 100; i++) { - graphData = appendMockGraphData(graphData); - } +test("GraphData.appendNewGraphData does not change graph data when entries are unchanged", () => { + let graphData = [[]]; + for (let i = 0; i < 100; i++) { + graphData = appendMockGraphData(graphData); + } - expect(graphData.length).toEqual(1); - expect(graphData[0].length).toEqual(1); -}); \ No newline at end of file + expect(graphData.length).toEqual(1); + expect(graphData[0].length).toEqual(1); +}); diff --git a/src/__tests__/panda/panda.test.js b/src/__tests__/panda/panda.test.js index be5d719..1641a01 100644 --- a/src/__tests__/panda/panda.test.js +++ b/src/__tests__/panda/panda.test.js @@ -1,23 +1,22 @@ -import Panda from '../../api/panda'; +import Panda from "../../api/panda"; function arrayBufferFromHex(hex) { - const buffer = Buffer.from(hex, 'hex'); - const arrayBuffer = new ArrayBuffer(buffer.length); - const view = new Uint8Array(arrayBuffer); - for(let i = 0; i < buffer.length; i++) { - view[i] = buffer[i]; - } - return arrayBuffer; + const buffer = Buffer.from(hex, "hex"); + const arrayBuffer = new ArrayBuffer(buffer.length); + const view = new Uint8Array(arrayBuffer); + for (let i = 0; i < buffer.length; i++) { + view[i] = buffer[i]; + } + return arrayBuffer; } -test('parseCanBuffer correctly parses a message', () => { - const panda = new Panda(); - // 16 byte buffer +test("parseCanBuffer correctly parses a message", () => { + const panda = new Panda(); + // 16 byte buffer - const arrayBuffer = arrayBufferFromHex('abababababababababababababababab'); + const arrayBuffer = arrayBufferFromHex("abababababababababababababababab"); - const messages = panda.parseCanBuffer(arrayBuffer); - expect(messages.length).toEqual(1) - expect(messages[0]).toEqual([1373, 43947, 'abababababababab', 10]); + const messages = panda.parseCanBuffer(arrayBuffer); + expect(messages.length).toEqual(1); + expect(messages[0]).toEqual([1373, 43947, "abababababababab", 10]); }); - diff --git a/src/__tests__/res/acura-dbc.js b/src/__tests__/res/acura-dbc.js index 5dca304..781e161 100644 --- a/src/__tests__/res/acura-dbc.js +++ b/src/__tests__/res/acura-dbc.js @@ -1,4 +1,4 @@ -export const ACURA_DBC= `VERSION "" +export const ACURA_DBC = `VERSION "" NS_ : @@ -318,4 +318,4 @@ VAL_ 506 CHIME 4 "double_chime" 3 "single_chime" 2 "continuous_chime" 1 "repeati VAL_ 506 FCW 3 "fcw" 2 "fcw" 1 "fcw" 0 "no_fcw" ; VAL_ 780 HUD_LEAD 3 "no_car" 2 "solid_car" 1 "dashed_car" 0 "no_car" ; VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ; -`; \ No newline at end of file +`; diff --git a/src/__tests__/res/tesla-dbc.js b/src/__tests__/res/tesla-dbc.js index 2380971..8ea1985 100644 --- a/src/__tests__/res/tesla-dbc.js +++ b/src/__tests__/res/tesla-dbc.js @@ -404,4 +404,4 @@ VAL_ 904 MCU_clusterReadyForDrive 0 "NO_SNA" 1 "YES" ; VAL_ 1160 DAS_steeringAngleRequest 16384 "ZERO_ANGLE" ; VAL_ 1160 DAS_steeringControlType 1 "ANGLE_CONTROL" 3 "DISABLED" 0 "NONE" 2 "RESERVED" ; VAL_ 1160 DAS_steeringHapticRequest 1 "ACTIVE" 0 "IDLE" ; -`; \ No newline at end of file +`; diff --git a/src/__tests__/utils/color.test.js b/src/__tests__/utils/color.test.js index a34f20e..c1a6f5c 100644 --- a/src/__tests__/utils/color.test.js +++ b/src/__tests__/utils/color.test.js @@ -1,8 +1,8 @@ -import {shade} from '../../utils/color'; +import { shade } from "../../utils/color"; -test('Shade darkens rgb white (255,255,255)', () => { - const rgb = [255,255,255]; - const darkenRgb = shade(rgb, -0.5); +test("Shade darkens rgb white (255,255,255)", () => { + const rgb = [255, 255, 255]; + const darkenRgb = shade(rgb, -0.5); - expect(darkenRgb).toEqual([128,128,128]); -}); \ No newline at end of file + expect(darkenRgb).toEqual([128, 128, 128]); +}); diff --git a/src/__tests__/utils/dbc.test.js b/src/__tests__/utils/dbc.test.js index 566c382..4580a43 100644 --- a/src/__tests__/utils/dbc.test.js +++ b/src/__tests__/utils/dbc.test.js @@ -1,63 +1,70 @@ -global.__JEST__ = 1 +global.__JEST__ = 1; -import DbcUtils from '../../utils/dbc'; -import DBC from '../../models/can/dbc'; -import Signal from '../../models/can/signal'; +import DbcUtils from "../../utils/dbc"; +import DBC from "../../models/can/dbc"; +import Signal from "../../models/can/signal"; // want to mock pandareader and test processStreamedCanMessages -const SAMPLE_MESSAGE = [0x10, 0, Buffer.from('abababababababab', 'hex'), 1]; -const SAMPLE_MESSAGE_ID = '1:10'; +const SAMPLE_MESSAGE = [0x10, 0, Buffer.from("abababababababab", "hex"), 1]; +const SAMPLE_MESSAGE_ID = "1:10"; function expectSampleMessageFieldsPreserved(messages, frame) { - const [address, busTime, data, source] = SAMPLE_MESSAGE; - expect(messages[SAMPLE_MESSAGE_ID].address).toEqual(address); - expect(messages[SAMPLE_MESSAGE_ID].id).toEqual(SAMPLE_MESSAGE_ID); - expect(messages[SAMPLE_MESSAGE_ID].bus).toEqual(source); - expect(messages[SAMPLE_MESSAGE_ID].frame).toEqual(frame); - expect(messages[SAMPLE_MESSAGE_ID].byteStateChangeCounts).toEqual(Array(8).fill(0)); + const [address, busTime, data, source] = SAMPLE_MESSAGE; + expect(messages[SAMPLE_MESSAGE_ID].address).toEqual(address); + expect(messages[SAMPLE_MESSAGE_ID].id).toEqual(SAMPLE_MESSAGE_ID); + expect(messages[SAMPLE_MESSAGE_ID].bus).toEqual(source); + expect(messages[SAMPLE_MESSAGE_ID].frame).toEqual(frame); + expect(messages[SAMPLE_MESSAGE_ID].byteStateChangeCounts).toEqual( + Array(8).fill(0) + ); } // function addCanMessage([address, busTime, data, source], dbc, canStartTime, messages, prevMsgEntries, byteStateChangeCountsByMessage) { function addMessages(messages, message, dbc, n) { - const firstCanTime = 0; - message = [...message]; - let nextMessage = () => {message[1] = message[1] + 1; return message}; + const firstCanTime = 0; + message = [...message]; + let nextMessage = () => { + message[1] = message[1] + 1; + return message; + }; - for(let i = 0; i < n; i++) { - DbcUtils.addCanMessage(nextMessage(), dbc, firstCanTime, messages, {}, {}); - } + for (let i = 0; i < n; i++) { + DbcUtils.addCanMessage(nextMessage(), dbc, firstCanTime, messages, {}, {}); + } } -test('addCanMessage should add raw can message with empty dbc', () => { - const messages = {}; - addMessages(messages, SAMPLE_MESSAGE, new DBC(), 1); +test("addCanMessage should add raw can message with empty dbc", () => { + const messages = {}; + addMessages(messages, SAMPLE_MESSAGE, new DBC(), 1); - expect(messages[SAMPLE_MESSAGE_ID].entries.length).toEqual(1); - expectSampleMessageFieldsPreserved(messages); + expect(messages[SAMPLE_MESSAGE_ID].entries.length).toEqual(1); + expectSampleMessageFieldsPreserved(messages); }); -test('addCanMessage should add multiple raw can messages with empty dbc', () => { - const messages = {}; - addMessages(messages, SAMPLE_MESSAGE, new DBC(), 3); +test("addCanMessage should add multiple raw can messages with empty dbc", () => { + const messages = {}; + addMessages(messages, SAMPLE_MESSAGE, new DBC(), 3); - expect(messages[SAMPLE_MESSAGE_ID].entries.length).toEqual(3); - expectSampleMessageFieldsPreserved(messages); + expect(messages[SAMPLE_MESSAGE_ID].entries.length).toEqual(3); + expectSampleMessageFieldsPreserved(messages); }); -test('addCanMessage should add parsed can message with dbc containing message spec', () => { - const messages = {}; - // create dbc with message spec and signal for sample_message - const dbc = new DBC(); - dbc.createFrame(SAMPLE_MESSAGE[0]); - const signal = new Signal({name: 'NEW_SIGNAL', startBit: 0, size: 8}); - dbc.addSignal(SAMPLE_MESSAGE[0], signal); +test("addCanMessage should add parsed can message with dbc containing message spec", () => { + const messages = {}; + // create dbc with message spec and signal for sample_message + const dbc = new DBC(); + dbc.createFrame(SAMPLE_MESSAGE[0]); + const signal = new Signal({ name: "NEW_SIGNAL", startBit: 0, size: 8 }); + dbc.addSignal(SAMPLE_MESSAGE[0], signal); - // add 1 sample_message - addMessages(messages, SAMPLE_MESSAGE, dbc, 1); + // add 1 sample_message + addMessages(messages, SAMPLE_MESSAGE, dbc, 1); - // verify message and parsed signal added - const sampleMessages = messages[SAMPLE_MESSAGE_ID]; - expect(sampleMessages.entries.length).toEqual(1); - expect(sampleMessages.entries[0].signals[signal.name]).toEqual(0xab); - expectSampleMessageFieldsPreserved(messages, dbc.messages.get(SAMPLE_MESSAGE[0])); + // verify message and parsed signal added + const sampleMessages = messages[SAMPLE_MESSAGE_ID]; + expect(sampleMessages.entries.length).toEqual(1); + expect(sampleMessages.entries[0].signals[signal.name]).toEqual(0xab); + expectSampleMessageFieldsPreserved( + messages, + dbc.messages.get(SAMPLE_MESSAGE[0]) + ); }); - diff --git a/src/acura-dbc.js b/src/acura-dbc.js index 648025c..e028644 100644 --- a/src/acura-dbc.js +++ b/src/acura-dbc.js @@ -1,4 +1,4 @@ -import DBC from './models/can/dbc'; +import DBC from "./models/can/dbc"; const AcuraDbc = new DBC(` VERSION "" diff --git a/src/api/OpenDbc.js b/src/api/OpenDbc.js index 013a605..872e517 100644 --- a/src/api/OpenDbc.js +++ b/src/api/OpenDbc.js @@ -1,12 +1,12 @@ -import GitHub from 'github-api'; +import GitHub from "github-api"; -import {OPENDBC_SOURCE_REPO} from '../config'; +import { OPENDBC_SOURCE_REPO } from "../config"; export default class OpenDBC { constructor(token) { this.token = token; - this.github = new GitHub({token}); - this.sourceRepo = this.github.getRepo('commaai', 'opendbc'); + this.github = new GitHub({ token }); + this.sourceRepo = this.github.getRepo("commaai", "opendbc"); this.githubUsername = null; } @@ -15,11 +15,11 @@ export default class OpenDBC { } async getGithubUsername() { - if(this.githubUsername) { + if (this.githubUsername) { return this.githubUsername; } else { const githubUsername = await this.fetchGithubUsername(); - if(githubUsername) { + if (githubUsername) { return githubUsername; } } @@ -28,13 +28,13 @@ export default class OpenDBC { async fetchGithubUsername() { try { const user = await this.github.getUser(); - if(user) { + if (user) { const profile = await user.getProfile(); - if(profile) { + if (profile) { return profile.data.login; } } - } catch(e) { + } catch (e) { return null; } } @@ -47,31 +47,31 @@ export default class OpenDBC { */ let repo; - if(repoFullName === undefined) { + if (repoFullName === undefined) { repo = this.sourceRepo; } else { - const [username, repoName] = repoFullName.split('/'); + const [username, repoName] = repoFullName.split("/"); repo = this.github.getRepo(username, repoName); } try { - const response = await repo.getContents('master', ''); + const response = await repo.getContents("master", ""); - return response.data.map((content) => content.path); - } catch(e) { + return response.data.map(content => content.path); + } catch (e) { return []; } } async getDbcContents(dbcPath, repoFullName) { let repo; - if(repoFullName === undefined) { + if (repoFullName === undefined) { repo = this.sourceRepo; } else { - const [username, repoName] = repoFullName.split('/'); + const [username, repoName] = repoFullName.split("/"); repo = this.github.getRepo(username, repoName); } - const fileContents = await repo.getContents('master', dbcPath); + const fileContents = await repo.getContents("master", dbcPath); const rawContentsUrl = fileContents.data.download_url; @@ -81,72 +81,83 @@ export default class OpenDBC { } repoSourceIsOpenDbc(repoDetails) { - return repoDetails.source - && repoDetails.source.full_name === OPENDBC_SOURCE_REPO; + return ( + repoDetails.source && repoDetails.source.full_name === OPENDBC_SOURCE_REPO + ); } async getUserOpenDbcFork() { - const githubUsername = await this.getGithubUsername(); - if(!githubUsername) return null; + const githubUsername = await this.getGithubUsername(); + if (!githubUsername) return null; - const openDbcFork = this.github.getRepo(githubUsername, 'opendbc'); - const repoDetailResp = await openDbcFork.getDetails(); - const repoDetails = repoDetailResp.data; + const openDbcFork = this.github.getRepo(githubUsername, "opendbc"); + const repoDetailResp = await openDbcFork.getDetails(); + const repoDetails = repoDetailResp.data; - if(this.repoSourceIsOpenDbc(repoDetails)) { - return repoDetails.full_name; - } else { - return null; - } + if (this.repoSourceIsOpenDbc(repoDetails)) { + return repoDetails.full_name; + } else { + return null; + } } async fork() { - const forkResponse = await this.sourceRepo.fork(); - if(forkResponse.status === 202) { - return true; - } else { - return false; - } + const forkResponse = await this.sourceRepo.fork(); + if (forkResponse.status === 202) { + return true; + } else { + return false; + } } async commitFile(repoFullName, path, contents) { - /* + /* repo is of format username/reponame authenciated user must have write access to repo */ - const [user, repoName] = repoFullName.split('/'); - const repo = this.github.getRepo(user, repoName); + const [user, repoName] = repoFullName.split("/"); + const repo = this.github.getRepo(user, repoName); - // get HEAD reference - const refResp = await repo.getRef('heads/master'); - const ref = refResp.data; + // get HEAD reference + const refResp = await repo.getRef("heads/master"); + const ref = refResp.data; - // get HEAD commit sha - const headCommitResp = await repo.getCommit(ref.object.sha); - const headCommit = headCommitResp.data; + // get HEAD commit sha + const headCommitResp = await repo.getCommit(ref.object.sha); + const headCommit = headCommitResp.data; - // get HEAD tree - const headTreeResp = await repo.getTree(headCommit.tree.sha); - const headTree = headTreeResp.data; + // get HEAD tree + const headTreeResp = await repo.getTree(headCommit.tree.sha); + const headTree = headTreeResp.data; - // create new tree - const tree = [{ - mode: '100644', - path: path, - type: 'blob', - content: contents, - }]; + // create new tree + const tree = [ + { + mode: "100644", + path: path, + type: "blob", + content: contents + } + ]; - const createTreeResp = await repo.createTree(tree, headTree.sha); - const createdTree = createTreeResp.data; + const createTreeResp = await repo.createTree(tree, headTree.sha); + const createdTree = createTreeResp.data; - // commit - const commitResp = await repo.commit(headCommit.sha, createdTree.sha, 'OpenDBC updates'); - const commit = commitResp.data; + // commit + const commitResp = await repo.commit( + headCommit.sha, + createdTree.sha, + "OpenDBC updates" + ); + const commit = commitResp.data; - // update HEAD - const updateHeadResp = await repo.updateHead('heads/master', commit.sha, false); + // update HEAD + const updateHeadResp = await repo.updateHead( + "heads/master", + commit.sha, + false + ); - return updateHeadResp.status === 200; + return updateHeadResp.status === 200; } } diff --git a/src/api/can.js b/src/api/can.js index 19ab492..da0a1a1 100644 --- a/src/api/can.js +++ b/src/api/can.js @@ -1,32 +1,38 @@ -import NumpyLoader from '../utils/loadnpy'; +import NumpyLoader from "../utils/loadnpy"; export async function fetchCanTimes(base, part) { - const url = base+"/Log/"+part+"/can/t"; + const url = base + "/Log/" + part + "/can/t"; - const canData = await NumpyLoader.promise(url); + const canData = await NumpyLoader.promise(url); - return canData.data; + return canData.data; } export async function fetchCanPart(base, part) { - var urls = [ base+"/Log/"+part+"/can/t", - base+"/Log/"+part+"/can/src", - base+"/Log/"+part+"/can/address", - base+"/Log/"+part+"/can/data"]; + var urls = [ + base + "/Log/" + part + "/can/t", + base + "/Log/" + part + "/can/src", + base + "/Log/" + part + "/can/address", + base + "/Log/" + part + "/can/data" + ]; - var messages = {}; - let canData = null; - try { - canData = await Promise.all(urls.map(NumpyLoader.promise)); - } catch (e) { - console.log('this is a 404 workaround that is hacky', e) - return {times: [], - sources: [], - addresses: [], - datas: []} - } - return {times: canData[0].data, - sources: canData[1].data, - addresses: canData[2].data, - datas: canData[3].data}; -} \ No newline at end of file + var messages = {}; + let canData = null; + try { + canData = await Promise.all(urls.map(NumpyLoader.promise)); + } catch (e) { + console.log("this is a 404 workaround that is hacky", e); + return { + times: [], + sources: [], + addresses: [], + datas: [] + }; + } + return { + times: canData[0].data, + sources: canData[1].data, + addresses: canData[2].data, + datas: canData[3].data + }; +} diff --git a/src/api/comma-auth.js b/src/api/comma-auth.js index b180991..90d3e93 100644 --- a/src/api/comma-auth.js +++ b/src/api/comma-auth.js @@ -1,19 +1,22 @@ -import Cookies from 'js-cookie'; +import Cookies from "js-cookie"; -import {COMMA_ACCESS_TOKEN_COOKIE, COMMA_OAUTH_REDIRECT_COOKIE} from '../config'; +import { + COMMA_ACCESS_TOKEN_COOKIE, + COMMA_OAUTH_REDIRECT_COOKIE +} from "../config"; function getCommaAccessToken() { - return Cookies.get(COMMA_ACCESS_TOKEN_COOKIE); + return Cookies.get(COMMA_ACCESS_TOKEN_COOKIE); } function isAuthenticated() { - return getCommaAccessToken() !== undefined; + return getCommaAccessToken() !== undefined; } function authUrl() { - Cookies.set(COMMA_OAUTH_REDIRECT_COOKIE, window.location.href); + Cookies.set(COMMA_OAUTH_REDIRECT_COOKIE, window.location.href); - return 'https://community.comma.ai/ucp.php?mode=login&login=external&oauth_service=google'; + return "https://community.comma.ai/ucp.php?mode=login&login=external&oauth_service=google"; } -export default {getCommaAccessToken, isAuthenticated, authUrl}; +export default { getCommaAccessToken, isAuthenticated, authUrl }; diff --git a/src/api/github-auth.js b/src/api/github-auth.js index dc279bf..1c2bb55 100644 --- a/src/api/github-auth.js +++ b/src/api/github-auth.js @@ -1,11 +1,13 @@ -import {GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL} from '../config'; -import {objToQuery} from '../utils/url'; +import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from "../config"; +import { objToQuery } from "../utils/url"; export function authorizeUrl(route) { - const params = {client_id: GITHUB_CLIENT_ID, - redirect_uri: GITHUB_REDIRECT_URL, - scope: 'user:email public_repo', - state: JSON.stringify({route})}; + const params = { + client_id: GITHUB_CLIENT_ID, + redirect_uri: GITHUB_REDIRECT_URL, + scope: "user:email public_repo", + state: JSON.stringify({ route }) + }; return `http://github.com/login/oauth/authorize?${objToQuery(params)}`; } diff --git a/src/api/localstorage.js b/src/api/localstorage.js index 77a4f9b..46078e4 100644 --- a/src/api/localstorage.js +++ b/src/api/localstorage.js @@ -1,24 +1,26 @@ -import DBC from '../models/can/dbc'; +import DBC from "../models/can/dbc"; export function fetchPersistedDbc(routeName) { const maybeDbc = window.localStorage.getItem(routeName); - if(maybeDbc !== null) { - const {dbcFilename, dbcText} = JSON.parse(maybeDbc); + if (maybeDbc !== null) { + const { dbcFilename, dbcText } = JSON.parse(maybeDbc); const dbc = new DBC(dbcText); - return {dbc, dbcText, dbcFilename}; + return { dbc, dbcText, dbcFilename }; } else return null; } -export function persistDbc(routeName, {dbcFilename, dbc}) { - const dbcJson = JSON.stringify({dbcFilename, - dbcText: dbc.text()}); +export function persistDbc(routeName, { dbcFilename, dbc }) { + const dbcJson = JSON.stringify({ + dbcFilename, + dbcText: dbc.text() + }); window.localStorage.setItem(routeName, dbcJson); } -const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = 'gh_auth_token'; +const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = "gh_auth_token"; export function fetchPersistedGithubAuthToken() { - return window.localStorage.getItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY); + return window.localStorage.getItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY); } export function unpersistGithubAuthToken() { @@ -26,5 +28,5 @@ export function unpersistGithubAuthToken() { } export function persistGithubAuthToken(token) { - return window.localStorage.setItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY, token); -} \ No newline at end of file + return window.localStorage.setItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY, token); +} diff --git a/src/api/panda-reader.js b/src/api/panda-reader.js index f215059..ee94e7a 100644 --- a/src/api/panda-reader.js +++ b/src/api/panda-reader.js @@ -1,66 +1,76 @@ -import Panda from './panda'; +import Panda from "./panda"; export default class PandaReader { + static ERROR_NO_DEVICE_SELECTED = 8; - static ERROR_NO_DEVICE_SELECTED = 8; + constructor() { + this.panda = new Panda(); + this.isReading = false; + this.onMessagesReceived = () => {}; + this.callbackQueue = []; + this.callbackQueueTimer = null; - constructor() { - this.panda = new Panda(); - this.isReading = false; - this.onMessagesReceived = () => {}; - this.callbackQueue = []; - this.callbackQueueTimer = null; + this.readLoop = this.readLoop.bind(this); + this.flushCallbackQueue = this.flushCallbackQueue.bind(this); + this._flushCallbackQueue = this._flushCallbackQueue.bind(this); + } - this.readLoop = this.readLoop.bind(this); - this.flushCallbackQueue = this.flushCallbackQueue.bind(this); - this._flushCallbackQueue = this._flushCallbackQueue.bind(this); + connect() { + return this.panda.connect(); + } + + setOnMessagesReceivedCallback(callback) { + this.onMessagesReceived = callback; + } + + stopReadLoop() { + this.isReading = false; + window.cancelAnimationFrame(this.callbackQueueTimer); + } + + _flushCallbackQueue() { + const messages = this.callbackQueue.reduce( + (arr, messages) => arr.concat(messages), + [] + ); + this.onMessagesReceived(messages); + + this.callbackQueue = []; + } + + flushCallbackQueue() { + if (this.callbackQueue.length > 0) { + this._flushCallbackQueue(); } - connect() { - return this.panda.connect(); + this.callbackQueueTimer = window.requestAnimationFrame( + this.flushCallbackQueue + ); + } + + readLoop() { + if (!this.isReading) { + this.isReading = true; + // this.flushCallbackQueueTimer = wi + this.callbackQueueTimer = window.requestAnimationFrame( + this.flushCallbackQueue, + 30 + ); } - setOnMessagesReceivedCallback(callback) { - this.onMessagesReceived = callback; - } - - stopReadLoop() { - this.isReading = false; - window.cancelAnimationFrame(this.callbackQueueTimer); - } - - _flushCallbackQueue() { - const messages = this.callbackQueue.reduce((arr, messages) => arr.concat(messages), []) - this.onMessagesReceived(messages); - - this.callbackQueue = []; - } - - flushCallbackQueue() { - if(this.callbackQueue.length > 0) { - this._flushCallbackQueue(); - } - - this.callbackQueueTimer = window.requestAnimationFrame(this.flushCallbackQueue); - } - - readLoop() { - if(!this.isReading) { - this.isReading = true; - // this.flushCallbackQueueTimer = wi - this.callbackQueueTimer = window.requestAnimationFrame(this.flushCallbackQueue, 30); + this.panda.canRecv().then( + messages => { + if (this.isReading && messages.canMessages.length > 0) { + this.callbackQueue.push(messages); } - - this.panda.canRecv().then(messages => { - if(this.isReading && messages.canMessages.length > 0) { - this.callbackQueue.push(messages); - } + this.readLoop(); + }, + error => { + if (this.isReading) { + console.log("canRecv error", error); this.readLoop(); - }, error => { - if(this.isReading) { - console.log('canRecv error', error); - this.readLoop(); - } - }); - } + } + } + ); + } } diff --git a/src/api/panda.js b/src/api/panda.js index 791d65c..34ddb8e 100644 --- a/src/api/panda.js +++ b/src/api/panda.js @@ -1,5 +1,5 @@ -import CloudLog from '../logging/CloudLog'; -require('core-js/fn/string/pad-end'); +import CloudLog from "../logging/CloudLog"; +require("core-js/fn/string/pad-end"); const PANDA_VENDOR_ID = 0xbbaa; const PANDA_PRODUCT_ID = 0xddcc; @@ -7,73 +7,93 @@ const PANDA_PRODUCT_ID = 0xddcc; const BUFFER_SIZE = 0x10 * 256; export default class Panda { - constructor() { - this.device = null; + constructor() { + this.device = null; + } + + connect() { + // Must be called via a mouse click handler, per Chrome restrictions. + return navigator.usb + .requestDevice({ filters: [{ vendorId: PANDA_VENDOR_ID }] }) + .then(device => { + this.device = device; + return device.open(); + }) + .then(() => this.device.selectConfiguration(1)) + .then(() => this.device.claimInterface(0)); + } + + async health() { + const controlParams = { + requestType: "vendor", + recipient: "device", + request: 0xd2, + value: 0, + index: 0 + }; + try { + return await this.device.controlTransferIn(controlParams, 13); + } catch (err) { + CloudLog.error({ event: "Panda.health failed", error: err }); + } + } + + parseCanBuffer(buffer) { + const messages = []; + + for (let i = 0; i < buffer.byteLength; i += 0x10) { + const dat = buffer.slice(i, i + 0x10); + + const datView = Buffer.from(dat); + const f1 = datView.readInt32LE(0), + f2 = datView.readInt32LE(4); + + const address = f1 >>> 21; + + const busTime = f2 >>> 16; + const data = new Buffer(dat.slice(8, 8 + (f2 & 0xf))); + const source = (f2 >> 4) & 0xf & 0xff; + + messages.push([ + address, + busTime, + data.toString("hex").padEnd(16, "0"), + source + ]); } - connect() { - // Must be called via a mouse click handler, per Chrome restrictions. - return navigator.usb.requestDevice({ filters: [{ vendorId: PANDA_VENDOR_ID }] }) - .then(device => { - this.device = device; - return device.open(); - }) - .then(() => this.device.selectConfiguration(1)) - .then(() => this.device.claimInterface(0)); + return messages; + } + + async mockCanRecv() { + const promise = new Promise(resolve => + setTimeout( + () => + resolve({ + time: performance.now() / 1000, + canMessages: [[0, Math.random() * 65000, "".padEnd(16, "0"), 0]] + }), + 100 + ) + ); + return await promise; + } + + async canRecv() { + let result = null, + receiptTime = null; + while (result === null) { + try { + result = await this.device.transferIn(1, BUFFER_SIZE); + receiptTime = performance.now() / 1000; + } catch (err) { + console.warn("can_recv failed, retrying"); + } } - async health() { - const controlParams = { requestType: 'vendor', - recipient: 'device', - request: 0xd2, - value: 0, - index: 0 }; - try { - return await this.device.controlTransferIn(controlParams, 13); - } catch(err) { - CloudLog.error({event: 'Panda.health failed', 'error': err}); - } - } - - parseCanBuffer(buffer) { - const messages = []; - - for(let i = 0; i < buffer.byteLength; i+=0x10) { - const dat = buffer.slice(i, i + 0x10); - - const datView = Buffer.from(dat); - const f1 = datView.readInt32LE(0), f2 = datView.readInt32LE(4); - - const address = f1 >>> 21; - - const busTime = (f2 >>> 16); - const data = new Buffer(dat.slice(8, 8 + (f2 & 0xF))); - const source = ((f2 >> 4) & 0xF) & 0xFF; - - messages.push([address, busTime, data.toString('hex').padEnd(16, '0'), source]); - } - - return messages; - } - - async mockCanRecv() { - const promise = new Promise((resolve) => - setTimeout(() => resolve({time: performance.now() / 1000, - canMessages: [[0, Math.random() * 65000, ''.padEnd(16, '0'), 0]]}), 100)); - return await promise; - } - - async canRecv() { - let result = null, receiptTime = null; - while(result === null) { - try { - result = await this.device.transferIn(1, BUFFER_SIZE); - receiptTime = performance.now() / 1000; - } catch(err) { - console.warn('can_recv failed, retrying'); - } - } - - return {time: receiptTime, canMessages: this.parseCanBuffer(result.data.buffer)}; - } + return { + time: receiptTime, + canMessages: this.parseCanBuffer(result.data.buffer) + }; + } } diff --git a/src/api/routes.js b/src/api/routes.js index a0ade40..37c976b 100644 --- a/src/api/routes.js +++ b/src/api/routes.js @@ -1,11 +1,11 @@ -import Cookies from 'js-cookie'; -import Moment from 'moment'; -import CommaAuth from './comma-auth'; +import Cookies from "js-cookie"; +import Moment from "moment"; +import CommaAuth from "./comma-auth"; -const ROUTES_ENDPOINT = 'https://api.commadotai.com/v1/{dongleId}/routes/'; +const ROUTES_ENDPOINT = "https://api.commadotai.com/v1/{dongleId}/routes/"; function momentizeTimes(routes) { - for(let routeName in routes) { + for (let routeName in routes) { routes[routeName].start_time = Moment(routes[routeName].start_time); routes[routeName].end_time = Moment(routes[routeName].end_time); } @@ -13,35 +13,34 @@ function momentizeTimes(routes) { } export async function fetchRoutes(dongleId) { - // will throw errors from fetch() on HTTP failure + // will throw errors from fetch() on HTTP failure - if(dongleId === undefined) { - dongleId = 'me'; + if (dongleId === undefined) { + dongleId = "me"; + } + + const accessToken = CommaAuth.getCommaAccessToken(); + if (accessToken) { + const endpoint = ROUTES_ENDPOINT.replace("{dongleId}", dongleId); + const headers = new Headers(); + headers.append("Authorization", `JWT ${accessToken}`); + + const request = new Request(endpoint, { headers }); + const resp = await fetch(request); + const routes = await resp.json(); + if ("routes" in routes) { + return momentizeTimes(routes.routes); } + } - const accessToken = CommaAuth.getCommaAccessToken(); - if(accessToken) { - const endpoint = ROUTES_ENDPOINT.replace('{dongleId}', dongleId); - const headers = new Headers(); - headers.append('Authorization', `JWT ${accessToken}`); - - - const request = new Request(endpoint, {headers}); - const resp = await fetch(request); - const routes = await resp.json(); - if('routes' in routes) { - return momentizeTimes(routes.routes); - } - } - - return {}; + return {}; } export function cameraPath(routeUrl, frame) { - return `${routeUrl}/sec${frame}.jpg` + return `${routeUrl}/sec${frame}.jpg`; } export function parseRouteName(name) { const startTime = Moment(name, "YYYY-MM-DD--H-m-s"); - return {startTime}; + return { startTime }; } diff --git a/src/api/unlogger.js b/src/api/unlogger.js index f62e730..33929e3 100644 --- a/src/api/unlogger.js +++ b/src/api/unlogger.js @@ -1,12 +1,12 @@ -import SocketIO from 'socket.io-client'; -import {UNLOGGER_HOST} from '../config'; +import SocketIO from "socket.io-client"; +import { UNLOGGER_HOST } from "../config"; export default class UnloggerClient { - constructor() { - this.socket = SocketIO(UNLOGGER_HOST); - } + constructor() { + this.socket = SocketIO(UNLOGGER_HOST); + } - seek(dongleId, baseTime, seekSeconds) { - this.socket.emit('seek', dongleId, baseTime, seekSeconds); - } -} \ No newline at end of file + seek(dongleId, baseTime, seekSeconds) { + this.socket.emit("seek", dongleId, baseTime, seekSeconds); + } +} diff --git a/src/api/video.js b/src/api/video.js index 70c966f..e9a29e6 100644 --- a/src/api/video.js +++ b/src/api/video.js @@ -5,16 +5,18 @@ function videoUrl(dongleId, hashedRouteName) { function videoUrlForRouteUrl(routeUrlString) { const url = new URL(routeUrlString); - const pathParts = url.pathname.split('/'); + const pathParts = url.pathname.split("/"); - const [dongleIdPrefixed, hashedRouteName] = pathParts.slice(pathParts.length - 2); - let dongleId = dongleIdPrefixed - if(dongleIdPrefixed.indexOf('comma-') === 0) { - const [_, dongleIdNoPrefix] = dongleIdPrefixed.split('comma-'); + const [dongleIdPrefixed, hashedRouteName] = pathParts.slice( + pathParts.length - 2 + ); + let dongleId = dongleIdPrefixed; + if (dongleIdPrefixed.indexOf("comma-") === 0) { + const [_, dongleIdNoPrefix] = dongleIdPrefixed.split("comma-"); dongleId = dongleIdNoPrefix; } return videoUrl(dongleId, hashedRouteName); } -export default {videoUrl, videoUrlForRouteUrl}; +export default { videoUrl, videoUrlForRouteUrl }; diff --git a/src/civic-dbc.js b/src/civic-dbc.js index ca95fa1..2afe69c 100644 --- a/src/civic-dbc.js +++ b/src/civic-dbc.js @@ -1,4 +1,4 @@ -import DBC from './models/can/dbc'; +import DBC from "./models/can/dbc"; const CivicDbc = new DBC(` VERSION "" @@ -345,4 +345,4 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ; VAL_ 927 ACC_ALERTS 29 "esp_active_acc_canceled" 10 "b_pedal_applied" 9 "speed_too_low" 8 "speed_too_high" 7 "p_brake_applied" 6 "gear_no_d" 5 "seatbelt" 4 "too_steep_downhill" 3 "too_steep_uphill" 2 "too_close" 1 "no_vehicle_ahead" ; `); -export default CivicDbc; \ No newline at end of file +export default CivicDbc; diff --git a/src/components/AddSignals.js b/src/components/AddSignals.js index bc6ff9e..0ac41a0 100644 --- a/src/components/AddSignals.js +++ b/src/components/AddSignals.js @@ -1,12 +1,12 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import { StyleSheet } from 'aphrodite/no-important'; -import css from '../utils/css'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { StyleSheet } from "aphrodite/no-important"; +import css from "../utils/css"; -import SignalLegend from './SignalLegend'; -import Signal from '../models/can/signal'; -import {shade} from '../utils/color'; -import DbcUtils from '../utils/dbc'; +import SignalLegend from "./SignalLegend"; +import Signal from "../models/can/signal"; +import { shade } from "../utils/color"; +import DbcUtils from "../utils/dbc"; /* AddSignals component draws an 8x8 matrix @@ -17,517 +17,569 @@ configurable in the legend. */ const Styles = StyleSheet.create({ - bit: { - margin: 0, - padding: 12, - userSelect: 'none', - cursor: 'pointer', - textAlign: 'center', - position: 'relative' - }, - bitSelectedStyle: { - backgroundColor: 'rgba(0,119,158,0.5)' - }, - bitSignificance: { - fontSize: 12, - display: 'block', - position: 'absolute', - bottom: 0, - left: 0, - right: 0, - margin: '0 auto' - }, - highlightedSignalTitle: { - backgroundColor: 'rgba(0,0,0,0.2)' - }, + bit: { + margin: 0, + padding: 12, + userSelect: "none", + cursor: "pointer", + textAlign: "center", + position: "relative" + }, + bitSelectedStyle: { + backgroundColor: "rgba(0,119,158,0.5)" + }, + bitSignificance: { + fontSize: 12, + display: "block", + position: "absolute", + bottom: 0, + left: 0, + right: 0, + margin: "0 auto" + }, + highlightedSignalTitle: { + backgroundColor: "rgba(0,0,0,0.2)" + } }); export default class AddSignals extends Component { - static propTypes = { - message: PropTypes.object, - onConfirmedSignalChange: PropTypes.func, - messageIndex: PropTypes.number, - onSignalPlotChange: PropTypes.func, - plottedSignalUids: PropTypes.array + static propTypes = { + message: PropTypes.object, + onConfirmedSignalChange: PropTypes.func, + messageIndex: PropTypes.number, + onSignalPlotChange: PropTypes.func, + plottedSignalUids: PropTypes.array + }; + + constructor(props) { + super(props); + + let signals = {}; + if (props.message && props.message.frame && props.message.frame.signals) { + signals = this.copySignals(props.message.frame.signals); + } + + this.state = { + bits: [], + signals: signals, + signalStyles: this.calcSignalStyles(signals), + highlightedSignal: null, + dragStartBit: null, + dragSignal: null, + dragCurrentBit: null }; - constructor(props) { - super(props); + this.updateSignalStyles = this.updateSignalStyles.bind(this); + this.onSignalHover = this.onSignalHover.bind(this); + this.onBitHover = this.onBitHover.bind(this); + this.onSignalHoverEnd = this.onSignalHoverEnd.bind(this); + this.onTentativeSignalChange = this.onTentativeSignalChange.bind(this); + this.onSignalChange = this.onSignalChange.bind(this); + this.onSignalRemove = this.onSignalRemove.bind(this); + this.onSignalPlotChange = this.onSignalPlotChange.bind(this); + this.resetDragState = this.resetDragState.bind(this); + } - let signals = {}; - if(props.message && props.message.frame && props.message.frame.signals) { - signals = this.copySignals(props.message.frame.signals); + copySignals(signals) { + return Object.entries(signals).reduce( + (signalsCopy, [signalName, signal]) => { + signalsCopy[signalName] = Object.assign(Object.create(signal), signal); + return signalsCopy; + }, + {} + ); + } + + shouldComponentUpdate(nextProps, nextState) { + return ( + nextProps.message.hexData !== this.props.message.hexData || + nextProps.messageIndex !== this.props.messageIndex || + JSON.stringify(nextProps.plottedSignalUids) !== + JSON.stringify(this.props.plottedSignalUids) || + JSON.stringify(this.state) !== JSON.stringify(nextState) + ); + } + + signalColorStyle(signal) { + const { colors } = signal; + + let colorRgbStr, backgroundColor; + if (this.state && this.state.highlightedSignal === signal.name) { + // when signal highlighted, + // darkened background and lightened text. + + const darkenedColors = shade(colors, -0.5); + const lightenedColors = shade(colors, 0.9); + colorRgbStr = `rgb(${lightenedColors.join(",")})`; + backgroundColor = `rgba(${darkenedColors.join(",")},0.5)`; + } else { + const colorsCommaSep = colors.join(","); + colorRgbStr = `rgb(${colorsCommaSep})`; + backgroundColor = `rgba(${colorsCommaSep},0.2)`; + } + + const style = StyleSheet.create({ + signal: { color: colorRgbStr, backgroundColor } + }).signal; + return style; + } + + updateSignalStyles() { + const signalStyles = this.calcSignalStyles(this.state.signals); + + this.setState({ signalStyles }); + } + + calcSignalStyles(signals) { + const signalStyles = {}; + Object.values(signals).forEach(signal => { + signalStyles[signal.name] = this.signalColorStyle(signal); + }); + + return signalStyles; + } + + componentWillReceiveProps({ message }) { + const isNewMessage = message.address !== this.props.message.address; + if (isNewMessage) { + const signals = message.frame ? message.frame.signals : {}; + + this.setState( + { signals: this.copySignals(signals) }, + this.updateSignalStyles + ); + } + } + + signalForBit(bitIdx) { + // bitIdx in [0,64) + // returns instance of Signal + + return Object.values(this.state.signals).filter(signal => { + return signal.bitDescription(bitIdx) !== null; + })[0]; + } + + onSignalHover(signal) { + if (!signal) return; + + this.setState({ highlightedSignal: signal.name }, this.updateSignalStyles); + } + + signalBitIndex(bitIdx, signal) { + // todo does this work for both big and little endian? + let { startBit } = signal; + if (!signal.isLittleEndian) { + startBit = DbcUtils.bigEndianBitIndex(startBit); + } + return bitIdx - startBit; + } + + onBitHover(bitIdx, signal) { + let { dragStartBit, signals, dragSignal } = this.state; + + if (dragStartBit !== null) { + if (dragSignal !== null) { + signals = this.copySignals(signals); + dragSignal = Object.assign(Object.create(dragSignal), dragSignal); + + if (dragStartBit === dragSignal.startBit && dragSignal.size > 1) { + if (!dragSignal.isLittleEndian) { + // should not be able to drag the msb past the lsb + const hoveredBigEndian = DbcUtils.bigEndianBitIndex(bitIdx); + const lsbBigEndian = dragSignal.lsbBitNumber(); + + if (hoveredBigEndian > lsbBigEndian) { + return; + } + } else { + // should not be able to drag the lsb past the msb + if (bitIdx > dragSignal.msbBitIndex()) { + return; + } + } + + const diff = bitIdx - dragStartBit; + + if (dragSignal.isLittleEndian) { + dragSignal.size -= diff; + } else if (dragSignal.bitDescription(bitIdx) === null) { + dragSignal.size += Math.abs(diff); + } else { + dragSignal.size -= Math.abs(diff); + } + + dragSignal.startBit += diff; + + signals[dragSignal.name] = dragSignal; + dragStartBit = dragSignal.startBit; + } else if (dragSignal.size === 1) { + // 1-bit signals can be dragged in either direction + if (Math.floor(bitIdx / 8) === Math.floor(dragStartBit / 8)) { + if (bitIdx > dragStartBit) { + if (dragSignal.isLittleEndian) { + dragSignal.size = bitIdx - dragSignal.startBit; + } else { + dragSignal.startBit = bitIdx; + dragSignal.size = bitIdx - dragStartBit + 1; + dragStartBit = bitIdx; + } + } else { + if (dragSignal.isLittleEndian) { + dragSignal.startBit = bitIdx; + dragSignal.size = dragStartBit - bitIdx + 1; + dragStartBit = bitIdx; + } else { + dragSignal.size = dragStartBit - bitIdx + 1; + dragStartBit = bitIdx; + } + } + } + + signals[dragSignal.name] = dragSignal; + } else if ( + dragSignal.isLittleEndian && + dragStartBit === dragSignal.msbBitIndex() + ) { + if (bitIdx < dragSignal.startBit) { + // should not be able to drag the MSB past the LSB + return; + } + const diff = bitIdx - dragStartBit; + if (dragSignal.bitDescription(bitIdx) === null) { + dragSignal.size += Math.abs(diff); + } else { + dragSignal.size -= Math.abs(diff); + } + signals[dragSignal.name] = dragSignal; + dragStartBit = dragSignal.msbBitIndex(); + } else if ( + !dragSignal.isLittleEndian && + dragStartBit === dragSignal.lsbBitIndex() + ) { + const diff = bitIdx - dragStartBit; + if (dragSignal.bitDescription(bitIdx) === null) { + dragSignal.size += Math.abs(diff); + } else { + dragSignal.size -= Math.abs(diff); + } + signals[dragSignal.name] = dragSignal; + dragStartBit = dragSignal.lsbBitIndex(); } - - this.state = { - bits: [], - signals: signals, - signalStyles: this.calcSignalStyles(signals), - highlightedSignal: null, - dragStartBit: null, - dragSignal: null, - dragCurrentBit: null - }; - - this.updateSignalStyles = this.updateSignalStyles.bind(this); - this.onSignalHover = this.onSignalHover.bind(this); - this.onBitHover = this.onBitHover.bind(this); - this.onSignalHoverEnd = this.onSignalHoverEnd.bind(this); - this.onTentativeSignalChange = this.onTentativeSignalChange.bind(this); - this.onSignalChange = this.onSignalChange.bind(this); - this.onSignalRemove = this.onSignalRemove.bind(this); - this.onSignalPlotChange = this.onSignalPlotChange.bind(this); - this.resetDragState = this.resetDragState.bind(this); - } - - copySignals(signals) { - return Object.entries(signals).reduce((signalsCopy, [signalName, signal]) => { - signalsCopy[signalName] = Object.assign(Object.create(signal), signal); - return signalsCopy; - }, {}); - } - - shouldComponentUpdate(nextProps, nextState) { - return nextProps.message.hexData !== this.props.message.hexData - || nextProps.messageIndex !== this.props.messageIndex - || JSON.stringify(nextProps.plottedSignalUids) !== JSON.stringify(this.props.plottedSignalUids) - || JSON.stringify(this.state) !== JSON.stringify(nextState); - } - - signalColorStyle(signal) { - const { colors } = signal; - - let colorRgbStr, backgroundColor; - if(this.state && this.state.highlightedSignal === signal.name) { - // when signal highlighted, - // darkened background and lightened text. - - const darkenedColors = shade(colors, -0.5); - const lightenedColors = shade(colors, 0.9); - colorRgbStr = `rgb(${lightenedColors.join(",")})`; - backgroundColor = `rgba(${darkenedColors.join(",")},0.5)`; - } else { - const colorsCommaSep = colors.join(","); - colorRgbStr = `rgb(${colorsCommaSep})`; - backgroundColor = `rgba(${colorsCommaSep},0.2)`; - } - - const style = StyleSheet.create({signal: {color: colorRgbStr, backgroundColor}}).signal; - return style; - } - - updateSignalStyles() { - const signalStyles = this.calcSignalStyles(this.state.signals); - - this.setState({signalStyles}) - } - - calcSignalStyles(signals) { - const signalStyles = {}; - Object.values(signals).forEach((signal) => { - signalStyles[signal.name] = this.signalColorStyle(signal); + this.setState({ + signals, + dragSignal, + dragCurrentBit: bitIdx, + dragStartBit }); - - return signalStyles; + } else { + this.setState({ dragCurrentBit: bitIdx }); + } } + if (signal) { + this.onSignalHover(signal); + } + } - componentWillReceiveProps({message}) { - const isNewMessage = message.address !== this.props.message.address; - if(isNewMessage) { - const signals = (message.frame ? message.frame.signals : {}); + onSignalHoverEnd(signal) { + if (!signal) return; - this.setState({signals: this.copySignals(signals)}, this.updateSignalStyles); + this.setState({ highlightedSignal: null }, this.updateSignalStyles); + } + + nextNewSignalName() { + const existingNames = Object.keys(this.state.signals); + let signalNum = 1, + signalName; + do { + signalName = "NEW_SIGNAL_" + signalNum; + signalNum++; + } while (existingNames.indexOf(signalName) !== -1); + + return signalName; + } + + onBitMouseDown(dragStartBit, dragSignal) { + this.setState({ + dragStartBit, + dragSignal: dragSignal || null + }); + } + + createSignal({ startBit, size, isLittleEndian }) { + const signal = new Signal({ + name: this.nextNewSignalName(), + startBit, + size: size, + isLittleEndian + }); + let { signals } = this.state; + signals = { ...signals }; + signals[signal.name] = signal; + + this.setState({ signals }, this.propagateUpSignalChange); + } + + createSignalIfNotExtendingOne(dragStartBit, dragEndBit) { + if (this.state.dragSignal === null) { + // check for overlapping bits + for (let i = dragStartBit; i <= dragEndBit; i++) { + if (this.signalForBit(i) !== undefined) { + // Don't create signal if a signal is already defined in the selected range. + return; } - } + } + const isDragAcrossSingleByte = + Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8); + const isDragDirectionUp = + !isDragAcrossSingleByte && dragEndBit < dragStartBit; - signalForBit(bitIdx) { - // bitIdx in [0,64) - // returns instance of Signal + let isLittleEndian; + if (isDragAcrossSingleByte || !isDragDirectionUp) { + isLittleEndian = dragStartBit % 8 < 4; + } else { + isLittleEndian = dragStartBit % 8 >= 4; + } + let size, + startBit = dragStartBit; - return Object.values(this.state.signals).filter((signal) => { - return signal.bitDescription(bitIdx) !== null - })[0]; - } - - onSignalHover(signal) { - if(!signal) return; - - this.setState({highlightedSignal: signal.name}, this.updateSignalStyles); - } - - signalBitIndex(bitIdx, signal) { - // todo does this work for both big and little endian? - let {startBit} = signal; - if(!signal.isLittleEndian) { - startBit = DbcUtils.bigEndianBitIndex(startBit); - } - return bitIdx - startBit; - } - - onBitHover(bitIdx, signal) { - let {dragStartBit, signals, dragSignal} = this.state; - - if(dragStartBit !== null) { - if(dragSignal !== null) { - signals = this.copySignals(signals); - dragSignal = Object.assign(Object.create(dragSignal), dragSignal); - - if(dragStartBit === dragSignal.startBit && dragSignal.size > 1) { - if(!dragSignal.isLittleEndian) { - // should not be able to drag the msb past the lsb - const hoveredBigEndian = DbcUtils.bigEndianBitIndex(bitIdx); - const lsbBigEndian = dragSignal.lsbBitNumber(); - - if(hoveredBigEndian > lsbBigEndian) { - return; - } - } else { - // should not be able to drag the lsb past the msb - if(bitIdx > dragSignal.msbBitIndex()) { - return; - } - } - - const diff = bitIdx - dragStartBit; - - - if(dragSignal.isLittleEndian) { - dragSignal.size -= diff; - } else if(dragSignal.bitDescription(bitIdx) === null) { - dragSignal.size += Math.abs(diff); - } else { - dragSignal.size -= Math.abs(diff); - } - - dragSignal.startBit += diff; - - signals[dragSignal.name] = dragSignal; - dragStartBit = dragSignal.startBit; - } else if(dragSignal.size === 1) { - // 1-bit signals can be dragged in either direction - if(Math.floor(bitIdx / 8) === Math.floor(dragStartBit / 8)) { - if(bitIdx > dragStartBit) { - if(dragSignal.isLittleEndian) { - dragSignal.size = bitIdx - dragSignal.startBit; - } else { - dragSignal.startBit = bitIdx; - dragSignal.size = bitIdx - dragStartBit + 1; - dragStartBit = bitIdx; - } - } else { - if(dragSignal.isLittleEndian) { - dragSignal.startBit = bitIdx; - dragSignal.size = dragStartBit - bitIdx + 1; - dragStartBit = bitIdx; - } else { - dragSignal.size = dragStartBit - bitIdx + 1; - dragStartBit = bitIdx; - } - } - } - - signals[dragSignal.name] = dragSignal; - } else if(dragSignal.isLittleEndian && dragStartBit === dragSignal.msbBitIndex()) { - if(bitIdx < dragSignal.startBit) { - // should not be able to drag the MSB past the LSB - return; - } - const diff = bitIdx - dragStartBit; - if(dragSignal.bitDescription(bitIdx) === null) { - dragSignal.size += Math.abs(diff); - } else { - dragSignal.size -= Math.abs(diff); - } - signals[dragSignal.name] = dragSignal; - dragStartBit = dragSignal.msbBitIndex(); - } else if(!dragSignal.isLittleEndian && dragStartBit === dragSignal.lsbBitIndex()) { - const diff = bitIdx - dragStartBit; - if(dragSignal.bitDescription(bitIdx) === null) { - dragSignal.size += Math.abs(diff); - } else { - dragSignal.size -= Math.abs(diff); - } - signals[dragSignal.name] = dragSignal; - dragStartBit = dragSignal.lsbBitIndex(); - } - this.setState({signals, dragSignal, dragCurrentBit: bitIdx, dragStartBit}); - } else { - this.setState({dragCurrentBit: bitIdx}); - } - } - if(signal) { - this.onSignalHover(signal); - } - } - - onSignalHoverEnd(signal) { - if(!signal) return; - - this.setState({highlightedSignal: null}, this.updateSignalStyles); - } - - nextNewSignalName() { - const existingNames = Object.keys(this.state.signals); - let signalNum = 1, signalName; - do { - signalName = 'NEW_SIGNAL_' + signalNum; - signalNum++; - } while(existingNames.indexOf(signalName) !== -1); - - return signalName; - } - - onBitMouseDown(dragStartBit, dragSignal) { - this.setState({dragStartBit, - dragSignal: dragSignal || null}) - } - - createSignal({startBit, size, isLittleEndian}) { - const signal = new Signal({name: this.nextNewSignalName(), - startBit, - size: size, - isLittleEndian}); - let {signals} = this.state; - signals = {...signals}; - signals[signal.name] = signal; - - this.setState({signals}, this.propagateUpSignalChange); - } - - createSignalIfNotExtendingOne(dragStartBit, dragEndBit) { - if(this.state.dragSignal === null) { - // check for overlapping bits - for(let i = dragStartBit; i <= dragEndBit; i++) { - if(this.signalForBit(i) !== undefined) { - // Don't create signal if a signal is already defined in the selected range. - return; - } - } - const isDragAcrossSingleByte = Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8); - const isDragDirectionUp = !isDragAcrossSingleByte && dragEndBit < dragStartBit; - - let isLittleEndian; - if(isDragAcrossSingleByte || !isDragDirectionUp) { - isLittleEndian = (dragStartBit % 8 < 4); - } else { - isLittleEndian = (dragStartBit % 8 >= 4); - } - let size, startBit = dragStartBit; - - if(isDragAcrossSingleByte){ - size = Math.abs(dragEndBit - dragStartBit) + 1; - } else { - if(isLittleEndian) { - if(dragEndBit > dragStartBit) { - startBit = dragStartBit; - size = dragEndBit - dragStartBit + 1; - } else { - startBit = dragEndBit; - size = dragStartBit - dragEndBit + 1; - } - } else { - if(dragEndBit < dragStartBit) { - startBit = dragEndBit; - } - size = Math.abs(DbcUtils.bigEndianBitIndex(dragEndBit) - DbcUtils.bigEndianBitIndex(dragStartBit)) + 1; - } - } - - this.createSignal({startBit, size, isLittleEndian}); - } - } - - onBitMouseUp(dragEndBit, signal) { - if(this.state.dragStartBit !== null) { - let {dragStartBit} = this.state; - - if(dragEndBit !== dragStartBit) { - // one-bit signal requires double click - // see onBitDoubleClick - this.createSignalIfNotExtendingOne(dragStartBit, dragEndBit); - } - this.propagateUpSignalChange(); - this.resetDragState(); - } - } - - byteValueHex(byteIdx) { - const {entries} = this.props.message; - if(this.props.messageIndex < entries.length) { - const entry = entries[this.props.messageIndex]; - - return entry.hexData.substr(byteIdx * 2, 2); + if (isDragAcrossSingleByte) { + size = Math.abs(dragEndBit - dragStartBit) + 1; + } else { + if (isLittleEndian) { + if (dragEndBit > dragStartBit) { + startBit = dragStartBit; + size = dragEndBit - dragStartBit + 1; + } else { + startBit = dragEndBit; + size = dragStartBit - dragEndBit + 1; + } } else { - return '--'; + if (dragEndBit < dragStartBit) { + startBit = dragEndBit; + } + size = + Math.abs( + DbcUtils.bigEndianBitIndex(dragEndBit) - + DbcUtils.bigEndianBitIndex(dragStartBit) + ) + 1; } + } + + this.createSignal({ startBit, size, isLittleEndian }); + } + } + + onBitMouseUp(dragEndBit, signal) { + if (this.state.dragStartBit !== null) { + let { dragStartBit } = this.state; + + if (dragEndBit !== dragStartBit) { + // one-bit signal requires double click + // see onBitDoubleClick + this.createSignalIfNotExtendingOne(dragStartBit, dragEndBit); + } + this.propagateUpSignalChange(); + this.resetDragState(); + } + } + + byteValueHex(byteIdx) { + const { entries } = this.props.message; + if (this.props.messageIndex < entries.length) { + const entry = entries[this.props.messageIndex]; + + return entry.hexData.substr(byteIdx * 2, 2); + } else { + return "--"; + } + } + + bitValue(byteIdx, byteBitIdx) { + const { entries } = this.props.message; + if (this.props.messageIndex < entries.length) { + const entry = entries[this.props.messageIndex]; + const data = Buffer.from(entry.hexData, "hex"); + if (byteIdx >= data.length) { + return "-"; + } + const byte = data.readInt8(byteIdx); + return (byte >> byteBitIdx) & 1; + } else { + return "-"; + } + } + + bitIsContainedInSelection(bitIdx, isLittleEndian = false) { + const { dragStartBit, dragCurrentBit } = this.state; + + if (isLittleEndian || dragStartBit % 8 < 4) { + return ( + dragStartBit !== null && + dragCurrentBit !== null && + bitIdx >= dragStartBit && + bitIdx <= dragCurrentBit + ); + } else { + const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit); + const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit); + const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx); + return ( + dragStartBit !== null && + dragCurrentBit !== null && + bigEndianBitIdx >= bigEndianStartBit && + bigEndianBitIdx <= bigEndianCurrentBit + ); + } + } + + onBitDoubleClick(startBit, signal) { + if (signal === undefined) { + this.createSignal({ startBit, size: 1, isLittleEndian: false }); + } + } + + renderBitMatrix() { + const rows = []; + let rowCount; + if (this.props.message.frame && this.props.message.frame.size) { + rowCount = Math.floor(this.props.message.frame.size * 8 / 8); + } else { + rowCount = 8; } - bitValue(byteIdx, byteBitIdx) { - const {entries} = this.props.message; - if(this.props.messageIndex < entries.length) { - const entry = entries[this.props.messageIndex]; - const data = Buffer.from(entry.hexData, 'hex'); - if (byteIdx >= data.length) { - return '-'; - } - const byte = data.readInt8(byteIdx); - return (byte >> byteBitIdx) & 1; - } else { - return '-'; + for (var i = 0; i < rowCount; i++) { + const rowBits = []; + for (var j = 7; j >= 0; j--) { + const bitIdx = i * 8 + j; + const signal = this.signalForBit(bitIdx); + let bitStyle = null, + bitSignificance = ""; + if (signal) { + bitStyle = this.state.signalStyles[signal.name] || null; + const bitDesc = signal.bitDescription(bitIdx); + bitSignificance = bitDesc.isMsb ? "msb" : bitDesc.isLsb ? "lsb" : ""; + } else if (this.bitIsContainedInSelection(bitIdx)) { + bitStyle = Styles.bitSelectedStyle; } - } + const className = css("bit", Styles.bit, bitStyle); + const bitValue = this.bitValue(i, j); - bitIsContainedInSelection(bitIdx, isLittleEndian = false) { - const {dragStartBit, dragCurrentBit} = this.state; - - if(isLittleEndian || (dragStartBit % 8 < 4)) { - return dragStartBit !== null && dragCurrentBit !== null - && bitIdx >= dragStartBit && bitIdx <= dragCurrentBit; - } else { - const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit); - const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit); - const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx); - return dragStartBit !== null && dragCurrentBit !== null - && bigEndianBitIdx >= bigEndianStartBit && bigEndianBitIdx <= bigEndianCurrentBit; - } - } - - onBitDoubleClick(startBit, signal) { - if(signal === undefined) { - this.createSignal({startBit, size: 1, isLittleEndian: false}); - } - } - - renderBitMatrix() { - const rows = []; - let rowCount; - if(this.props.message.frame && this.props.message.frame.size) { - rowCount = Math.floor((this.props.message.frame.size * 8) / 8); - } else { - rowCount = 8; - } - - for(var i = 0; i < rowCount; i++) { - const rowBits = []; - for(var j = 7; j >= 0; j--) { - const bitIdx = i * 8 + j; - const signal = this.signalForBit(bitIdx); - let bitStyle = null, bitSignificance = ''; - if(signal) { - bitStyle = this.state.signalStyles[signal.name] || null; - const bitDesc = signal.bitDescription(bitIdx); - bitSignificance = bitDesc.isMsb ? 'msb' : (bitDesc.isLsb ? 'lsb' : ''); - } else if(this.bitIsContainedInSelection(bitIdx)) { - bitStyle = Styles.bitSelectedStyle; - } - const className = css('bit', Styles.bit, bitStyle); - const bitValue = this.bitValue(i, j); - - rowBits.push(( this.onBitHover(bitIdx, signal)} - onMouseLeave={() => this.onSignalHoverEnd(signal)} - onMouseDown={this.onBitMouseDown.bind(this, bitIdx, signal)} - onMouseUp={this.onBitMouseUp.bind(this, bitIdx, signal)} - onDoubleClick={(() => this.onBitDoubleClick(bitIdx, signal))} - > - { bitValue } - - - { bitSignificance } - - )); - } - - rowBits.push(({this.byteValueHex(i)})); - rows.push(({rowBits})); - } - - return ( -
- - - {rows} - -
- -
+ rowBits.push( + this.onBitHover(bitIdx, signal)} + onMouseLeave={() => this.onSignalHoverEnd(signal)} + onMouseDown={this.onBitMouseDown.bind(this, bitIdx, signal)} + onMouseUp={this.onBitMouseUp.bind(this, bitIdx, signal)} + onDoubleClick={() => this.onBitDoubleClick(bitIdx, signal)} + > + {bitValue} + + {bitSignificance} + + ); + } + + rowBits.push( + + {this.byteValueHex(i)} + + ); + rows.push({rowBits}); } - resetDragState() { - this.setState({dragStartBit: null, - dragSignal: null, - dragCurrentBit: null}) + return ( +
+ + {rows} +
+
+ ); + } + + resetDragState() { + this.setState({ + dragStartBit: null, + dragSignal: null, + dragCurrentBit: null + }); + } + + onTentativeSignalChange(signal) { + // Tentative signal changes are not propagated up + // but their effects are displayed in the bitmatrix + const { signals } = this.state; + signals[signal.name] = signal; + this.setState({ signals }); + } + + onSignalChange(signal, oldSignal) { + const { signals } = this.state; + + for (let signalName in signals) { + if (signals[signalName].uid === signal.uid) { + delete signals[signalName]; + } } + signals[signal.name] = signal; - onTentativeSignalChange(signal) { - // Tentative signal changes are not propagated up - // but their effects are displayed in the bitmatrix - const {signals} = this.state; - signals[signal.name] = signal; - this.setState({signals}); - } + this.setState({ signals }, this.propagateUpSignalChange); + } - onSignalChange(signal, oldSignal) { - const {signals} = this.state; + onSignalRemove(signal) { + const { signals } = this.state; + delete signals[signal.name]; + this.setState({ signals }, this.propagateUpSignalChange); + } - for(let signalName in signals) { - if(signals[signalName].uid === signal.uid) { - delete signals[signalName]; - } - } - signals[signal.name] = signal; + propagateUpSignalChange() { + const { signals } = this.state; - this.setState({signals}, this.propagateUpSignalChange); - } + this.props.onConfirmedSignalChange( + this.props.message, + this.copySignals(signals) + ); + } - onSignalRemove(signal) { - const {signals} = this.state; - delete signals[signal.name]; - this.setState({signals}, this.propagateUpSignalChange); - } + onSignalPlotChange(shouldPlot, signalUid) { + const { message } = this.props; - propagateUpSignalChange() { - const {signals} = this.state; + this.props.onSignalPlotChange(shouldPlot, message.id, signalUid); + } - this.props.onConfirmedSignalChange(this.props.message, this.copySignals(signals)); - } - - onSignalPlotChange(shouldPlot, signalUid) { - const {message} = this.props; - - this.props.onSignalPlotChange(shouldPlot, message.id, signalUid) - } - - render() { - return ( -
- {Object.keys(this.state.signals).length === 0 ? -

Double click or drag to add a signal

: null - } - {this.props.message.entries[this.props.messageIndex] ? -
-

time: {this.props.message.entries[this.props.messageIndex].relTime.toFixed(3)}

-
: null} - {this.renderBitMatrix()} - -
- ); - } + render() { + return ( +
+ {Object.keys(this.state.signals).length === 0 ? ( +

Double click or drag to add a signal

+ ) : null} + {this.props.message.entries[this.props.messageIndex] ? ( +
+

+ time:{" "} + {this.props.message.entries[ + this.props.messageIndex + ].relTime.toFixed(3)} +

+
+ ) : null} + {this.renderBitMatrix()} + +
+ ); + } } diff --git a/src/components/CanGraph.js b/src/components/CanGraph.js index 51c63fe..9da865c 100644 --- a/src/components/CanGraph.js +++ b/src/components/CanGraph.js @@ -1,268 +1,306 @@ -import React, {Component} from 'react'; -import Measure from 'react-measure'; -import PropTypes from 'prop-types'; -import cx from 'classnames'; +import React, { Component } from "react"; +import Measure from "react-measure"; +import PropTypes from "prop-types"; +import cx from "classnames"; -import Signal from '../models/can/signal'; -import CanPlot from '../vega/CanPlot'; +import Signal from "../models/can/signal"; +import CanPlot from "../vega/CanPlot"; const DefaultPlotInnerStyle = { - position: 'absolute', - top: 0, - left: 0, + position: "absolute", + top: 0, + left: 0 }; export default class CanGraph extends Component { - static emptyTable = []; + static emptyTable = []; - static propTypes = { - data: PropTypes.object, - messages: PropTypes.object, - messageId: PropTypes.string, - messageName: PropTypes.string, - signalSpec: PropTypes.instanceOf(Signal), - segment: PropTypes.array, - unplot: PropTypes.func, - onRelativeTimeClick: PropTypes.func, - currentTime: PropTypes.number, - onSegmentChanged: PropTypes.func, - onDragStart: PropTypes.func, - onDragEnd: PropTypes.func, - container: PropTypes.node, - dragPos: PropTypes.object, - canReceiveGraphDrop: PropTypes.bool, - onGraphRefAvailable: PropTypes.func, - plottedSignals: PropTypes.array, + static propTypes = { + data: PropTypes.object, + messages: PropTypes.object, + messageId: PropTypes.string, + messageName: PropTypes.string, + signalSpec: PropTypes.instanceOf(Signal), + segment: PropTypes.array, + unplot: PropTypes.func, + onRelativeTimeClick: PropTypes.func, + currentTime: PropTypes.number, + onSegmentChanged: PropTypes.func, + onDragStart: PropTypes.func, + onDragEnd: PropTypes.func, + container: PropTypes.node, + dragPos: PropTypes.object, + canReceiveGraphDrop: PropTypes.bool, + onGraphRefAvailable: PropTypes.func, + plottedSignals: PropTypes.array + }; + + constructor(props) { + super(props); + + this.state = { + plotInnerStyle: null, + shiftX: 0, + shiftY: 0, + bounds: null, + isDataInserted: false }; + this.onNewView = this.onNewView.bind(this); + this.onSignalClickTime = this.onSignalClickTime.bind(this); + this.onSignalSegment = this.onSignalSegment.bind(this); + this.onDragAnchorMouseDown = this.onDragAnchorMouseDown.bind(this); + this.onDragAnchorMouseUp = this.onDragAnchorMouseUp.bind(this); + this.onDragStart = this.onDragStart.bind(this); + this.onPlotResize = this.onPlotResize.bind(this); + } - constructor(props) { - super(props); + segmentIsNew(newSegment) { + return ( + newSegment.length !== this.props.segment.length || + !newSegment.every((val, idx) => this.props.segment[idx] === val) + ); + } - this.state = { - plotInnerStyle: null, - shiftX: 0, - shiftY: 0, - bounds: null, - isDataInserted: false, - }; - this.onNewView = this.onNewView.bind(this); - this.onSignalClickTime = this.onSignalClickTime.bind(this); - this.onSignalSegment = this.onSignalSegment.bind(this); - this.onDragAnchorMouseDown = this.onDragAnchorMouseDown.bind(this); - this.onDragAnchorMouseUp = this.onDragAnchorMouseUp.bind(this); - this.onDragStart = this.onDragStart.bind(this); - this.onPlotResize = this.onPlotResize.bind(this); - } + dataChanged(prevProps, nextProps) { + return ( + nextProps.data.series.length !== prevProps.data.series.length || + !prevProps.signalSpec.equals(nextProps.signalSpec) || + nextProps.data.updated !== this.props.data.updated + ); + } - segmentIsNew(newSegment) { - return newSegment.length !== this.props.segment.length - || !(newSegment.every((val, idx) => this.props.segment[idx] === val)); - } + visualChanged(prevProps, nextProps) { + return ( + prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop || + JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos) + ); + } - dataChanged(prevProps, nextProps) { - return nextProps.data.series.length !== prevProps.data.series.length - || !prevProps.signalSpec.equals(nextProps.signalSpec) - || nextProps.data.updated !== this.props.data.updated; - } + onPlotResize({ bounds }) { + this.setState({ bounds }); - visualChanged(prevProps, nextProps) { - return prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop - || JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos); - } + this.view.run(); + this.view.signal("width", bounds.width); + this.view.signal("height", 0.4 * bounds.width); // 5:2 aspect ratio + this.view.run(); + } + shouldComponentUpdate(nextProps, nextState) { + if (this.view) { + // only update if segment is new + let segmentChanged = false; + if (this.segmentIsNew(nextProps.segment)) { + if (nextProps.segment.length > 0) { + // Set segmented domain + this.view.signal("segment", nextProps.segment); + } else { + // Reset segment to full domain + this.view.signal("segment", 0); + } + segmentChanged = true; + } - onPlotResize({bounds}) { - this.setState({bounds}); + if (!nextProps.live && nextProps.currentTime !== this.props.currentTime) { + this.view.signal("videoTime", nextProps.currentTime); + segmentChanged = true; + } + if (segmentChanged) { this.view.run(); - this.view.signal('width', bounds.width); - this.view.signal('height', 0.4 * bounds.width); // 5:2 aspect ratio - this.view.run(); + } } - shouldComponentUpdate(nextProps, nextState) { - if(this.view) { - // only update if segment is new - let segmentChanged = false; - if(this.segmentIsNew(nextProps.segment)) { - if(nextProps.segment.length > 0) { - // Set segmented domain - this.view.signal('segment', nextProps.segment) - } else { - // Reset segment to full domain - this.view.signal('segment', 0); - } - segmentChanged = true; - } + const dataChanged = this.dataChanged(this.props, nextProps); - if(!nextProps.live && nextProps.currentTime !== this.props.currentTime) { - this.view.signal('videoTime', nextProps.currentTime); - segmentChanged = true; - } + return ( + dataChanged || + JSON.stringify(this.state) !== JSON.stringify(nextState) || + this.visualChanged(this.props, nextProps) + ); + } - if(segmentChanged) { - this.view.run(); - } - } + insertData() { + this.view.remove("table", () => true).run(); + this.view.insert("table", this.props.data.series).run(); + } - const dataChanged = this.dataChanged(this.props, nextProps); + componentDidUpdate(prevProps, prevState) { + if (this.dataChanged(prevProps, this.props)) { + this.insertData(); + } + } - return dataChanged - || JSON.stringify(this.state) !== JSON.stringify(nextState) - || this.visualChanged(this.props, nextProps); + componentWillReceiveProps(nextProps) { + if ( + nextProps.dragPos && + JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos) + ) { + this.updateStyleFromDragPos(nextProps.dragPos); + } else if (!nextProps.dragPos && this.state.plotInnerStyle !== null) { + this.setState({ plotInnerStyle: null }); + } + } + + updateStyleFromDragPos({ left, top }) { + const plotInnerStyle = this.state.plotInnerStyle || {}; + plotInnerStyle.left = left; + plotInnerStyle.top = top; + this.setState({ plotInnerStyle }); + } + + onNewView(view) { + this.view = view; + if (this.state.bounds) { + this.onPlotResize({ bounds: this.state.bounds }); + } + if (this.props.segment.length > 0) { + view.signal("segment", this.props.segment); } - insertData() { - this.view.remove('table', () => true).run(); - this.view.insert('table', this.props.data.series).run(); + this.insertData(); + } + + onSignalClickTime(signal, clickTime) { + if (clickTime !== undefined) { + this.props.onRelativeTimeClick(this.props.messageId, clickTime); + } + } + + onSignalSegment(signal, segment) { + if (!Array.isArray(segment)) { + return; } - componentDidUpdate(prevProps, prevState) { - if(this.dataChanged(prevProps, this.props)) { - this.insertData(); - } + this.props.onSegmentChanged(this.props.messageId, segment); + if (this.view) { + const state = this.view.getState(); + state.subcontext[0].signals.brush = 0; + this.view = this.view.setState(state); } + } - componentWillReceiveProps(nextProps) { - if(nextProps.dragPos && JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)) { - this.updateStyleFromDragPos(nextProps.dragPos); - } else if(!nextProps.dragPos && this.state.plotInnerStyle !== null) { - this.setState({plotInnerStyle: null}); - } - } + plotInnerStyleFromMouseEvent(e) { + const { shiftX, shiftY } = this.state; + const plotInnerStyle = { ...DefaultPlotInnerStyle }; + const rect = this.props.container.getBoundingClientRect(); - updateStyleFromDragPos({left, top}) { - const plotInnerStyle = this.state.plotInnerStyle || {}; - plotInnerStyle.left = left; - plotInnerStyle.top = top; - this.setState({plotInnerStyle}); - } + const x = e.clientX - rect.left - shiftX; + const y = e.clientY - rect.top - shiftY; + plotInnerStyle.left = x; + plotInnerStyle.top = y; + return plotInnerStyle; + } - onNewView(view) { - this.view = view; - if(this.state.bounds) { - this.onPlotResize({bounds: this.state.bounds}); - } - if(this.props.segment.length > 0) { - view.signal('segment', this.props.segment); - } + onDragAnchorMouseDown(e) { + e.persist(); + const shiftX = e.clientX - e.target.getBoundingClientRect().left; + const shiftY = e.clientY - e.target.getBoundingClientRect().top; + this.setState({ shiftX, shiftY }, () => { + this.setState({ plotInnerStyle: this.plotInnerStyleFromMouseEvent(e) }); + }); + this.props.onDragStart( + this.props.messageId, + this.props.signalSpec.uid, + shiftX, + shiftY + ); + } - this.insertData(); - } + onDragAnchorMouseUp(e) { + this.props.onDragEnd(); + this.setState({ + plotInnerStyle: null, + shiftX: 0, + shiftY: 0 + }); + } - onSignalClickTime(signal, clickTime) { - if(clickTime !== undefined) { - this.props.onRelativeTimeClick(this.props.messageId, clickTime); - } - } + onDragStart(e) { + e.preventDefault(); + return false; + } - onSignalSegment(signal, segment) { - if(!Array.isArray(segment)) { - return; - } + render() { + const { plotInnerStyle } = this.state; + const canReceiveDropClass = this.props.canReceiveGraphDrop + ? "is-droppable" + : null; - this.props.onSegmentChanged(this.props.messageId, segment); - if(this.view) { - const state = this.view.getState(); - state.subcontext[0].signals.brush = 0; - this.view = this.view.setState(state); - } - } + return ( +
+
+
+ +
+ {this.props.plottedSignals.map( + ({ messageId, signalUid, messageName }) => { + const signal = Object.values( + this.props.messages[messageId].frame.signals + ).find(s => s.uid === signalUid); + const { colors } = signal; - plotInnerStyleFromMouseEvent(e) { - const {shiftX, shiftY} = this.state; - const plotInnerStyle = {...DefaultPlotInnerStyle}; - const rect = this.props.container.getBoundingClientRect(); - - const x = e.clientX - rect.left - shiftX; - const y = e.clientY - rect.top - shiftY; - plotInnerStyle.left = x; - plotInnerStyle.top = y; - return plotInnerStyle; - } - - onDragAnchorMouseDown(e) { - e.persist(); - const shiftX = e.clientX - e.target.getBoundingClientRect().left; - const shiftY = e.clientY - e.target.getBoundingClientRect().top; - this.setState({shiftX, shiftY}, - () => { - this.setState({plotInnerStyle: this.plotInnerStyleFromMouseEvent(e)}); - }); - this.props.onDragStart(this.props.messageId, this.props.signalSpec.uid, shiftX, shiftY); - } - - onDragAnchorMouseUp(e) { - this.props.onDragEnd(); - this.setState({plotInnerStyle: null, - shiftX: 0, - shiftY: 0}); - } - - onDragStart(e) { - e.preventDefault(); - return false; - } - - render() { - const {plotInnerStyle} = this.state; - const canReceiveDropClass = this.props.canReceiveGraphDrop ? 'is-droppable' : null; - - return ( -
-
-
- + return ( +
+
+ +
+
+
+ {messageName}
- {this.props.plottedSignals.map(({ messageId, signalUid, messageName }) => { - const signal = Object.values(this.props.messages[messageId].frame.signals).find((s) => s.uid === signalUid); - const { colors } = signal; - - return ( -
-
- -
-
-
- {messageName} -
-
-
- {signal.name} -
-
-
- )} - )} - - {({measureRef}) => { - return (
- -
); - } - } -
+
+
+ {signal.name} +
+
-
- ); - } + ); + } + )} + + {({ measureRef }) => { + return ( +
+ +
+ ); + }} +
+
+
+ ); + } } diff --git a/src/components/CanLog.js b/src/components/CanLog.js index 383aec7..8653b93 100644 --- a/src/components/CanLog.js +++ b/src/components/CanLog.js @@ -1,268 +1,310 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import ReactList from 'react-list'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import ReactList from "react-list"; -import cx from 'classnames'; +import cx from "classnames"; export default class CanLog extends Component { - static ITEMS_PER_PAGE = 50; + static ITEMS_PER_PAGE = 50; - static propTypes = { - plottedSignals: PropTypes.array, - segmentIndices: PropTypes.array, - onSignalUnplotPressed: PropTypes.func, - onSignalPlotPressed: PropTypes.func, - message: PropTypes.object, - messageIndex: PropTypes.number, - onMessageExpanded: PropTypes.func, + static propTypes = { + plottedSignals: PropTypes.array, + segmentIndices: PropTypes.array, + onSignalUnplotPressed: PropTypes.func, + onSignalPlotPressed: PropTypes.func, + message: PropTypes.object, + messageIndex: PropTypes.number, + onMessageExpanded: PropTypes.func + }; + + constructor(props) { + super(props); + // only want to display up to length elements at a time + // offset, length + + this.state = { + length: 0, + expandedMessages: [], + messageHeights: [], + allPacketsExpanded: false }; - constructor(props) { - super(props); - // only want to display up to length elements at a time - // offset, length + this.renderLogListItemMessage = this.renderLogListItemMessage.bind(this); + this.addDisplayedMessages = this.addDisplayedMessages.bind(this); + this.renderLogListItem = this.renderLogListItem.bind(this); + this.renderLogList = this.renderLogList.bind(this); + this.onExpandAllChanged = this.onExpandAllChanged.bind(this); + this.toggleExpandAllPackets = this.toggleExpandAllPackets.bind(this); + this.toggleSignalPlot = this.toggleSignalPlot.bind(this); + } - this.state = { - length: 0, - expandedMessages: [], - messageHeights: [], - allPacketsExpanded: false - } - - this.renderLogListItemMessage = this.renderLogListItemMessage.bind(this); - this.addDisplayedMessages = this.addDisplayedMessages.bind(this); - this.renderLogListItem = this.renderLogListItem.bind(this); - this.renderLogList = this.renderLogList.bind(this); - this.onExpandAllChanged = this.onExpandAllChanged.bind(this); - this.toggleExpandAllPackets = this.toggleExpandAllPackets.bind(this); - this.toggleSignalPlot = this.toggleSignalPlot.bind(this); + componentWillReceiveProps(nextProps) { + if (nextProps.message && !this.props.message) { + this.addDisplayedMessages(); } + } - componentWillReceiveProps(nextProps) { - if(nextProps.message && !this.props.message) { - this.addDisplayedMessages(); - } - } + shouldComponentUpdate(nextProps, nextState) { + const curMessageLength = this.props.message + ? this.props.message.entries.length + : 0; + const nextMessageLength = nextProps.message + ? nextProps.message.entries.length + : 0; - shouldComponentUpdate(nextProps, nextState) { - const curMessageLength = this.props.message ? this.props.message.entries.length : 0; - const nextMessageLength = nextProps.message ? nextProps.message.entries.length : 0; + const shouldUpdate = + this.props.message !== nextProps.message || + nextMessageLength !== curMessageLength || + nextProps.messageIndex !== this.props.messageIndex || + nextProps.plottedSignals.length !== this.props.plottedSignals.length || + JSON.stringify(nextProps.segmentIndices) !== + JSON.stringify(this.props.segmentIndices) || + JSON.stringify(nextState) !== JSON.stringify(this.state) || + this.props.message !== nextProps.message || + (this.props.message !== undefined && + nextProps.message !== undefined && + this.props.message.frame !== undefined && + nextProps.message.frame !== undefined && + JSON.stringify(this.props.message.frame) !== + JSON.stringify(nextProps.message.frame)); - const shouldUpdate = this.props.message !== nextProps.message - || nextMessageLength !== curMessageLength - || nextProps.messageIndex !== this.props.messageIndex - || nextProps.plottedSignals.length !== this.props.plottedSignals.length - || JSON.stringify(nextProps.segmentIndices) !== JSON.stringify(this.props.segmentIndices) - || JSON.stringify(nextState) !== JSON.stringify(this.state) - || this.props.message !== nextProps.message - || (this.props.message !== undefined - && nextProps.message !== undefined - && this.props.message.frame !== undefined - && nextProps.message.frame !== undefined - && - ( - (JSON.stringify(this.props.message.frame) !== JSON.stringify(nextProps.message.frame)) - )); + return shouldUpdate; + } - return shouldUpdate; - } + addDisplayedMessages() { + const { length } = this.state; + const newLength = length + CanLog.ITEMS_PER_PAGE; - addDisplayedMessages() { - const {length} = this.state; - const newLength = length + CanLog.ITEMS_PER_PAGE; + this.setState({ length: newLength }); + } - this.setState({length: newLength}); - } + expandMessage(msg, msgIdx) { + this.setState({ + expandedMessages: this.state.expandedMessages.concat([msg.time]) + }); + this.props.onMessageExpanded(); + } - expandMessage(msg, msgIdx) { - this.setState({expandedMessages: this.state.expandedMessages.concat([msg.time])}) - this.props.onMessageExpanded(); - } - - collapseMessage(msg, msgIdx) { - this.setState({expandedMessages: this.state.expandedMessages - .filter((expMsgTime) => expMsgTime !== msg.time)}) - } - - isSignalPlotted(msgId, signalUid) { - const plottedSignal = this.props.plottedSignals.find((plot) => - plot.some((signal) => signal.messageId === msgId && signal.signalUid === signalUid)); - return plottedSignal !== undefined; - } - - signalValuePretty(signal, value) { - if(signal.isFloat) { - return value.toFixed(3); - } else return value; - } - - isMessageExpanded(msg) { - return this.state.expandedMessages.indexOf(msg.time) !== -1; - } - - toggleSignalPlot(msg, signalUid, plotted) { - if (!plotted) { - this.props.onSignalPlotPressed(msg, signalUid); - } else { - this.props.onSignalUnplotPressed(msg, signalUid); - } - } - - toggleExpandPacketSignals(msgEntry) { - if(!this.props.message.frame) { - return; - } - const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry); - - const msgHasSignals = Object.keys(this.props.message.frame.signals).length > 0; - if (msgIsExpanded && msgHasSignals) { - this.setState({expandedMessages: this.state.expandedMessages - .filter((expMsgTime) => expMsgTime !== msgEntry.time)}) - } else if (msgHasSignals) { - this.setState({expandedMessages: this.state.expandedMessages.concat([msgEntry.time])}) - this.props.onMessageExpanded(); - } else { return; } - } - - renderLogListItemSignals(msgEntry) { - const { message } = this.props; - return ( -
- { Object.entries(msgEntry.signals).map( - ([name, value]) => { - const signal = message.frame.signals[name]; - if (signal === undefined) { - // Signal removed? - return null; - } - const unit = signal.unit.length > 0 ? signal.unit : 'units'; - const isPlotted = this.isSignalPlotted(message.id, signal.uid); - const plottedButtonClass = isPlotted ? null : 'button--alpha'; - const plottedButtonText = isPlotted ? 'Hide Plot' : 'Show Plot'; - return ( -
-
- { name } -
-
- - ({ this.signalValuePretty(signal, value) } { unit }) - -
-
{ this.toggleSignalPlot(message.id, signal.uid, isPlotted) } }> - -
-
- ); - })} -
+ collapseMessage(msg, msgIdx) { + this.setState({ + expandedMessages: this.state.expandedMessages.filter( + expMsgTime => expMsgTime !== msg.time ) + }); + } + + isSignalPlotted(msgId, signalUid) { + const plottedSignal = this.props.plottedSignals.find(plot => + plot.some( + signal => signal.messageId === msgId && signal.signalUid === signalUid + ) + ); + return plottedSignal !== undefined; + } + + signalValuePretty(signal, value) { + if (signal.isFloat) { + return value.toFixed(3); + } else return value; + } + + isMessageExpanded(msg) { + return this.state.expandedMessages.indexOf(msg.time) !== -1; + } + + toggleSignalPlot(msg, signalUid, plotted) { + if (!plotted) { + this.props.onSignalPlotPressed(msg, signalUid); + } else { + this.props.onSignalUnplotPressed(msg, signalUid); } + } - renderLogListItemMessage(msgEntry, key) { - const { message } = this.props; - const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry); - const msgHasSignals = Object.keys(msgEntry.signals).length > 0; - const hasSignalsClass = msgHasSignals ? 'has-signals' : null; - const expandedClass = msgIsExpanded ? 'is-expanded' : null; - const row = ( -
-
{ this.toggleExpandPacketSignals(msgEntry) } }> -
- {(message.frame ? message.frame.name : null) || message.id} -
-
- [{msgEntry.relTime.toFixed(3)}] -
-
- {msgEntry.hexData} -
-
-
- { msgIsExpanded ? this.renderLogListItemSignals(msgEntry) : null} -
-
- ); - - return row; + toggleExpandPacketSignals(msgEntry) { + if (!this.props.message.frame) { + return; } + const msgIsExpanded = + this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry); - renderLogListItem(index, key) { - let offset = this.props.messageIndex; - if(offset === 0 && this.props.segmentIndices.length === 2) { - offset = this.props.segmentIndices[0]; - } - if((offset + index) < this.props.message.entries.length) { - return this.renderLogListItemMessage(this.props.message.entries[offset + index], key); - } else { - return null; - } - } - - renderLogList(items, ref) { - return ( -
-
-
Message
-
Time
-
Bytes
-
-
- {items} -
-
+ const msgHasSignals = + Object.keys(this.props.message.frame.signals).length > 0; + if (msgIsExpanded && msgHasSignals) { + this.setState({ + expandedMessages: this.state.expandedMessages.filter( + expMsgTime => expMsgTime !== msgEntry.time ) + }); + } else if (msgHasSignals) { + this.setState({ + expandedMessages: this.state.expandedMessages.concat([msgEntry.time]) + }); + this.props.onMessageExpanded(); + } else { + return; } + } - listLength() { - const {segmentIndices, messageIndex} = this.props; - if(messageIndex > 0) { - return this.props.message.entries.length - messageIndex; - } else if(segmentIndices.length === 2) { - return segmentIndices[1] - segmentIndices[0]; - } else if(this.props.message) { - return this.props.message.entries.length; - } else { - // no message yet - return 0; - } - } - - onExpandAllChanged(e) { - this.setState({allPacketsExpanded: e.target.checked}); - } - - toggleExpandAllPackets() { - this.setState({allPacketsExpanded: !this.state.allPacketsExpanded}); - } - - render() { - let expandAllText = this.state.allPacketsExpanded ? 'Collapse All' : 'Expand All'; - let expandAllClass = this.state.allPacketsExpanded ? null : 'button--alpha'; - return ( -
-
- Message Packets - -
-
- + renderLogListItemSignals(msgEntry) { + const { message } = this.props; + return ( +
+ {Object.entries(msgEntry.signals).map(([name, value]) => { + const signal = message.frame.signals[name]; + if (signal === undefined) { + // Signal removed? + return null; + } + const unit = signal.unit.length > 0 ? signal.unit : "units"; + const isPlotted = this.isSignalPlotted(message.id, signal.uid); + const plottedButtonClass = isPlotted ? null : "button--alpha"; + const plottedButtonText = isPlotted ? "Hide Plot" : "Show Plot"; + return ( +
+
+ {name} +
+
+ + ({this.signalValuePretty(signal, value)}{" "} + {unit}) + +
+
{ + this.toggleSignalPlot(message.id, signal.uid, isPlotted); + }} + > + +
+ ); + })} +
+ ); + } + + renderLogListItemMessage(msgEntry, key) { + const { message } = this.props; + const msgIsExpanded = + this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry); + const msgHasSignals = Object.keys(msgEntry.signals).length > 0; + const hasSignalsClass = msgHasSignals ? "has-signals" : null; + const expandedClass = msgIsExpanded ? "is-expanded" : null; + const row = ( +
+
{ + this.toggleExpandPacketSignals(msgEntry); + }} + > +
+ + {(message.frame ? message.frame.name : null) || message.id} +
- ); +
+ [{msgEntry.relTime.toFixed(3)}] +
+
+ {msgEntry.hexData} +
+
+
+ {msgIsExpanded ? this.renderLogListItemSignals(msgEntry) : null} +
+
+ ); + + return row; + } + + renderLogListItem(index, key) { + let offset = this.props.messageIndex; + if (offset === 0 && this.props.segmentIndices.length === 2) { + offset = this.props.segmentIndices[0]; } + if (offset + index < this.props.message.entries.length) { + return this.renderLogListItemMessage( + this.props.message.entries[offset + index], + key + ); + } else { + return null; + } + } + + renderLogList(items, ref) { + return ( +
+
+
Message
+
Time
+
Bytes
+
+
+ {items} +
+
+ ); + } + + listLength() { + const { segmentIndices, messageIndex } = this.props; + if (messageIndex > 0) { + return this.props.message.entries.length - messageIndex; + } else if (segmentIndices.length === 2) { + return segmentIndices[1] - segmentIndices[0]; + } else if (this.props.message) { + return this.props.message.entries.length; + } else { + // no message yet + return 0; + } + } + + onExpandAllChanged(e) { + this.setState({ allPacketsExpanded: e.target.checked }); + } + + toggleExpandAllPackets() { + this.setState({ allPacketsExpanded: !this.state.allPacketsExpanded }); + } + + render() { + let expandAllText = this.state.allPacketsExpanded + ? "Collapse All" + : "Expand All"; + let expandAllClass = this.state.allPacketsExpanded ? null : "button--alpha"; + return ( +
+
+ Message Packets + +
+
+ +
+
+ ); + } } diff --git a/src/components/DbcUpload.js b/src/components/DbcUpload.js index 9c656c4..ce057ad 100644 --- a/src/components/DbcUpload.js +++ b/src/components/DbcUpload.js @@ -1,40 +1,42 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; export default class DbcUpload extends Component { - static propTypes = { - onDbcLoaded: PropTypes.func + static propTypes = { + onDbcLoaded: PropTypes.func + }; + constructor(props) { + super(props); + this.state = { + dbcText: "" }; - constructor(props) { - super(props); - this.state = { - dbcText: '' - }; - this.onTextChanged = this.onTextChanged.bind(this); - } + this.onTextChanged = this.onTextChanged.bind(this); + } - onTextChanged(e) { - const dbcText = e.target.value; - this.setState({dbcText}) - this.props.onDbcLoaded('from paste', dbcText); - } + onTextChanged(e) { + const dbcText = e.target.value; + this.setState({ dbcText }); + this.props.onDbcLoaded("from paste", dbcText); + } - render() { - return ( -
-
- -