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' | 
