Bug 1304634 - Part 4: Apply form autofill API and add mochitest, r=MattN
-Commit-ID: 5eHRYoMbH7J
MozReview-Commit-ID: 47EnZ5Oyf88
--- a/browser/extensions/formautofill/moz.build
+++ b/browser/extensions/formautofill/moz.build
@@ -14,12 +14,14 @@ FINAL_TARGET_FILES.features['formautofil
FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [
'install.rdf.in'
]
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
+MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
+
JAR_MANIFESTS += ['jar.mn']
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'Form Manager')
copy from toolkit/components/satchel/test/satchel_common.js
copy to browser/extensions/formautofill/test/mochitest/formautofill_common.js
--- a/toolkit/components/satchel/test/satchel_common.js
+++ b/browser/extensions/formautofill/test/mochitest/formautofill_common.js
@@ -1,16 +1,18 @@
/* 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/. */
var gPopupShownExpected = false;
var gPopupShownListener;
var gLastAutoCompleteResults;
var gChromeScript;
+var controller = SpecialPowers.Cc["@mozilla.org/satchel/form-fill-controller;1"].
+ getService(SpecialPowers.Ci.nsIFormFillController);
/*
* Returns the element with the specified |name| attribute.
*/
function $_(formNum, name) {
var form = document.getElementById("form" + formNum);
if (!form) {
ok(false, "$_ couldn't find requested form " + formNum);
@@ -67,28 +69,37 @@ function getMenuEntries() {
throw new Error("no autocomplete results");
}
var results = gLastAutoCompleteResults;
gLastAutoCompleteResults = null;
return results;
}
+function checkMenuEntries(expectedValues) {
+ var actualValues = getMenuEntries();
+
+ is(actualValues.length, expectedValues.length, " Checking length of expected menu");
+ for (var i = 0; i < expectedValues.length; i++)
+ is(actualValues[i], expectedValues[i], " Checking menu entry #" + i);
+}
+
function checkArrayValues(actualValues, expectedValues, msg) {
is(actualValues.length, expectedValues.length, "Checking array values: " + msg);
for (var i = 0; i < expectedValues.length; i++)
is(actualValues[i], expectedValues[i], msg + " Checking array entry #" + i);
}
var checkObserver = {
verifyStack: [],
callback: null,
init() {
gChromeScript.sendAsyncMessage("addObserver");
+ // TODO: We don't have changed event right now, but it might be necessary for preference
gChromeScript.addMessageListener("satchel-storage-changed", this.observe.bind(this));
},
uninit() {
gChromeScript.sendAsyncMessage("removeObserver");
},
waitForChecks: function(callback) {
@@ -159,34 +170,19 @@ function countEntries(name, value, then
if (then) {
then(data.count);
}
resolve(data.count);
});
});
}
-// Wrapper around FormHistory.update which handles errors. Calls then() when done.
-function updateFormHistory(changes, then = null) {
- return new Promise(resolve => {
- gChromeScript.sendAsyncMessage("updateFormHistory", { changes });
- gChromeScript.addMessageListener("formHistoryUpdated", function updated({ ok }) {
- gChromeScript.removeMessageListener("formHistoryUpdated", updated);
- if (!ok) {
- ok(false, "Error occurred updating form history");
- SimpleTest.finish();
- return;
- }
-
- if (then) {
- then();
- }
- resolve();
- });
- });
+// Wrapper around profile storage update which handles errors. Calls then() when done.
+function updateProfileStorage(changes, then = null) {
+ // TODO: Update profile
}
function notifyMenuChanged(expectedCount, expectedFirstValue, then = null) {
return new Promise(resolve => {
gChromeScript.sendAsyncMessage("waitForMenuChange",
{ expectedCount,
expectedFirstValue });
gChromeScript.addMessageListener("gotMenuChange", function changed({ results }) {
@@ -243,25 +239,32 @@ function promiseACShown() {
return new Promise(resolve => {
gChromeScript.addMessageListener("onpopupshown", ({ results }) => {
gPopupShownExpected = false;
resolve(results);
});
});
}
-function satchelCommonSetup() {
+function markAsAutofillField(element) {
+ controller.markAsAutofillField(element);
+}
+
+function formAutoFillCommonSetup() {
var chromeURL = SimpleTest.getTestFileURL("parent_utils.js");
gChromeScript = SpecialPowers.loadChromeScript(chromeURL);
+ SpecialPowers.setBoolPref("dom.forms.autocomplete.experimental", true);
+
gChromeScript.addMessageListener("onpopupshown", ({ results }) => {
gLastAutoCompleteResults = results;
if (gPopupShownListener)
gPopupShownListener();
});
SimpleTest.registerCleanupFunction(() => {
+ SpecialPowers.clearUserPref("dom.forms.autocomplete.experimental");
gChromeScript.sendAsyncMessage("cleanup");
gChromeScript.destroy();
});
}
-satchelCommonSetup();
+formAutoFillCommonSetup();
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/test/mochitest/mochitest.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+skip-if = toolkit == 'android'
+support-files =
+ formautofill_common.js
+ parent_utils.js
+
+[test_basic_autocomplete_form.html]
+
copy from toolkit/components/satchel/test/parent_utils.js
copy to browser/extensions/formautofill/test/mochitest/parent_utils.js
--- a/toolkit/components/satchel/test/parent_utils.js
+++ b/browser/extensions/formautofill/test/mochitest/parent_utils.js
@@ -1,11 +1,11 @@
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/FormHistory.jsm");
+Cu.import("resource://formautofill/FormAutofillParent.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://testing-common/ContentTaskUtils.jsm");
var gAutocompletePopup = Services.ww.activeWindow.
document.
getElementById("PopupAutoComplete");
assert.ok(gAutocompletePopup, "Got autocomplete popup");
@@ -14,32 +14,22 @@ var ParentUtils = {
let entries = [];
let numRows = gAutocompletePopup.view.matchCount;
for (let i = 0; i < numRows; i++) {
entries.push(gAutocompletePopup.view.getValueAt(i));
}
return entries;
},
- cleanUpFormHist() {
- FormHistory.update({ op: "remove" });
+ cleanUpProfile() {
+ //TODO: Call profile storage clean up API
},
- updateFormHistory(changes) {
- let handler = {
- handleError: function(error) {
- assert.ok(false, error);
- sendAsyncMessage("formHistoryUpdated", { ok: false });
- },
- handleCompletion: function(reason) {
- if (!reason)
- sendAsyncMessage("formHistoryUpdated", { ok: true });
- },
- };
- FormHistory.update(changes, handler);
+ updateProfile(changes) {
+ //TODO: Call profile storage update API
},
popupshownListener() {
let results = this.getMenuEntries();
sendAsyncMessage("onpopupshown", { results });
},
countEntries(name, value) {
@@ -58,17 +48,17 @@ var ParentUtils = {
},
handleCompletion(reason) {
if (!reason) {
sendAsyncMessage("entriesCounted", { ok: true, count });
}
}
};
- FormHistory.count(obj, listener);
+ //TODO: Call profile storage count API
},
checkRowCount(expectedCount, expectedFirstValue = null) {
ContentTaskUtils.waitForCondition(() => {
// This may be called before gAutocompletePopup has initialised
// which causes it to throw
try {
return gAutocompletePopup.view.matchCount === expectedCount &&
@@ -103,27 +93,27 @@ var ParentUtils = {
observe(subject, topic, data) {
assert.ok(topic === "satchel-storage-changed");
sendAsyncMessage("satchel-storage-changed", { subject: null, topic, data });
},
cleanup() {
gAutocompletePopup.removeEventListener("popupshown", this._popupshownListener);
- this.cleanUpFormHist();
+ this.cleanUpProfile();
}
};
ParentUtils._popupshownListener =
ParentUtils.popupshownListener.bind(ParentUtils);
gAutocompletePopup.addEventListener("popupshown", ParentUtils._popupshownListener);
-ParentUtils.cleanUpFormHist();
+ParentUtils.cleanUpProfile();
-addMessageListener("updateFormHistory", (msg) => {
- ParentUtils.updateFormHistory(msg.changes);
+addMessageListener("updateProfile", (msg) => {
+ ParentUtils.updateProfile(msg.changes);
});
addMessageListener("countEntries", ({ name, value }) => {
ParentUtils.countEntries(name, value);
});
addMessageListener("waitForMenuChange", ({ expectedCount, expectedFirstValue }) => {
ParentUtils.checkRowCount(expectedCount, expectedFirstValue);
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/test/mochitest/test_basic_autocomplete_form.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test basic autofill</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="formautofill_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Form autofill test: simple form profile autofill
+
+<script>
+
+var expectingPopup = null;
+
+function expectPopup() {
+ info("expecting a popup");
+ return new Promise(resolve => {
+ expectingPopup = resolve;
+ });
+}
+
+function popupShownListener() {
+ info("popup shown for test ");
+ if (expectingPopup) {
+ expectingPopup();
+ expectingPopup = null;
+ }
+}
+
+function setInput(input, value) {
+ input.value = value;
+ input.focus();
+}
+
+function setupTest(id, str) {
+ let element = document.getElementById(id);
+ markAsAutofillField(element);
+ setInput(element, str);
+}
+
+function* runTests() {
+ setupTest("name", "");
+ doKey("down");
+ yield expectPopup();
+ checkMenuEntries(["Mary", "John"]);
+
+ setupTest("address", "");
+ doKey("down");
+ yield expectPopup();
+ checkMenuEntries(["Mary", "John"]);
+
+ setupTest("tel", "");
+ doKey("down");
+ yield expectPopup();
+ checkMenuEntries(["Mary", "John"]);
+
+ SimpleTest.finish();
+}
+
+function startTest() {
+ //TODO: Setup storage
+ spawn_task(runTests);
+}
+
+registerPopupShownListener(popupShownListener);
+SimpleTest.waitForExplicitFinish();
+window.onload = startTest;
+
+</script>
+
+<p id="display"></p>
+
+<div id="content">
+
+ <form id="form1">
+ <p>This is form 1.</p>
+ <input type="text" id="name"><br>
+ <input type="text" id="address"><br>
+ <input type="text" id="tel">
+ </form>
+
+</div>
+
+<pre id="test"></pre>
+</body>
+</html>
+
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -352,8 +352,11 @@ user_pref("plugin.load_flash_only", fals
// cannot easily be upgraded.
user_pref("media.libavcodec.allow-obsolete", true);
user_pref("media.openUnsupportedTypeWithExternalApp", false);
// Disable password capture, so that mochitests that include forms aren't
// influenced by the presence of the persistent doorhanger notification.
user_pref("signon.rememberSignons", false);
+
+// Enable form autofill feature testing.
+user_pref("browser.formautofill.enabled", true);