<?xml version="1.0"?>

<!-- This Source Code Form is subject to the terms of the Mozilla Public
   - License, v. 2.0. If a copy of the MPL was not distributed with this
   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

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

<window id="FindbarTest"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        width="600"
        height="600"
        onload="SimpleTest.executeSoon(startTest);"
        title="findbar events test">

  <script type="application/javascript"><![CDATA[
    const {interfaces: Ci, classes: Cc, results: Cr, utils: Cu} = Components;
    Cu.import("resource://gre/modules/Task.jsm");
    Cu.import("resource://testing-common/BrowserTestUtils.jsm");
    Cu.import("resource://testing-common/ContentTask.jsm");
    ContentTask.setTestScope(window.opener.wrappedJSObject);

    var gFindBar = null;
    var gBrowser;
    const kTimeout = 5000; // 5 seconds.

    var imports = ["SimpleTest", "ok", "is", "info"];
    for (var name of imports) {
      window[name] = window.opener.wrappedJSObject[name];
    }
    SimpleTest.requestLongerTimeout(2);

    function startTest() {
      Task.spawn(function* () {
        gFindBar = document.getElementById("FindToolbar");
        for (let browserId of ["content", "content-remote"]) {
          yield startTestWithBrowser(browserId);
        }
      }).then(() => {
        window.close();
        SimpleTest.finish();
      });
    }

    function* startTestWithBrowser(browserId) {
      info("Starting test with browser '" + browserId + "'");
      gBrowser = document.getElementById(browserId);
      gFindBar.browser = gBrowser;
      let promise = BrowserTestUtils.browserLoaded(gBrowser);
      gBrowser.loadURI("data:text/html,hello there");
      yield promise;
      yield onDocumentLoaded();
    }

    function* onDocumentLoaded() {
      gFindBar.open();
      gFindBar.onFindCommand();

      yield testFind();
      yield testFindAgain();
      yield testCaseSensitivity();
      yield testHighlight();
    }

    function checkSelection() {
      return new Promise(resolve => {
        SimpleTest.executeSoon(() => {
          ContentTask.spawn(gBrowser, null, function* () {
            let selected = content.getSelection();
            Assert.equal(String(selected), "", "No text is selected");

            let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                     .getInterface(Ci.nsISelectionDisplay)
                                     .QueryInterface(Ci.nsISelectionController);
            let selection = controller.getSelection(controller.SELECTION_FIND);
            Assert.equal(selection.rangeCount, 0, "No text is highlighted");
          }).then(resolve);
        });
      });
    }

    function once(node, eventName, preventDefault = true) {
      return new Promise((resolve, reject) => {
        let timeout = window.setTimeout(() => {
          reject("Event wasn't fired within " + kTimeout + "ms for event '" +
            eventName + "'.");
        }, kTimeout);

        node.addEventListener(eventName, function clb(e) {
          window.clearTimeout(timeout);
          node.removeEventListener(eventName, clb);
          if (preventDefault)
            e.preventDefault();
          resolve(e);
        });
      });
    }

    function* testFind() {
      info("Testing normal find.");
      let query = "t";
      let promise = once(gFindBar, "find");

      // Put some text in the find box.
      let event = document.createEvent("KeyboardEvent");
      event.initKeyEvent("keypress", true, true, null, false, false,
                         false, false, 0, query.charCodeAt(0));
      gFindBar._findField.inputField.dispatchEvent(event);

      let e = yield promise;
      ok(e.detail.query === query, "find event query should match '" + query + "'");
      // Since we're preventing the default make sure nothing was selected.
      yield checkSelection();
    }

    function testFindAgain() {
      info("Testing repeating normal find.");
      let promise = once(gFindBar, "findagain");

      gFindBar.onFindAgainCommand();

      yield promise;
      // Since we're preventing the default make sure nothing was selected.
      yield checkSelection();
    }

    function* testCaseSensitivity() {
      info("Testing normal case sensitivity.");
      let promise = once(gFindBar, "findcasesensitivitychange", false);

      let matchCaseCheckbox = gFindBar.getElement("find-case-sensitive");
      matchCaseCheckbox.click();

      let e = yield promise;
      ok(e.detail.caseSensitive, "find should be case sensitive");

      // Toggle it back to the original setting.
      matchCaseCheckbox.click();

      // Changing case sensitivity does the search so clear the selected text
      // before the next test.
      yield ContentTask.spawn(gBrowser, null, () => content.getSelection().removeAllRanges());
    }

    function* testHighlight() {
      info("Testing find with highlight all.");
      // Update the find state so the highlight button is clickable.
      gFindBar.updateControlState(Ci.nsITypeAheadFind.FIND_FOUND, false);

      let promise = once(gFindBar, "findhighlightallchange");

      let highlightButton = gFindBar.getElement("highlight");
      if (!highlightButton.checked)
        highlightButton.click();

      let e = yield promise;
      ok(e.detail.highlightAll, "find event should have highlight all set");
      // Since we're preventing the default make sure nothing was highlighted.
      yield checkSelection();

      // Toggle it back to the original setting.
      if (highlightButton.checked)
        highlightButton.click();
    }
  ]]></script>

  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
  <browser type="content-primary" flex="1" id="content-remote" remote="true" src="about:blank"/>
  <findbar id="FindToolbar" browserid="content"/>
</window>