cylon/spec/lib/digital-pin.spec.js

529 lines
13 KiB
JavaScript
Raw Normal View History

2014-12-15 07:21:28 +08:00
/* jshint expr:true */
"use strict";
2014-01-03 08:47:40 +08:00
2014-12-15 07:21:28 +08:00
var fs = require("fs");
2014-01-03 08:47:40 +08:00
2014-12-15 07:21:28 +08:00
var DigitalPin = source("io/digital-pin"),
Utils = source("utils");
describe("Cylon.IO.DigitalPin", function() {
2014-12-16 01:37:52 +08:00
var pin = new DigitalPin({ pin: "4", mode: "w" });
2014-02-28 06:52:25 +08:00
describe("constructor", function() {
it("sets @pinNum to the pin number passed in opts", function() {
2014-12-15 07:21:28 +08:00
expect(pin.pinNum).to.be.eql("4");
});
2014-02-28 06:52:25 +08:00
it("sets @status to 'low' by default", function() {
expect(pin.status).to.be.eql("low");
2014-01-03 08:47:40 +08:00
});
2014-02-28 06:52:25 +08:00
it("sets @ready to false by default", function() {
expect(pin.ready).to.be.false;
2014-01-03 08:47:40 +08:00
});
2014-02-28 06:52:25 +08:00
it("sets @mode to the mode passed in opts", function() {
expect(pin.mode).to.be.eql("w");
2014-01-03 08:47:40 +08:00
});
2014-02-28 06:52:25 +08:00
});
describe("#connect", function() {
var path = "/sys/class/gpio/gpio4";
2014-02-28 06:52:25 +08:00
context("if the GPIO file for the pin exists", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "exists").callsArgWith(1, true);
stub(pin, "_openPin");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.exists.restore();
pin._openPin.restore();
});
it("opens the pin", function() {
pin.connect(pin.mode);
expect(fs.exists).to.be.calledWith(path);
expect(pin._openPin).to.be.called;
});
2014-01-03 08:47:40 +08:00
});
2014-02-28 06:52:25 +08:00
context("if the GPIO file for the pin doesn't exist", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "exists").callsArgWith(1, false);
stub(pin, "_createGPIOPin");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.exists.restore();
pin._createGPIOPin.restore();
});
it("creates a new GPIO pin", function() {
pin.connect(pin.mode);
expect(fs.exists).to.be.calledWith(path);
expect(pin._createGPIOPin).to.be.called;
});
2014-01-04 04:18:29 +08:00
});
2014-02-28 06:52:25 +08:00
});
describe("#close", function() {
var path = "/sys/class/gpio/unexport";
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFile").callsArgWith(2, false);
stub(pin, "_closeCallback");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
2014-02-28 06:52:25 +08:00
fs.writeFile.restore();
pin._closeCallback.restore();
});
it("writes to the GPIO unexport path with the pin's value", function() {
pin.close();
2014-12-15 07:21:28 +08:00
expect(fs.writeFile).to.be.calledWith(path, "4");
});
it("calls the closeCallback", function() {
pin.close();
expect(pin._closeCallback).to.be.calledWith(false);
2014-01-04 04:18:29 +08:00
});
2014-02-28 06:52:25 +08:00
});
describe("#closeSync", function() {
var path = "/sys/class/gpio/unexport";
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFileSync");
stub(pin, "_closeCallback");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFileSync.restore();
pin._closeCallback.restore();
});
it("writes to the GPIO unexport path with the pin's value", function() {
2014-02-28 06:52:25 +08:00
pin.closeSync();
2014-12-15 07:21:28 +08:00
expect(fs.writeFileSync).to.be.calledWith(path, "4");
});
it("calls the closeCallback", function() {
pin.closeSync();
expect(pin._closeCallback).to.be.calledWith(false);
2014-02-28 06:52:25 +08:00
});
});
describe("#digitalWrite", function() {
var path = "/sys/class/gpio/gpio4/value";
context("if pin mode isn't 'w'", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFile");
stub(pin, "_setMode");
});
2014-02-28 06:52:25 +08:00
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin._setMode.restore();
});
it("sets the pin mode to 'w'", function() {
2014-12-15 07:21:28 +08:00
pin.mode = "r";
pin.digitalWrite(1);
2014-12-15 07:21:28 +08:00
expect(pin._setMode).to.be.calledWith("w");
});
2014-02-28 06:52:25 +08:00
});
context("when successful", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
pin.mode = "w";
stub(fs, "writeFile").callsArgWith(2, null);
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin.emit.restore();
});
it("emits a digitalWrite event with the written value", function() {
pin.digitalWrite(1);
expect(fs.writeFile).to.be.calledWith(path, 1);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("digitalWrite", 1);
});
it("returns the passed value", function() {
expect(pin.digitalWrite(1)).to.be.eql(1);
});
it("changes the pin's @status", function() {
2014-12-15 07:21:28 +08:00
pin.status = "low";
pin.digitalWrite(1);
2014-12-15 07:21:28 +08:00
expect(pin.status).to.be.eql("high");
});
2014-02-28 06:52:25 +08:00
});
context("when there is an error", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
pin.mode = "w";
stub(fs, "writeFile").callsArgWith(2, true);
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin.emit.restore();
});
it("emits an error message", function() {
pin.digitalWrite(1);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("error");
});
2014-02-28 06:52:25 +08:00
});
});
describe("#digitalRead", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
this.clock = sinon.useFakeTimers();
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
this.clock.restore();
});
context("if the mode isn't 'r'", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(Utils, "every");
stub(pin, "_setMode");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
Utils.every.restore();
pin._setMode.restore();
});
it("sets the pin mode to 'r'", function() {
2014-12-15 07:21:28 +08:00
pin.mode = "w";
pin.digitalRead(500);
2014-12-15 07:21:28 +08:00
expect(pin._setMode).to.be.calledWith("r");
});
});
context("when successful", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "readFile").callsArgWith(1, null, 1);
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.readFile.restore();
pin.emit.restore();
});
it("requests the pin value on the specified interval", function() {
pin.digitalRead(500);
this.clock.tick(510);
expect(fs.readFile).to.be.calledOnce;
this.clock.tick(500);
expect(fs.readFile).to.be.calledTwice;
});
it("emits a 'digitalRead' event with the data recieved", function() {
pin.digitalRead(500);
this.clock.tick(510);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("digitalRead", 1);
});
});
context("when an error occurs", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "readFile").callsArgWith(1, true, null);
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.readFile.restore();
pin.emit.restore();
});
it("emits an error message", function() {
pin.digitalRead(500);
this.clock.tick(500);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("error");
});
2014-02-28 06:52:25 +08:00
});
});
describe("#setHigh", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "digitalWrite");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.digitalWrite.restore();
});
it("calls #digitalWrite with a value of 1", function() {
2014-02-28 06:52:25 +08:00
pin.setHigh();
expect(pin.digitalWrite).to.be.calledWith(1);
2014-01-04 04:18:29 +08:00
});
2014-02-28 06:52:25 +08:00
});
describe("#setLow", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "digitalWrite");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.digitalWrite.restore();
});
it("calls #digitalWrite with a value of 0", function() {
2014-02-28 06:52:25 +08:00
pin.setLow();
expect(pin.digitalWrite).to.be.calledWith(0);
2014-02-28 06:52:25 +08:00
});
});
2014-02-28 09:39:02 +08:00
2014-02-28 06:52:25 +08:00
describe("#toggle", function() {
context("when @status is 'high'", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-16 01:37:52 +08:00
stub(pin, "setLow");
pin.status = "high";
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.setLow.restore();
});
it("calls #setLow", function() {
2014-02-28 06:52:25 +08:00
pin.toggle();
expect(pin.setLow).to.be.called;
2014-01-04 04:18:29 +08:00
});
2014-02-28 06:52:25 +08:00
});
context("when @status is 'low'", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-16 01:37:52 +08:00
stub(pin, "setHigh");
pin.status = "low";
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.setHigh.restore();
});
it("calls #setHigh", function() {
2014-02-28 06:52:25 +08:00
pin.toggle();
expect(pin.setHigh).to.be.called;
});
});
});
describe("#_createGPIOPin", function() {
var path = "/sys/class/gpio/export";
context("when successful", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFile").callsArgWith(2, null);
stub(pin, "_openPin");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin._openPin.restore();
});
it("writes the pin number to the GPIO export path", function() {
pin._createGPIOPin();
2014-12-16 01:37:52 +08:00
expect(fs.writeFile).to.be.calledWith(path, "4");
});
it("calls #_openPin", function() {
pin._createGPIOPin();
expect(pin._openPin).to.be.called;
});
});
context("when an error occurs", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFile").callsArgWith(2, true);
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin.emit.restore();
});
it("emits an error", function() {
pin._createGPIOPin();
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("error");
});
});
2014-12-16 01:37:52 +08:00
});
describe("#_openPin", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "_setMode");
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin._setMode.restore();
pin.emit.restore();
});
it("sets the pin's mode", function() {
pin._openPin();
expect(pin._setMode).to.be.calledWith(pin.mode);
});
it("emits the 'open' event", function() {
pin._openPin();
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("open");
});
});
describe("_closeCallback", function() {
context("if there is an error", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "emit");
pin._closeCallback(true);
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.emit.restore();
});
it("emits an error", function() {
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("error");
});
});
context("if there is no error", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "emit");
pin._closeCallback(false);
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.emit.restore();
2014-01-04 04:18:29 +08:00
});
it("emits a 'close' event with the pin number", function() {
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("close", "4");
2014-12-16 01:37:52 +08:00
});
});
});
describe("#_setMode", function() {
var path = "/sys/class/gpio/gpio4/direction";
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(fs, "writeFile").callsArgWith(2, "error");
stub(pin, "_setModeCallback");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
fs.writeFile.restore();
pin._setModeCallback.restore();
});
context("when mode is 'w'", function() {
it("writes to the pin's direction path with 'out'", function() {
2014-12-15 07:21:28 +08:00
pin._setMode("w");
expect(fs.writeFile).to.be.calledWith(path, "out");
});
it("calls #_setModeCallback with any error message", function() {
2014-12-15 07:21:28 +08:00
pin._setMode("w", true);
expect(pin._setModeCallback).to.be.calledWith("error", true);
});
});
context("when mode is 'r'", function() {
it("writes to the pin's direction path with 'in'", function() {
2014-12-15 07:21:28 +08:00
pin._setMode("r");
expect(fs.writeFile).to.be.calledWith(path, "in");
});
});
});
describe("#_setModeCallback", function() {
2014-07-05 00:49:29 +08:00
beforeEach(function() {
2014-12-15 07:21:28 +08:00
stub(pin, "emit");
});
2014-07-05 00:49:29 +08:00
afterEach(function() {
pin.emit.restore();
});
context("when successful", function() {
it("sets @ready to true", function() {
pin.ready = false;
pin._setModeCallback(false);
expect(pin.ready).to.be.eql(true);
});
context("when emitConnect is true", function() {
it("emits a 'connect' event with the pin's mode", function() {
pin._setModeCallback(false, true);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("connect", pin.mode);
});
});
});
context("when passed an error", function() {
2014-12-15 07:21:28 +08:00
it("emits an error", function() {
pin._setModeCallback(true);
2014-12-15 07:21:28 +08:00
expect(pin.emit).to.be.calledWith("error");
});
});
});
describe("#_pinPath", function() {
var path = "/sys/class/gpio/gpio4";
it("returns the path to the GPIO pin", function() {
expect(pin._pinPath()).to.be.eql(path);
});
});
describe("#_directionPath", function() {
var path = "/sys/class/gpio/gpio4/direction";
it("returns the path to the GPIO pin's direction file", function() {
expect(pin._directionPath()).to.be.eql(path);
});
});
describe("#_valuePath", function() {
var path = "/sys/class/gpio/gpio4/value";
it("returns the path to the GPIO pin's value file", function() {
expect(pin._valuePath()).to.be.eql(path);
});
});
describe("#_exportPath", function() {
var path = "/sys/class/gpio/export";
it("returns the GPIO export path", function() {
expect(pin._exportPath()).to.be.eql(path);
});
});
describe("#_unexportPath", function() {
var path = "/sys/class/gpio/unexport";
it("returns the GPIO unexport path", function() {
expect(pin._unexportPath()).to.be.eql(path);
2014-01-04 04:18:29 +08:00
});
});
2014-02-28 06:52:25 +08:00
});