From 26ff39d355f7d405eeb1b1394afbb677fa01e4a2 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Mon, 19 Jan 2015 05:39:24 +0000
Subject: Rework DOM tests.
- Set up modes such that they can be re-initialised.
- Move initialisation of BadgeMode to general initialisation function.
- Add reset() method for handlerStack.
- Consistently use initializeModeState() in all tests' setup().
- Refactor focusInput tests.
- Add some more tests.
- Simplify some other tests.
Note: Clean-up of the inputFocus overlay now happens when the exit()
method is called in Mode.reset(). This eliminates most needs to
artificially bubble a keyboard event to clear the overlay.
---
content_scripts/mode.coffee | 12 +-
content_scripts/vimium_frontend.coffee | 21 ++-
lib/handler_stack.coffee | 3 +
tests/dom_tests/chrome.coffee | 5 +-
tests/dom_tests/dom_tests.coffee | 297 +++++++++++++++------------------
5 files changed, 167 insertions(+), 171 deletions(-)
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index acc3978e..42ea9930 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -169,14 +169,19 @@ class Mode
log: (args...) ->
console.log args... if @debug
- # Return the must-recently activated mode (only used in tests).
+ # For tests only.
@top: ->
@modes[@modes.length-1]
+ # For tests only.
+ @reset: ->
+ mode.exit() for mode in @modes
+ @modes = []
+
# BadgeMode is a pseudo mode for triggering badge updates on focus changes and state updates. It sits at the
# bottom of the handler stack, and so it receives state changes *after* all other modes, and can override the
-# badge choice of the other modes. We create the the one-and-only instance here.
-new class BadgeMode extends Mode
+# badge choice of the other modes.
+class BadgeMode extends Mode
constructor: () ->
super
name: "badge"
@@ -200,3 +205,4 @@ new class BadgeMode extends Mode
root = exports ? window
root.Mode = Mode
+root.BadgeMode = BadgeMode
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index fdd36ab9..643f9c6b 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -103,13 +103,8 @@ frameId = Math.floor(Math.random()*999999999)
hasModifiersRegex = /^<([amc]-)+.>/
-#
-# Complete initialization work that sould be done prior to DOMReady.
-#
-initializePreDomReady = ->
- settings.addEventListener("load", LinkHints.init.bind(LinkHints))
- settings.load()
-
+# Only exported for tests.
+window.initializeModes = ->
class NormalMode extends Mode
constructor: ->
super
@@ -122,12 +117,20 @@ initializePreDomReady = ->
# Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and
# activates/deactivates itself accordingly.
+ new BadgeMode
new NormalMode
new PassKeysMode
new InsertMode permanent: true
- checkIfEnabledForUrl()
+#
+# Complete initialization work that sould be done prior to DOMReady.
+#
+initializePreDomReady = ->
+ settings.addEventListener("load", LinkHints.init.bind(LinkHints))
+ settings.load()
+ initializeModes()
+ checkIfEnabledForUrl()
refreshCompletionKeys()
# Send the key to the key handler in the background page.
@@ -179,7 +182,7 @@ installListener = (element, event, callback) ->
# Run this as early as possible, so the page can't register any event handlers before us.
#
installedListeners = false
-initializeWhenEnabled = (newPassKeys) ->
+window.initializeWhenEnabled = (newPassKeys) ->
isEnabledForUrl = true
passKeys = newPassKeys
if (!installedListeners)
diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee
index 76d835b7..b8049b81 100644
--- a/lib/handler_stack.coffee
+++ b/lib/handler_stack.coffee
@@ -95,5 +95,8 @@ class HandlerStack
label ||= if result then "continue/truthy" else "suppress"
console.log "#{@eventNumber}", type, handler._name, label
+ reset: ->
+ @stack = []
+
root.HandlerStack = HandlerStack
root.handlerStack = new HandlerStack()
diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee
index ad4ae74b..2e7c6a5a 100644
--- a/tests/dom_tests/chrome.coffee
+++ b/tests/dom_tests/chrome.coffee
@@ -3,6 +3,9 @@
#
root = exports ? window
+root.chromeMessages = []
+
+document.hasFocus = -> true
root.chrome = {
runtime: {
@@ -18,7 +21,7 @@ root.chrome = {
onMessage: {
addListener: ->
}
- sendMessage: ->
+ sendMessage: (message) -> chromeMessages.unshift message
getManifest: ->
getURL: (url) -> "../../#{url}"
}
diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee
index 33177c59..d8b499f2 100644
--- a/tests/dom_tests/dom_tests.coffee
+++ b/tests/dom_tests/dom_tests.coffee
@@ -12,18 +12,22 @@ mockKeyboardEvent = (keyChar) ->
event.preventDefault = -> @suppressed = true
event
-# Some of these tests have side effects on the handler stack and active mode. Therefore, we take backups and
-# restore them on tear down.
-backupStackState = ->
- Mode.backup = Mode.modes[..]
- InsertMode.permanentInstance.exit()
- handlerStack.backup = handlerStack.stack[..]
-restoreStackState = ->
- for mode in Mode.modes
- mode.exit() unless mode in Mode.backup
- Mode.modes = Mode.backup
- InsertMode.permanentInstance.exit()
- handlerStack.stack = handlerStack.backup
+# Some tests have side effects on the handler stack and the active mode, so these are reset as necessary.
+initializeModeState = ->
+ Mode.reset()
+ handlerStack.reset()
+ initializeModes()
+ # We use "m" as the only mapped key, "p" as a passkey (sometimes), and "u" as an unmapped key.
+ refreshCompletionKeys
+ completionKeys: "mp"
+ handlerStack.bubbleEvent "registerStateChange",
+ enabled: true
+ passKeys: ""
+ handlerStack.bubbleEvent "registerKeyQueue",
+ keyQueue: ""
+
+# Install event handlers.
+initializeWhenEnabled()
#
# Retrieve the hint markers as an array object.
@@ -40,6 +44,7 @@ createGeneralHintTests = (isFilteredMode) ->
context "Link hints",
setup ->
+ initializeModeState()
testContent = "test" + "tress"
document.getElementById("test-div").innerHTML = testContent
stub settings.values, "filterLinkHints", false
@@ -77,6 +82,7 @@ createGeneralHintTests true
context "Alphabetical link hints",
setup ->
+ initializeModeState()
stub settings.values, "filterLinkHints", false
stub settings.values, "linkHintCharacters", "ab"
@@ -112,6 +118,7 @@ context "Filtered link hints",
context "Text hints",
setup ->
+ initializeModeState()
testContent = "test" + "tress" + "trait" + "track
"
document.getElementById("test-div").innerHTML = testContent
LinkHints.init()
@@ -139,6 +146,7 @@ context "Filtered link hints",
context "Image hints",
setup ->
+ initializeModeState()
testContent = "![alt text]()
" + "
"
document.getElementById("test-div").innerHTML = testContent
@@ -158,6 +166,7 @@ context "Filtered link hints",
context "Input hints",
setup ->
+ initializeModeState()
testContent = "
a label
@@ -180,33 +189,38 @@ context "Filtered link hints",
context "Input focus",
setup ->
+ initializeModeState()
testContent = "
"
document.getElementById("test-div").innerHTML = testContent
- backupStackState()
tearDown ->
document.getElementById("test-div").innerHTML = ""
- restoreStackState()
- should "focus the right element", ->
+ should "focus the first element", ->
focusInput 1
assert.equal "first", document.activeElement.id
+ should "focus the nth element", ->
focusInput 100
assert.equal "third", document.activeElement.id
- handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A")
- # This is the same as above, but also verifies that focusInput activates insert mode.
- should "activate insert mode", ->
+ should "activate insert mode on the first element", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
focusInput 1
- handlerStack.bubbleEvent 'focus', target: document.activeElement
assert.isTrue InsertMode.permanentInstance.isActive()
+ should "activate insert mode on the first element", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
focusInput 100
- handlerStack.bubbleEvent 'focus', target: document. activeElement
assert.isTrue InsertMode.permanentInstance.isActive()
+ should "not trigger insert if there are no inputs", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+ document.getElementById("test-div").innerHTML = ""
+ focusInput 1
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+
# TODO: these find prev/next link tests could be refactored into unit tests which invoke a function which has
# a tighter contract than goNext(), since they test minor aspects of goNext()'s link matching behavior, and we
# don't need to construct external state many times over just to test that.
@@ -216,6 +230,7 @@ context "Input focus",
context "Find prev / next links",
setup ->
+ initializeModeState()
window.location.hash = ""
should "find exact matches", ->
@@ -275,19 +290,14 @@ createLinks = (n) ->
# 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 ->
- document.activeElement?.blur()
- backupStackState()
- refreshCompletionKeys
- completionKeys: "m"
-
- tearDown ->
- restoreStackState()
+ initializeModeState()
should "suppress mapped keys", ->
- for event in [ "keydown", "keypress", "keyup" ]
- key = mockKeyboardEvent "m"
- handlerStack.bubbleEvent event, key
- assert.isTrue key.suppressed
+ for k in [ "m", "p" ]
+ for event in [ "keydown", "keypress", "keyup" ]
+ key = mockKeyboardEvent "p"
+ handlerStack.bubbleEvent event, key
+ assert.isTrue key.suppressed
should "not suppress unmapped keys", ->
for event in [ "keydown", "keypress", "keyup" ]
@@ -297,67 +307,29 @@ context "Normal mode",
context "Passkeys mode",
setup ->
- backupStackState()
- refreshCompletionKeys
- completionKeys: "mp"
-
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: ""
-
- handlerStack.bubbleEvent "registerKeyQueue",
- keyQueue: ""
-
- tearDown ->
- restoreStackState()
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: ""
-
- handlerStack.bubbleEvent "registerKeyQueue",
- keyQueue: ""
-
- should "not suppress passKeys", ->
- # First check normal-mode key (just to verify the framework).
- for k in [ "m", "p" ]
- for event in [ "keydown", "keypress", "keyup" ]
- key = mockKeyboardEvent "p"
- handlerStack.bubbleEvent event, key
- assert.isTrue key.suppressed
-
- # Install passKey.
+ initializeModeState()
handlerStack.bubbleEvent "registerStateChange",
enabled: true
passKeys: "p"
- # Then verify passKey.
+ 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
- # And re-verify a mapped key.
+ # Verify mapped key.
for event in [ "keydown", "keypress", "keyup" ]
key = mockKeyboardEvent "m"
handlerStack.bubbleEvent event, key
assert.isTrue key.suppressed
should "suppress passKeys with a non-empty keyQueue", ->
- # Install passKey.
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: "p"
-
- # First check the key is indeed not suppressed.
- for event in [ "keydown", "keypress", "keyup" ]
- key = mockKeyboardEvent "p"
- handlerStack.bubbleEvent event, key
- assert.isFalse key.suppressed
-
handlerStack.bubbleEvent "registerKeyQueue",
- keyQueue: "1"
+ keyQueue: "p"
- # Now verify that the key is suppressed.
+ # Verify that the passKey is indeed now suppressed.
for event in [ "keydown", "keypress", "keyup" ]
key = mockKeyboardEvent "p"
handlerStack.bubbleEvent event, key
@@ -365,13 +337,7 @@ context "Passkeys mode",
context "Insert mode",
setup ->
- document.activeElement?.blur()
- backupStackState()
- refreshCompletionKeys
- completionKeys: "m"
-
- tearDown ->
- backupStackState()
+ initializeModeState()
should "not suppress mapped keys in insert mode", ->
# First verify normal-mode key (just to verify the framework).
@@ -381,8 +347,7 @@ context "Insert mode",
assert.isTrue key.suppressed
# Install insert mode.
- insertMode = new InsertMode
- global: true
+ insertMode = new InsertMode global: true
# Then verify insert mode.
for event in [ "keydown", "keypress", "keyup" ]
@@ -400,57 +365,53 @@ context "Insert mode",
context "Triggering insert mode",
setup ->
- document.activeElement?.blur()
- backupStackState()
- refreshCompletionKeys
- completionKeys: "m"
+ initializeModeState()
testContent = "
- "
+
+
+ "
document.getElementById("test-div").innerHTML = testContent
tearDown ->
- restoreStackState()
+ document.activeElement?.blur()
document.getElementById("test-div").innerHTML = ""
should "trigger insert mode on focus of contentEditable elements", ->
- handlerStack.bubbleEvent "focus",
- target:
- isContentEditable: true
-
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+ document.getElementById("fourth").focus()
assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
should "trigger insert mode on focus of text input", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("first").focus()
- handlerStack.bubbleEvent "focus", { target: document.activeElement }
-
assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
should "trigger insert mode on focus of password input", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("third").focus()
- handlerStack.bubbleEvent "focus", { target: document.activeElement }
-
assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
+ should "not trigger insert mode on other elements", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+ document.getElementById("fifth").focus()
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+
should "not handle suppressed events", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("first").focus()
- handlerStack.bubbleEvent "focus", { target: document.activeElement }
assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
for event in [ "keydown", "keypress", "keyup" ]
- # Because "m" is mapped, we expect insert mode to ignore it, and normal mode to suppress it.
key = mockKeyboardEvent "m"
InsertMode.suppressEvent key
handlerStack.bubbleEvent event, key
assert.isTrue key.suppressed
-
context "Mode utilities",
setup ->
- backupStackState()
- refreshCompletionKeys
- completionKeys: "m"
+ initializeModeState()
testContent = "
@@ -458,7 +419,6 @@ context "Mode utilities",
document.getElementById("test-div").innerHTML = testContent
tearDown ->
- restoreStackState()
document.getElementById("test-div").innerHTML = ""
should "not have duplicate singletons", ->
@@ -485,13 +445,14 @@ context "Mode utilities",
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 != "test"
+ assert.isTrue Mode.top().name == "insert"
should "not exit on escape if not enabled", ->
escape =
@@ -499,6 +460,7 @@ context "Mode utilities",
keyIdentifier: ""
stopImmediatePropagation: ->
+ assert.isTrue Mode.top().name == "insert"
new Mode
exitOnEscape: false
name: "test"
@@ -511,25 +473,27 @@ context "Mode utilities",
element = document.getElementById("first")
element.focus()
+ assert.isTrue Mode.top().name == "insert"
new Mode
exitOnBlur: element
name: "test"
assert.isTrue Mode.top().name == "test"
- handlerStack.bubbleEvent "blur", { target: element }
- assert.isTrue Mode.top().name != "test"
+ element.blur()
+ assert.isTrue Mode.top().name == "insert"
- should "not exit on blur if not enabled", ->
- element = document.getElementById("first")
- element.focus()
+ should "not exit on blur if not enabled", ->
+ element = document.getElementById("first")
+ element.focus()
- new Mode
- exitOnBlur: null
- name: "test"
+ assert.isTrue Mode.top().name == "insert"
+ new Mode
+ exitOnBlur: null
+ name: "test"
- assert.isTrue Mode.top().name == "test"
- handlerStack.bubbleEvent "blur", { target: element }
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue Mode.top().name == "test"
+ element.blur()
+ assert.isTrue Mode.top().name == "test"
should "register state change", ->
enabled = null
@@ -540,21 +504,17 @@ context "Mode utilities",
super
trackState: true
- registerStateChange: ->
- enabled = @enabled
- passKeys = @passKeys
-
- new Test()
+ test = new Test()
handlerStack.bubbleEvent "registerStateChange",
enabled: "enabled"
passKeys: "passKeys"
- assert.isTrue enabled == "enabled"
- assert.isTrue passKeys == "passKeys"
+
+ assert.isTrue test.enabled == "enabled"
+ assert.isTrue test.passKeys == "passKeys"
should "suppress printable keys", ->
element = document.getElementById("first")
element.focus()
- handlerStack.bubbleEvent "focus", { target: document.activeElement }
# Verify that a key is not suppressed.
for event in [ "keydown", "keypress", "keyup" ]
@@ -589,9 +549,7 @@ context "Mode utilities",
context "PostFindMode",
setup ->
- backupStackState()
- refreshCompletionKeys
- completionKeys: "m"
+ initializeModeState()
testContent = "
@@ -606,15 +564,11 @@ context "PostFindMode",
@element = document.getElementById("first")
@element.focus()
- handlerStack.bubbleEvent "focus", { target: document.activeElement }
tearDown ->
- restoreStackState()
document.getElementById("test-div").innerHTML = ""
should "be a singleton", ->
- count = 0
-
assert.isTrue Mode.top().name == "insert"
new PostFindMode @element
assert.isTrue Mode.top().name == "post-find"
@@ -624,30 +578,29 @@ context "PostFindMode",
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.
- for event in [ "keydown", "keypress", "keyup" ]
- key = mockKeyboardEvent "u"
- handlerStack.bubbleEvent event, key
- assert.isFalse key.suppressed
+ testKeys assert.isFalse
- new PostFindMode @element
+ new PostFindMode
# Verify key is now suppressed for keypress.
- key = mockKeyboardEvent "u"
- handlerStack.bubbleEvent "keypress",
- extend key,
- srcElement: @element
- assert.isTrue key.suppressed
+ testKeys assert.isTrue
should "be clickable to focus", ->
new PostFindMode @element
-
assert.isTrue Mode.top().name != "insert"
- handlerStack.bubbleEvent "click", { target: document.activeElement }
+ handlerStack.bubbleEvent "click", target: document.activeElement
assert.isTrue Mode.top().name == "insert"
should "enter insert mode on immediate escape", ->
-
new PostFindMode @element
assert.isTrue Mode.top().name == "post-find"
handlerStack.bubbleEvent "keydown", @escape
@@ -662,33 +615,61 @@ context "PostFindMode",
context "Mode badges",
setup ->
- backupStackState()
+ initializeModeState()
+
+ testContent = "
+
+ "
+ document.getElementById("test-div").innerHTML = testContent
tearDown ->
- restoreStackState()
+ document.getElementById("test-div").innerHTML = ""
should "have no badge without passKeys", ->
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: ""
-
- handlerStack.bubbleEvent "updateBadge", badge = { badge: "" }
- assert.isTrue badge.badge == ""
+ Mode.updateBadge()
+ assert.isTrue chromeMessages[0].badge == ""
should "have no badge with passKeys", ->
handlerStack.bubbleEvent "registerStateChange",
enabled: true
passKeys: "p"
+ Mode.updateBadge()
+ assert.isTrue chromeMessages[0].badge == ""
+
+ should "have an I badge in insert mode by focus", ->
+ document.getElementById("first").focus()
+ assert.isTrue chromeMessages[0].badge == "I"
+
+ should "have no badge after insert mode by focus", ->
+ document.getElementById("first").focus()
+ document.getElementById("first").blur()
+ assert.isTrue chromeMessages[0].badge == ""
+
+ should "have an I badge in global insert mode", ->
+ new InsertMode global: true
+ assert.isTrue chromeMessages[0].badge == "I"
- handlerStack.bubbleEvent "updateBadge", badge = { badge: "" }
- assert.isTrue badge.badge == ""
+ should "have no badge after global insert mode", ->
+ mode = new InsertMode global: true
+ mode.exit()
+ assert.isTrue chromeMessages[0].badge == ""
+
+ should "have a ? badge in PostFindMode (immediately)", ->
+ document.getElementById("first").focus()
+ new PostFindMode
+ assert.isTrue chromeMessages[0].badge == "?"
+
+ should "have no badge in PostFindMode (subsequently)", ->
+ document.getElementById("first").focus()
+ new PostFindMode
+ handlerStack.bubbleEvent "keydown", mockKeyboardEvent "u"
+ assert.isTrue chromeMessages[0].badge == ""
should "have no badge when disabled", ->
handlerStack.bubbleEvent "registerStateChange",
enabled: false
passKeys: ""
- new InsertMode()
- handlerStack.bubbleEvent "updateBadge", badge = { badge: "" }
- assert.isTrue badge.badge == ""
+ element = document.getElementById("first").focus()
+ assert.isTrue chromeMessages[0].badge == ""
--
cgit v1.2.3
From bbfcacbd944527ef403dd04f2b36ec0f74934d16 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Mon, 19 Jan 2015 13:42:31 +0000
Subject: 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.
---
content_scripts/mode_passkeys.coffee | 2 +-
lib/handler_stack.coffee | 2 +-
tests/dom_tests/dom_tests.coffee | 243 +++++++++++-----------------------
tests/dom_tests/phantom_runner.coffee | 12 +-
4 files changed, 90 insertions(+), 169 deletions(-)
diff --git a/content_scripts/mode_passkeys.coffee b/content_scripts/mode_passkeys.coffee
index 94a7c7ec..64db5447 100644
--- a/content_scripts/mode_passkeys.coffee
+++ b/content_scripts/mode_passkeys.coffee
@@ -6,7 +6,7 @@ class PassKeysMode extends Mode
trackState: true # Maintain @enabled, @passKeys and @keyQueue.
keydown: (event) => @handleKeyChar KeyboardUtils.getKeyChar event
keypress: (event) => @handleKeyChar String.fromCharCode event.charCode
- keyup: (event) => @handleKeyChar String.fromCharCode event.charCode
+ keyup: (event) => @handleKeyChar KeyboardUtils.getKeyChar event
# Keystrokes are *never* considered passKeys if the keyQueue is not empty. So, for example, if 't' is a
# passKey, then 'gt' and '99t' will neverthless be handled by Vimium.
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 d8b499f2..3a134d28 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",
@@ -287,23 +292,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 ->
@@ -312,56 +315,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 ->
@@ -403,12 +383,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()
@@ -442,51 +416,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"
@@ -512,41 +476,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()
@@ -555,62 +484,44 @@ context "PostFindMode",
"
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",
@@ -640,7 +551,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 == ""
@@ -649,7 +560,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 == ""
@@ -662,7 +573,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", ->
@@ -670,6 +581,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'
--
cgit v1.2.3
From ec1add1a10c216d84462cc8afcf7cf0a27dce90e Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Tue, 20 Jan 2015 05:27:56 +0000
Subject: Rework DOM tests (clean up).
---
content_scripts/mode_insert.coffee | 2 +-
tests/dom_tests/dom_tests.coffee | 157 ++++++++++++-------------------------
2 files changed, 51 insertions(+), 108 deletions(-)
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index eac4a3d0..6932f419 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -48,7 +48,7 @@ class InsertMode extends Mode
if @insertModeLock != event.target and DomUtils.isFocusable event.target
@activateOnElement event.target
- # Only for tests. This gives us a hook to test the status of the permanent instance.
+ # Only for tests. This gives us a hook to test the status of the permanently-installed instance.
InsertMode.permanentInstance = @ if @permanent
isActive: (event) ->
diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee
index 3a134d28..b0ee1a66 100644
--- a/tests/dom_tests/dom_tests.coffee
+++ b/tests/dom_tests/dom_tests.coffee
@@ -25,12 +25,12 @@ initializeModeState = ->
Mode.reset()
handlerStack.reset()
initializeModes()
- # We use "m" as the only mapped key, "p" as a passkey (sometimes), and "u" as an unmapped key.
+ # We use "m" as the only mapped key, "p" as a passkey, and "u" as an unmapped key.
refreshCompletionKeys
completionKeys: "mp"
handlerStack.bubbleEvent "registerStateChange",
enabled: true
- passKeys: ""
+ passKeys: "p"
handlerStack.bubbleEvent "registerKeyQueue",
keyQueue: ""
@@ -211,20 +211,17 @@ context "Input focus",
assert.equal "third", document.activeElement.id
should "activate insert mode on the first element", ->
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
focusInput 1
assert.isTrue InsertMode.permanentInstance.isActive()
should "activate insert mode on the first element", ->
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
focusInput 100
assert.isTrue InsertMode.permanentInstance.isActive()
should "not trigger insert if there are no inputs", ->
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("test-div").innerHTML = ""
focusInput 1
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+ assert.isFalse InsertMode.permanentInstance.isActive()
# TODO: these find prev/next link tests could be refactored into unit tests which invoke a function which has
# a tighter contract than goNext(), since they test minor aspects of goNext()'s link matching behavior, and we
@@ -308,17 +305,6 @@ context "Normal mode",
sendKeyboardEvent "escape"
assert.equal pageKeyboardEventCount, 2
-context "Passkeys mode",
- setup ->
- initializeModeState()
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: "p"
-
- should "suppress mapped keys", ->
- sendKeyboardEvent "m"
- assert.equal pageKeyboardEventCount, 0
-
should "not suppress passKeys", ->
sendKeyboardEvent "p"
assert.equal pageKeyboardEventCount, 3
@@ -331,15 +317,19 @@ context "Passkeys mode",
context "Insert mode",
setup ->
initializeModeState()
+ @insertMode = new InsertMode global: true
should "not suppress mapped keys in insert mode", ->
- insertMode = new InsertMode global: true
sendKeyboardEvent "m"
assert.equal pageKeyboardEventCount, 3
- should "resume normal mode after insert mode", ->
- insertMode = new InsertMode global: true
- insertMode.exit()
+ should "exit on escape", ->
+ assert.isTrue @insertMode.modeIsActive
+ sendKeyboardEvent "escape"
+ assert.isFalse @insertMode.modeIsActive
+
+ should "resume normal mode after leaving insert mode", ->
+ @insertMode.exit()
sendKeyboardEvent "m"
assert.equal pageKeyboardEventCount, 0
@@ -358,11 +348,6 @@ context "Triggering insert mode",
document.activeElement?.blur()
document.getElementById("test-div").innerHTML = ""
- should "trigger insert mode on focus of contentEditable elements", ->
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
- document.getElementById("fourth").focus()
- assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
-
should "trigger insert mode on focus of text input", ->
assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("first").focus()
@@ -373,16 +358,16 @@ context "Triggering insert mode",
document.getElementById("third").focus()
assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
+ should "trigger insert mode on focus of contentEditable elements", ->
+ assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
+ document.getElementById("fourth").focus()
+ assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
+
should "not trigger insert mode on other elements", ->
assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
document.getElementById("fifth").focus()
assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
- should "not handle suppressed events", ->
- assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive()
- document.getElementById("first").focus()
- assert.isTrue Mode.top().name == "insert" and Mode.top().isActive()
-
context "Mode utilities",
setup ->
initializeModeState()
@@ -399,151 +384,109 @@ context "Mode utilities",
count = 0
class Test extends Mode
- constructor: ->
- count += 1
- super
- singleton: Test
-
- exit: ->
- count -= 1
- super()
+ constructor: -> count += 1; super singleton: Test
+ exit: -> count -= 1; super()
assert.isTrue count == 0
for [1..10]
- mode = new Test(); assert.isTrue count == 1
+ mode = new Test()
+ assert.isTrue count == 1
mode.exit()
assert.isTrue count == 0
should "exit on escape", ->
- new Mode
- exitOnEscape: true
- name: "test"
+ test = new Mode exitOnEscape: true
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
sendKeyboardEvent "escape"
assert.equal pageKeyboardEventCount, 0
- assert.isTrue Mode.top().name != "test"
+ assert.isFalse test.modeIsActive
should "not exit on escape if not enabled", ->
- new Mode
- exitOnEscape: false
- name: "test"
+ test = new Mode exitOnEscape: false
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
sendKeyboardEvent "escape"
assert.equal pageKeyboardEventCount, 2
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
should "exit on blur", ->
element = document.getElementById("first")
element.focus()
+ test = new Mode exitOnBlur: element
- new Mode
- exitOnBlur: element
- name: "test"
-
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
element.blur()
- assert.isTrue Mode.top().name != "test"
+ assert.isFalse test.modeIsActive
should "not exit on blur if not enabled", ->
element = document.getElementById("first")
element.focus()
+ test = new Mode exitOnBlur: false
- new Mode
- exitOnBlur: null
- name: "test"
-
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
element.blur()
- assert.isTrue Mode.top().name == "test"
+ assert.isTrue test.modeIsActive
should "register state change", ->
- enabled = null
- passKeys = null
+ test = new Mode trackState: true
+ handlerStack.bubbleEvent "registerStateChange", { enabled: "one", passKeys: "two" }
- class Test extends Mode
- constructor: ->
- super
- trackState: true
+ assert.isTrue test.enabled == "one"
+ assert.isTrue test.passKeys == "two"
- test = new Test()
- handlerStack.bubbleEvent "registerStateChange",
- enabled: "enabled"
- passKeys: "passKeys"
+ should "register the keyQueue", ->
+ test = new Mode trackState: true
+ handlerStack.bubbleEvent "registerKeyQueue", keyQueue: "hello"
- assert.isTrue test.enabled == "enabled"
- assert.isTrue test.passKeys == "passKeys"
+ assert.isTrue test.keyQueue == "hello"
context "PostFindMode",
setup ->
initializeModeState()
- testContent = "
-
- "
+ testContent = ""
document.getElementById("test-div").innerHTML = testContent
document.getElementById("first").focus()
+ @postFindMode = new PostFindMode
tearDown ->
document.getElementById("test-div").innerHTML = ""
should "be a singleton", ->
- assert.isTrue Mode.top().name == "insert"
- new PostFindMode
- assert.isTrue Mode.top().name == "post-find"
+ assert.isTrue @postFindMode.modeIsActive
new PostFindMode
- assert.isTrue Mode.top().name == "post-find"
- Mode.top().exit()
- assert.isTrue Mode.top().name == "insert"
+ assert.isFalse @postFindMode.modeIsActive
should "suppress unmapped printable keys", ->
- new PostFindMode
sendKeyboardEvent "m"
assert.equal pageKeyboardEventCount, 0
- should "be clickable to focus", ->
- new PostFindMode
- assert.isTrue Mode.top().name == "post-find"
+ should "be deactivated on click events", ->
handlerStack.bubbleEvent "click", target: document.activeElement
- assert.isTrue Mode.top().name != "post-find"
+ assert.isFalse @postFindMode.modeIsActive
should "enter insert mode on immediate escape", ->
- new PostFindMode
- assert.isTrue Mode.top().name == "post-find"
sendKeyboardEvent "escape"
assert.equal pageKeyboardEventCount, 0
- assert.isTrue Mode.top().name == "insert"
+ assert.isFalse @postFindMode.modeIsActive
should "not enter insert mode on subsequent escapes", ->
- new PostFindMode
- assert.isTrue Mode.top().name == "post-find"
sendKeyboardEvent "a"
sendKeyboardEvent "escape"
- assert.equal pageKeyboardEventCount, 0
- assert.isTrue Mode.top().name == "post-find"
+ assert.isTrue @postFindMode.modeIsActive
context "Mode badges",
setup ->
initializeModeState()
-
- testContent = "
-
- "
+ testContent = ""
document.getElementById("test-div").innerHTML = testContent
tearDown ->
document.getElementById("test-div").innerHTML = ""
- should "have no badge without passKeys", ->
- Mode.updateBadge()
- assert.isTrue chromeMessages[0].badge == ""
-
- should "have no badge with passKeys", ->
- handlerStack.bubbleEvent "registerStateChange",
- enabled: true
- passKeys: "p"
+ should "have no badge in normal mode", ->
Mode.updateBadge()
assert.isTrue chromeMessages[0].badge == ""
--
cgit v1.2.3