UNPKG

johnny-five-electron

Version:

Temporary fork to support Electron (to be deprecated)

439 lines (372 loc) 9.56 kB
var five = require("../lib/johnny-five.js"), sinon = require("sinon"), MockFirmata = require("./util/mock-firmata"), Board = five.Board, Piezo = five.Piezo; 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["Piezo"] = { setUp: function(done) { this.board = newBoard(); this.clock = sinon.useFakeTimers(); this.digitalWrite = sinon.spy(MockFirmata.prototype, "digitalWrite"); this.piezo = new Piezo({ pin: 3, board: this.board }); this.proto = [{ name: "frequency", }, { name: "tone" }, { name: "noTone" }, { name: "off" }, { name: "play" }]; this.instance = [{ name: "isPlaying" }]; done(); }, tearDown: function(done) { Board.purge(); this.piezo.defaultOctave(4); restore(this); done(); }, notes: function(test) { test.expect(108); var notes = { "c0": 16, "c#0": 17, "d0": 18, "d#0": 19, "e0": 21, "f0": 22, "f#0": 23, "g0": 25, "g#0": 26, "a0": 28, "a#0": 29, "b0": 31, "c1": 33, "c#1": 35, "d1": 37, "d#1": 39, "e1": 41, "f1": 44, "f#1": 47, "g1": 49, "g#1": 52, "a1": 55, "a#1": 58, "b1": 62, "c2": 65, "c#2": 69, "d2": 73, "d#2": 78, "e2": 82, "f2": 87, "f#2": 93, "g2": 98, "g#2": 104, "a2": 110, "a#2": 117, "b2": 124, "c3": 131, "c#3": 139, "d3": 147, "d#3": 156, "e3": 165, "f3": 175, "f#3": 185, "g3": 196, "g#3": 208, "a3": 220, "a#3": 233, "b3": 247, "c4": 262, "c#4": 277, "d4": 294, "d#4": 311, "e4": 330, "f4": 349, "f#4": 370, "g4": 392, "g#4": 415, "a4": 440, "a#4": 466, "b4": 494, "c5": 523, "c#5": 554, "d5": 587, "d#5": 622, "e5": 659, "f5": 698, "f#5": 740, "g5": 784, "g#5": 831, "a5": 880, "a#5": 932, "b5": 988, "c6": 1047, "c#6": 1109, "d6": 1175, "d#6": 1245, "e6": 1319, "f6": 1397, "f#6": 1480, "g6": 1568, "g#6": 1661, "a6": 1760, "a#6": 1865, "b6": 1976, "c7": 2093, "c#7": 2217, "d7": 2349, "d#7": 2489, "e7": 2637, "f7": 2794, "f#7": 2960, "g7": 3136, "g#7": 3322, "a7": 3520, "a#7": 3729, "b7": 3951, "c8": 4186, "c#8": 4435, "d8": 4699, "d#8": 4978, "e8": 5274, "f8": 5588, "f#8": 5920, "g8": 6272, "g#8": 6645, "a8": 7040, "a#8": 7459, "b8": 7902 }; Object.keys(notes).forEach(function(note) { test.equal(notes[note], Piezo.Notes[note]); }); test.done(); }, shape: function(test) { test.expect(this.proto.length + this.instance.length); this.proto.forEach(function(method) { test.equal(typeof this.piezo[method.name], "function"); }, this); this.instance.forEach(function(property) { test.notEqual(typeof this.piezo[property.name], "undefined"); }, this); test.done(); }, defaultOctave: function(test) { test.expect(6); // 4 is the default. test.equal(4, this.piezo.defaultOctave()); // Changes are returned as well as stored. test.equal(5, this.piezo.defaultOctave(5)); // 0 - 9 only, remembers last good value. test.equal(5, this.piezo.defaultOctave(-1)); test.equal(5, this.piezo.defaultOctave(9)); test.equal(5, this.piezo.defaultOctave("foo")); test.equal(5, this.piezo.defaultOctave(null)); test.done(); }, note: function(test) { test.expect(4); // note delegates to tone; var toneSpy = sinon.spy(this.piezo, "tone"); // accepts octave. test.equal(this.piezo.note("c4", 100), this.piezo); test.ok(toneSpy.calledWith(262, 100)); // or not. test.equal(this.piezo.note("c#", 100), this.piezo); test.ok(toneSpy.calledWith(277, 100)); test.done(); }, tone: function(test) { test.expect(2); var returned = this.piezo.tone(1915, 1000); this.clock.tick(100); test.ok(this.digitalWrite.called); test.equal(returned, this.piezo); test.done(); }, toneWhileNewToneIsPlayingCancelsExisting: function(test) { test.expect(1); this.piezo.tone(1915, 100); var timerSpy = sinon.spy(this.piezo.timer, "clearInterval"); this.piezo.tone(1915, 100); test.ok(timerSpy.called); test.done(); }, toneRejectsWonkyToneValues: function(test) { var lameValues = [ ["florp", 5], ["ding", "dong"], ["c4", "zimple"], ["?", "foof"] // ["C4", 1][null, 1/2] // Original bad value; jshint won't allow ]; test.expect(lameValues.length); lameValues.forEach(function(element) { try { if (element && element.length) { this.piezo.tone(element[0], element[1]); } else { this.piezo.tone(element); } } catch (e) { test.equal(e.message, "Piezo.tone: invalid tone or duration"); } }, this); test.done(); }, toneLovesHappyValues: function(test) { test.expect(1); var happy = this.piezo.tone(350, 500); test.equal(happy, this.piezo); // tone returns piezo obj when happy test.done(); }, frequency: function(test) { test.expect(2); var toneSpy = sinon.spy(this.piezo, "tone"); var returned = this.piezo.frequency(440, 100); test.ok(toneSpy.calledWith(1136, 100)); test.equal(returned, this.piezo); test.done(); }, noTone: function(test) { test.expect(2); var returned = this.piezo.noTone(); test.ok(this.digitalWrite.calledWith(3, 0)); test.equal(returned, this.piezo); test.done(); }, noToneStopsExistingTone: function(test) { test.expect(2); this.piezo.tone(500, 1000); var timerSpy = sinon.spy(this.piezo.timer, "clearInterval"); this.piezo.noTone(); test.ok(timerSpy.called); test.equal(this.piezo.timer, undefined); test.done(); }, play: function(test) { test.expect(3); var returned = this.piezo.play({ song: [ [] // No tone ], tempo: 150 }); test.ok(this.digitalWrite.calledWith(3, 0)); test.equal(returned, this.piezo); this.piezo.play({ song: [ [] // No tone ], tempo: 150 }); test.ok(this.digitalWrite.calledWith(3, 0)); test.done(); }, playTune: function(test) { var tempo = 10000; // Make it really fast test.expect(6); var freqSpy = sinon.spy(this.piezo, "frequency"); this.piezo.play({ song: [ ["c", 1], ["d", 2], [null, 1], 672, "e4", null ], tempo: tempo // Make it real fast }, function() { // frequency should get called 4x; not for the null notes test.ok(freqSpy.callCount === 4); test.ok(freqSpy.neverCalledWith(null)); // First call should have been with frequency for "c4" test.ok(freqSpy.args[0][0] === Piezo.Notes["c4"]); // Default duration === tempo if not provided test.ok(freqSpy.calledWith(Piezo.Notes["e4"], 60000 / tempo)); // Duration should change if different beat value given test.ok(freqSpy.calledWith(Piezo.Notes["d4"], (60000 / tempo) * 2)); // OK to pass frequency directly... test.ok(freqSpy.calledWith(672, 60000 / tempo)); test.done(); }); this.clock.tick(100); }, playTuneWithStringSongAndBeat: function(test) { var tempo = 10000; // Make it really fast test.expect(6); var freqSpy = sinon.spy(this.piezo, "frequency"); var beats = 0.125; this.piezo.play({ song: "c d d - 672 e4 -", beats: beats, tempo: tempo // Make it real fast }, function() { // frequency should get called 4x; not for the null notes test.ok(freqSpy.callCount === 4); test.ok(freqSpy.neverCalledWith(null)); // First call should have been with frequency for "c4" test.ok(freqSpy.args[0][0] === Piezo.Notes["c4"]); // Default duration === tempo if not provided test.ok(freqSpy.calledWith(Piezo.Notes["e4"], 60000 * beats / tempo)); // Duration should change if different beat value given test.ok(freqSpy.calledWith(Piezo.Notes["d4"], (60000 * beats / tempo) * 2)); // OK to pass frequency directly... test.ok(freqSpy.calledWith(672, 60000 * beats / tempo)); test.done(); }); this.clock.tick(100); }, playCanDealWithWonkyValues: function(test) { var tempo = 10000, tune = { song: [ ["c4"], ["drunk"], ["d4", 0] ], tempo: tempo }; test.expect(1); this.piezo.play(tune, function() { test.ok(1); // We made it this far, no choking on bad values test.done(); }.bind(this)); this.clock.tick(100); }, };