mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1474905 - Use a dropdown for the state/province field when possible. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D11854 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
4b7924d93b
commit
4bf1467ca5
@ -96,6 +96,10 @@ let PaymentFrameScript = {
|
|||||||
return Cu.cloneInto(format, waivedContent);
|
return Cu.cloneInto(format, waivedContent);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
findAddressSelectOption(selectEl, address, fieldName) {
|
||||||
|
return FormAutofillUtils.findAddressSelectOption(selectEl, address, fieldName);
|
||||||
|
},
|
||||||
|
|
||||||
getDefaultPreferences() {
|
getDefaultPreferences() {
|
||||||
let prefValues = Cu.cloneInto({
|
let prefValues = Cu.cloneInto({
|
||||||
saveCreditCardDefaultChecked:
|
saveCreditCardDefaultChecked:
|
||||||
|
@ -100,6 +100,7 @@ export default class AddressForm extends
|
|||||||
}, record, {
|
}, record, {
|
||||||
DEFAULT_REGION: PaymentDialogUtils.DEFAULT_REGION,
|
DEFAULT_REGION: PaymentDialogUtils.DEFAULT_REGION,
|
||||||
getFormFormat: PaymentDialogUtils.getFormFormat,
|
getFormFormat: PaymentDialogUtils.getFormFormat,
|
||||||
|
findAddressSelectOption: PaymentDialogUtils.findAddressSelectOption,
|
||||||
countries: PaymentDialogUtils.countries,
|
countries: PaymentDialogUtils.countries,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ var PaymentDialogUtils = {
|
|||||||
addressLevel3Label: "suburb",
|
addressLevel3Label: "suburb",
|
||||||
addressLevel2Label: "city",
|
addressLevel2Label: "city",
|
||||||
addressLevel1Label: "province",
|
addressLevel1Label: "province",
|
||||||
|
addressLevel1Options: null,
|
||||||
postalCodeLabel: "postalCode",
|
postalCodeLabel: "postalCode",
|
||||||
fieldsOrder: [
|
fieldsOrder: [
|
||||||
{
|
{
|
||||||
@ -79,6 +80,21 @@ var PaymentDialogUtils = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let addressLevel1Options = null;
|
||||||
|
if (country == "US") {
|
||||||
|
addressLevel1Options = new Map([
|
||||||
|
["CA", "California"],
|
||||||
|
["MA", "Massachusetts"],
|
||||||
|
["MI", "Michigan"],
|
||||||
|
]);
|
||||||
|
} else if (country == "CA") {
|
||||||
|
addressLevel1Options = new Map([
|
||||||
|
["NS", "Nova Scotia"],
|
||||||
|
["ON", "Ontario"],
|
||||||
|
["YT", "Yukon"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
let fieldsOrder = [
|
let fieldsOrder = [
|
||||||
{fieldId: "name", newLine: true},
|
{fieldId: "name", newLine: true},
|
||||||
{fieldId: "street-address", newLine: true},
|
{fieldId: "street-address", newLine: true},
|
||||||
@ -95,6 +111,7 @@ var PaymentDialogUtils = {
|
|||||||
addressLevel3Label: "suburb",
|
addressLevel3Label: "suburb",
|
||||||
addressLevel2Label: "city",
|
addressLevel2Label: "city",
|
||||||
addressLevel1Label: country == "US" ? "state" : "province",
|
addressLevel1Label: country == "US" ? "state" : "province",
|
||||||
|
addressLevel1Options,
|
||||||
postalCodeLabel: country == "US" ? "zip" : "postalCode",
|
postalCodeLabel: country == "US" ? "zip" : "postalCode",
|
||||||
fieldsOrder,
|
fieldsOrder,
|
||||||
// The following values come from addressReferences.js and should not be changed.
|
// The following values come from addressReferences.js and should not be changed.
|
||||||
@ -105,6 +122,9 @@ var PaymentDialogUtils = {
|
|||||||
["street-address", "address-level2", "postal-code"],
|
["street-address", "address-level2", "postal-code"],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
findAddressSelectOption(selectEl, address, fieldName) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
getDefaultPreferences() {
|
getDefaultPreferences() {
|
||||||
let prefValues = {
|
let prefValues = {
|
||||||
saveCreditCardDefaultChecked: false,
|
saveCreditCardDefaultChecked: false,
|
||||||
|
@ -205,7 +205,11 @@ add_task(async function test_saveButton() {
|
|||||||
fillField(form.form.querySelector("#country"), "CA");
|
fillField(form.form.querySelector("#country"), "CA");
|
||||||
ok(form.saveButton.disabled, "Save button is disabled after changing the country to Canada");
|
ok(form.saveButton.disabled, "Save button is disabled after changing the country to Canada");
|
||||||
fillField(form.form.querySelector("#country"), "US");
|
fillField(form.form.querySelector("#country"), "US");
|
||||||
ok(!form.saveButton.disabled, "Save button is enabled after changing the country to US");
|
ok(form.saveButton.disabled,
|
||||||
|
"Save button is disabled after changing the country back to US since address-level1 " +
|
||||||
|
"got cleared when changing countries");
|
||||||
|
fillField(form.form.querySelector("#address-level1"), "CA");
|
||||||
|
ok(!form.saveButton.disabled, "Save button is enabled after re-entering address-level1");
|
||||||
|
|
||||||
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
||||||
is(form.saveButton.textContent, "Next", "Check label");
|
is(form.saveButton.textContent, "Next", "Check label");
|
||||||
@ -444,25 +448,25 @@ add_task(async function test_field_validation() {
|
|||||||
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
|
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", false);
|
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
|
sendStringAndCheckValidity(addressLevel1Input, "NS", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", false);
|
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "11109", true);
|
sendStringAndCheckValidity(postalCodeInput, "11109", true);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
|
sendStringAndCheckValidity(addressLevel1Input, "NS", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "06390-0001", true);
|
sendStringAndCheckValidity(postalCodeInput, "06390-0001", true);
|
||||||
|
|
||||||
fillField(countrySelect, "CA");
|
fillField(countrySelect, "CA");
|
||||||
|
|
||||||
sendStringAndCheckValidity(postalCodeInput, "00001", false);
|
sendStringAndCheckValidity(postalCodeInput, "00001", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "CA", true);
|
sendStringAndCheckValidity(addressLevel1Input, "CA", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "94043", false);
|
sendStringAndCheckValidity(postalCodeInput, "94043", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", true);
|
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", true);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
|
sendStringAndCheckValidity(addressLevel1Input, "MI", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", true);
|
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", true);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "11109", false);
|
sendStringAndCheckValidity(postalCodeInput, "11109", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
|
sendStringAndCheckValidity(addressLevel1Input, "NS", true);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "06390-0001", false);
|
sendStringAndCheckValidity(postalCodeInput, "06390-0001", false);
|
||||||
|
|
||||||
form.remove();
|
form.remove();
|
||||||
|
@ -94,7 +94,7 @@ let AddressDataLoader = {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties = ["languages", "sub_keys", "sub_names", "sub_lnames"];
|
const properties = ["languages", "sub_keys", "sub_isoids", "sub_names", "sub_lnames"];
|
||||||
for (let key of properties) {
|
for (let key of properties) {
|
||||||
if (!data[key]) {
|
if (!data[key]) {
|
||||||
continue;
|
continue;
|
||||||
@ -536,6 +536,40 @@ this.FormAutofillUtils = {
|
|||||||
}, []);
|
}, []);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to populate dropdowns in the UI (e.g. FormAutofill preferences, Web Payments).
|
||||||
|
* Use findAddressSelectOption for matching a value to a region.
|
||||||
|
*
|
||||||
|
* @param {string[]} subKeys An array of regionCode strings
|
||||||
|
* @param {string[]} subIsoids An array of ISO ID strings, if provided will be preferred over the key
|
||||||
|
* @param {string[]} subNames An array of regionName strings
|
||||||
|
* @param {string[]} subLnames An array of latinised regionName strings
|
||||||
|
* @returns {Map?} Returns null if subKeys or subNames are not truthy.
|
||||||
|
* Otherwise, a Map will be returned mapping keys -> names.
|
||||||
|
*/
|
||||||
|
buildRegionMapIfAvailable(subKeys, subIsoids, subNames, subLnames) {
|
||||||
|
// Not all regions have sub_keys. e.g. DE
|
||||||
|
if (!subKeys || !subKeys.length ||
|
||||||
|
(!subNames && !subLnames) ||
|
||||||
|
(subNames && subKeys.length != subNames.length ||
|
||||||
|
subLnames && subKeys.length != subLnames.length)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite subKeys with subIsoids, when available
|
||||||
|
if (subIsoids && subIsoids.length && subIsoids.length == subKeys.length) {
|
||||||
|
for (let i = 0; i < subIsoids.length; i++) {
|
||||||
|
if (subIsoids[i]) {
|
||||||
|
subKeys[i] = subIsoids[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sub_lnames if sub_names does not exist
|
||||||
|
let names = subNames || subLnames;
|
||||||
|
return new Map(subKeys.map((key, index) => [key, names[index]]));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a require string and outputs an array of fields.
|
* Parse a require string and outputs an array of fields.
|
||||||
* Spaces, commas, and other literals are ignored in this implementation.
|
* Spaces, commas, and other literals are ignored in this implementation.
|
||||||
@ -866,10 +900,11 @@ this.FormAutofillUtils = {
|
|||||||
addressLevel3Label: dataset.sublocality_name_type || "suburb",
|
addressLevel3Label: dataset.sublocality_name_type || "suburb",
|
||||||
addressLevel2Label: dataset.locality_name_type || "city",
|
addressLevel2Label: dataset.locality_name_type || "city",
|
||||||
addressLevel1Label: dataset.state_name_type || "province",
|
addressLevel1Label: dataset.state_name_type || "province",
|
||||||
postalCodeLabel: dataset.zip_name_type || "postalCode",
|
addressLevel1Options: this.buildRegionMapIfAvailable(dataset.sub_keys, dataset.sub_isoids, dataset.sub_names, dataset.sub_lnames),
|
||||||
fieldsOrder: this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C"),
|
|
||||||
postalCodePattern: dataset.zip,
|
|
||||||
countryRequiredFields: this.parseRequireString(dataset.require || "AC"),
|
countryRequiredFields: this.parseRequireString(dataset.require || "AC"),
|
||||||
|
fieldsOrder: this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C"),
|
||||||
|
postalCodeLabel: dataset.zip_name_type || "postalCode",
|
||||||
|
postalCodePattern: dataset.zip,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -135,6 +135,8 @@ class EditAddress extends EditAutofillForm {
|
|||||||
* @param {object} config
|
* @param {object} config
|
||||||
* @param {string[]} config.DEFAULT_REGION
|
* @param {string[]} config.DEFAULT_REGION
|
||||||
* @param {function} config.getFormFormat Function to return form layout info for a given country.
|
* @param {function} config.getFormFormat Function to return form layout info for a given country.
|
||||||
|
* @param {function} config.findAddressSelectOption Finds the matching select option for a given
|
||||||
|
select element, address, and fieldName.
|
||||||
* @param {string[]} config.countries
|
* @param {string[]} config.countries
|
||||||
* @param {boolean} [config.noValidate=undefined] Whether to validate the form
|
* @param {boolean} [config.noValidate=undefined] Whether to validate the form
|
||||||
*/
|
*/
|
||||||
@ -167,7 +169,12 @@ class EditAddress extends EditAutofillForm {
|
|||||||
country: this.DEFAULT_REGION,
|
country: this.DEFAULT_REGION,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let {addressLevel1Options} = this.getFormFormat(record.country);
|
||||||
|
this.populateAddressLevel1(addressLevel1Options, record.country);
|
||||||
|
|
||||||
super.loadRecord(record);
|
super.loadRecord(record);
|
||||||
|
this.loadAddressLevel1(record["address-level1"], record.country);
|
||||||
this.formatForm(record.country);
|
this.formatForm(record.country);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +235,7 @@ class EditAddress extends EditAutofillForm {
|
|||||||
addressLevel3Label,
|
addressLevel3Label,
|
||||||
addressLevel2Label,
|
addressLevel2Label,
|
||||||
addressLevel1Label,
|
addressLevel1Label,
|
||||||
|
addressLevel1Options,
|
||||||
postalCodeLabel,
|
postalCodeLabel,
|
||||||
fieldsOrder: mailingFieldsOrder,
|
fieldsOrder: mailingFieldsOrder,
|
||||||
postalCodePattern,
|
postalCodePattern,
|
||||||
@ -248,6 +256,7 @@ class EditAddress extends EditAutofillForm {
|
|||||||
}
|
}
|
||||||
this.arrangeFields(fieldClasses, requiredFields);
|
this.arrangeFields(fieldClasses, requiredFields);
|
||||||
this.updatePostalCodeValidation(postalCodePattern);
|
this.updatePostalCodeValidation(postalCodePattern);
|
||||||
|
this.populateAddressLevel1(addressLevel1Options, country);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,6 +327,85 @@ class EditAddress extends EditAutofillForm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the address-level1 value on the form field (input or select, whichever is present).
|
||||||
|
*
|
||||||
|
* @param {string} addressLevel1Value Value of the address-level1 from the autofill record
|
||||||
|
* @param {string} country The corresponding country
|
||||||
|
*/
|
||||||
|
loadAddressLevel1(addressLevel1Value, country) {
|
||||||
|
let field = this._elements.form.querySelector("#address-level1");
|
||||||
|
|
||||||
|
if (field.localName == "input") {
|
||||||
|
field.value = addressLevel1Value || "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchedSelectOption = this.findAddressSelectOption(field, {
|
||||||
|
country,
|
||||||
|
"address-level1": addressLevel1Value,
|
||||||
|
}, "address-level1");
|
||||||
|
if (matchedSelectOption && !matchedSelectOption.selected) {
|
||||||
|
field.value = matchedSelectOption.value;
|
||||||
|
field.dispatchEvent(new Event("input", {bubbles: true}));
|
||||||
|
field.dispatchEvent(new Event("change", {bubbles: true}));
|
||||||
|
} else if (addressLevel1Value) {
|
||||||
|
// If the option wasn't found, insert an option at the beginning of
|
||||||
|
// the select that matches the stored value.
|
||||||
|
field.insertBefore(new Option(addressLevel1Value, addressLevel1Value, true, true), field.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the text input for address-level1 with a select dropdown if
|
||||||
|
* a fixed set of names exists. Otherwise show a text input.
|
||||||
|
*
|
||||||
|
* @param {Map?} options Map of options with regionCode -> name mappings
|
||||||
|
* @param {string} country The corresponding country
|
||||||
|
*/
|
||||||
|
populateAddressLevel1(options, country) {
|
||||||
|
let field = this._elements.form.querySelector("#address-level1");
|
||||||
|
|
||||||
|
if (field.dataset.country == country) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
if (field.localName == "input") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = document.createElement("input");
|
||||||
|
input.setAttribute("type", "text");
|
||||||
|
input.id = "address-level1";
|
||||||
|
input.required = field.required;
|
||||||
|
input.disabled = field.disabled;
|
||||||
|
input.tabIndex = field.tabIndex;
|
||||||
|
field.replaceWith(input);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.localName == "input") {
|
||||||
|
let select = document.createElement("select");
|
||||||
|
select.id = "address-level1";
|
||||||
|
select.required = field.required;
|
||||||
|
select.disabled = field.disabled;
|
||||||
|
select.tabIndex = field.tabIndex;
|
||||||
|
field.replaceWith(select);
|
||||||
|
field = select;
|
||||||
|
}
|
||||||
|
|
||||||
|
field.textContent = "";
|
||||||
|
field.dataset.country = country;
|
||||||
|
let fragment = document.createDocumentFragment();
|
||||||
|
fragment.appendChild(new Option(undefined, undefined, true, true));
|
||||||
|
for (let [regionCode, regionName] of options) {
|
||||||
|
let option = new Option(regionName, regionCode);
|
||||||
|
fragment.appendChild(option);
|
||||||
|
}
|
||||||
|
field.appendChild(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
populateCountries() {
|
populateCountries() {
|
||||||
let fragment = document.createDocumentFragment();
|
let fragment = document.createDocumentFragment();
|
||||||
// Sort countries by their visible names.
|
// Sort countries by their visible names.
|
||||||
|
@ -53,6 +53,9 @@
|
|||||||
<span class="label-text"/>
|
<span class="label-text"/>
|
||||||
</label>
|
</label>
|
||||||
<label id="address-level1-container" class="container">
|
<label id="address-level1-container" class="container">
|
||||||
|
<!-- The address-level1 input will get replaced by a select dropdown
|
||||||
|
by autofillEditForms.js when the selected country has provided
|
||||||
|
specific options. -->
|
||||||
<input id="address-level1" type="text"/>
|
<input id="address-level1" type="text"/>
|
||||||
<span class="label-text"/>
|
<span class="label-text"/>
|
||||||
</label>
|
</label>
|
||||||
@ -89,6 +92,7 @@
|
|||||||
} = FormAutofill;
|
} = FormAutofill;
|
||||||
let {
|
let {
|
||||||
getFormFormat,
|
getFormFormat,
|
||||||
|
findAddressSelectOption,
|
||||||
} = FormAutofillUtils;
|
} = FormAutofillUtils;
|
||||||
let args = window.arguments || [];
|
let args = window.arguments || [];
|
||||||
let {
|
let {
|
||||||
@ -102,6 +106,7 @@
|
|||||||
}, record, {
|
}, record, {
|
||||||
DEFAULT_REGION,
|
DEFAULT_REGION,
|
||||||
getFormFormat: getFormFormat.bind(FormAutofillUtils),
|
getFormFormat: getFormFormat.bind(FormAutofillUtils),
|
||||||
|
findAddressSelectOption: findAddressSelectOption.bind(FormAutofillUtils),
|
||||||
countries,
|
countries,
|
||||||
noValidate,
|
noValidate,
|
||||||
});
|
});
|
||||||
|
@ -25,6 +25,7 @@ class AutofillEditDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
this.updateSaveButtonState();
|
||||||
this.attachEventListeners();
|
this.attachEventListeners();
|
||||||
// For testing only: signal to tests that the dialog is ready for testing.
|
// For testing only: signal to tests that the dialog is ready for testing.
|
||||||
// This is likely no longer needed since retrieving from storage is fully
|
// This is likely no longer needed since retrieving from storage is fully
|
||||||
@ -108,13 +109,7 @@ class AutofillEditDialog {
|
|||||||
* @param {DOMEvent} event
|
* @param {DOMEvent} event
|
||||||
*/
|
*/
|
||||||
handleInput(event) {
|
handleInput(event) {
|
||||||
// Toggle disabled attribute on the save button based on
|
this.updateSaveButtonState();
|
||||||
// whether the form is filled or empty.
|
|
||||||
if (Object.keys(this._elements.fieldContainer.buildFormObject()).length == 0) {
|
|
||||||
this._elements.save.setAttribute("disabled", true);
|
|
||||||
} else {
|
|
||||||
this._elements.save.removeAttribute("disabled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,6 +123,16 @@ class AutofillEditDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSaveButtonState() {
|
||||||
|
// Toggle disabled attribute on the save button based on
|
||||||
|
// whether the form is filled or empty.
|
||||||
|
if (Object.keys(this._elements.fieldContainer.buildFormObject()).length == 0) {
|
||||||
|
this._elements.save.setAttribute("disabled", true);
|
||||||
|
} else {
|
||||||
|
this._elements.save.removeAttribute("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach event listener
|
* Attach event listener
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,7 @@ add_task(async function test_saveAddress() {
|
|||||||
is(doc.querySelector("#postal-code-container > .label-text").textContent, "ZIP Code",
|
is(doc.querySelector("#postal-code-container > .label-text").textContent, "ZIP Code",
|
||||||
"US postal-code label should be 'ZIP Code'");
|
"US postal-code label should be 'ZIP Code'");
|
||||||
// Input address info and verify move through form with tab keys
|
// Input address info and verify move through form with tab keys
|
||||||
const keyInputs = [
|
const keypresses = [
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_1["given-name"],
|
TEST_ADDRESS_1["given-name"],
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
@ -83,7 +83,16 @@ add_task(async function test_saveAddress() {
|
|||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
"VK_RETURN",
|
"VK_RETURN",
|
||||||
];
|
];
|
||||||
keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
|
keypresses.forEach(keypress => {
|
||||||
|
if (doc.activeElement.localName == "select" && !keypress.startsWith("VK_")) {
|
||||||
|
let field = doc.activeElement;
|
||||||
|
while (field.value != keypress) {
|
||||||
|
EventUtils.synthesizeKey(keypress[0], {}, win);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EventUtils.synthesizeKey(keypress, {}, win);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
let addresses = await getAddresses();
|
let addresses = await getAddresses();
|
||||||
|
|
||||||
@ -100,6 +109,11 @@ add_task(async function test_editAddress() {
|
|||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey("VK_RIGHT", {}, win);
|
EventUtils.synthesizeKey("VK_RIGHT", {}, win);
|
||||||
EventUtils.synthesizeKey("test", {}, win);
|
EventUtils.synthesizeKey("test", {}, win);
|
||||||
|
|
||||||
|
let stateSelect = win.document.querySelector("#address-level1");
|
||||||
|
is(stateSelect.selectedOptions[0].value, TEST_ADDRESS_1["address-level1"],
|
||||||
|
"address-level1 should be selected in the dropdown");
|
||||||
|
|
||||||
win.document.querySelector("#save").click();
|
win.document.querySelector("#save").click();
|
||||||
}, {
|
}, {
|
||||||
record: addresses[0],
|
record: addresses[0],
|
||||||
@ -114,6 +128,31 @@ add_task(async function test_editAddress() {
|
|||||||
is(addresses.length, 0, "Address storage is empty");
|
is(addresses.length, 0, "Address storage is empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(async function test_editAddressFrenchCanadianChangedToEnglishRepresentation() {
|
||||||
|
let addressClone = Object.assign({}, TEST_ADDRESS_CA_1);
|
||||||
|
addressClone["address-level1"] = "Colombie-Britannique";
|
||||||
|
await saveAddress(addressClone);
|
||||||
|
|
||||||
|
let addresses = await getAddresses();
|
||||||
|
await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
|
||||||
|
let stateSelect = win.document.querySelector("#address-level1");
|
||||||
|
is(stateSelect.selectedOptions[0].value, "BC",
|
||||||
|
"address-level1 should have 'BC' selected in the dropdown");
|
||||||
|
|
||||||
|
win.document.querySelector("#save").click();
|
||||||
|
}, {
|
||||||
|
record: addresses[0],
|
||||||
|
});
|
||||||
|
addresses = await getAddresses();
|
||||||
|
|
||||||
|
is(addresses.length, 1, "only one address is in storage");
|
||||||
|
is(addresses[0]["address-level1"], "BC", "address-level1 changed");
|
||||||
|
await removeAddresses([addresses[0].guid]);
|
||||||
|
|
||||||
|
addresses = await getAddresses();
|
||||||
|
is(addresses.length, 0, "Address storage is empty");
|
||||||
|
});
|
||||||
|
|
||||||
add_task(async function test_editSparseAddress() {
|
add_task(async function test_editSparseAddress() {
|
||||||
let record = {...TEST_ADDRESS_1};
|
let record = {...TEST_ADDRESS_1};
|
||||||
info("delete some usually required properties");
|
info("delete some usually required properties");
|
||||||
@ -294,7 +333,7 @@ add_task(async function test_saveAddressIE() {
|
|||||||
await removeAllRecords();
|
await removeAllRecords();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_countryFieldLabels() {
|
add_task(async function test_countryAndStateFieldLabels() {
|
||||||
await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
|
await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
|
||||||
let doc = win.document;
|
let doc = win.document;
|
||||||
// Change country to verify labels
|
// Change country to verify labels
|
||||||
@ -309,7 +348,7 @@ add_task(async function test_countryFieldLabels() {
|
|||||||
|
|
||||||
for (let countryOption of doc.querySelector("#country").options) {
|
for (let countryOption of doc.querySelector("#country").options) {
|
||||||
if (countryOption.value == "") {
|
if (countryOption.value == "") {
|
||||||
info("Skipping the empty option");
|
info("Skipping the empty country option");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +373,31 @@ add_task(async function test_countryFieldLabels() {
|
|||||||
is(labelEl.dataset.localization, undefined,
|
is(labelEl.dataset.localization, undefined,
|
||||||
"Ensure data-localization was removed: " + countryOption.value);
|
"Ensure data-localization was removed: " + countryOption.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stateOptions = doc.querySelector("#address-level1").options;
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
let expectedStateOptions = {
|
||||||
|
"BS": {
|
||||||
|
// The Bahamas is an interesting testcase because they have some keys that are full names, and others are replaced with ISO IDs.
|
||||||
|
"keys": "Abaco~AK~Andros~BY~BI~CI~Crooked Island~Eleuthera~EX~Grand Bahama~HI~IN~LI~MG~N.P.~RI~RC~SS~SW".split("~"),
|
||||||
|
"names": "Abaco Islands~Acklins~Andros Island~Berry Islands~Bimini~Cat Island~Crooked Island~Eleuthera~Exuma and Cays~Grand Bahama~Harbour Island~Inagua~Long Island~Mayaguana~New Providence~Ragged Island~Rum Cay~San Salvador~Spanish Wells".split("~"),
|
||||||
|
},
|
||||||
|
"US": {
|
||||||
|
"keys": "AL~AK~AS~AZ~AR~AA~AE~AP~CA~CO~CT~DE~DC~FL~GA~GU~HI~ID~IL~IN~IA~KS~KY~LA~ME~MH~MD~MA~MI~FM~MN~MS~MO~MT~NE~NV~NH~NJ~NM~NY~NC~ND~MP~OH~OK~OR~PW~PA~PR~RI~SC~SD~TN~TX~UT~VT~VI~VA~WA~WV~WI~WY".split("~"),
|
||||||
|
"names": "Alabama~Alaska~American Samoa~Arizona~Arkansas~Armed Forces (AA)~Armed Forces (AE)~Armed Forces (AP)~California~Colorado~Connecticut~Delaware~District of Columbia~Florida~Georgia~Guam~Hawaii~Idaho~Illinois~Indiana~Iowa~Kansas~Kentucky~Louisiana~Maine~Marshall Islands~Maryland~Massachusetts~Michigan~Micronesia~Minnesota~Mississippi~Missouri~Montana~Nebraska~Nevada~New Hampshire~New Jersey~New Mexico~New York~North Carolina~North Dakota~Northern Mariana Islands~Ohio~Oklahoma~Oregon~Palau~Pennsylvania~Puerto Rico~Rhode Island~South Carolina~South Dakota~Tennessee~Texas~Utah~Vermont~Virgin Islands~Virginia~Washington~West Virginia~Wisconsin~Wyoming".split("~"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* eslint-enable max-len */
|
||||||
|
|
||||||
|
if (expectedStateOptions[countryOption.value]) {
|
||||||
|
let {keys, names} = expectedStateOptions[countryOption.value];
|
||||||
|
is(stateOptions.length, keys.length + 1, "stateOptions should list all options plus a blank entry");
|
||||||
|
is(stateOptions[0].value, "", "First State option should be blank");
|
||||||
|
for (let i = 1; i < stateOptions.length; i++) {
|
||||||
|
is(stateOptions[i].value, keys[i - 1], "Each State should be listed in alphabetical name order (key)");
|
||||||
|
is(stateOptions[i].text, names[i - 1], "Each State should be listed in alphabetical name order (name)");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.querySelector("#cancel").click();
|
doc.querySelector("#cancel").click();
|
||||||
@ -454,7 +518,9 @@ add_task(async function test_hiddenFieldRemovedWhenCountryChanged() {
|
|||||||
doc.querySelector("#address-level2").focus();
|
doc.querySelector("#address-level2").focus();
|
||||||
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
|
||||||
doc.querySelector("#address-level1").focus();
|
doc.querySelector("#address-level1").focus();
|
||||||
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"], {}, win);
|
while (doc.querySelector("#address-level1").value != TEST_ADDRESS_1["address-level1"]) {
|
||||||
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"][0], {}, win);
|
||||||
|
}
|
||||||
doc.querySelector("#save").focus();
|
doc.querySelector("#save").focus();
|
||||||
EventUtils.synthesizeKey("VK_RETURN", {}, win);
|
EventUtils.synthesizeKey("VK_RETURN", {}, win);
|
||||||
});
|
});
|
||||||
@ -496,6 +562,7 @@ add_task(async function test_countrySpecificFieldsGetRequiredness() {
|
|||||||
EventUtils.synthesizeKey("United States", {}, win);
|
EventUtils.synthesizeKey("United States", {}, win);
|
||||||
|
|
||||||
await TestUtils.waitForCondition(() => {
|
await TestUtils.waitForCondition(() => {
|
||||||
|
provinceField = doc.getElementById("address-level1");
|
||||||
return provinceField.parentNode.style.display != "none";
|
return provinceField.parentNode.style.display != "none";
|
||||||
}, "Wait for address-level1 to become visible", 10);
|
}, "Wait for address-level1 to become visible", 10);
|
||||||
|
|
||||||
@ -506,6 +573,7 @@ add_task(async function test_countrySpecificFieldsGetRequiredness() {
|
|||||||
EventUtils.synthesizeKey("Romania", {}, win);
|
EventUtils.synthesizeKey("Romania", {}, win);
|
||||||
|
|
||||||
await TestUtils.waitForCondition(() => {
|
await TestUtils.waitForCondition(() => {
|
||||||
|
provinceField = doc.getElementById("address-level1");
|
||||||
return provinceField.parentNode.style.display == "none";
|
return provinceField.parentNode.style.display == "none";
|
||||||
}, "Wait for address-level1 to become hidden", 10);
|
}, "Wait for address-level1 to become hidden", 10);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user