diff options
| author | Stephen Blott | 2015-01-19 13:42:31 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-01-20 06:50:08 +0000 |
| commit | 2cb0079bde5461490e0ae09286b2b3c75056fe1a (patch) | |
| tree | bd9b910ba34826709cd9933e52d75fb748dc0a00 | |
| parent | 97e61e29d59b9557fe1fb8d7ae1a34be1d47fcc1 (diff) | |
| download | vimium-2cb0079bde5461490e0ae09286b2b3c75056fe1a.tar.bz2 | |
Rework DOM tests (integrate keyboard-event handling).
This uses phantomjs to generate keyboard events. So the events are
propagated through the regular event listeners. So we're testing the
full keyboard-event flow.
| -rw-r--r-- | lib/handler_stack.coffee | 2 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 243 | ||||
| -rw-r--r-- | tests/dom_tests/phantom_runner.coffee | 12 |
3 files changed, 89 insertions, 168 deletions
diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee index b8049b81..3d635005 100644 --- a/lib/handler_stack.coffee +++ b/lib/handler_stack.coffee @@ -1,7 +1,6 @@ root = exports ? window class HandlerStack - constructor: -> @debug = false @eventNumber = 0 @@ -95,6 +94,7 @@ class HandlerStack label ||= if result then "continue/truthy" else "suppress" console.log "#{@eventNumber}", type, handler._name, label + # For tests only. reset: -> @stack = [] diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee index 8cae8289..06f505ed 100644 --- a/tests/dom_tests/dom_tests.coffee +++ b/tests/dom_tests/dom_tests.coffee @@ -1,18 +1,26 @@ -# -# Dispatching keyboard events via the DOM would require async tests, -# which tend to be more complicated. Here we create mock events and -# invoke the handlers directly. -# -mockKeyboardEvent = (keyChar) -> - event = {} - event.charCode = (if keyCodes[keyChar] isnt undefined then keyCodes[keyChar] else keyChar.charCodeAt(0)) - event.keyIdentifier = "U+00" + event.charCode.toString(16) - event.keyCode = event.charCode - event.stopImmediatePropagation = -> @suppressed = true - event.preventDefault = -> @suppressed = true - event - -# Some tests have side effects on the handler stack and the active mode, so these are reset as necessary. + +# Install frontend event handlers. +initializeWhenEnabled() + +installListener = (element, event, callback) -> + element.addEventListener event, (-> callback.apply(this, arguments)), true + +# A count of the number of keyboard events received by the page (for the most recently-sent keystroke). E.g., +# we expect 3 if the keystroke is passed through (keydown, keypress, keyup), and 0 if it is suppressed. +pageKeyboardEventCount = 0 + +sendKeyboardEvent = (key) -> + pageKeyboardEventCount = 0 + response = window.callPhantom + request: "keyboard" + key: key + +# These listeners receive events after the main frontend listeners, and do not receive suppressed events. +for type in [ "keydown", "keypress", "keyup" ] + installListener window, type, (event) -> + pageKeyboardEventCount += 1 + +# Some tests have side effects on the handler stack and the active mode, so these are reset on setup. initializeModeState = -> Mode.reset() handlerStack.reset() @@ -26,9 +34,6 @@ initializeModeState = -> handlerStack.bubbleEvent "registerKeyQueue", keyQueue: "" -# Install event handlers. -initializeWhenEnabled() - # # Retrieve the hint markers as an array object. # @@ -105,7 +110,7 @@ context "Alphabetical link hints", should "narrow the hints", -> hintMarkers = getHintMarkers() - LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("A") + sendKeyboardEvent "A" assert.equal "none", hintMarkers[1].style.display assert.equal "", hintMarkers[0].style.display @@ -135,12 +140,12 @@ context "Filtered link hints", should "narrow the hints", -> hintMarkers = getHintMarkers() - LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("T") - LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("R") + sendKeyboardEvent "T" + sendKeyboardEvent "R" assert.equal "none", hintMarkers[0].style.display assert.equal "1", hintMarkers[1].hintString assert.equal "", hintMarkers[1].style.display - LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("A") + sendKeyboardEvent "A" assert.equal "2", hintMarkers[3].hintString context "Image hints", @@ -293,23 +298,21 @@ createLinks = (n) -> link.textContent = "test" document.getElementById("test-div").appendChild link -# For these tests, we use "m" as a mapped key, "p" as a pass key, and "u" as an unmapped key. context "Normal mode", setup -> initializeModeState() should "suppress mapped keys", -> - for k in [ "m", "p" ] - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "p" - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed + sendKeyboardEvent "m" + assert.equal pageKeyboardEventCount, 0 should "not suppress unmapped keys", -> - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent event, key - assert.isFalse key.suppressed + sendKeyboardEvent "u" + assert.equal pageKeyboardEventCount, 3 + + should "not suppress escape", -> + sendKeyboardEvent "escape" + assert.equal pageKeyboardEventCount, 2 context "Passkeys mode", setup -> @@ -318,56 +321,33 @@ context "Passkeys mode", enabled: true passKeys: "p" - should "not suppress passKeys, but suppress other mapped keys", -> - # Verify passKey. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "p" - handlerStack.bubbleEvent event, key - assert.isFalse key.suppressed + should "suppress mapped keys", -> + sendKeyboardEvent "m" + assert.equal pageKeyboardEventCount, 0 - # Verify mapped key. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "m" - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed + should "not suppress passKeys", -> + sendKeyboardEvent "p" + assert.equal pageKeyboardEventCount, 3 should "suppress passKeys with a non-empty keyQueue", -> - handlerStack.bubbleEvent "registerKeyQueue", - keyQueue: "p" - - # Verify that the passKey is indeed now suppressed. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "p" - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed + handlerStack.bubbleEvent "registerKeyQueue", keyQueue: "p" + sendKeyboardEvent "p" + assert.equal pageKeyboardEventCount, 0 context "Insert mode", setup -> initializeModeState() should "not suppress mapped keys in insert mode", -> - # First verify normal-mode key (just to verify the framework). - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "m" - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed - - # Install insert mode. insertMode = new InsertMode global: true + sendKeyboardEvent "m" + assert.equal pageKeyboardEventCount, 3 - # Then verify insert mode. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "m" - handlerStack.bubbleEvent event, key - assert.isFalse key.suppressed - + should "resume normal mode after insert mode", -> + insertMode = new InsertMode global: true insertMode.exit() - - # Then verify that insert mode has been successfully removed. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "m" - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed + sendKeyboardEvent "m" + assert.equal pageKeyboardEventCount, 0 context "Triggering insert mode", setup -> @@ -409,12 +389,6 @@ context "Triggering insert mode", document.getElementById("first").focus() assert.isTrue Mode.top().name == "insert" and Mode.top().isActive() - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "m" - InsertMode.suppressEvent key - handlerStack.bubbleEvent event, key - assert.isTrue key.suppressed - context "Mode utilities", setup -> initializeModeState() @@ -448,51 +422,41 @@ context "Mode utilities", assert.isTrue count == 0 should "exit on escape", -> - escape = - keyCode: 27 - - assert.isTrue Mode.top().name == "insert" new Mode exitOnEscape: true name: "test" assert.isTrue Mode.top().name == "test" - handlerStack.bubbleEvent "keydown", escape - assert.isTrue Mode.top().name == "insert" + sendKeyboardEvent "escape" + assert.equal pageKeyboardEventCount, 0 + assert.isTrue Mode.top().name != "test" should "not exit on escape if not enabled", -> - escape = - keyCode: 27 - keyIdentifier: "" - stopImmediatePropagation: -> - - assert.isTrue Mode.top().name == "insert" new Mode exitOnEscape: false name: "test" assert.isTrue Mode.top().name == "test" - handlerStack.bubbleEvent "keydown", escape + sendKeyboardEvent "escape" + assert.equal pageKeyboardEventCount, 2 assert.isTrue Mode.top().name == "test" should "exit on blur", -> element = document.getElementById("first") element.focus() - assert.isTrue Mode.top().name == "insert" new Mode exitOnBlur: element name: "test" assert.isTrue Mode.top().name == "test" element.blur() - assert.isTrue Mode.top().name == "insert" + assert.isTrue Mode.top().name != "test" should "not exit on blur if not enabled", -> element = document.getElementById("first") element.focus() - assert.isTrue Mode.top().name == "insert" new Mode exitOnBlur: null name: "test" @@ -518,41 +482,6 @@ context "Mode utilities", assert.isTrue test.enabled == "enabled" assert.isTrue test.passKeys == "passKeys" - should "suppress printable keys", -> - element = document.getElementById("first") - element.focus() - - # Verify that a key is not suppressed. - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent event, key - assert.isFalse key.suppressed - - new PostFindMode {} - - # Verify that the key is now suppressed for keypress. - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent "keypress", - extend key, - srcElement: element - assert.isTrue key.suppressed - - # Verify key is not suppressed with Control key. - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent "keypress", - extend key, - srcElement: element - ctrlKey: true - assert.isFalse key.suppressed - - # Verify key is not suppressed with Meta key. - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent "keypress", - extend key, - srcElement: element - metaKey: true - assert.isFalse key.suppressed - context "PostFindMode", setup -> initializeModeState() @@ -561,62 +490,44 @@ context "PostFindMode", <input style='display:none;' id='second'/> <input type='password' id='third' value='some value'/>" document.getElementById("test-div").innerHTML = testContent - - @escape = - keyCode: 27 - keyIdentifier: "" - stopImmediatePropagation: -> - preventDefault: -> - - @element = document.getElementById("first") - @element.focus() + document.getElementById("first").focus() tearDown -> document.getElementById("test-div").innerHTML = "" should "be a singleton", -> assert.isTrue Mode.top().name == "insert" - new PostFindMode @element + new PostFindMode assert.isTrue Mode.top().name == "post-find" - new PostFindMode @element + new PostFindMode assert.isTrue Mode.top().name == "post-find" Mode.top().exit() assert.isTrue Mode.top().name == "insert" - should "suppress unmapped printable keypress events", -> - testKeys = (verify) -> - for event in [ "keydown", "keypress", "keyup" ] - key = mockKeyboardEvent "u" - handlerStack.bubbleEvent event, - extend key, - srcElement: @element - verify key.suppressed - - # Verify key is passed through. - testKeys assert.isFalse - + should "suppress unmapped printable keys", -> new PostFindMode - - # Verify key is now suppressed for keypress. - testKeys assert.isTrue + sendKeyboardEvent "m" + assert.equal pageKeyboardEventCount, 0 should "be clickable to focus", -> - new PostFindMode @element - assert.isTrue Mode.top().name != "insert" + new PostFindMode + assert.isTrue Mode.top().name == "post-find" handlerStack.bubbleEvent "click", target: document.activeElement - assert.isTrue Mode.top().name == "insert" + assert.isTrue Mode.top().name != "post-find" should "enter insert mode on immediate escape", -> - new PostFindMode @element + new PostFindMode assert.isTrue Mode.top().name == "post-find" - handlerStack.bubbleEvent "keydown", @escape + sendKeyboardEvent "escape" + assert.equal pageKeyboardEventCount, 0 assert.isTrue Mode.top().name == "insert" - should "not enter insert mode on subsequent escape", -> - new PostFindMode @element + should "not enter insert mode on subsequent escapes", -> + new PostFindMode assert.isTrue Mode.top().name == "post-find" - handlerStack.bubbleEvent "keydown", mockKeyboardEvent "u" - handlerStack.bubbleEvent "keydown", @escape + sendKeyboardEvent "a" + sendKeyboardEvent "escape" + assert.equal pageKeyboardEventCount, 0 assert.isTrue Mode.top().name == "post-find" context "Mode badges", @@ -646,7 +557,7 @@ context "Mode badges", document.getElementById("first").focus() assert.isTrue chromeMessages[0].badge == "I" - should "have no badge after insert mode by focus", -> + should "have no badge after leaving insert mode by focus", -> document.getElementById("first").focus() document.getElementById("first").blur() assert.isTrue chromeMessages[0].badge == "" @@ -655,7 +566,7 @@ context "Mode badges", new InsertMode global: true assert.isTrue chromeMessages[0].badge == "I" - should "have no badge after global insert mode", -> + should "have no badge after leaving global insert mode", -> mode = new InsertMode global: true mode.exit() assert.isTrue chromeMessages[0].badge == "" @@ -668,7 +579,7 @@ context "Mode badges", should "have no badge in PostFindMode (subsequently)", -> document.getElementById("first").focus() new PostFindMode - handlerStack.bubbleEvent "keydown", mockKeyboardEvent "u" + sendKeyboardEvent "a" assert.isTrue chromeMessages[0].badge == "" should "have no badge when disabled", -> @@ -676,6 +587,6 @@ context "Mode badges", enabled: false passKeys: "" - element = document.getElementById("first").focus() + document.getElementById("first").focus() assert.isTrue chromeMessages[0].badge == "" diff --git a/tests/dom_tests/phantom_runner.coffee b/tests/dom_tests/phantom_runner.coffee index d05d9ab4..93218724 100644 --- a/tests/dom_tests/phantom_runner.coffee +++ b/tests/dom_tests/phantom_runner.coffee @@ -14,13 +14,23 @@ page.onConsoleMessage = (msg) -> console.log msg page.onError = (msg, trace) -> - console.log(msg); + console.log(msg) trace.forEach (item) -> console.log(' ', item.file, ':', item.line) page.onResourceError = (resourceError) -> console.log(resourceError.errorString) +page.onCallback = (request) -> + switch request.request + when "keyboard" + switch request.key + when "escape" + page.sendEvent "keydown", page.event.key.Escape + page.sendEvent "keyup", page.event.key.Escape + else + page.sendEvent "keypress", request.key + testfile = path.join(path.dirname(system.args[0]), 'dom_tests.html') page.open testfile, (status) -> if status != 'success' |
