diff options
| -rw-r--r-- | Cakefile | 3 | ||||
| -rw-r--r-- | background_scripts/main.coffee | 93 | ||||
| -rw-r--r-- | content_scripts/link_hints.coffee | 6 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 3 | ||||
| -rw-r--r-- | test_harnesses/automated.html | 312 | ||||
| -rw-r--r-- | test_harnesses/automated/automated.coffee | 197 | ||||
| -rw-r--r-- | test_harnesses/automated/automated.html | 49 | 
7 files changed, 287 insertions, 376 deletions
| @@ -8,7 +8,8 @@ spawn_with_opts = (proc_name, opts) ->      opt_array.push "--#{key}=#{value}"    spawn proc_name, opt_array -src_directories = ["tests", "background_scripts", "content_scripts", "lib", "options"] +src_directories = ["tests", "background_scripts", "content_scripts", "lib", "options", +                   "test_harnesses/automated"]  task "build", "compile all coffeescript files to javascript", ->    coffee = spawn "coffee", ["-c"].concat(src_directories) diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 7b703893..5c10b9ae 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -196,15 +196,6 @@ filterCompleter = (args, port) ->    queryTerms = if (args.query == "") then [] else args.query.split(" ")    completers[args.name].filter(queryTerms, (results) -> port.postMessage({ id: args.id, results: results })) -# -# Used by everyone to get settings from local storage. -# -getSettingFromLocalStorage = (setting) -> -  if (localStorage[setting] != "" && !localStorage[setting]) -    defaultSettings[setting] -  else -    localStorage[setting] -  getCurrentTimeInSeconds = -> Math.floor((new Date()).getTime() / 1000)  chrome.tabs.onSelectionChanged.addListener((tabId, selectionInfo) -> @@ -257,6 +248,16 @@ BackgroundCommands =      chrome.tabs.getSelected(null, (tab) ->        chrome.tabs.sendRequest(tab.id,          { name: "toggleHelpDialog", dialogHtml: helpDialogHtml(), frameId:frameId })) +  nextFrame: (count) -> +    chrome.tabs.getSelected(null, (tab) -> +      frames = framesForTab[tab.id].frames +      curr_index = getCurrFrameIndex(frames) + +      # TODO: Skip the "top" frame (which doesn't actually have a <frame> tag), +      # since it exists only to contain the other frames. +      new_index = (curr_index + count) % frames.length + +      chrome.tabs.sendRequest(tab.id, { name: "focusFrame", frameId: frames[new_index].id, highlight: true }))  # Selects a tab before or after the currently selected tab.  # - direction: "next", "previous", "first" or "last". @@ -522,35 +523,8 @@ registerFrame = (request, sender) ->    framesForTab[sender.tab.id].frames.push({ id: request.frameId, area: request.area }) -  # We've seen all the frames. Time to focus the largest one. -  # NOTE: Disabled because it's buggy with iframes. -  # if (framesForTab[sender.tab.id].frames.length >= framesForTab[sender.tab.id].total) -  #  focusLargestFrame(sender.tab.id) - -focusLargestFrame = (tabId) -> -  mainFrameId = null -  mainFrameArea = 0 - -  for frame in framesForTab[tabId] -    if (frame.area > mainFrameArea) -      mainFrameId = frame.id -      mainFrameArea = frame.area - -  chrome.tabs.sendRequest(tabId, { name: "focusFrame", frameId: mainFrameId, highlight: false }) -  handleFrameFocused = (request, sender) -> focusedFrame = request.frameId -nextFrame = (count) -> -  chrome.tabs.getSelected(null, (tab) -> -    frames = framesForTab[tab.id].frames -    curr_index = getCurrFrameIndex(frames) - -    # TODO: Skip the "top" frame (which doesn't actually have a <frame> tag), -    # since it exists only to contain the other frames. -    new_index = (curr_index + count) % frames.length - -    chrome.tabs.sendRequest(tab.id, { name: "focusFrame", frameId: frames[new_index].id, highlight: true })) -  getCurrFrameIndex = (frames) ->    for i in [0...frames.length]      return i if frames[i].id == focusedFrame @@ -578,28 +552,27 @@ sendRequestHandlers =    selectSpecificTab: selectSpecificTab,    refreshCompleter: refreshCompleter -init = -> -  Commands.clearKeyMappingsAndSetDefaults() - -  if Settings.has("keyMappings") -    Commands.parseCustomKeyMappings(Settings.get("keyMappings")) - -  populateValidFirstKeys() -  populateSingleKeyCommands() -  if shouldShowUpgradeMessage() -    sendRequestToAllTabs({ name: "showUpgradeNotification", version: currentVersion }) - -  # Ensure that openTabs is populated when Vimium is installed. -  chrome.windows.getAll({ populate: true }, (windows) -> -    for window in windows -      for tab in window.tabs -        updateOpenTabs(tab) -        createScrollPositionHandler = -> -          (response) -> updateScrollPosition(tab, response.scrollX, response.scrollY) if response? -        chrome.tabs.sendRequest(tab.id, { name: "getScrollPosition" }, createScrollPositionHandler())) - - -init() -  # Convenience function for development use. -runTests = -> open(chrome.extension.getURL('test_harnesses/automated.html')) +window.runTests = -> open(chrome.extension.getURL('test_harnesses/automated/automated.html')) + +# +# Begin initialization. +# +Commands.clearKeyMappingsAndSetDefaults() + +if Settings.has("keyMappings") +  Commands.parseCustomKeyMappings(Settings.get("keyMappings")) + +populateValidFirstKeys() +populateSingleKeyCommands() +if shouldShowUpgradeMessage() +  sendRequestToAllTabs({ name: "showUpgradeNotification", version: currentVersion }) + +# Ensure that openTabs is populated when Vimium is installed. +chrome.windows.getAll({ populate: true }, (windows) -> +  for window in windows +    for tab in window.tabs +      updateOpenTabs(tab) +      createScrollPositionHandler = -> +        (response) -> updateScrollPosition(tab, response.scrollX, response.scrollY) if response? +      chrome.tabs.sendRequest(tab.id, { name: "getScrollPosition" }, createScrollPositionHandler())) diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 5cdbc6a7..1d5d668a 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -178,9 +178,9 @@ LinkHints =        else if (linksMatched.length == 1)          @activateLink(linksMatched[0], delay)        else -        for i, marker of hintMarkers +        for marker in hintMarkers            @hideMarker(marker) -        for i, matched of linksMatched +        for matched in linksMatched            @showMarker(matched, @markerMatcher.hintKeystrokeQueue.length)      false # We've handled this key, so prevent propagation. @@ -404,7 +404,7 @@ filterHints =      if (event.keyCode == keyCodes.enter)        # activate the lowest-numbered link hint that is visible        for marker in hintMarkers -        if (marker.style.display  != "none") +        if (marker.style.display != "none")            return { linksMatched: [ marker ] }      else if (event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey)        # backspace clears hint key queue first, then acts on link text key queue. diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 034c241b..ab3b1fbf 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -115,6 +115,9 @@ initializePreDomReady = ->      disableVimium: disableVimium    chrome.extension.onRequest.addListener (request, sender, sendResponse) -> +    # in the options page, we will receive requests from both content and background scripts. ignore those +    # from the former. +    return unless sender.tab?.url.startsWith 'chrome-extension://'      sendResponse requestHandlers[request.name](request, sender)      # Ensure the sendResponse callback is freed.      false diff --git a/test_harnesses/automated.html b/test_harnesses/automated.html deleted file mode 100644 index 4c5f08ab..00000000 --- a/test_harnesses/automated.html +++ /dev/null @@ -1,312 +0,0 @@ -<!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="../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="../content_scripts/link_hints.js"></script> -    <script type="text/javascript" src="../lib/clipboard.js"></script> -    <script type="text/javascript" src="../content_scripts/vimium_frontend.js"></script> -    <script type="text/javascript" src="../tests/shoulda.js/shoulda.js"></script> -    <script type="text/javascript"> -      /* -       * 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. -       */ -      function mockKeyboardEvent(keyChar) { -        var event = {}; -        event.charCode = keyCodes[keyChar] !== undefined ? keyCodes[keyChar] : keyChar.charCodeAt(0); -        event.keyIdentifier = "U+00" + event.charCode.toString(16); -        event.keyCode = event.charCode; -        event.stopPropagation = function(){}; -        event.preventDefault = function(){}; -        return event; -      } - -      /* -       * Generate tests that are common to both default and filtered -       * link hinting modes. -       */ -      function createGeneralHintTests(isFilteredMode) { -        context("Link hints", - -          setup(function() { -            var testContent = -              "<a>test</a>" + -              "<a>tress</a>"; -            document.getElementById("test-div").innerHTML = testContent; -            LinkHints.markerMatcher = alphabetHints; -          }), - -          tearDown(function() { -            document.getElementById("test-div").innerHTML = ""; -          }), - -          should("create hints when activated, discard them when deactivated", function() { -            LinkHints.activateMode(); -            assert.isFalse(LinkHints.hintMarkerContainingDiv == null); -            LinkHints.deactivateMode(); -            assert.isTrue(LinkHints.hintMarkerContainingDiv == null); -          }), - -          should("position items correctly", function() { -            function 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(); -            assertStartPosition(document.getElementsByTagName("a")[0], LinkHints.hintMarkers[0]); -            assertStartPosition(document.getElementsByTagName("a")[1], LinkHints.hintMarkers[1]); -            LinkHints.deactivateMode(); - -            stub(document.body.style, "position", "relative"); -            LinkHints.activateMode(); -            assertStartPosition(document.getElementsByTagName("a")[0], LinkHints.hintMarkers[0]); -            assertStartPosition(document.getElementsByTagName("a")[1], LinkHints.hintMarkers[1]); -            LinkHints.deactivateMode(); -          }) - -        ); -      } -      createGeneralHintTests(false); -      createGeneralHintTests(true); - -      context("Alphabetical link hints", - -        setup(function() { -          stub(settings.values, "filterLinkHints", "false"); -          stub(settings.values, "linkHintCharacters", "ab") -          LinkHints.markerMatcher = alphabetHints; - -          // Three hints will trigger double hint chars. -          createLinks(3); -          LinkHints.activateMode(); -        }), - -        tearDown(function() { -          LinkHints.deactivateMode(); -          document.getElementById("test-div").innerHTML = ""; -        }), - -        should("label the hints correctly", function() { -          // TODO(philc): This test verifies the current behavior, but the current behavior is incorrect. -          // The output here should be something like aa, ab, b. -          var expectedHints = ["aa", "ba", "ab"]; -          console.log(LinkHints.hintMarkers); -          for (var i = 0; i < expectedHints.length; i++) -            assert.equal(expectedHints[i], LinkHints.hintMarkers[i].hintString); -        }), - -        should("narrow the hints", function() { -          LinkHints.onKeyDownInMode(mockKeyboardEvent("A")); -          assert.equal("none", LinkHints.hintMarkers[1].style.display); -          assert.equal("", LinkHints.hintMarkers[0].style.display); -        }) - -      ); - -      context("Filtered link hints", - -        setup(function() { -          stub(settings.values, "filterLinkHints", "true"); -          LinkHints.markerMatcher = filterHints; -        }), - -        context("Text hints", - -          setup(function() { -            var testContent = -              "<a>test</a>" + -              "<a>tress</a>" + -              "<a>trait</a>" + -              "<a>track<img alt='alt text'/></a>"; -            document.getElementById("test-div").innerHTML = testContent; -            LinkHints.activateMode(); -          }), - -          tearDown(function() { -            document.getElementById("test-div").innerHTML = ""; -            LinkHints.deactivateMode(); -          }), - -          should("label the hints", function() { -            for (var i = 0; i < 4; i++) -              assert.equal((i + 1).toString(), LinkHints.hintMarkers[i].textContent.toLowerCase()); -          }), - -          should("narrow the hints", function() { -            LinkHints.onKeyDownInMode(mockKeyboardEvent("T")); -            LinkHints.onKeyDownInMode(mockKeyboardEvent("R")); -            assert.equal("none", LinkHints.hintMarkers[0].style.display); -            assert.equal("1", LinkHints.hintMarkers[1].hintString); -            assert.equal("", LinkHints.hintMarkers[1].style.display); -            LinkHints.onKeyDownInMode(mockKeyboardEvent("A")); -            assert.equal("2", LinkHints.hintMarkers[3].hintString); -          }) - -        ), - -        context("Image hints", - -          setup(function() { -            var 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(function() { -            document.getElementById("test-div").innerHTML = ""; -            LinkHints.deactivateMode(); -          }), - -          should("label the images", function() { -            assert.equal("1: alt text", LinkHints.hintMarkers[0].textContent.toLowerCase()); -            assert.equal("2: alt text", LinkHints.hintMarkers[1].textContent.toLowerCase()); -            assert.equal("3: some title", LinkHints.hintMarkers[2].textContent.toLowerCase()); -            assert.equal("4", LinkHints.hintMarkers[3].textContent.toLowerCase()); -          }) - -        ), - -        context("Input hints", - -          setup(function() { -            var 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(function() { -            document.getElementById("test-div").innerHTML = ""; -            LinkHints.deactivateMode(); -          }), - -          should("label the input elements", function() { -            assert.equal("1", LinkHints.hintMarkers[0].textContent.toLowerCase()); -            assert.equal("2", LinkHints.hintMarkers[1].textContent.toLowerCase()); -            assert.equal("3", LinkHints.hintMarkers[2].textContent.toLowerCase()); -            assert.equal("4: a label", LinkHints.hintMarkers[3].textContent.toLowerCase()); -            assert.equal("5: a label", LinkHints.hintMarkers[4].textContent.toLowerCase()); -          }) - -        ), - -        context("Input focus", - -          setup(function() { -            var 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(function() { -            document.getElementById("test-div").innerHTML = ""; -          }), - -          should("focus the right element", function() { -            focusInput(1); -            assert.equal('first', document.activeElement.id); -            focusInput(100); -            assert.equal('third', document.activeElement.id); -          }) -        ) - -      ); - -      context("Input focus", - -        setup(function() { -          var 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(function() { -          document.getElementById("test-div").innerHTML = ""; -        }), - -        should("focus the right element", function() { -          focusInput(1); -          assert.equal('first', document.activeElement.id); -          focusInput(100); -          assert.equal('third', document.activeElement.id); -        }) - -      ); - -      Tests.outputMethod = function(output) { -        var newOutput = Array.prototype.join.call(arguments, "\n"); -        newOutput = newOutput.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); // escape html -        // 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, arguments); -      } - -      // ensure the extension has time to load before commencing the tests -      document.addEventListener("DOMContentLoaded", function() { -        setTimeout(Tests.run, 200); -      }); - -      function createLinks(n) { -        for (var i = 0; i < n; i++) { -          var link = document.createElement("a"); -          link.textContent = "test"; -          document.getElementById("test-div").appendChild(link); -        } -      } -    </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/test_harnesses/automated/automated.coffee b/test_harnesses/automated/automated.coffee new file mode 100644 index 00000000..c6f7639a --- /dev/null +++ b/test_harnesses/automated/automated.coffee @@ -0,0 +1,197 @@ +# +# 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 + +    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 + +document.addEventListener "DOMContentLoaded", -> +  setTimeout Tests.run, 200 + +# ensure the extension has time to load before commencing the tests +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/test_harnesses/automated/automated.html b/test_harnesses/automated/automated.html new file mode 100644 index 00000000..a0c8c7de --- /dev/null +++ b/test_harnesses/automated/automated.html @@ -0,0 +1,49 @@ +<!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="../../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="../../tests/shoulda.js/shoulda.js"></script> +    <script type="text/javascript" src="automated.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> | 
