diff --git a/src/io/keyboard.js b/src/io/keyboard.js
index ea423fd40..e72f689f2 100644
--- a/src/io/keyboard.js
+++ b/src/io/keyboard.js
@@ -18,6 +18,7 @@ function Keyboard (runtime) {
  * Convert a Scratch key name to a DOM keyCode.
  * @param {Any} keyName Scratch key argument.
  * @return {number} Key code corresponding to a DOM event.
+ * @private
  */
 Keyboard.prototype._scratchKeyToKeyCode = function (keyName) {
     if (typeof keyName == 'number') {
@@ -37,6 +38,12 @@ Keyboard.prototype._scratchKeyToKeyCode = function (keyName) {
     return keyString.toUpperCase().charCodeAt(0);
 };
 
+/**
+ * Convert a DOM keyCode into a Scratch key name.
+ * @param  {number} Key code from DOM event.
+ * @return {Any} Scratch key argument.
+ * @private
+ */
 Keyboard.prototype._keyCodeToScratchKey = function (keyCode) {
     if (keyCode >= 48 && keyCode <= 90) {
         // Standard letter.
@@ -52,6 +59,11 @@ Keyboard.prototype._keyCodeToScratchKey = function (keyCode) {
     return null;
 };
 
+/**
+ * Keyboard DOM event handler.
+ * @param  {object} DOM event object.
+ * @return {void}
+ */
 Keyboard.prototype.postData = function (data) {
     if (data.keyCode) {
         var index = this._keysPressed.indexOf(data.keyCode);
@@ -74,6 +86,11 @@ Keyboard.prototype.postData = function (data) {
     }
 };
 
+/**
+ * Get key down state for a specified Scratch key name.
+ * @param  {Any} Scratch key argument.
+ * @return {boolean}
+ */
 Keyboard.prototype.getKeyIsDown = function (key) {
     if (key == 'any') {
         return this._keysPressed.length > 0;
diff --git a/test/unit/io_keyboard.js b/test/unit/io_keyboard.js
new file mode 100644
index 000000000..ad3a65c6d
--- /dev/null
+++ b/test/unit/io_keyboard.js
@@ -0,0 +1,73 @@
+var test = require('tap').test;
+var Keyboard = require('../../src/io/keyboard');
+var Runtime = require('../../src/engine/runtime');
+
+test('spec', function (t) {
+    var rt = new Runtime();
+    var k = new Keyboard(rt);
+
+    t.type(k, 'object');
+    t.type(k.postData, 'function');
+    t.type(k.getKeyIsDown, 'function');
+    t.end();
+});
+
+test('space', function (t) {
+    var rt = new Runtime();
+    var k = new Keyboard(rt);
+
+    k.postData({
+        keyCode: 32,
+        isDown: true
+    });
+    t.strictDeepEquals(k._keysPressed, [32]);
+    t.strictEquals(k.getKeyIsDown('space'), true);
+    t.strictEquals(k.getKeyIsDown('any'), true);
+    t.end();
+});
+
+test('letter', function (t) {
+    var rt = new Runtime();
+    var k = new Keyboard(rt);
+
+    k.postData({
+        keyCode: 65,
+        isDown: true
+    });
+    t.strictDeepEquals(k._keysPressed, [65]);
+    t.strictEquals(k.getKeyIsDown('a'), true);
+    t.strictEquals(k.getKeyIsDown('any'), true);
+    t.end();
+});
+
+test('number', function (t) {
+    var rt = new Runtime();
+    var k = new Keyboard(rt);
+
+    k.postData({
+        keyCode: 49,
+        isDown: true
+    });
+    t.strictDeepEquals(k._keysPressed, [49]);
+    t.strictEquals(k.getKeyIsDown(49), true);
+    t.strictEquals(k.getKeyIsDown('any'), true);
+    t.end();
+});
+
+test('keyup', function (t) {
+    var rt = new Runtime();
+    var k = new Keyboard(rt);
+
+    k.postData({
+        keyCode: 37,
+        isDown: true
+    });
+    k.postData({
+        keyCode: 37,
+        isDown: false
+    });
+    t.strictDeepEquals(k._keysPressed, []);
+    t.strictEquals(k.getKeyIsDown(37), false);
+    t.strictEquals(k.getKeyIsDown('any'), false);
+    t.end();
+});