#
# 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.stopPropagation = ->
event.preventDefault = ->
event
#
# Retrieve the hint markers as an array object.
#
getHintMarkers = ->
Array::slice.call document.getElementsByClassName("vimiumHintMarker"), 0
#
# Generate tests that are common to both default and filtered
# link hinting modes.
#
createGeneralHintTests = (isFilteredMode) ->
context "Link hints",
setup ->
testContent = "test" + "tress"
document.getElementById("test-div").innerHTML = testContent
stub settings.values, "filterLinkHints", false
stub settings.values, "linkHintCharacters", "ab"
tearDown ->
document.getElementById("test-div").innerHTML = ""
should "create hints when activated, discard them when deactivated", ->
LinkHints.activateMode()
assert.isFalse not LinkHints.hintMarkerContainingDiv?
LinkHints.deactivateMode()
assert.isTrue not LinkHints.hintMarkerContainingDiv?
should "position items correctly", ->
assertStartPosition = (element1, element2) ->
assert.equal element1.getClientRects()[0].left, element2.getClientRects()[0].left
assert.equal element1.getClientRects()[0].top, element2.getClientRects()[0].top
stub document.body, "style", "static"
LinkHints.activateMode()
hintMarkers = getHintMarkers()
assertStartPosition document.getElementsByTagName("a")[0], hintMarkers[0]
assertStartPosition document.getElementsByTagName("a")[1], hintMarkers[1]
LinkHints.deactivateMode()
stub document.body.style, "position", "relative"
LinkHints.activateMode()
hintMarkers = getHintMarkers()
assertStartPosition document.getElementsByTagName("a")[0], hintMarkers[0]
assertStartPosition document.getElementsByTagName("a")[1], hintMarkers[1]
LinkHints.deactivateMode()
createGeneralHintTests false
createGeneralHintTests true
context "Alphabetical link hints",
setup ->
stub settings.values, "filterLinkHints", false
stub settings.values, "linkHintCharacters", "ab"
# Three hints will trigger double hint chars.
createLinks 3
LinkHints.init()
LinkHints.activateMode()
tearDown ->
LinkHints.deactivateMode()
document.getElementById("test-div").innerHTML = ""
should "label the hints correctly", ->
# TODO(philc): This test verifies the current behavior, but the current behavior is incorrect.
# The output here should be something like aa, ab, b.
hintMarkers = getHintMarkers()
expectedHints = ["aa", "ba", "ab"]
for hint, i in expectedHints
assert.equal hint, hintMarkers[i].hintString
should "narrow the hints", ->
hintMarkers = getHintMarkers()
LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("A")
assert.equal "none", hintMarkers[1].style.display
assert.equal "", hintMarkers[0].style.display
context "Filtered link hints",
setup ->
stub settings.values, "filterLinkHints", true
context "Text hints",
setup ->
testContent = "test" + "tress" + "trait" + "track"
document.getElementById("test-div").innerHTML = testContent
LinkHints.init()
LinkHints.activateMode()
tearDown ->
document.getElementById("test-div").innerHTML = ""
LinkHints.deactivateMode()
should "label the hints", ->
hintMarkers = getHintMarkers()
for i in [0...4]
assert.equal (i + 1).toString(), hintMarkers[i].textContent.toLowerCase()
should "narrow the hints", ->
hintMarkers = getHintMarkers()
LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("T")
LinkHints.onKeyDownInMode hintMarkers, mockKeyboardEvent("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")
assert.equal "2", hintMarkers[3].hintString
context "Image hints",
setup ->
testContent = "
" + "
"
document.getElementById("test-div").innerHTML = testContent
LinkHints.activateMode()
tearDown ->
document.getElementById("test-div").innerHTML = ""
LinkHints.deactivateMode()
should "label the images", ->
hintMarkers = getHintMarkers()
assert.equal "1: alt text", hintMarkers[0].textContent.toLowerCase()
assert.equal "2: alt text", hintMarkers[1].textContent.toLowerCase()
assert.equal "3: some title", hintMarkers[2].textContent.toLowerCase()
assert.equal "4", hintMarkers[3].textContent.toLowerCase()
context "Input hints",
setup ->
testContent = "
a label
a label: "
document.getElementById("test-div").innerHTML = testContent
LinkHints.activateMode()
tearDown ->
document.getElementById("test-div").innerHTML = ""
LinkHints.deactivateMode()
should "label the input elements", ->
hintMarkers = getHintMarkers()
assert.equal "1", hintMarkers[0].textContent.toLowerCase()
assert.equal "2", hintMarkers[1].textContent.toLowerCase()
assert.equal "3", hintMarkers[2].textContent.toLowerCase()
assert.equal "4: a label", hintMarkers[3].textContent.toLowerCase()
assert.equal "5: a label", hintMarkers[4].textContent.toLowerCase()
context "Input focus",
setup ->
testContent = "
"
document.getElementById("test-div").innerHTML = testContent
tearDown ->
document.getElementById("test-div").innerHTML = ""
should "focus the right element", ->
focusInput 1
assert.equal "first", document.activeElement.id
# deactivate the tabbing mode and its overlays
handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A")
focusInput 100
assert.equal "third", document.activeElement.id
handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A")
context "Find prev / next links",
setup ->
window.location.hash = ""
should "find exact matches", ->
document.getElementById("test-div").innerHTML = """
nextcorrupted
next page
"""
stub settings.values, "nextPatterns", "next"
goNext()
assert.equal '#second', window.location.hash
should "match against non-word patterns", ->
document.getElementById("test-div").innerHTML = """
>>
"""
stub settings.values, "nextPatterns", ">>"
goNext()
assert.equal '#first', window.location.hash
should "favor matches with fewer words", ->
document.getElementById("test-div").innerHTML = """
lorem ipsum next
next!
"""
stub settings.values, "nextPatterns", "next"
goNext()
assert.equal '#second', window.location.hash
Tests.outputMethod = (args...) ->
newOutput = args.join "\n"
# escape html
newOutput = newOutput.replace(/&/g, "&").replace(//g, ">")
# highlight the source of the error
newOutput = newOutput.replace /\/([^:/]+):([0-9]+):([0-9]+)/, "/$1:$2:$3"
document.getElementById("output-div").innerHTML += "