<?xml version="1.0"?>

<!-- Any copyright is dedicated to the Public Domain.
     http://creativecommons.org/publicdomain/zero/1.0/ -->

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                 type="text/css"?>

<?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>

<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>

<!DOCTYPE window [
  <!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
  %editBookmarkOverlayDTD;
]>

<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        title="Bug 631374 - Editing tags in the selector scrolls up the listbox"
        onload="runTest();">

  <script type="application/javascript"
          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
  <script type="application/javascript"
          src="chrome://browser/content/places/editBookmarkOverlay.js"/>

  <body xmlns="http://www.w3.org/1999/xhtml" />

  <vbox id="editBookmarkPanelContent"/>

  <script type="application/javascript">
  <![CDATA[

     /**
      * This test checks that editing tags doesn't scroll the tags selector
      * listbox to wrong positions.
      */

    function runTest() {
      SimpleTest.waitForExplicitFinish();

      Components.utils.import("resource://gre/modules/NetUtil.jsm");

      let tags = ["a", "b", "c", "d", "e", "f", "g",
                  "h", "i", "l", "m", "n", "o", "p"];

      // Add a bookmark and tag it.
      let uri1 = NetUtil.newURI("http://www1.mozilla.org/");
      let id1 = PlacesUtils.bookmarks.insertBookmark(
        PlacesUtils.toolbarFolderId, uri1,
        PlacesUtils.bookmarks.DEFAULT_INDEX, "mozilla"
      );
      PlacesUtils.tagging.tagURI(uri1, tags);

      // Add a second bookmark so that tags won't disappear when unchecked.
      let uri2 = NetUtil.newURI("http://www2.mozilla.org/");
      let id2 = PlacesUtils.bookmarks.insertBookmark(
        PlacesUtils.toolbarFolderId, uri2,
        PlacesUtils.bookmarks.DEFAULT_INDEX, "mozilla"
      );
      PlacesUtils.tagging.tagURI(uri2, tags);

      // Init panel.
      ok(gEditItemOverlay, "gEditItemOverlay is in context");
      gEditItemOverlay.initPanel(id1);
      ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");

      // Wait for the tags selector to be open.
      let tagsSelectorRow = document.getElementById("editBMPanel_tagsSelectorRow");
      tagsSelectorRow.addEventListener("DOMAttrModified", function (event) {
        tagsSelectorRow.removeEventListener("DOMAttrModified", arguments.callee, false);
        SimpleTest.executeSoon(function () {
          let tagsSelector = document.getElementById("editBMPanel_tagsSelector");

          // Go by two so there is some untouched tag in the middle.
          for (let i = 8; i < tags.length; i += 2) {
            tagsSelector.selectedIndex = i;
            let listItem = tagsSelector.selectedItem;
            SimpleTest.isnot(listItem, null, "Valid listItem found");

            tagsSelector.ensureElementIsVisible(listItem);
            let visibleIndex = tagsSelector.getIndexOfFirstVisibleRow();

            SimpleTest.ok(listItem.checked, "Item is checked " + i);
            let selectedTag = listItem.label;

            // Uncheck the tag.
            listItem.checked = false;
            SimpleTest.is(visibleIndex,
                          tagsSelector.getIndexOfFirstVisibleRow(),
                          "Scroll position did not change");

            // The listbox is rebuilt, so we have to get the new element.
            let newItem = tagsSelector.selectedItem;
            SimpleTest.isnot(newItem, null, "Valid new listItem found");
            SimpleTest.ok(!newItem.checked, "New listItem is unchecked " + i);
            SimpleTest.is(newItem.label, selectedTag,
                          "Correct tag is still selected");

            // Check the tag.
            newItem.checked = true;
            SimpleTest.is(visibleIndex,
                          tagsSelector.getIndexOfFirstVisibleRow(),
                          "Scroll position did not change");
          }

          // Remove the second bookmark, then nuke some of the tags.
          PlacesUtils.bookmarks.removeItem(id2);

          // Doing this backwords tests more interesting paths.
          for (let i = tags.length - 1; i >= 0 ; i -= 2) {
            tagsSelector.selectedIndex = i;
            let listItem = tagsSelector.selectedItem;
            SimpleTest.isnot(listItem, null, "Valid listItem found");

            tagsSelector.ensureElementIsVisible(listItem);
            let visibleIndex = tagsSelector.getIndexOfFirstVisibleRow();

            SimpleTest.ok(listItem.checked, "Item is checked " + i);
            let selectedTag = listItem.label;

            // Uncheck the tag.
            listItem.checked = false;
            SimpleTest.is(tagsSelector.getIndexOfFirstVisibleRow(),
                          Math.max(visibleIndex -1, 0),
                          "Scroll position is correct");

            // The listbox is rebuilt, so we have to get the new element.
            let newItem = tagsSelector.selectedItem;
            SimpleTest.isnot(newItem, null, "Valid new listItem found");
            SimpleTest.ok(newItem.checked, "New listItem is checked " + i);
            SimpleTest.is(tagsSelector.selectedItem.label,
                          tags[Math.min(i + 1, tags.length - 2)],
                          "The next tag is now selected");
          }

          // Cleanup.
          PlacesUtils.bookmarks.removeItem(id1);

          SimpleTest.finish();
        });
      }, false);

      // Open the tags selector.
      document.getElementById("editBMPanel_tagsSelectorExpander").doCommand();
    }
  ]]>
  </script>

</window>
