diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/dom_tests/bind.js | 27 | ||||
| -rw-r--r-- | tests/dom_tests/chrome.coffee | 20 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 200 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.html | 51 | ||||
| -rw-r--r-- | tests/dom_tests/phantom_runner.coffee | 32 | ||||
| -rw-r--r-- | tests/unit_tests/completion_test.coffee (renamed from tests/completion_test.coffee) | 4 | ||||
| -rw-r--r-- | tests/unit_tests/test_helper.coffee (renamed from tests/test_helper.coffee) | 4 | ||||
| -rw-r--r-- | tests/unit_tests/utils_test.coffee (renamed from tests/utils_test.coffee) | 2 |
8 files changed, 335 insertions, 5 deletions
diff --git a/tests/dom_tests/bind.js b/tests/dom_tests/bind.js new file mode 100644 index 00000000..833f8006 --- /dev/null +++ b/tests/dom_tests/bind.js @@ -0,0 +1,27 @@ +/* + * Polyfill taken from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind + * Necessary because the current version of PhantomJS doesn't yet support bind(). + */ +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + }; +} diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee new file mode 100644 index 00000000..ff7a53d0 --- /dev/null +++ b/tests/dom_tests/chrome.coffee @@ -0,0 +1,20 @@ +# +# Mock the Chrome extension API. +# + +root = exports ? window + +root.chrome = { + extension: { + connect: -> { + onMessage: { + addListener: -> + } + postMessage: -> + } + onRequest: { + addListener: -> + } + sendRequest: -> + } +} diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee new file mode 100644 index 00000000..f4e63270 --- /dev/null +++ b/tests/dom_tests/dom_tests.coffee @@ -0,0 +1,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 diff --git a/tests/dom_tests/dom_tests.html b/tests/dom_tests/dom_tests.html new file mode 100644 index 00000000..1dc45782 --- /dev/null +++ b/tests/dom_tests/dom_tests.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> + <head> + <style type="text/css"> + body { + font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif; + width: 800px; + margin: 0px auto; + } + #output-div { + white-space: pre-wrap; + background-color: #eee; + font-family: monospace; + margin: 0 0 50px 0; + border-style: dashed; + border-width: 1px 1px 0 1px; + border-color: #999; + } + .errorPosition { + color: #f33; + font-weight: bold; + } + .output-section { + padding: 10px 15px 10px 15px; + border-bottom: dashed 1px #999; + } + </style> + <link rel="stylesheet" type="text/css" href="../../vimium.css" /> + <script type="text/javascript" src="bind.js"></script> + <script type="text/javascript" src="chrome.js"></script> + <script type="text/javascript" src="../../lib/utils.js"></script> + <script type="text/javascript" src="../../lib/keyboard_utils.js"></script> + <script type="text/javascript" src="../../lib/dom_utils.js"></script> + <script type="text/javascript" src="../../lib/clipboard.js"></script> + <script type="text/javascript" src="../../content_scripts/link_hints.js"></script> + <script type="text/javascript" src="../../content_scripts/vomnibar.js"></script> + <script type="text/javascript" src="../../content_scripts/vimium_frontend.js"></script> + <script type="text/javascript" src="../shoulda.js/shoulda.js"></script> + <script type="text/javascript" src="dom_tests.js"></script> + </head> + <body> + <!-- should always be the first element on the page --> + <div id="test-div"></div> + + <h1>Vimium Tests</h1> + + <div id="output-div"></div> + + </body> +</html> diff --git a/tests/dom_tests/phantom_runner.coffee b/tests/dom_tests/phantom_runner.coffee new file mode 100644 index 00000000..f0f2b128 --- /dev/null +++ b/tests/dom_tests/phantom_runner.coffee @@ -0,0 +1,32 @@ +page = require('webpage').create() + +page.settings.userAgent = 'phantom' + +# ensure that the elements we test the link hints on are actually visible +page.viewportSize = + width: 900 + height: 600 + +page.onConsoleMessage = (msg) -> + console.log msg + +system = require 'system' +fs = require 'fs' + +pathParts = system.args[0].split(fs.separator) +pathParts[pathParts.length - 1] = '' +dirname = pathParts.join(fs.separator) + +page.open dirname + 'dom_tests.html', (status) -> + if status != 'success' + console.log 'Unable to load tests.' + phantom.exit 1 + + testsFailed = page.evaluate -> + Tests.run() + return Tests.testsFailed + + if testsFailed > 0 + phantom.exit 1 + else + phantom.exit 0 diff --git a/tests/completion_test.coffee b/tests/unit_tests/completion_test.coffee index 7094d720..d3369398 100644 --- a/tests/completion_test.coffee +++ b/tests/unit_tests/completion_test.coffee @@ -1,6 +1,6 @@ require "./test_helper.js" -extend(global, require "../lib/utils.js") -extend(global, require "../background_scripts/completion.js") +extend(global, require "../../lib/utils.js") +extend(global, require "../../background_scripts/completion.js") global.chrome = {} diff --git a/tests/test_helper.coffee b/tests/unit_tests/test_helper.coffee index 237f8e24..bb73bf54 100644 --- a/tests/test_helper.coffee +++ b/tests/unit_tests/test_helper.coffee @@ -1,5 +1,5 @@ -require("./shoulda.js/shoulda.js") +require("../shoulda.js/shoulda.js") global.extend = (hash1, hash2) -> for key of hash2 hash1[key] = hash2[key] - hash1
\ No newline at end of file + hash1 diff --git a/tests/utils_test.coffee b/tests/unit_tests/utils_test.coffee index c5e5d002..6a44b460 100644 --- a/tests/utils_test.coffee +++ b/tests/unit_tests/utils_test.coffee @@ -1,5 +1,5 @@ require "./test_helper.js" -extend(global, require "../lib/utils.js") +extend(global, require "../../lib/utils.js") context "convertToUrl", should "detect and clean up valid URLs", -> |
