From e67ae198826aefc636ea44ebc55de5ee567352a5 Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Mon, 10 Nov 2014 15:56:25 -0800 Subject: [PATCH 1/3] Remove Connection and Device classes They are now functions that return instances of Adaptors and Drivers respectively. --- lib/adaptor.js | 28 ++++++++++++++- lib/api/routes.js | 8 ++--- lib/basestar.js | 11 +++--- lib/connection.js | 89 +++-------------------------------------------- lib/cylon.js | 2 +- lib/device.js | 84 ++------------------------------------------ lib/driver.js | 31 +++++++++++++---- lib/robot.js | 22 ++++++------ lib/test/ping.js | 2 +- 9 files changed, 80 insertions(+), 197 deletions(-) diff --git a/lib/adaptor.js b/lib/adaptor.js index 6706305..96e48f0 100644 --- a/lib/adaptor.js +++ b/lib/adaptor.js @@ -23,7 +23,33 @@ var Adaptor = module.exports = function Adaptor(opts) { opts = opts || {}; this.name = opts.name; - this.connection = opts.connection; + + // the Robot the adaptor belongs to + this.robot = opts.robot; + + // some default options + this.host = opts.host; + this.port = opts.port; + + // misc. details provided in args hash + this.details = {}; + + for (var opt in opts) { + if (['robot', 'name', 'adaptor'].indexOf(opt) < 0) { + this.details[opt] = opts[opt]; + } + } }; Utils.subclass(Adaptor, Basestar); + +// Public: Expresses the Connection in JSON format +// +// Returns an Object containing Connection data +Adaptor.prototype.toJSON = function() { + return { + name: this.name, + adaptor: this.constructor.name || this.name, + details: this.details + }; +}; diff --git a/lib/api/routes.js b/lib/api/routes.js index f4e100a..7c55bd8 100644 --- a/lib/api/routes.js +++ b/lib/api/routes.js @@ -42,7 +42,7 @@ var load = function load(req, res, next) { }; router.get("/", function(req, res) { - res.json({ MCP: Cylon }); + res.json({ MCP: Cylon.toJSON() }); }); router.get("/commands", function(req, res) { @@ -102,12 +102,12 @@ router.get("/robots/:robot/devices/:device/events/:event", load, function(req, r }); router.get("/robots/:robot/devices/:device/commands", load, function(req, res) { - res.json({ commands: Object.keys(req.device.driver.commands) }); + res.json({ commands: Object.keys(req.device.commands) }); }); router.all("/robots/:robot/devices/:device/commands/:command", load, function(req, res) { - var command = req.device.driver.commands[req.params.command]; - var result = command.apply(req.device.driver, req.commandParams); + var command = req.device.commands[req.params.command]; + var result = command.apply(req.device, req.commandParams); res.json({ result: result }); }); diff --git a/lib/basestar.js b/lib/basestar.js index 129aa74..6d8f83f 100644 --- a/lib/basestar.js +++ b/lib/basestar.js @@ -69,24 +69,23 @@ Basestar.prototype.defineEvent = function(opts) { // Public: Creates an event handler that proxies events from an adaptor's // 'connector' (reference to whatever module is actually talking to the hw) -// to the adaptor's associated connection. +// to the adaptor // // opts - hash of opts to be passed to defineEvent() // // Returns this.connector Basestar.prototype.defineAdaptorEvent = function(opts) { - return this._proxyEvents(opts, this.connector, this.connection); + return this._proxyEvents(opts, this.connector, this); }; -// Public: Creates an event handler that proxies events from an device's -// 'connector' (reference to whatever module is actually talking to the hw) -// to the device's associated connection. +// Public: Creates an event handler that proxies events from an driver's +// adaptor to the driver // // opts - hash of opts to be passed to defineEvent() // // Returns this.connection Basestar.prototype.defineDriverEvent = function(opts) { - return this._proxyEvents(opts, this.connection, this.device); + return this._proxyEvents(opts, this.adaptor, this); }; Basestar.prototype._proxyEvents = function(opts, source, target) { diff --git a/lib/connection.js b/lib/connection.js index 94291d6..33a4af2 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -8,18 +8,15 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter; - var Registry = require('./registry'), Config = require('./config'), - Logger = require('./logger'), - Utils = require('./utils'); + Logger = require('./logger'); var testMode = function() { return process.env.NODE_ENV === 'test' && Config.testMode; }; -// Public: Creates a new Connection +// Public: Creates a new Adaptor and returns it. // // opts - hash of acceptable params: // robot - Robot the Connection belongs to @@ -28,81 +25,17 @@ var testMode = function() { // port - string port to use for the Connection // // Returns the newly set-up connection -var Connection = module.exports = function Connection(opts) { - opts = opts || {}; - - this.connect = this.connect.bind(this); - - this.robot = opts.robot; - this.name = opts.name; - this.port = opts.port; - this.adaptor = this.initAdaptor(opts); - - this.details = {}; - - for (var opt in opts) { - if (['robot', 'name', 'adaptor', 'connection'].indexOf(opt) < 0) { - this.details[opt] = opts[opt]; - } - } -}; - -Utils.subclass(Connection, EventEmitter); - -// Public: Expresses the Connection in JSON format -// -// Returns an Object containing Connection data -Connection.prototype.toJSON = function() { - return { - name: this.name, - adaptor: this.adaptor.constructor.name || this.adaptor.name, - details: this.details - }; -}; - -// Public: Connect the adaptor's connection -// -// callback - callback function to run when the adaptor is connected -// -// Returns nothing -Connection.prototype.connect = function(callback) { - var msg = this._logstring("Connecting to"); - Logger.info(msg); - this.adaptor.connect(function() { - Utils.proxyFunctions(this.adaptor, this) - callback.apply(this, arguments); - }.bind(this)); -}; - -// Public: Disconnect the adaptor's connection -// -// callback - function to be triggered then the adaptor has disconnected -// -// Returns nothing -Connection.prototype.disconnect = function(callback) { - var msg = this._logstring("Disconnecting from"); - Logger.info(msg); - this.removeAllListeners(); - this.adaptor.disconnect(callback); -}; - -// Public: sets up adaptor with @robot -// -// opts - options for adaptor being initialized -// adaptor - name of the adaptor -// -// Returns the set-up adaptor -Connection.prototype.initAdaptor = function(opts) { +module.exports = function Connection(opts) { var module; + opts = opts || {}; + if (opts.module) { module = Registry.register(opts.module); } else { module = Registry.findByAdaptor(opts.adaptor); } - opts.connection = this; - if (!module) { Registry.register('cylon-' + opts.adaptor); module = Registry.findByAdaptor(opts.adaptor); @@ -124,15 +57,3 @@ Connection.prototype.initAdaptor = function(opts) { return adaptor; }; - -Connection.prototype._logstring = function _logstring(action) { - var msg = action + " '" + this.name + "'"; - - if (this.port != null) { - msg += " on port " + this.port; - } - - msg += "."; - - return msg; -}; diff --git a/lib/cylon.js b/lib/cylon.js index 9e7cb9a..33c9636 100644 --- a/lib/cylon.js +++ b/lib/cylon.js @@ -133,7 +133,7 @@ Cylon.toJSON = function() { var robots = []; for (var bot in this.robots) { - robots.push(this.robots[bot]); + robots.push(this.robots[bot].toJSON()); } return { diff --git a/lib/device.js b/lib/device.js index 2475f99..4d0f0dc 100644 --- a/lib/device.js +++ b/lib/device.js @@ -8,12 +8,8 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter; - var Registry = require('./registry'), - Config = require('./config'), - Logger = require('./logger'), - Utils = require('./utils'); + Config = require('./config'); var testMode = function() { return process.env.NODE_ENV === 'test' && Config.testMode; @@ -29,83 +25,7 @@ var testMode = function() { // driver - string name of the module the device driver logic lives in // // Returns a new Device -var Device = module.exports = function Device(opts) { - if (opts == null) { - opts = {}; - } - - this.halt = this.halt.bind(this); - this.start = this.start.bind(this); - - this.robot = opts.robot; - this.name = opts.name; - this.pin = opts.pin; - this.connection = opts.connection; - this.driver = this.initDriver(opts); - - this.details = {}; - - for (var opt in opts) { - if (['robot', 'name', 'connection', 'driver', 'device', 'adaptor'].indexOf(opt) < 0) { - this.details[opt] = opts[opt]; - } - } -}; - -Utils.subclass(Device, EventEmitter); - -// Public: Starts the device driver -// -// callback - callback function to be executed by the driver start -// -// Returns nothing -Device.prototype.start = function(callback) { - var msg = "Starting device '" + this.name + "'"; - - if (this.pin != null) { - msg += " on pin " + this.pin; - } - - msg += "."; - - Logger.info(msg); - this.driver.start(function() { - Utils.proxyFunctions(this.driver, this) - callback.apply(this, arguments); - }.bind(this)); -}; - -// Public: Halt the device driver -// -// callback - function to trigger when the device has been halted -// -// Returns nothing -Device.prototype.halt = function(callback) { - Logger.info("Halting device '" + this.name + "'."); - this.removeAllListeners(); - this.driver.halt(callback); -}; - -// Public: Expresses the Device in JSON format -// -// Returns an Object containing Connection data -Device.prototype.toJSON = function() { - return { - name: this.name, - driver: this.driver.constructor.name || this.driver.name, - connection: this.connection.name, - commands: Object.keys(this.driver.commands), - details: this.details - }; -}; - -// Public: sets up driver with @robot -// -// opts - object containing options when initializing driver -// driver - name of the driver to intt() -// -// Returns the set-up driver -Device.prototype.initDriver = function(opts) { +module.exports = function Device(opts) { var module; if (opts.module) { diff --git a/lib/driver.js b/lib/driver.js index 472f9f6..615df9d 100644 --- a/lib/driver.js +++ b/lib/driver.js @@ -23,21 +23,30 @@ var Driver = module.exports = function Driver(opts) { opts = opts || {}; this.name = opts.name; + this.robot = opts.robot - this.device = opts.device; - this.connection = opts.device.connection; - this.adaptor = this.connection.adaptor; - - this.interval = opts.interval || 10; + this.adaptor = opts.adaptor this.commands = {}; + + // some default options + this.pin = opts.pin; + this.interval = opts.interval || 10; + + this.details = {}; + + for (var opt in opts) { + if (['robot', 'name', 'adaptor', 'driver'].indexOf(opt) < 0) { + this.details[opt] = opts[opt]; + } + } }; Utils.subclass(Driver, Basestar); Driver.prototype.setupCommands = function(commands, proxy) { if (proxy == null) { - proxy = this.connection; + proxy = this.adaptor; } this.proxyMethods(commands, proxy, this); @@ -58,3 +67,13 @@ Driver.prototype.setupCommands = function(commands, proxy) { this.commands[snake_case] = this[command]; } } + +Driver.prototype.toJSON = function() { + return { + name: this.name, + driver: this.constructor.name || this.name, + connection: this.adaptor.name, + commands: Object.keys(this.commands), + details: this.details + }; +}; diff --git a/lib/robot.js b/lib/robot.js index a527847..168b06b 100644 --- a/lib/robot.js +++ b/lib/robot.js @@ -139,11 +139,11 @@ Robot.prototype.toJSON = function() { n; for (n in this.connections) { - connections.push(this.connections[n]); + connections.push(this.connections[n].toJSON()); } for (n in this.devices) { - devices.push(this.devices[n]); + devices.push(this.devices[n].toJSON()); } return { @@ -173,7 +173,7 @@ Robot.prototype.initConnections = function(opts) { Logger.warn("Connection names must be unique. Renaming '" + original + "' to '" + conn.name + "'"); } - this.connections[conn.name] = new Connection(conn); + this.connections[conn.name] = Connection(conn); }.bind(this); if (opts.connection == null && opts.connections == null) { @@ -229,15 +229,15 @@ Robot.prototype.initDevices = function(opts) { process.emit('SIGINT'); } - device.connection = this.connections[device.connection]; + device.adaptor = this.connections[device.connection]; } else { for (var conn in this.connections) { - device.connection = this.connections[conn]; + device.adaptor = this.connections[conn]; break; } } - this.devices[device.name] = new Device(device); + this.devices[device.name] = Device(device); }.bind(this); if (opts.device == null && opts.devices == null) { @@ -334,9 +334,8 @@ Robot.prototype.startConnections = function(callback) { Logger.info("Starting connections."); for (var n in this.connections) { - var connection = this.connections[n]; - this[n] = connection; - starters[n] = connection.connect; + this[n] = this.connections[n]; + starters[n] = this.connections[n].connect; } return Async.parallel(starters, callback); @@ -353,9 +352,8 @@ Robot.prototype.startDevices = function(callback) { Logger.info("Starting devices."); for (var n in this.devices) { - var device = this.devices[n]; - this[n] = device; - starters[n] = device.start; + this[n] = this.devices[n]; + starters[n] = this.devices[n].start; } return Async.parallel(starters, callback); diff --git a/lib/test/ping.js b/lib/test/ping.js index 47564e3..c9348a9 100644 --- a/lib/test/ping.js +++ b/lib/test/ping.js @@ -22,7 +22,7 @@ var Ping = module.exports = function Ping() { Utils.subclass(Ping, Driver); Ping.prototype.ping = function() { - this.device.emit('ping', 'ping'); + this.emit('ping', 'ping'); return "pong"; }; From ce87a355f0523b1d3a5d3f0e19ad6d761ad0f7a1 Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Tue, 11 Nov 2014 11:41:18 -0800 Subject: [PATCH 2/3] Modifications, fix test suite --- lib/connection.js | 6 ++ lib/device.js | 6 ++ lib/robot.js | 2 +- spec/lib/adaptor.spec.js | 9 +- spec/lib/basestar.spec.js | 16 ++-- spec/lib/connection.spec.js | 120 ++------------------------ spec/lib/cylon.spec.js | 7 +- spec/lib/device.spec.js | 162 ++---------------------------------- spec/lib/driver.spec.js | 27 ++---- spec/lib/robot.spec.js | 22 ++--- 10 files changed, 54 insertions(+), 323 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 33a4af2..94a454b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -43,6 +43,12 @@ module.exports = function Connection(opts) { var adaptor = module.adaptor(opts); + for (var prop in adaptor) { + if (typeof adaptor[prop] === 'function') { + adaptor[prop] = adaptor[prop].bind(adaptor); + } + } + if (testMode()) { var testAdaptor = Registry.findByAdaptor('test').adaptor(opts); diff --git a/lib/device.js b/lib/device.js index 4d0f0dc..919080f 100644 --- a/lib/device.js +++ b/lib/device.js @@ -43,6 +43,12 @@ module.exports = function Device(opts) { var driver = module.driver(opts); + for (var prop in driver) { + if (typeof driver[prop] === 'function') { + driver[prop] = driver[prop].bind(driver); + } + } + if (testMode()) { var testDriver = Registry.findByDriver('test').driver(opts); diff --git a/lib/robot.js b/lib/robot.js index 168b06b..193fed4 100644 --- a/lib/robot.js +++ b/lib/robot.js @@ -353,7 +353,7 @@ Robot.prototype.startDevices = function(callback) { for (var n in this.devices) { this[n] = this.devices[n]; - starters[n] = this.devices[n].start; + starters[n] = this.devices[n].start.bind(this.devices[n]); } return Async.parallel(starters, callback); diff --git a/spec/lib/adaptor.spec.js b/spec/lib/adaptor.spec.js index 7d01bb3..821af9a 100644 --- a/spec/lib/adaptor.spec.js +++ b/spec/lib/adaptor.spec.js @@ -1,22 +1,15 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter; - var Adaptor = source("adaptor"), Logger = source('logger'), Utils = source('utils'); describe("Adaptor", function() { - var connection = new EventEmitter; - var adaptor = new Adaptor({ name: 'adaptor', connection: connection }); + var adaptor = new Adaptor({ name: 'adaptor' }); describe("#constructor", function() { it("sets @name to the provided name", function() { expect(adaptor.name).to.be.eql('adaptor'); }); - - it("sets @connection to the provided connection", function() { - expect(adaptor.connection).to.be.eql(connection); - }); }); }); diff --git a/spec/lib/basestar.spec.js b/spec/lib/basestar.spec.js index 0a42313..a2cb4cd 100644 --- a/spec/lib/basestar.spec.js +++ b/spec/lib/basestar.spec.js @@ -107,13 +107,12 @@ describe('Basestar', function() { beforeEach(function() { basestar = new Basestar(); basestar.connector = new EventEmitter(); - basestar.connection = new EventEmitter(); }); it("proxies events between the connector and connection", function() { var eventSpy = spy(); - basestar.connection.on('testevent', eventSpy); + basestar.on('testevent', eventSpy); basestar.defineAdaptorEvent({ eventName: "testevent" }); basestar.connector.emit("testevent", "data"); @@ -124,7 +123,7 @@ describe('Basestar', function() { it("uses it as the eventName", function() { var eventSpy = spy(); - basestar.connection.on('testevent', eventSpy); + basestar.on('testevent', eventSpy); basestar.defineAdaptorEvent("testevent"); basestar.connector.emit("testevent", "data"); @@ -138,17 +137,16 @@ describe('Basestar', function() { beforeEach(function() { basestar = new Basestar(); - basestar.connection = new EventEmitter(); - basestar.device = new EventEmitter(); + basestar.adaptor = new EventEmitter(); }); it("proxies events between the connection and device", function() { var eventSpy = spy(); - basestar.device.on('testevent', eventSpy); + basestar.on('testevent', eventSpy); basestar.defineDriverEvent({ eventName: "testevent" }); - basestar.connection.emit("testevent", "data"); + basestar.adaptor.emit("testevent", "data"); assert(eventSpy.calledWith('data')); }); @@ -156,10 +154,10 @@ describe('Basestar', function() { it("uses it as the eventName", function() { var eventSpy = spy(); - basestar.device.on('testevent', eventSpy); + basestar.on('testevent', eventSpy); basestar.defineDriverEvent("testevent"); - basestar.connection.emit("testevent", "data"); + basestar.adaptor.emit("testevent", "data"); assert(eventSpy.calledWith('data')); }); }); diff --git a/spec/lib/connection.spec.js b/spec/lib/connection.spec.js index 9555e0b..5c5a2dc 100644 --- a/spec/lib/connection.spec.js +++ b/spec/lib/connection.spec.js @@ -1,123 +1,15 @@ "use strict"; var Loopback = source('test/loopback'), - Robot = source("robot"), - Logger = source('logger'), - Utils = source('utils'); + Connection = source("connection"); describe("Connection", function() { - var robot, connection; - - beforeEach(function() { - robot = new Robot({ - name: "Robby", - connection: { name: 'loopback', adaptor: 'loopback', port: "/dev/null" } + it("returns a Adaptor instance", function() { + var conn = Connection({ + name: 'test', + adaptor: 'loopback' }); - connection = robot.connections.loopback; - }); - - - describe("#constructor", function() { - it("sets @robot to the passed robot", function() { - expect(connection.robot).to.be.eql(robot); - }); - - it("sets @name to the passed name", function() { - expect(connection.name).to.be.eql('loopback'); - }); - - it("sets @port to the passed port", function() { - expect(connection.port.toString()).to.be.eql("/dev/null"); - }); - - }); - - describe("#toJSON", function() { - var json; - - beforeEach(function() { - json = connection.toJSON(); - }); - - it("returns an object", function() { - expect(json).to.be.an('object'); - }); - - it("contains the connection's name", function() { - expect(json.name).to.be.eql("loopback"); - }); - - it("contains the connection's port", function() { - expect(json.details.port).to.be.eql("/dev/null"); - }); - - it("contains the connection's adaptor name", function() { - expect(json.adaptor).to.be.eql("Loopback"); - }); - }); - - describe("#connect", function() { - var callback; - - beforeEach(function() { - callback = spy(); - Loopback.prototype.test = function() { return "Test" }; - - stub(Logger, 'info').returns(true); - connection.adaptor.connect = stub(); - - connection.connect(callback); - }); - - afterEach(function() { - Logger.info.restore(); - delete Loopback.prototype.test; - }) - - it("logs that it's connecting the device", function() { - var message = "Connecting to 'loopback' on port /dev/null."; - expect(Logger.info).to.be.calledWith(message); - }); - - it("triggers the provided callback after the adaptor finishes connecting", function() { - expect(callback).to.not.be.called; - connection.adaptor.connect.yield(); - expect(callback).to.be.called; - }); - - it("proxies methods from the Adaptor", function() { - connection.adaptor.connect.yield(); - expect(connection.test()).to.be.eql("Test"); - }) - }); - - describe("#disconnect", function() { - beforeEach(function() { - stub(Logger, 'info').returns(true); - stub(connection, 'removeAllListeners'); - - connection.adaptor.disconnect = stub().returns(true); - - connection.disconnect(); - }); - - afterEach(function() { - connection.removeAllListeners.restore(); - Logger.info.restore(); - }); - - it("logs that it's disconnecting from the device", function() { - var message = "Disconnecting from 'loopback' on port /dev/null."; - expect(Logger.info).to.be.calledWith(message); - }); - - it("tells the adaptor to disconnect", function() { - expect(connection.adaptor.disconnect).to.be.called; - }); - - it("disconnects all event listeners", function() { - expect(connection.removeAllListeners).to.be.called; - }); + expect(conn).to.be.an.instanceOf(Loopback); }); }); diff --git a/spec/lib/cylon.spec.js b/spec/lib/cylon.spec.js index e129903..2a86a3f 100644 --- a/spec/lib/cylon.spec.js +++ b/spec/lib/cylon.spec.js @@ -1,6 +1,7 @@ "use strict"; var Cylon = source("cylon"), + Robot = source("robot"), Utils = source('utils'); var API = source('api'), @@ -164,8 +165,8 @@ describe("Cylon", function() { var json, bot1, bot2, echo; beforeEach(function() { - bot1 = {}; - bot2 = {}; + bot1 = new Robot(); + bot2 = new Robot(); Cylon.robots = { 'bot1': bot1, 'bot2': bot2 }; Cylon.commands.echo = echo = function(arg) { return arg; }; @@ -174,7 +175,7 @@ describe("Cylon", function() { }); it("contains all robots the MCP knows about", function() { - expect(json.robots).to.be.eql([bot1, bot2]); + expect(json.robots).to.be.eql([bot1.toJSON(), bot2.toJSON()]); }); it("contains an array of MCP commands", function() { diff --git a/spec/lib/device.spec.js b/spec/lib/device.spec.js index 3f1b2c5..cccf9c9 100644 --- a/spec/lib/device.spec.js +++ b/spec/lib/device.spec.js @@ -1,165 +1,15 @@ "use strict"; var Ping = source('test/ping'), - Device = source("device"), - Robot = source("robot"), - Logger = source('logger'), - Utils = source('utils'); + Device = source("device"); describe("Device", function() { - var robot, connection, driver, device, initDriver; - - beforeEach(function() { - robot = new Robot({ - name: "TestingBot", - connection: { name: 'loopback', adaptor: 'loopback' } + it("returns a Driver instance", function() { + var driver = Device({ + name: 'test', + driver: 'ping' }); - connection = robot.connections.loopback; - - driver = new Ping({ - name: 'driver', - device: { connection: connection, pin: 13 }, - connection: connection - }); - - driver.cmd = spy(); - driver.string = ""; - driver.robot = spy(); - - initDriver = stub(Device.prototype, 'initDriver').returns(driver); - - device = new Device({ - robot: robot, - name: "ping", - pin: 13, - connection: connection - }); - }); - - afterEach(function() { - initDriver.restore(); - }); - - describe("constructor", function() { - it("sets @robot to the passed robot", function() { - expect(device.robot).to.be.eql(robot); - }); - - it("sets @name to the passed name", function() { - expect(device.name).to.be.eql('ping'); - }); - - it("sets @pin to the passed pin", function() { - expect(device.pin).to.be.eql(13); - }); - - it("sets @connection to the name of the specified connection on the Robot", function() { - expect(device.connection).to.be.eql(connection); - }); - - it("asks the Robot to init a driver", function() { - expect(device.driver).to.be.eql(driver); - expect(initDriver).to.be.calledOnce - }); - - it("does not override existing functions", function() { - expect(device.robot).to.not.be.a('function'); - }); - }); - - describe("#start", function() { - var callback; - - beforeEach(function() { - callback = spy(); - - stub(Logger, 'info'); - driver.start = stub(); - - device.start(callback); - }); - - afterEach(function() { - Logger.info.restore(); - }); - - it("logs that it's starting the device", function() { - var message = "Starting device 'ping' on pin 13."; - expect(Logger.info).to.be.calledWith(message); - }); - - it("triggers the provided callback after the adaptor finishes connecting", function() { - expect(callback).to.not.be.called; - driver.start.yield(); - expect(callback).to.be.called; - }); - - it("binds driver methods to the device", function() { - driver.start.yield(); - device.cmd(); - expect(driver.cmd).to.be.called; - }); - }); - - describe("#halt", function() { - beforeEach(function() { - stub(Logger, 'info'); - - driver.halt = stub().returns(true); - device.removeAllListeners = spy(); - - device.halt(); - }); - - afterEach(function() { - Logger.info.restore(); - }); - - it("halts the driver", function() { - expect(driver.halt).to.be.called; - }); - - it("logs that it's halt the device", function() { - var message = "Halting device 'ping'."; - - expect(Logger.info).to.be.calledWith(message); - }); - - it("disconnects all event listeners", function() { - expect(device.removeAllListeners).to.be.called; - }); - }); - - describe("#toJSON", function() { - var json; - - beforeEach(function() { - json = device.toJSON(); - }); - - it("returns an object", function() { - expect(json).to.be.a('object'); - }); - - it("contains the device's name", function() { - expect(json.name).to.be.eql(device.name); - }); - - it("contains the device's pin", function() { - expect(json.details.pin).to.be.eql(device.pin); - }); - - it("contains the device's driver name", function() { - expect(json.driver).to.be.eql('Ping'); - }); - - it("contains the device's connection name", function() { - expect(json.connection).to.be.eql('loopback'); - }); - - it("contains the device's driver commands", function() { - expect(json.commands).to.be.eql(Object.keys(driver.commands)); - }); + expect(driver).to.be.an.instanceOf(Ping); }); }); diff --git a/spec/lib/driver.spec.js b/spec/lib/driver.spec.js index 8df2c4e..3eaa0c3 100644 --- a/spec/lib/driver.spec.js +++ b/spec/lib/driver.spec.js @@ -7,22 +7,16 @@ var Driver = source("driver"), Utils = source('utils'); describe("Driver", function() { - var connection, device, driver; + var adaptor, device, driver; beforeEach(function() { - connection = { + adaptor = { adaptor: 'adaptor' }; - device = { - connection: connection, - emit: spy() - }; - driver = new Driver({ name: 'driver', - device: device, - connection: connection + adaptor: adaptor, }); }); @@ -31,16 +25,8 @@ describe("Driver", function() { expect(driver.name).to.be.eql('driver'); }); - it("sets @device to the provided device", function() { - expect(driver.device).to.be.eql(device); - }); - - it("sets @connection to the provided device's connection", function() { - expect(driver.connection).to.be.eql(device.connection); - }); - - it("sets @connection to the device's connection adaptor", function() { - expect(driver.adaptor).to.be.eql(device.connection.adaptor); + it("sets @adaptor to the provided adaptor", function() { + expect(driver.adaptor).to.be.eql(adaptor); }); it("sets @commands to an empty object by default", function() { @@ -52,9 +38,8 @@ describe("Driver", function() { driver = new Driver({ name: 'driver', - device: device, + adaptor: adaptor, interval: 2000, - connection: { } }); expect(driver.interval).to.be.eql(2000); diff --git a/spec/lib/robot.spec.js b/spec/lib/robot.spec.js index 24e5814..d1498cc 100644 --- a/spec/lib/robot.spec.js +++ b/spec/lib/robot.spec.js @@ -1,7 +1,7 @@ "use strict"; -var Device = source('device'), - Connection = source('connection'), +var Driver = source('driver'), + Adaptor = source('adaptor'), Robot = source("robot"), Utils = source('utils'); @@ -217,11 +217,11 @@ describe("Robot", function() { }); it("contains the robot's devices", function() { - expect(json.devices).to.eql([bot.devices.ping]); + expect(json.devices).to.eql([bot.devices.ping.toJSON()]); }); it("contains the robot's connections", function() { - expect(json.connections).to.eql([bot.connections.loopback]); + expect(json.connections).to.eql([bot.connections.loopback.toJSON()]); }); }); @@ -243,7 +243,7 @@ describe("Robot", function() { it("instantiates a new connection with the provided object", function() { var connection = { name: 'loopback', adaptor: 'loopback' }; bot.initConnections({ connection: connection }); - expect(bot.connections['loopback']).to.be.instanceOf(Connection); + expect(bot.connections['loopback']).to.be.instanceOf(Adaptor); }); }); @@ -251,7 +251,7 @@ describe("Robot", function() { it("instantiates a new connection with each of the provided objects", function() { var connections = [{ name: 'loopback', adaptor: 'loopback' }] bot.initConnections({ connections: connections }); - expect(bot.connections['loopback']).to.be.instanceOf(Connection); + expect(bot.connections['loopback']).to.be.instanceOf(Adaptor); }); it("avoids name collisions", function() { @@ -286,20 +286,20 @@ describe("Robot", function() { }); }); - context("when passed a devicw object", function() { - it("instantiates a new device with the provided object", function() { + context("when passed a device object", function() { + it("instantiates a new driver with the provided object", function() { var device = { name: 'ping', driver: 'ping' }; bot.initDevices({ device: device }); - expect(bot.devices['ping']).to.be.instanceOf(Device); + expect(bot.devices['ping']).to.be.instanceOf(Driver); }); }); context("when passed an array of device objects", function() { - it("instantiates a new device with each of the provided objects", function() { + it("instantiates a new driver with each of the provided objects", function() { var devices = [{ name: 'ping', driver: 'ping' }] bot.initDevices({ devices: devices}); - expect(bot.devices['ping']).to.be.instanceOf(Device); + expect(bot.devices['ping']).to.be.instanceOf(Driver); }); it("avoids name collisions collisions", function() { From 39f9c8b637ee9e96773e658e608f8e438a9a48b2 Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Tue, 11 Nov 2014 13:41:09 -0800 Subject: [PATCH 3/3] Fix up API errors --- lib/connection.js | 4 ++++ lib/device.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/connection.js b/lib/connection.js index 94a454b..4ac3426 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -44,6 +44,10 @@ module.exports = function Connection(opts) { var adaptor = module.adaptor(opts); for (var prop in adaptor) { + if (~['constructor'].indexOf(prop)) { + continue; + } + if (typeof adaptor[prop] === 'function') { adaptor[prop] = adaptor[prop].bind(adaptor); } diff --git a/lib/device.js b/lib/device.js index 919080f..5f0a95e 100644 --- a/lib/device.js +++ b/lib/device.js @@ -44,6 +44,10 @@ module.exports = function Device(opts) { var driver = module.driver(opts); for (var prop in driver) { + if (~['constructor'].indexOf(prop)) { + continue; + } + if (typeof driver[prop] === 'function') { driver[prop] = driver[prop].bind(driver); }