UNPKG

johnny-five

Version:

The JavaScript Arduino Programming Framework.

315 lines (252 loc) 8.14 kB
var MockFirmata = require("./mock-firmata"), pins = require("./mock-pins"), five = require("../lib/johnny-five.js"), Board = five.Board, LCD = five.LCD, sinon = require("sinon"), util = require("util"); function newBoard() { return new Board({ io: new MockFirmata(), debug: false, repl: false }); } exports["LCD"] = { setUp: function(done) { this.board = newBoard(); this.spy = sinon.spy(this.board.io, "digitalWrite"); this.lcd = new LCD({ pins: [7, 8, 9, 10, 11, 12], board: this.board }); this.proto = [{ name: "autoscroll" }, { name: "blink" }, { name: "clear" }, { name: "command" }, { name: "createChar" }, { name: "cursor" }, { name: "display" }, { name: "home" }, { name: "noAutoscroll" }, { name: "noBlink" }, { name: "noCursor" }, { name: "noDisplay" }, { name: "print" }, { name: "pulse" }, { name: "setCursor" }, { name: "useChar" }, { name: "write" }, { name: "writeBits" }]; this.instance = [{ name: "bitMode" }, { name: "cols" }, { name: "dots" }, { name: "id" }, { name: "lines" }, { name: "pins" }, { name: "rows" }]; done(); }, shape: function(test) { test.expect(this.proto.length + this.instance.length); this.proto.forEach(function(method) { test.equal(typeof this.lcd[method.name], "function"); }, this); this.instance.forEach(function(property) { test.notEqual(typeof this.lcd[property.name], "undefined"); }, this); test.done(); }, writeBits: function(test) { test.expect(4); this.lcd.writeBits(10); test.ok(this.spy.calledWith(12, 1)); test.ok(this.spy.calledWith(11, 0)); test.ok(this.spy.calledWith(10, 1)); test.ok(this.spy.calledWith(9, 0)); test.done(); }, command: function(test) { test.expect(10); var wbStub = sinon.stub(this.lcd, "writeBits"); this.lcd.command(15); test.ok(wbStub.calledTwice); test.ok(wbStub.calledWith(0)); test.ok(wbStub.calledWith(15)); wbStub.reset(); this.lcd.command(32); test.ok(wbStub.calledTwice); test.ok(wbStub.firstCall.calledWith(2)); test.ok(wbStub.secondCall.calledWith(32)); this.lcd.bitMode = 8; wbStub.reset(); this.lcd.command(15); test.ok(wbStub.calledOnce); test.ok(wbStub.calledWith(15)); wbStub.reset(); this.lcd.command(32); test.ok(wbStub.calledOnce); test.ok(wbStub.calledWith(32)); test.done(); }, write: function(test) { test.expect(3); var cSpy = sinon.spy(this.lcd, "command"); var hiloSpy = sinon.spy(LCD, "hilo"); this.lcd.write(42); test.ok(hiloSpy.calledOn(this.lcd)); test.ok(cSpy.calledOnce); test.ok(cSpy.calledWith(42)); hiloSpy.restore(); test.done(); }, cursor: function(test) { test.expect(6); var scSpy = sinon.stub(this.lcd, "setCursor"); var cSpy = sinon.stub(this.lcd, "command"); this.lcd.cursor(); test.ok(!scSpy.called); test.ok(cSpy.calledOnce); test.ok(cSpy.firstCall.args[0] & LCD.CURSORON, "command not called with LCD.CURSORON bit high"); cSpy.reset(); this.lcd.cursor(1, 1); test.ok(scSpy.calledOnce); test.ok(scSpy.calledWith(1, 1)); test.ok(!cSpy.called); test.done(); }, noCursor: function(test) { test.expect(2); var cSpy = sinon.stub(this.lcd, "command"); this.lcd.noCursor(); test.ok(cSpy.calledOnce); test.ok(0 === (cSpy.firstCall.args[0] & LCD.CURSORON), "command not called with LCD.CURSORON bit low"); test.done(); }, createChar: function(test) { test.expect(143); // Numbers capped to 7, direct addresses, proper commands var cSpy = sinon.spy(this.lcd, "command"); var charMap = [0, 1, 2, 3, 4, 5, 6, 7]; for (var num = 0; num <= 8; ++num) { cSpy.reset(); test.strictEqual(this.lcd.createChar(num, charMap), num & 7, "Incorrect returned address"); test.strictEqual(cSpy.callCount, 9, "Improper command call count"); test.ok(cSpy.firstCall.calledWith(LCD.SETCGRAMADDR | ((num > 7 ? num & 7 : num) << 3)), "SETCGRAMADDR mask is incorrect"); for (var i = 0, l = charMap.length; i < l; ++i) { test.ok(cSpy.getCall(i + 1).calledWith(charMap[i]), "CharMap call #" + (i + 1) + " incorrect"); } } // Named-based: rotating addresses (from LCD.MEMORYLIMIT -1 down), ignores existing name ["foo", "bar", "baz", "bar"].forEach(function(name, index) { cSpy.reset(); var addr = LCD.MEMORYLIMIT - (1 + index % LCD.MEMORYLIMIT); test.strictEqual(this.lcd.createChar(name, charMap), addr, "Incorrect returned address"); test.strictEqual(cSpy.callCount, 9, "Improper command call count"); test.ok(cSpy.firstCall.calledWith(LCD.SETCGRAMADDR | (addr << 3)), "SETCGRAMADDR mask is incorrect"); for (var i = 0, l = charMap.length; i < l; ++i) { test.ok(cSpy.getCall(i + 1).calledWith(charMap[i]), "CharMap call #" + (i + 1) + " incorrect"); } }, this); test.done(); }, useChar: function(test) { test.expect(2); var ccSpy = sinon.spy(this.lcd, "createChar"); this.lcd.useChar("heart"); test.ok(ccSpy.calledWith("heart")); ccSpy.reset(); this.lcd.useChar("heart"); test.strictEqual(ccSpy.callCount, 0, "createChar should not have been called on an existing name"); test.done(); }, printRegularTexts: function(test) { // No test.expect() as these are a bit cumbersome/coupled to obtain var sentences = ["hello world", "", " ", " hello ", " hello "]; var cSpy = sinon.spy(this.lcd, "command"); sentences.forEach(function(text) { var comparison = text; cSpy.reset(); this.lcd.print(text); test.strictEqual(cSpy.callCount, comparison.length, "Unexpected amount of #command calls"); for (var i = 0, l = comparison.length; i < l; ++i) { test.strictEqual(cSpy.getCall(i).args[0], comparison.charCodeAt(i), "Unexpected byte #" + i + " on " + util.inspect(text) + " (comparing with " + util.inspect(comparison) + ")"); } }, this); test.done(); }, printSpecialTexts: function(test) { // No test.expect() as these are a bit cumbersome/coupled to obtain // These assume LCD.MEMORYLIMIT is 8, for readability var sentences = [ [":heart:", "\07"], [":heart: JS", "\07 JS"], [":heart:JS", "\07JS"], ["JS :heart:", "JS \07"], ["JS:heart:", "JS\07"], ["I :heart: JS", "I \07 JS"], ["I:heart:JS", "I\07JS"], ["I :heart: JS :smile:", "I \07 JS \06"], ["I:heart:JS :smile:", "I\07JS \06"], ["I :heart::heart::heart: JS :smile: !", "I \07\07\07 JS \06 !"], ["I :heart: :unknown: symbols", "I \07 :unknown: symbols"] ]; sentences.forEach(function(pair) { var text = pair[0], comparison = pair[1]; (text.match(/:\w+?:/g) || []).forEach(function(match) { if (":unknown:" !== match) { this.lcd.useChar(match.slice(1, -1)); } }, this); var cSpy = sinon.spy(this.lcd, "command"); this.lcd.print(text); test.strictEqual(cSpy.callCount, comparison.length, "Unexpected amount of #command calls for " + util.inspect(text)); var i, output = ""; for (i = 0; i < cSpy.callCount; ++i) { output += String.fromCharCode(cSpy.getCall(i).args[0]); } for (i = 0; i < cSpy.callCount; ++i) { test.strictEqual(cSpy.getCall(i).args[0], comparison.charCodeAt(i), "Unexpected byte #" + i + " on " + util.inspect(text) + " (comparing " + util.inspect(output) + " with " + util.inspect(comparison) + ")"); } cSpy.restore(); }, this); test.done(); } // TODO: Remaining tests: clear, home, display/noDisplay, blink/noBlink, setCursor, pulse, autoscroll/noAutoscroll };