зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1370475 - Part 2: Convert the address related fields for display purpose. r=lchang
MozReview-Commit-ID: 1Jk0pRc1snu --HG-- extra : rebase_source : 310824d6952b9f156dcddf6408b376e75623b565
This commit is contained in:
Родитель
e119e20da4
Коммит
7c64597fd1
|
@ -114,11 +114,14 @@ AutofillProfileAutoCompleteSearch.prototype = {
|
|||
// Sort addresses by timeLastUsed for showing the lastest used address at top.
|
||||
addresses.sort((a, b) => b.timeLastUsed - a.timeLastUsed);
|
||||
|
||||
let handler = FormAutofillContent.getFormHandler(focusedInput);
|
||||
let adaptedAddresses = handler.getAdaptedProfiles(addresses);
|
||||
|
||||
let allFieldNames = FormAutofillContent.getAllFieldNames(focusedInput);
|
||||
let result = new ProfileAutoCompleteResult(searchString,
|
||||
info.fieldName,
|
||||
allFieldNames,
|
||||
addresses,
|
||||
adaptedAddresses,
|
||||
{});
|
||||
|
||||
listener.onSearchResult(this, result);
|
||||
|
@ -442,8 +445,8 @@ var FormAutofillContent = {
|
|||
},
|
||||
|
||||
getAllFieldNames(element) {
|
||||
let formDetails = this.getFormDetails(element);
|
||||
return formDetails.map(record => record.fieldName);
|
||||
let formHandler = this.getFormHandler(element);
|
||||
return formHandler ? formHandler.allFieldNames : null;
|
||||
},
|
||||
|
||||
identifyAutofillFields(element) {
|
||||
|
|
|
@ -90,12 +90,63 @@ FormAutofillHandler.prototype = {
|
|||
* Set fieldDetails from the form about fields that can be autofilled.
|
||||
*/
|
||||
collectFormFields() {
|
||||
this._cacheValue.allFieldNames = null;
|
||||
this._formFieldCount = this.form.elements.length;
|
||||
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form);
|
||||
this.fieldDetails = fieldDetails ? fieldDetails : [];
|
||||
log.debug("Collected details on", this.fieldDetails.length, "fields");
|
||||
},
|
||||
|
||||
getFieldDetailByName(fieldName) {
|
||||
return this.fieldDetails.find(detail => detail.fieldName == fieldName);
|
||||
},
|
||||
|
||||
_cacheValue: {
|
||||
allFieldNames: null,
|
||||
oneLineStreetAddress: null,
|
||||
},
|
||||
|
||||
get allFieldNames() {
|
||||
if (!this._cacheValue.allFieldNames) {
|
||||
this._cacheValue.allFieldNames = this.fieldDetails.map(record => record.fieldName);
|
||||
}
|
||||
return this._cacheValue.allFieldNames;
|
||||
},
|
||||
|
||||
_getOneLineStreetAddress(address) {
|
||||
if (!this._cacheValue.oneLineStreetAddress) {
|
||||
this._cacheValue.oneLineStreetAddress = {};
|
||||
}
|
||||
if (!this._cacheValue.oneLineStreetAddress[address]) {
|
||||
this._cacheValue.oneLineStreetAddress[address] = FormAutofillUtils.toOneLineAddress(address);
|
||||
}
|
||||
return this._cacheValue.oneLineStreetAddress[address];
|
||||
},
|
||||
|
||||
_addressTransformer(profile) {
|
||||
if (profile["street-address"]) {
|
||||
profile["street-address"] = this._getOneLineStreetAddress(profile["street-address"]);
|
||||
|
||||
let waitForConcat = [];
|
||||
for (let f of ["address-line3", "address-line2", "address-line1"]) {
|
||||
waitForConcat.unshift(profile[f]);
|
||||
if (this.getFieldDetailByName(f)) {
|
||||
if (waitForConcat.length > 1) {
|
||||
profile[f] = FormAutofillUtils.toOneLineAddress(waitForConcat);
|
||||
}
|
||||
waitForConcat = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getAdaptedProfiles(originalProfiles) {
|
||||
for (let profile of originalProfiles) {
|
||||
this._addressTransformer(profile);
|
||||
}
|
||||
return originalProfiles;
|
||||
},
|
||||
|
||||
/**
|
||||
* Processes form fields that can be autofilled, and populates them with the
|
||||
* profile provided by backend.
|
||||
|
|
|
@ -56,6 +56,24 @@ this.FormAutofillUtils = {
|
|||
return categories;
|
||||
},
|
||||
|
||||
getAddressSeparator() {
|
||||
// The separator should be based on the L10N address format, and using a
|
||||
// white space is a temporary solution.
|
||||
return " ";
|
||||
},
|
||||
|
||||
toOneLineAddress(address, delimiter = "\n") {
|
||||
let array = typeof address == "string" ? address.split(delimiter) : address;
|
||||
|
||||
if (!Array.isArray(array)) {
|
||||
return null;
|
||||
}
|
||||
return array
|
||||
.map(s => s.trim())
|
||||
.filter(s => s)
|
||||
.join(this.getAddressSeparator());
|
||||
},
|
||||
|
||||
defineLazyLogGetter(scope, logPrefix) {
|
||||
XPCOMUtils.defineLazyGetter(scope, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
|
||||
|
|
|
@ -152,6 +152,11 @@ ManageProfileDialog.prototype = {
|
|||
];
|
||||
|
||||
let parts = [];
|
||||
if (address["street-address"]) {
|
||||
address["street-address"] = FormAutofillUtils.toOneLineAddress(
|
||||
address["street-address"]
|
||||
);
|
||||
}
|
||||
for (const fieldName of fieldOrder) {
|
||||
let string = address[fieldName];
|
||||
if (string) {
|
||||
|
|
|
@ -19,15 +19,17 @@ Form autofill test: simple form address autofill
|
|||
|
||||
"use strict";
|
||||
|
||||
const {FormAutofillUtils} = SpecialPowers.Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
||||
|
||||
let MOCK_STORAGE = [{
|
||||
organization: "Sesame Street",
|
||||
"street-address": "123 Sesame Street.",
|
||||
"street-address": "123 Sesame Street.\n2-line\n3-line",
|
||||
tel: "1-345-345-3456",
|
||||
country: "US",
|
||||
"address-level1": "NY",
|
||||
}, {
|
||||
organization: "Mozilla",
|
||||
"street-address": "331 E. Evelyn Avenue",
|
||||
"street-address": "331 E. Evelyn Avenue\n2-line\n3-line",
|
||||
tel: "1-650-903-0800",
|
||||
country: "US",
|
||||
"address-level1": "CA",
|
||||
|
@ -67,7 +69,11 @@ function checkFormFilled(address) {
|
|||
if (document.activeElement == element) {
|
||||
promises.push(checkAutoCompleteInputFilled(element, address[prop]));
|
||||
} else {
|
||||
promises.push(...checkElementFilled(element, address[prop]));
|
||||
let converted = address[prop];
|
||||
if (prop == "street-address") {
|
||||
converted = FormAutofillUtils.toOneLineAddress(converted);
|
||||
}
|
||||
promises.push(...checkElementFilled(element, converted));
|
||||
}
|
||||
}
|
||||
doKey("return");
|
||||
|
@ -106,21 +112,40 @@ add_task(async function check_menu_when_both_existed() {
|
|||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||
JSON.stringify({
|
||||
primary: address.organization,
|
||||
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
})
|
||||
));
|
||||
|
||||
await setInput("#street-address", "");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address["street-address"], secondary: address.organization})
|
||||
JSON.stringify({
|
||||
primary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
secondary: address.organization,
|
||||
})
|
||||
));
|
||||
|
||||
await setInput("#tel", "");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.tel, secondary: address["street-address"]})
|
||||
JSON.stringify({
|
||||
primary: address.tel,
|
||||
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
})
|
||||
));
|
||||
|
||||
await setInput("#address-line1", "");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
primary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
secondary: address.organization,
|
||||
})
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -138,7 +163,10 @@ add_task(async function check_fields_after_form_autofill() {
|
|||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||
JSON.stringify({
|
||||
primary: address.organization,
|
||||
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
})
|
||||
).slice(1));
|
||||
doKey("down");
|
||||
await checkFormFilled(MOCK_STORAGE[1]);
|
||||
|
@ -160,7 +188,10 @@ add_task(async function check_form_autofill_resume() {
|
|||
doKey("down");
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.tel, secondary: address["street-address"]})
|
||||
JSON.stringify({
|
||||
primary: address.tel,
|
||||
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
})
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -174,6 +205,7 @@ add_task(async function check_form_autofill_resume() {
|
|||
<p>This is a basic form.</p>
|
||||
<p><label>organization: <input id="organization" name="organization" autocomplete="organization" type="text"></label></p>
|
||||
<p><label>streetAddress: <input id="street-address" name="street-address" autocomplete="street-address" type="text"></label></p>
|
||||
<p><label>address-line1: <input id="address-line1" name="address-line1" autocomplete="address-line1" type="text"></label></p>
|
||||
<p><label>tel: <input id="tel" name="tel" autocomplete="tel" type="text"></label></p>
|
||||
<p><label>email: <input id="email" name="email" autocomplete="email" type="text"></label></p>
|
||||
<p><label>country: <select id="country" name="country" autocomplete="country">
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Test for form auto fill content helper fill all inputs function.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://formautofill/FormAutofillHandler.jsm");
|
||||
|
||||
const DEFAULT_PROFILE = {
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St\nline2\nline3",
|
||||
"address-line1": "2 Harrison St",
|
||||
"address-line2": "line2",
|
||||
"address-line3": "line3",
|
||||
};
|
||||
|
||||
const TESTCASES = [
|
||||
{
|
||||
description: "Form with street-address",
|
||||
document: `<form>
|
||||
<input id="street-addr" autocomplete="street-address">
|
||||
</form>`,
|
||||
profileData: [Object.assign({}, DEFAULT_PROFILE)],
|
||||
expectedResult: [{
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St line2 line3",
|
||||
"-moz-street-address-one-line": "2 Harrison St line2 line3",
|
||||
"address-line1": "2 Harrison St",
|
||||
"address-line2": "line2",
|
||||
"address-line3": "line3",
|
||||
}],
|
||||
},
|
||||
{
|
||||
description: "Form with street-address, address-line[1, 2, 3]",
|
||||
document: `<form>
|
||||
<input id="street-addr" autocomplete="street-address">
|
||||
<input id="line1" autocomplete="address-line1">
|
||||
<input id="line2" autocomplete="address-line2">
|
||||
<input id="line3" autocomplete="address-line3">
|
||||
</form>`,
|
||||
profileData: [Object.assign({}, DEFAULT_PROFILE)],
|
||||
expectedResult: [{
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St line2 line3",
|
||||
"-moz-street-address-one-line": "2 Harrison St line2 line3",
|
||||
"address-line1": "2 Harrison St",
|
||||
"address-line2": "line2",
|
||||
"address-line3": "line3",
|
||||
}],
|
||||
},
|
||||
{
|
||||
description: "Form with street-address, address-line1",
|
||||
document: `<form>
|
||||
<input id="street-addr" autocomplete="street-address">
|
||||
<input id="line1" autocomplete="address-line1">
|
||||
</form>`,
|
||||
profileData: [Object.assign({}, DEFAULT_PROFILE)],
|
||||
expectedResult: [{
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St line2 line3",
|
||||
"-moz-street-address-one-line": "2 Harrison St line2 line3",
|
||||
"address-line1": "2 Harrison St line2 line3",
|
||||
"address-line2": "line2",
|
||||
"address-line3": "line3",
|
||||
}],
|
||||
},
|
||||
{
|
||||
description: "Form with street-address, address-line[1, 2]",
|
||||
document: `<form>
|
||||
<input id="street-addr" autocomplete="street-address">
|
||||
<input id="line1" autocomplete="address-line1">
|
||||
<input id="line2" autocomplete="address-line2">
|
||||
</form>`,
|
||||
profileData: [Object.assign({}, DEFAULT_PROFILE)],
|
||||
expectedResult: [{
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St line2 line3",
|
||||
"-moz-street-address-one-line": "2 Harrison St line2 line3",
|
||||
"address-line1": "2 Harrison St",
|
||||
"address-line2": "line2 line3",
|
||||
"address-line3": "line3",
|
||||
}],
|
||||
},
|
||||
{
|
||||
description: "Form with street-address, address-line[1, 3]",
|
||||
document: `<form>
|
||||
<input id="street-addr" autocomplete="street-address">
|
||||
<input id="line1" autocomplete="address-line1">
|
||||
<input id="line3" autocomplete="address-line3">
|
||||
</form>`,
|
||||
profileData: [Object.assign({}, DEFAULT_PROFILE)],
|
||||
expectedResult: [{
|
||||
"guid": "123",
|
||||
"street-address": "2 Harrison St line2 line3",
|
||||
"-moz-street-address-one-line": "2 Harrison St line2 line3",
|
||||
"address-line1": "2 Harrison St line2",
|
||||
"address-line2": "line2",
|
||||
"address-line3": "line3",
|
||||
}],
|
||||
},
|
||||
];
|
||||
|
||||
for (let testcase of TESTCASES) {
|
||||
add_task(async function() {
|
||||
do_print("Starting testcase: " + testcase.description);
|
||||
|
||||
let doc = MockDocument.createTestDocument("http://localhost:8080/test/",
|
||||
testcase.document);
|
||||
let form = doc.querySelector("form");
|
||||
let formLike = FormLikeFactory.createFromForm(form);
|
||||
let handler = new FormAutofillHandler(formLike);
|
||||
|
||||
handler.collectFormFields();
|
||||
let adaptedAddresses = handler.getAdaptedProfiles(testcase.profileData);
|
||||
Assert.deepEqual(adaptedAddresses, testcase.expectedResult);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
||||
|
||||
add_task(async function test_getCategoriesFromFieldNames() {
|
||||
const TEST_CASES = [
|
||||
{
|
||||
strings: ["A", "B", "C", "D"],
|
||||
expectedValue: "A B C D",
|
||||
},
|
||||
{
|
||||
strings: ["A", "B", "", "D"],
|
||||
expectedValue: "A B D",
|
||||
},
|
||||
{
|
||||
strings: ["", "B", "", "D"],
|
||||
expectedValue: "B D",
|
||||
},
|
||||
{
|
||||
strings: "A B C",
|
||||
expectedValue: "A B C",
|
||||
},
|
||||
{
|
||||
strings: "A\nB\n\n\nC",
|
||||
expectedValue: "A B C",
|
||||
},
|
||||
{
|
||||
strings: "A B \nC",
|
||||
expectedValue: "A B C",
|
||||
},
|
||||
{
|
||||
strings: "A-B-C",
|
||||
expectedValue: "A B C",
|
||||
delimiter: "-",
|
||||
},
|
||||
{
|
||||
strings: "A B\n \nC",
|
||||
expectedValue: "A B C",
|
||||
},
|
||||
];
|
||||
|
||||
for (let tc of TEST_CASES) {
|
||||
let result;
|
||||
if (tc.delimiter) {
|
||||
result = FormAutofillUtils.toOneLineAddress(tc.strings, tc.delimiter);
|
||||
} else {
|
||||
result = FormAutofillUtils.toOneLineAddress(tc.strings);
|
||||
}
|
||||
Assert.deepEqual(result, tc.expectedValue);
|
||||
}
|
||||
});
|
|
@ -23,6 +23,7 @@ support-files =
|
|||
[test_creditCardRecords.js]
|
||||
[test_extractLabelStrings.js]
|
||||
[test_findLabelElements.js]
|
||||
[test_getAdaptedProfiles.js]
|
||||
[test_getCategoriesFromFieldNames.js]
|
||||
[test_getFormInputDetails.js]
|
||||
[test_getInfo.js]
|
||||
|
@ -33,4 +34,5 @@ support-files =
|
|||
[test_onFormSubmitted.js]
|
||||
[test_profileAutocompleteResult.js]
|
||||
[test_savedFieldNames.js]
|
||||
[test_toOneLineAddress.js]
|
||||
[test_transformFields.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче