diff --git a/karma.conf.js b/karma.conf.js index 37ded8bc..33ea1dde 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,6 +15,7 @@ module.exports = function(config) { 'test/lib/angular-mocks.js', 'test/helpers.js', 'test/matchers.js', + 'src/constants.js', 'test/*.spec.js', 'src/init.js', 'src/*.js', diff --git a/src/auto-complete.js b/src/auto-complete.js index 212b1e4c..4927bbeb 100644 --- a/src/auto-complete.js +++ b/src/auto-complete.js @@ -219,9 +219,10 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags }) .on('input-keydown', function(event) { var key = event.keyCode, + isModifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey, handled = false; - if (hotkeys.indexOf(key) === -1) { + if (isModifier || hotkeys.indexOf(key) === -1) { return; } diff --git a/test/auto-complete.spec.js b/test/auto-complete.spec.js index 1e853f0f..608f7f3a 100644 --- a/test/auto-complete.spec.js +++ b/test/auto-complete.spec.js @@ -69,8 +69,8 @@ describe('autoComplete directive', function() { $scope.$digest(); } - function sendKeyDown(keyCode) { - var event = jQuery.Event('keydown', { keyCode: keyCode }); + function sendKeyDown(keyCode, properties) { + var event = jQuery.Event('keydown', angular.extend({ keyCode: keyCode }, properties || {})); eventHandlers.call('input-keydown', event); return event; @@ -615,157 +615,6 @@ describe('autoComplete directive', function() { }); }); - describe('keys propagation handling', function() { - describe('hotkeys - suggestion box is visible', function() { - beforeEach(function() { - suggestionList.show(); - }); - - it('prevents the down arrow keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.down); - - // Assert - expect(event.isDefaultPrevented()).toBe(true); - expect(event.isPropagationStopped()).toBe(true); - }); - - it('prevents the up arrow keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.up); - - // Assert - expect(event.isDefaultPrevented()).toBe(true); - expect(event.isPropagationStopped()).toBe(true); - }); - - it('prevents the enter keydown event from being propagated if there is a suggestion selected', function() { - // Arrange - suggestionList.selected = 'suggestion'; - - // Act - var event = sendKeyDown(KEYS.enter); - - // Assert - expect(event.isDefaultPrevented()).toBe(true); - expect(event.isPropagationStopped()).toBe(true); - }); - - it('does not prevent the enter keydown event from begin propagated if there is no suggestion selected', function() { - // Arrange - suggestionList.selected = null; - - // Act - var event = sendKeyDown(KEYS.enter); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('prevents the tab keydown event from being propagated if there is a suggestion selected', function() { - // Arrange - suggestionList.selected = 'suggestion'; - - // Act - var event = sendKeyDown(KEYS.tab); - - // Assert - expect(event.isDefaultPrevented()).toBe(true); - expect(event.isPropagationStopped()).toBe(true); - }); - - it('does not prevent the tab keydown event from being propagated if there is no suggestion selected', function() { - // Arrange - suggestionList.selected = null; - - // Act - var event = sendKeyDown(KEYS.tab); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('prevents the escape keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.escape); - - // Assert - expect(event.isDefaultPrevented()).toBe(true); - expect(event.isPropagationStopped()).toBe(true); - }); - }); - - describe('hotkeys - suggestion box is hidden', function() { - beforeEach(function() { - suggestionList.reset(); - }); - - it('does not prevent the down arrow keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.down); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('does not prevent the up arrow keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.up); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('does not prevent the enter keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.enter); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('does not prevent the tab keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.tab); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - - it('does not prevent the escape keydown event from being propagated', function() { - // Act - var event = sendKeyDown(KEYS.escape); - - // Assert - expect(event.isDefaultPrevented()).toBe(false); - expect(event.isPropagationStopped()).toBe(false); - }); - }); - - describe('non-hotkeys', function() { - it('does not prevent non-hotkeys keystrokes from being propagated', function() { - // Act - var events = [sendKeyDown(65), sendKeyDown(66), sendKeyDown(67)]; - - // Assert - expect(events[0].isDefaultPrevented()).toBe(false); - expect(events[0].isPropagationStopped()).toBe(false); - - expect(events[1].isDefaultPrevented()).toBe(false); - expect(events[1].isPropagationStopped()).toBe(false); - - expect(events[2].isDefaultPrevented()).toBe(false); - expect(events[2].isPropagationStopped()).toBe(false); - }); - }); - }); - describe('load-on-down-arrow option', function() { it('initializes the option to false', function() { // Arrange @@ -1308,4 +1157,149 @@ describe('autoComplete directive', function() { expect(scope.$getDisplayText).not.toBeUndefined(); }); }); + + describe('keys propagation handling', function() { + describe('hotkeys', function() { + var hotkeys = [KEYS.enter, KEYS.tab, KEYS.escape, KEYS.up, KEYS.down]; + + describe('suggestion box is visible', function() { + beforeEach(function() { + suggestionList.show(); + }); + + it('prevents the down arrow keydown event from being propagated', function() { + // Act + var event = sendKeyDown(KEYS.down); + + // Assert + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(true); + }); + + it('prevents the up arrow keydown event from being propagated', function() { + // Act + var event = sendKeyDown(KEYS.up); + + // Assert + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(true); + }); + + it('prevents the enter keydown event from being propagated if there is a suggestion selected', function() { + // Arrange + suggestionList.selected = 'suggestion'; + + // Act + var event = sendKeyDown(KEYS.enter); + + // Assert + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(true); + }); + + it('does not prevent the enter keydown event from begin propagated if there is no suggestion selected', function() { + // Arrange + suggestionList.selected = null; + + // Act + var event = sendKeyDown(KEYS.enter); + + // Assert + expect(event.isDefaultPrevented()).toBe(false); + expect(event.isPropagationStopped()).toBe(false); + }); + + it('prevents the tab keydown event from being propagated if there is a suggestion selected', function() { + // Arrange + suggestionList.selected = 'suggestion'; + + // Act + var event = sendKeyDown(KEYS.tab); + + // Assert + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(true); + }); + + it('does not prevent the tab keydown event from being propagated if there is no suggestion selected', function() { + // Arrange + suggestionList.selected = null; + + // Act + var event = sendKeyDown(KEYS.tab); + + // Assert + expect(event.isDefaultPrevented()).toBe(false); + expect(event.isPropagationStopped()).toBe(false); + }); + + it('prevents the escape keydown event from being propagated', function() { + // Act + var event = sendKeyDown(KEYS.escape); + + // Assert + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(true); + }); + }); + + describe('suggestion box is hidden', function() { + beforeEach(function() { + suggestionList.reset(); + }); + + hotkeys.forEach(function(hotkey) { + it('does not prevent the keydown event from being propagated (keycode ' + hotkey + ')', function() { + // Act + var event = sendKeyDown(hotkey); + + // Assert + expect(event.isDefaultPrevented()).toBe(false); + expect(event.isPropagationStopped()).toBe(false); + }); + }); + }); + + describe('modifier key is on', function() { + beforeEach(function() { + suggestionList.show(); + }); + + hotkeys.forEach(function(hotkey) { + it('does not prevent a hotkey from being propagated when the shift key is down (hotkey ' + hotkey + ')', function() { + expect(sendKeyDown(hotkey, { shiftKey: true }).isDefaultPrevented()).toBe(false); + }); + + it('does not prevent a hotkey from being propagated when the alt key is down (hotkey ' + hotkey + ')', function() { + expect(sendKeyDown(hotkey, { altKey: true }).isDefaultPrevented()).toBe(false); + }); + + it('does not prevent a hotkey from being propagated when the ctrl key is down (hotkey ' + hotkey + ')', function() { + expect(sendKeyDown(hotkey, { ctrlKey: true }).isDefaultPrevented()).toBe(false); + }); + + it('does not prevent a hotkey from being propagated when the meta key is down (hotkey ' + hotkey + ')', function() { + expect(sendKeyDown(hotkey, { metaKey: true }).isDefaultPrevented()).toBe(false); + }); + }); + }); + }); + + describe('non-hotkeys', function() { + it('does not prevent non-hotkeys keystrokes from being propagated', function() { + // Act + var events = [sendKeyDown(65), sendKeyDown(66), sendKeyDown(67)]; + + // Assert + expect(events[0].isDefaultPrevented()).toBe(false); + expect(events[0].isPropagationStopped()).toBe(false); + + expect(events[1].isDefaultPrevented()).toBe(false); + expect(events[1].isPropagationStopped()).toBe(false); + + expect(events[2].isDefaultPrevented()).toBe(false); + expect(events[2].isPropagationStopped()).toBe(false); + }); + }); + }); });