Files
archeo010110-ananthology/bower_components/KeyboardJS/test/keyboard.spec.js
T

701 lines
21 KiB
JavaScript

var sinon = require('sinon');
var assert = require('assert');
var Keyboard = require('../lib/keyboard');
var KeyCombo = require('../lib/key-combo');
var Locale = require('../lib/locale');
var doc = require('./fixtures/document');
var win = require('./fixtures/window');
describe('Keyboard', function() {
var keyboard;
beforeEach(function() {
keyboard = new Keyboard(win, doc);
});
describe('#setLocale', function() {
it('creates and sets a locale', function() {
keyboard.setLocale('testName', function(locale, platform, userAgent) {
assert.equal(platform, 'test-platform');
assert.equal(userAgent, 'test-user-agent');
locale.test = 1;
});
assert.equal(keyboard._locale.test, 1);
assert.equal(keyboard._locales.testName.test, 1);
});
it('sets a locale', function() {
keyboard._locales.testName = { test: 2 };
keyboard.setLocale('testName');
assert.equal(keyboard._locale.test, 2);
});
it('accepts locale instance and sets it', function() {
keyboard.setLocale({
localeName: 'testName',
test: 3
});
assert.equal(keyboard._locale.test, 3);
});
});
describe('#getLocale', function() {
it('returns the current locale', function() {
keyboard._locales.testName = { test: 4, localeName: 'testName' };
keyboard._locale = keyboard._locales.testName;
var locale = keyboard.getLocale();
assert.equal(locale.test, 4);
});
it('returns the a locale by name', function() {
keyboard._locales.testName = { test: 5 };
keyboard._locale = keyboard._locales.testName;
var locale = keyboard.getLocale('testName');
assert.equal(locale.test, 5);
});
});
describe('#bind', function() {
it('binds a combo to press handler and release handlers', function() {
var pressHandler = function() {};
var releaseHandler = function() {};
keyboard.bind('a', pressHandler, releaseHandler);
assert.equal(keyboard._listeners[0].keyCombo.sourceStr, 'a');
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
});
it('binds a combo to a press handler', function() {
var pressHandler = function() {};
keyboard.bind('a', pressHandler);
assert.equal(keyboard._listeners[0].keyCombo.sourceStr, 'a');
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, null);
});
it('binds a combo to a release handler', function() {
var releaseHandler = function() {};
keyboard.bind('a', null, releaseHandler);
assert.equal(keyboard._listeners[0].keyCombo.sourceStr, 'a');
assert.equal(keyboard._listeners[0].pressHandler, null);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
});
it('binds several combos to press and release handlers', function() {
var pressHandler = function() {};
var releaseHandler = function() {};
keyboard.bind(['a', 'b'], pressHandler, releaseHandler);
assert.equal(keyboard._listeners[0].keyCombo.sourceStr, 'a');
assert.equal(keyboard._listeners[1].keyCombo.sourceStr, 'b');
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[1].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].releaseHandler, releaseHandler);
});
it('binds press and release handlers to any keypress', function() {
var pressHandler = function() {};
var releaseHandler = function() {};
keyboard.bind(pressHandler, releaseHandler);
assert.equal(keyboard._listeners[0].keyCombo, null);
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
});
it('accepts preventRepeat as a final argument', function() {
var pressHandler = function() {};
var releaseHandler = function() {};
keyboard.bind('a', pressHandler, releaseHandler, true);
keyboard.bind(pressHandler, releaseHandler, true);
assert.equal(keyboard._listeners[0].keyCombo.sourceStr, 'a');
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[0].preventRepeat, true);
assert.equal(keyboard._listeners[1].keyCombo, null);
assert.equal(keyboard._listeners[1].pressHandler, pressHandler);
assert.equal(keyboard._listeners[1].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].preventRepeat, true);
});
});
describe('#addListener', function() {
it('is an alias for bind', function() {
assert.equal(keyboard.addListener, keyboard.bind);
});
});
describe('#on', function() {
it('is an alias for bind', function() {
assert.equal(keyboard.on, keyboard.bind);
});
});
describe('#unbind', function() {
var pressHandler = function() {};
var releaseHandler = function() {};
beforeEach(function() {
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: pressHandler,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: pressHandler,
releaseHandler: null,
preventRepeat: false
});
});
afterEach(function() {
keyboard._listeners.length = 0;
});
it('unbinds a combo from press handler and release handlers', function() {
keyboard.unbind('a', pressHandler, releaseHandler);
assert.equal(keyboard._listeners.length, 2);
assert.equal(keyboard._listeners[0].pressHandler, null);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].pressHandler, pressHandler);
assert.equal(keyboard._listeners[1].releaseHandler, null);
});
it('unbinds a combo from a press handler', function() {
keyboard.unbind('a', pressHandler);
assert.equal(keyboard._listeners.length, 2);
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].pressHandler, null);
assert.equal(keyboard._listeners[1].releaseHandler, releaseHandler);
});
it('unbinds a combo from a release handler', function() {
keyboard.unbind('a', null, releaseHandler);
assert.equal(keyboard._listeners.length, 2);
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].pressHandler, pressHandler);
assert.equal(keyboard._listeners[1].releaseHandler, null);
});
it('unbinds a several combos from press and release handlers', function() {
keyboard._listeners.push({
keyCombo: new KeyCombo('b'),
pressHandler: pressHandler,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.unbind(['a', 'b'], pressHandler, releaseHandler);
assert.equal(keyboard._listeners.length, 2);
assert.equal(keyboard._listeners[0].pressHandler, null);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].pressHandler, pressHandler);
assert.equal(keyboard._listeners[1].releaseHandler, null);
});
it('unbinds press and release handlers bound to any key press', function() {
keyboard._listeners.push({
keyCombo: null,
pressHandler: pressHandler,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.unbind(pressHandler, releaseHandler);
assert.equal(keyboard._listeners.length, 3);
assert.equal(keyboard._listeners[0].pressHandler, pressHandler);
assert.equal(keyboard._listeners[0].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[1].pressHandler, null);
assert.equal(keyboard._listeners[1].releaseHandler, releaseHandler);
assert.equal(keyboard._listeners[2].pressHandler, pressHandler);
assert.equal(keyboard._listeners[2].releaseHandler, null);
});
});
describe('#removeListener', function() {
it('is an alias for unbind', function() {
assert.equal(keyboard.removeListener, keyboard.unbind);
});
});
describe('#off', function() {
it('is an alias for unbind', function() {
assert.equal(keyboard.off, keyboard.unbind);
});
});
describe('#setContext', function() {
it('releases all keys before setting the context', function() {
keyboard._locale = {};
sinon.stub(keyboard, 'releaseAllKeys');
keyboard.setContext('myContext');
assert.ok(keyboard.releaseAllKeys.calledOnce);
keyboard.releaseAllKeys.restore();
});
it('creates a new context with the given name if it doesn\'t exist.', function() {
keyboard.setContext('myContext');
assert.ok(keyboard._contexts.myContext);
assert.equal(keyboard._currentContext, 'myContext');
});
it('applies an existing context if one with the given name already exists', function() {
keyboard._contexts.myContext = [1];
keyboard.setContext('myContext');
assert.equal(keyboard._currentContext, 'myContext');
assert.equal(keyboard._contexts[keyboard._currentContext][0], 1);
});
});
describe('#getContext', function() {
it('returns the current context', function() {
keyboard._currentContext = 'myContext';
assert.equal(keyboard.getContext(), 'myContext');
});
});
describe('#watch', function() {
it('calls stop', function() {
sinon.stub(keyboard, 'stop');
keyboard.watch(win, doc);
assert.ok(keyboard.stop.calledOnce);
keyboard.stop.restore();
});
it('attaches to a given window and document', function() {
var win = { addEventListener: sinon.stub() };
var doc = { addEventListener: sinon.stub() };
keyboard.watch(win, doc);
assert.equal(keyboard._isModernBrowser, true);
assert.equal(keyboard._targetWindow, win);
assert.equal(keyboard._targetElement, doc);
assert.ok(win.addEventListener.firstCall.args[0], 'focus');
assert.ok(win.addEventListener.secondCall.args[0], 'blur');
assert.ok(doc.addEventListener.firstCall.args[0], 'keydown');
assert.ok(doc.addEventListener.secondCall.args[0], 'keyup');
});
it('attaches to a given window and document (Legacy IE)', function() {
var win = { attachEvent: sinon.stub() };
var doc = { attachEvent: sinon.stub() };
keyboard.watch(win, doc);
assert.equal(keyboard._isModernBrowser, false);
assert.equal(keyboard._targetWindow, win);
assert.equal(keyboard._targetElement, doc);
assert.ok(win.attachEvent.firstCall.args[0], 'onfocus');
assert.ok(win.attachEvent.secondCall.args[0], 'onblur');
assert.ok(doc.attachEvent.firstCall.args[0], 'onkeydown');
assert.ok(doc.attachEvent.secondCall.args[0], 'onkeyup');
});
it('attaches to the global namespace if a window and document is not given', function() {
global.addEventListener = sinon.stub();
global.document = { addEventListener: sinon.stub() };
keyboard.watch();
assert.equal(keyboard._isModernBrowser, true);
assert.equal(keyboard._targetWindow, global);
assert.equal(keyboard._targetElement, global.document);
assert.ok(global.addEventListener.firstCall.args[0], 'focus');
assert.ok(global.addEventListener.secondCall.args[0], 'blur');
assert.ok(global.document.addEventListener.firstCall.args[0], 'keydown');
assert.ok(global.document.addEventListener.secondCall.args[0], 'keyup');
delete global.addEventListener;
delete global.document;
});
it('throws is error if the target window does not have the nessisary methods', function() {
var win = {};
var doc = {};
assert.throws(function() {
keyboard.watch(win, doc);
}, /^(?=.*targetWindow)(?=.*addEventListener)(?=.*attachEvent).*$/);
});
it('throws is error a target window was not given and if the global does contain the nessisary functions', function() {
assert.throws(function() {
keyboard.watch();
}, /^(?=.*global)(?=.*addEventListener)(?=.*attachEvent).*$/);
});
});
describe('#stop', function() {
it('dettaches from the currently attached window and document', function() {
var doc = keyboard._targetElement = { removeEventListener: sinon.stub() };
var win = keyboard._targetWindow = { removeEventListener: sinon.stub() };
keyboard.stop();
assert.equal(keyboard._targetWindow, null);
assert.equal(keyboard._targetElement, null);
assert.ok(win.removeEventListener.firstCall.args[0], 'focus');
assert.ok(win.removeEventListener.secondCall.args[0], 'blur');
assert.ok(doc.removeEventListener.firstCall.args[0], 'keydown');
assert.ok(doc.removeEventListener.secondCall.args[0], 'keyup');
});
it('dettaches from the currently attached window and document (Legacy IE)', function() {
var doc = { detachEvent: sinon.stub() };
var win = { detachEvent: sinon.stub() };
keyboard._isModernBrowser = false;
keyboard._targetElement = doc;
keyboard._targetWindow = win;
keyboard.stop();
assert.equal(keyboard._targetWindow, null);
assert.equal(keyboard._targetElement, null);
assert.ok(win.detachEvent.firstCall.args[0], 'onfocus');
assert.ok(win.detachEvent.secondCall.args[0], 'onblur');
assert.ok(doc.detachEvent.firstCall.args[0], 'onkeydown');
assert.ok(doc.detachEvent.secondCall.args[0], 'onkeyup');
});
});
describe('#pressKey', function() {
var locale;
beforeEach(function() {
locale = new Locale('test');
locale.bindKeyCode(0, 'a');
locale.bindKeyCode(1, 'b');
keyboard._locale = locale;
});
it('calls pressKey on the locale', function() {
sinon.stub(locale, 'pressKey');
keyboard.pressKey('a');
assert.equal(locale.pressKey.lastCall.args[0], 'a');
locale.pressKey.restore();
});
it('executes bindings with a combo matching the pressed keys within the locale', function() {
var pressHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: pressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard.pressKey('a');
assert.ok(pressHandler.calledOnce);
});
it('executes bindings without a combo', function() {
var pressHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: null,
pressHandler: pressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard.pressKey('a');
keyboard.pressKey('b');
assert.ok(pressHandler.calledTwice);
});
it('prevents combo overlap by marking off keys once they have been used by a combo', function() {
var aPressHandler = sinon.stub();
var aBPressHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: aPressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard._listeners.push({
keyCombo: new KeyCombo('a + b'),
pressHandler: aBPressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard.pressKey('a'); // combo a fires
keyboard.pressKey('b'); // combo a + b fires, but not combo a because the
// a key has been consumed by combo a + b
assert.ok(aPressHandler.calledOnce);
assert.ok(aBPressHandler.calledOnce);
});
it('allows any number of identical bindings to fire without inhibiting each other', function() {
var a1PressHandler = sinon.stub();
var a2PressHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: a1PressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: a2PressHandler,
releaseHandler: null,
preventRepeat: false
});
keyboard.pressKey('a'); // combo a1 and a2 fires
assert.ok(a1PressHandler.calledOnce);
assert.ok(a2PressHandler.calledOnce);
});
it('does nothing when paused', function() {
sinon.stub(locale, 'pressKey');
keyboard._paused = true;
keyboard.pressKey('a');
assert.equal(locale.pressKey.called, false);
assert.equal(locale.pressedKeys.length, 0);
locale.pressKey.restore();
});
});
describe('#releaseKey', function() {
var locale;
beforeEach(function() {
locale = new Locale('test');
locale.bindKeyCode(0, 'a');
keyboard._locale = locale;
});
it('calls releaseKey on the locale', function() {
sinon.stub(locale, 'releaseKey');
keyboard.releaseKey('a');
assert.equal(locale.releaseKey.lastCall.args[0], 'a');
locale.releaseKey.restore();
});
it('will not execute a binding\'s releaseHandler unless it was triggered first by a press', function() {
var releaseHandler = sinon.stub();
keyboard.pressKey('a');
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.releaseKey('a');
assert.equal(releaseHandler.calledOnce, false);
});
it('executes the releaseHandler of active bindings that no longer match the pressed keys', function() {
var releaseHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.pressKey('a');
keyboard.releaseKey('a');
assert.ok(releaseHandler.calledOnce);
});
it('executes the releaseHandler without a combo', function() {
var releaseHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: null,
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.pressKey('a');
keyboard.pressKey('b');
keyboard.releaseKey('a');
keyboard.releaseKey('b');
assert.ok(releaseHandler.calledTwice);
});
});
describe('#releaseAllKeys', function() {
var locale;
beforeEach(function() {
locale = new Locale('test');
locale.bindKeyCode(0, 'a');
keyboard._locale = locale;
});
it('clears pressedKeys on the locale', function() {
keyboard.releaseAllKeys();
assert.equal(locale.pressedKeys.length, 0);
});
it('will not execute a binding\'s releaseHandler unless it was triggered first by a press', function() {
var releaseHandler = sinon.stub();
keyboard.pressKey('a');
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.releaseAllKeys();
assert.equal(releaseHandler.calledOnce, false);
});
it('executes the releaseHandler of active bindings that no longer match the pressed keys', function() {
var releaseHandler = sinon.stub();
keyboard._listeners.push({
keyCombo: new KeyCombo('a'),
pressHandler: null,
releaseHandler: releaseHandler,
preventRepeat: false
});
keyboard.pressKey('a');
keyboard.releaseAllKeys();
assert.ok(releaseHandler.calledOnce);
});
});
describe('#pause', function() {
it('pauses the instance', function() {
keyboard.pause();
assert.ok(keyboard._paused);
});
});
describe('#resume', function() {
it('resumes the instance', function() {
keyboard.resume();
assert.equal(keyboard._paused, false);
});
});
describe('#reset', function() {
it('calls releaseAllKeys', function() {
sinon.stub(keyboard, 'releaseAllKeys');
keyboard.reset();
assert.ok(keyboard.releaseAllKeys.calledOnce);
keyboard.releaseAllKeys.reset();
});
it('clears all listeners', function() {
sinon.stub(keyboard, 'releaseAllKeys');
keyboard._listeners = [1];
keyboard.reset();
assert.equal(keyboard._listeners.length, 0);
keyboard.releaseAllKeys.reset();
});
});
});