toolkit/components/satchel/test/test_form_autocomplete_with_list.html
author Marco Bonardo <mbonardo@mozilla.com>
Wed, 02 Mar 2016 14:34:38 +0100
changeset 325906 ee0cb75bcbf99f082f6c31ba4e54d88a8b2d9f7b
parent 319501 6c56f5dad3b24506c41d5a38115d19456fe2a802
child 349443 ab1d29e62ee411f1f1d344616dc5ea98bab33f76
permissions -rw-r--r--
Bug 1252074 - test_form_autocomplete.html and test_form_autocomplete_with_list.html should pass on e10s. r=paolo MozReview-Commit-ID: CISKztr4p4N

<!DOCTYPE HTML>
<html>
<head>
  <title>Test for Form History Autocomplete</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="satchel_common.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Form History test: form field autocomplete
<p id="display"></p>

<!-- we presumably can't hide the content for this test. -->
<div id="content">

  <!-- normal, basic form -->
  <form id="form1" onsubmit="return false;">
    <input list="suggest" type="text" name="field1">
    <button type="submit">Submit</button>
  </form>

  <!-- form with autocomplete=off on input -->
  <form id="form3" onsubmit="return false;">
    <input list="suggest" type="text" name="field2" autocomplete="off">
    <button type="submit">Submit</button>
  </form>

  <!-- form with autocomplete=off on form -->
  <form id="form4" autocomplete="off" onsubmit="return false;">
    <input list="suggest" type="text" name="field2">
    <button type="submit">Submit</button>
  </form>

  <datalist id="suggest">
    <option value="Google" label="PASS1">FAIL</option>
    <option value="Reddit">PASS2</option>
    <option value="final"></option>
  </datalist>
</div>

<pre id="test">
<script class="testbody" type="text/javascript">

/** Test for Form History autocomplete **/

var input = $_(1, "field1");
const shiftModifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;

function setupFormHistory(aCallback) {
  updateFormHistory([
    { op : "remove" },
    { op : "add", fieldname : "field1", value : "historyvalue" },
    { op : "add", fieldname : "field2", value : "othervalue" },
  ], aCallback);
}

function setForm(value) {
    input.value = value;
    input.focus();
}

// Restore the form to the default state.
function restoreForm() {
    setForm("");
}

// Check for expected form data.
function checkForm(expectedValue) {
    var formID = input.parentNode.id;
    is(input.value, expectedValue, "Checking " + formID + " input");
}

var testNum = 0;
var prevValue;
var expectingPopup = false;

function expectPopup() {
  info("expecting popup for test " + testNum);
  expectingPopup = true;
}

function popupShownListener() {
  info("popup shown for test " + testNum);
  if (expectingPopup) {
    expectingPopup = false;
    SimpleTest.executeSoon(runTest);
  }
  else {
    ok(false, "Autocomplete popup not expected during test " + testNum);
  }
}

registerPopupShownListener(popupShownListener);

/*
* Main section of test...
*
* This is a bit hacky, as many operations happen asynchronously.
* Various mechanisms call runTests as a result of operations:
*   - set expectingPopup to true, and the next test will occur when the autocomplete popup is shown
*   - call waitForMenuChange(x) to run the next test when the autocomplete popup to have x items in it
*/
function runTest() {
    testNum++;

    info("Starting test #" + testNum);

    switch(testNum) {
    case 1:
        // Make sure initial form is empty.
        checkForm("");
        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;
    case 2:
        checkMenuEntries(["historyvalue", "PASS1", "PASS2", "final"], testNum);
        // Check first entry
        doKey("down");
        checkForm(""); // value shouldn't update
        doKey("return"); // not "enter"!
        checkForm("historyvalue");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 3:
        // Check second entry
        doKey("down");
        doKey("down");
        doKey("return"); // not "enter"!
        checkForm("Google");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 4:
        // Check third entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkForm("Reddit");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 5:
        // Check fourth entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkForm("final");
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 6:
        //Delete the first entry (of 3)
        doKey("down");
        doKey("delete", shiftModifier);
        waitForMenuChange(3);
        break;

    case 7:
        checkForm("");
        countEntries("field1", "historyvalue",
          function (num) {
            ok(!num, testNum + " checking that form history value was deleted");
            runTest();
          });
        break;

    case 8:
        doKey("return");
        checkForm("Google")

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 9:
        //Test deletion
        checkMenuEntries(["PASS1", "PASS2", "final"], testNum);
        // Check the new first entry (of 3)
        doKey("down");
        doKey("return");
        checkForm("Google");

        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 10:
        // Test autocompletion of datalists with cached results.
        sendString("PAS");
        waitForMenuChange(2);
        break;

    case 11:
        // Continuation of test 10
        sendString("S1");
        waitForMenuChange(1);
        break;

    case 12:
        doKey("down");
        doKey("return");
        checkForm("Google");

        // Trigger autocomplete popup
        // Look at form 3, try to trigger autocomplete popup
        input.value = "";
        input = $_(3, "field2");
        testNum = 99;
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 100:
        checkMenuEntries(["PASS1", "PASS2", "final"], testNum);
        // Check first entry
        doKey("down");
        checkForm(""); // value shouldn't update
        doKey("return"); // not "enter"!
        checkForm("Google");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 101:
        // Check second entry
        doKey("down");
        doKey("down");
        doKey("return"); // not "enter"!
        checkForm("Reddit");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 102:
        // Check third entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkForm("final");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 103:
        checkMenuEntries(["PASS1", "PASS2", "final"], testNum);
        // Check first entry
        doKey("down");
        checkForm(""); // value shouldn't update
        doKey("return"); // not "enter"!
        checkForm("Google");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 104:
        // Check second entry
        doKey("down");
        doKey("down");
        doKey("return"); // not "enter"!
        checkForm("Reddit");

        // Trigger autocomplete popup
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    case 105:
        // Check third entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkForm("final");

        testNum = 199;
        expectPopup();
        restoreForm();
        doKey("down");
        break;

    // Test dynamic updates.
    // For some reasons, when there is an update of the list, the selection is
    // lost so we need to go down like if we were at the beginning of the list
    // again.
    case 200:
      // Removing the second element while on the first then going down and
      // push enter. Value should be one from the third suggesion.
      doKey("down");
      var datalist = document.getElementById('suggest');
      var toRemove = datalist.children[1]
      datalist.removeChild(toRemove);

      SimpleTest.executeSoon(function() {
        doKey("down");
        doKey("down");
        doKey("return");
        checkForm("final");

        // Restore the element.
        datalist.insertBefore(toRemove, datalist.children[1]);
        expectPopup();
        restoreForm();
        doKey("down");
      });
      break;

    case 201:
      // Adding an attribute after the first one while on the first then going
      // down and push enter. Value should be the on from the new suggestion.
      doKey("down");
      datalist = document.getElementById('suggest');
      var added = new Option("Foo");
      datalist.insertBefore(added, datalist.children[1]);
      waitForMenuChange(4);
      break;

    case 202:
      doKey("down");
      doKey("down");
      doKey("return");
      checkForm("Foo");

      // Remove the element.
      datalist = document.getElementById('suggest');
      datalist.removeChild(datalist.children[1]);
      waitForMenuChange(0);
      break;

    case 203:
      // Change the first element value attribute.
      restoreForm();
      datalist = document.getElementById('suggest');
      prevValue = datalist.children[0].value;
      datalist.children[0].value = "foo";
      expectPopup();
      break;

    case 204:
      doKey("down");
      doKey("return");
      checkForm("foo");

      datalist = document.getElementById('suggest');
      datalist.children[0].value = prevValue;
      waitForMenuChange(0);
      break;

    case 205:
      // Change the textContent to update the value attribute.
      restoreForm();
      datalist = document.getElementById('suggest');
      prevValue = datalist.children[0].getAttribute('value');
      datalist.children[0].removeAttribute('value');
      datalist.children[0].textContent = "foobar";
      expectPopup();
      break;

    case 206:
      doKey("down");
      doKey("return");
      checkForm("foobar");

      datalist = document.getElementById('suggest');
      datalist.children[0].setAttribute('value', prevValue);
      testNum = 299;
      waitForMenuChange(0);
      break;

    // Tests for filtering (or not).
    case 300:
      // Filters with first letter of the word.
      restoreForm();
      synthesizeKey("f", {});
      expectPopup();
      break;

    case 301:
      doKey("down");
      doKey("return");
      checkForm("final");
      expectPopup();
      restoreForm();
      doKey("down");
      break;

    case 302:
      // Filter with a letter in the middle of the word.
      synthesizeKey("i", {});
      synthesizeKey("n", {});
      waitForMenuChange(1);
      break;

    case 303:
      // Continuation of test 302.
      doKey("down");
      doKey("return");
      checkForm("final");
      expectPopup();
      restoreForm();
      doKey("down");
      break;

    case 304:
      // Filter is disabled with mozNoFilter.
      input.setAttribute('mozNoFilter', 'true');
      synthesizeKey("f", {});
      waitForMenuChange(3); // no change
      break;

    case 305:
      // Continuation of test 304.
      doKey("down");
      doKey("return");
      checkForm("Google");
      input.removeAttribute('mozNoFilter');
      testNum = 399;
      expectPopup();
      restoreForm();
      doKey("down");
      break;

    case 400:
      // Check that the input event is fired.
      input.addEventListener("input", function(event) {
        input.removeEventListener("input", arguments.callee, false);
        ok(true, "oninput should have been received");
        ok(event.bubbles, "input event should bubble");
        ok(event.cancelable, "input event should be cancelable");
        checkForm("Google");
        input.blur();
        SimpleTest.finish();
      }, false);

      doKey("down");
      checkForm("");
      doKey("return");
      break;

    default:
      ok(false, "Unexpected invocation of test #" + testNum);
      SimpleTest.finish();
      return;
    }
}

function waitForMenuChange(expectedCount) {
    notifyMenuChanged(expectedCount, null, runTest);
}

function checkMenuEntries(expectedValues, testNum) {
    var actualValues = getMenuEntries();
    is(actualValues.length, expectedValues.length, testNum + " Checking length of expected menu");
    for (var i = 0; i < expectedValues.length; i++)
        is(actualValues[i], expectedValues[i], testNum + " Checking menu entry #"+i);
}

function startTest() {
    setupFormHistory(runTest);
}

window.onload = startTest;

SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>