johnny-five-electron
Version:
Temporary fork to support Electron (to be deprecated)
602 lines (445 loc) • 12.6 kB
JavaScript
var five = require("../lib/johnny-five.js"),
MockFirmata = require("./util/mock-firmata"),
sinon = require("sinon"),
events = require("events"),
Board = five.Board,
Pin = five.Pin;
function newBoard() {
var io = new MockFirmata();
var board = new Board({
io: io,
debug: false,
repl: false
});
io.emit("connect");
io.emit("ready");
return board;
}
function restore(target) {
for (var prop in target) {
if (Array.isArray(target[prop])) {
continue;
}
if (target[prop] != null && typeof target[prop].restore === "function") {
target[prop].restore();
}
if (typeof target[prop] === "object") {
restore(target[prop]);
}
}
}
exports["Pin"] = {
setUp: function(done) {
this.spies = [
"analogWrite", "digitalWrite",
"analogRead", "digitalRead",
"queryPinState"
];
this.spies.forEach(function(method) {
this[method] = sinon.spy(MockFirmata.prototype, method);
}.bind(this));
this.board = newBoard();
this.clock = sinon.useFakeTimers();
this.digital = new Pin({
pin: 11,
board: this.board
});
this.analog = new Pin({
pin: "A1",
board: this.board
});
this.dtoa = new Pin({
pin: 14,
board: this.board
});
this.proto = [{
name: "query"
}, {
name: "high"
}, {
name: "low"
}, {
name: "read"
}, {
name: "write"
}];
this.instance = [{
name: "id"
}, {
name: "pin"
}, {
name: "type"
}, {
name: "addr"
}, {
name: "value"
}, {
name: "mode"
}];
done();
},
tearDown: function(done) {
Board.purge();
restore(this);
done();
},
shape: function(test) {
test.expect(this.proto.length + this.instance.length);
this.proto.forEach(function(method) {
test.equal(typeof this.digital[method.name], "function");
}, this);
this.instance.forEach(function(property) {
test.notEqual(typeof this.digital[property.name], "undefined");
}, this);
test.done();
},
emitter: function(test) {
test.expect(1);
test.ok(this.digital instanceof events.EventEmitter);
test.done();
},
addr: function(test) {
test.expect(2);
test.equal(this.digital.addr, 11, "11 -> 11");
test.equal(this.analog.addr, 1, "A1 -> 1");
test.done();
},
digital: function(test) {
test.expect(2);
test.equal(this.digital.type, "digital");
test.equal(this.digital.mode, 1);
test.done();
},
analog: function(test) {
test.expect(2);
test.equal(this.analog.type, "analog");
test.equal(this.analog.mode, 2);
test.done();
},
dtoa: function(test) {
test.expect(2);
test.equal(this.dtoa.type, "digital");
test.equal(this.dtoa.mode, 1);
test.done();
},
high: function(test) {
test.expect(2);
this.digital.high();
test.ok(this.digitalWrite.calledWith(11, 1));
this.analog.high();
test.ok(this.analogWrite.calledWith(1, 255));
test.done();
},
low: function(test) {
test.expect(2);
this.digital.low();
test.ok(this.digitalWrite.calledWith(11, 0));
this.analog.low();
test.ok(this.analogWrite.calledWith(1, 0));
test.done();
},
write: function(test) {
test.expect(8);
this.digital.write(1);
test.ok(this.digitalWrite.calledWith(11, 1));
test.equal(this.digital.value, 1);
this.digital.write(0);
test.ok(this.digitalWrite.calledWith(11, 0));
test.equal(this.digital.value, 0);
this.analog.write(1023);
test.ok(this.analogWrite.calledWith(1, 1023));
test.equal(this.analog.value, 1023);
this.analog.write(0);
test.ok(this.analogWrite.calledWith(1, 0));
test.equal(this.analog.value, 0);
test.done();
},
readDigital: function(test) {
test.expect(22);
this.digitalRead.reset();
var pin = new Pin({
pin: 8,
mode: Pin.INPUT,
board: newBoard()
});
var readHandler = this.digitalRead.args[0][1];
var spy = sinon.spy();
pin.read(spy);
this.clock.tick(25);
test.ok(spy.called);
spy.reset();
for (var i = 0; i < 10; i++) {
readHandler(1);
}
this.clock.tick(200);
test.equal(spy.callCount, 10);
spy.args.forEach(function(args) {
test.equal(args[0], null);
test.equal(args[1], 1);
});
test.done();
},
readDigitalUpdateMode: function(test) {
test.expect(3);
var pin = new Pin({
pin: 11,
mode: Pin.OUTPUT,
board: newBoard()
});
var spy = sinon.spy();
test.equal(pin.mode, 1);
pin.read(spy);
test.equal(pin.mode, 0);
this.clock.tick(200);
test.equal(spy.callCount, 10);
test.done();
},
readAnalog: function(test) {
test.expect(22);
this.analogRead.reset();
var pin = new Pin({
pin: "A0",
mode: Pin.ANALOG,
board: newBoard()
});
var readHandler = this.analogRead.args[0][1];
var spy = sinon.spy();
pin.read(spy);
this.clock.tick(25);
test.ok(spy.called);
spy.reset();
for (var i = 0; i < 10; i++) {
readHandler(1023);
}
this.clock.tick(200);
test.equal(spy.callCount, 10);
spy.args.forEach(function(args) {
test.equal(args[0], null);
test.equal(args[1], 1023);
});
test.done();
},
readAnalogUpdateMode: function(test) {
/*
An analog pin will only be type="analog"
*/
test.expect(3);
var pin = new Pin({
pin: "A0",
board: newBoard()
});
var spy = sinon.spy();
test.equal(pin.mode, 2);
pin.read(spy);
test.equal(pin.mode, 2);
this.clock.tick(200);
test.equal(spy.callCount, 10);
test.done();
},
query: function(test) {
test.expect(2);
this.analog.query(function() {});
this.digital.query(function() {});
// A1 => 15
test.ok(this.queryPinState.calledWith(15));
// 11 => 11
test.ok(this.queryPinState.calledWith(11));
test.done();
}
};
exports["Pin.Array"] = {
setUp: function(done) {
this.board = newBoard();
Pin.purge();
this.digital = new Pin({
pin: 11,
board: this.board
});
this.analog = new Pin({
pin: "A1",
board: this.board
});
this.dtoa = new Pin({
pin: 14,
board: this.board
});
this.spies = [
"write", "low"
];
this.spies.forEach(function(method) {
this[method] = sinon.spy(Pin.prototype, method);
}.bind(this));
done();
},
tearDown: function(done) {
Board.purge();
restore(this);
done();
},
initFromPinNumbers: function(test) {
test.expect(1);
var pins = new Pin.Array([3, 7, 9]);
test.equal(pins.length, 3);
test.done();
},
initFromPins: function(test) {
test.expect(1);
var pins = new Pin.Array([
this.digital, this.analog, this.dtoa
]);
test.equal(pins.length, 3);
test.done();
},
callForwarding: function(test) {
test.expect(3);
var pins = new Pin.Array([3, 7, 9]);
pins.write(1);
test.equal(this.write.callCount, pins.length);
test.equal(this.write.getCall(0).args[0], 1);
pins.low();
test.equal(this.low.callCount, pins.length);
test.done();
},
};
exports["Pin.isPrefixed"] = {
is: function(test) {
test.expect(2);
test.ok(Pin.isPrefixed("A0", ["A", "I"]));
test.ok(Pin.isPrefixed("I0", ["A", "I"]));
test.done();
},
not: function(test) {
test.expect(2);
test.ok(!Pin.isPrefixed(9, ["A", "I"]));
test.ok(!Pin.isPrefixed("O0", ["A", "I"]));
test.done();
}
};
exports["Pin.isAnalog"] = {
is: function(test) {
test.expect(6);
test.ok(Pin.isAnalog("A0"));
test.ok(Pin.isAnalog("I0"));
test.ok(Pin.isAnalog({
pin: "A0"
}));
test.ok(Pin.isAnalog({
pin: "I0"
}));
test.ok(Pin.isAnalog({
addr: "A0"
}));
test.ok(Pin.isAnalog({
addr: "I0"
}));
test.done();
},
not: function(test) {
test.expect(2);
test.ok(!Pin.isAnalog(9));
test.ok(!Pin.isAnalog("O0"));
test.done();
}
};
exports["PinShape"] = {
setUp: function(done) {
// This will put a board in the cache
newBoard();
// Pins to test
// default Pin instances passing only the pin number
this.dig2Def = new Pin(2);
this.dig19Def = new Pin(19);
this.ana0Def = new Pin("A0");
this.ana1Def = new Pin("A1");
//CODE
done();
},
tearDown: function(done) {
Board.purge();
done();
},
defaultPinShape: function(test) {
test.expect(23);
// Check for cases that should throw an exception
test.throws(function () {
test.rawDef = new Pin();
}, function(msg) {return msg.toString() === "Error: Pins must have a pin number"; });
test.throws(function () {
test.rawDef = new Pin({});
}, function(msg) {return msg.toString() === "Error: Pins must have a pin number"; });
test.throws(function () {
test.rawDef = new Pin({ id: "No Pin number"});
}, function(msg) {return msg.toString() === "Error: Pins must have a pin number"; });
// default digital pin : new Pin(2)
test.equal(this.dig2Def.mode, 1, "pin(2) mode --> 1 (output)");
test.equal(typeof this.dig2Def.id, "string", "pin(2) id --> a string");
test.equal(this.dig2Def.type, "digital", "pin(2) type");
test.equal(this.dig2Def.pin, 2, "pin(2) pin number");
test.equal(this.dig2Def.addr, 2, "pin(2) address");
// default DToA pin : new Pin(19)
test.equal(this.dig19Def.mode, 1, "pin(19) mode --> 1 (output)");
test.equal(typeof this.dig19Def.id, "string", "pin(19) id --> a string");
test.equal(this.dig19Def.type, "digital", "pin(19) type");
test.equal(this.dig19Def.pin, 5, "pin(19) pin number");
test.equal(this.dig19Def.addr, 19, "pin(19) address");
// default analog pin : new Pin("A0")
test.equal(this.ana0Def.mode, 2, "pin('A0') mode --> 2 (analog)");
test.equal(typeof this.ana0Def.id, "string", "pin('A0') id --> a string");
test.equal(this.ana0Def.type, "analog", "pin('A0') type");
test.equal(this.ana0Def.pin, 0, "pin('A0') pin");
test.equal(this.ana0Def.addr, 0, "pin('A0') address");
// default analog pin : new Pin("A1")
test.equal(this.ana1Def.mode, 2, "pin('A1') mode --> 2 (analog)");
test.equal(typeof this.ana1Def.id, "string", "pin('A1') id --> a string");
test.equal(this.ana1Def.type, "analog", "pin('A1') type");
test.equal(this.ana1Def.pin, 1, "pin('A1') pin");
test.equal(this.ana1Def.addr, 1, "pin('A1') address");
test.done();
}
};
exports["PinMode"] = {
setUp: function(done) {
newBoard();
// Pins to test
this.modeD0 = new Pin({ pin: 4, mode: 0});
this.modeD1 = new Pin({ pin: 7, mode: 1});
this.modeD2 = new Pin({ pin: 14, mode: 2});
this.modeD3 = new Pin({ pin: 3, mode: 3});
this.modeD4 = new Pin({ pin: 5, mode: 4});
this.modeA0 = new Pin({ pin: 15, mode: 0});
this.modeA1 = new Pin({ pin: 16, mode: 1});
this.modeA2 = new Pin({ pin: 17, mode: 2});
this.modeA3 = new Pin({ pin: 18, mode: 3});
this.modeA4 = new Pin({ pin: 19, mode: 4});
done();
},
tearDown: function(done) {
Board.purge();
done();
},
specifiedMode: function(test) {
test.expect(15);
test.equal(this.modeD0.mode, 0, "mode 0 (input) specified");
test.equal(this.modeD1.mode, 1, "mode 1 (output) specified");
test.equal(this.modeD2.mode, 2, "mode 2 (analog) specified");
test.equal(this.modeD3.mode, 3, "mode 3 (pwm) specified");
test.equal(this.modeD4.mode, 4, "mode 4 (servo) specified");
test.equal(this.modeA0.mode, 0, "mode 0 (input) specified");
test.equal(this.modeA1.mode, 1, "mode 1 (input) specified");
test.equal(this.modeA2.mode, 2, "mode 2 (analog) specified");
test.equal(this.modeA3.mode, 3, "mode 3 (pwm) specified");
test.equal(this.modeA4.mode, 4, "mode 4 (servo) specified");
// Double check that the provided class constants exist and match
test.equal(this.modeD0.mode, Pin.INPUT, "mode 0 (input) specified");
test.equal(this.modeD1.mode, Pin.OUTPUT, "mode 1 (output) specified");
test.equal(this.modeD2.mode, Pin.ANALOG, "mode 2 (analog) specified");
test.equal(this.modeD3.mode, Pin.PWM, "mode 3 (pwm) specified");
test.equal(this.modeD4.mode, Pin.SERVO, "mode 4 (servo) specified");
test.done();
}
};
// * Pin.INPUT = 0x00
// * Pin.OUTPUT = 0x01
// * Pin.ANALOG = 0x02
// * Pin.PWM = 0x03
// * Pin.SERVO = 0x04