1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#
# 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 = "<a>test</a>" + "<a>tress</a>"
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 = "<a>test</a>" + "<a>tress</a>" + "<a>trait</a>" + "<a>track<img alt='alt text'/></a>"
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 = "<a><img alt='alt text'/></a>" + "<a><img alt='alt text' title='some title'/></a>" + "<a><img title='some title'/></a>" + "<a><img src='' width='320px' height='100px'/></a>"
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 = "<input type='text' value='some value'/>" + "<input type='password' value='some value'/>" + "<textarea>some text</textarea>" + "<label for='test-input'/>a label</label><input type='text' id='test-input' value='some value'/>" + "<label for='test-input-2'/>a label: </label><input type='text' id='test-input-2' value='some value'/>"
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 = "<input type='text' id='first'/>" + "<input style='display:none;' id='second'/>" + "<input type='password' id='third' value='some value'/>"
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[handlerStack.length - 1].keydown mockKeyboardEvent("A")
focusInput 100
assert.equal "third", document.activeElement.id
handlerStack[handlerStack.length - 1].keydown mockKeyboardEvent("A")
Tests.outputMethod = (args...) ->
newOutput = args.join "\n"
# escape html
newOutput = newOutput.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
# highlight the source of the error
newOutput = newOutput.replace(/\/([^:/]+):([0-9]+):([0-9]+)/, "/<span class='errorPosition'>$1:$2</span>:$3")
document.getElementById("output-div").innerHTML += "<div class='output-section'>" + newOutput + "</div>"
console.log.apply console, args
# PhantomJS will call the tests manually
unless navigator.userAgent == 'phantom'
# ensure the extension has time to load before commencing the tests
document.addEventListener "DOMContentLoaded", ->
setTimeout Tests.run, 200
createLinks = (n) ->
for i in [0...n] by 1
link = document.createElement("a")
link.textContent = "test"
document.getElementById("test-div").appendChild link
|