summaryrefslogtreecommitdiffstats
path: root/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/extensions/formautofill/test/browser/browser_editAddressDialog.js')
-rw-r--r--browser/extensions/formautofill/test/browser/browser_editAddressDialog.js951
1 files changed, 951 insertions, 0 deletions
diff --git a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
new file mode 100644
index 0000000000..0088f916bd
--- /dev/null
+++ b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
@@ -0,0 +1,951 @@
+"use strict";
+
+const { FormAutofillUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/shared/FormAutofillUtils.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ Region: "resource://gre/modules/Region.sys.mjs",
+});
+
+requestLongerTimeout(6);
+
+add_task(async function setup_supportedCountries() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[SUPPORTED_COUNTRIES_PREF, "US,CA,DE"]],
+ });
+});
+
+add_task(async function test_cancelEditAddressDialog() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ win.document.querySelector("#cancel").click();
+ });
+});
+
+add_task(async function test_cancelEditAddressDialogWithESC() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
+ });
+});
+
+add_task(async function test_defaultCountry() {
+ Region._setHomeRegion("CA", false);
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ is(
+ doc.querySelector("#country").value,
+ "CA",
+ "Default country set to Canada"
+ );
+ doc.querySelector("#cancel").click();
+ });
+ Region._setHomeRegion("DE", false);
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ is(
+ doc.querySelector("#country").value,
+ "DE",
+ "Default country set to Germany"
+ );
+ doc.querySelector("#cancel").click();
+ });
+ // Test unsupported country
+ Region._setHomeRegion("XX", false);
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ is(doc.querySelector("#country").value, "", "Default country set to empty");
+ doc.querySelector("#cancel").click();
+ });
+ Region._setHomeRegion("US", false);
+});
+
+add_task(async function test_saveAddress() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ // Verify labels
+ is(
+ doc.querySelector("#address-level1-container > .label-text").textContent,
+ "State",
+ "US address-level1 label should be 'State'"
+ );
+ is(
+ doc.querySelector("#postal-code-container > .label-text").textContent,
+ "ZIP Code",
+ "US postal-code label should be 'ZIP Code'"
+ );
+ // Input address info and verify move through form with tab keys
+ let keypresses = [
+ "VK_TAB",
+ TEST_ADDRESS_1["given-name"],
+ "VK_TAB",
+ TEST_ADDRESS_1["additional-name"],
+ "VK_TAB",
+ TEST_ADDRESS_1["family-name"],
+ "VK_TAB",
+ TEST_ADDRESS_1["street-address"],
+ "VK_TAB",
+ TEST_ADDRESS_1["address-level2"],
+ "VK_TAB",
+ TEST_ADDRESS_1["address-level1"],
+ "VK_TAB",
+ TEST_ADDRESS_1["postal-code"],
+ "VK_TAB",
+ TEST_ADDRESS_1.organization,
+ "VK_TAB",
+ // TEST_ADDRESS_1.country, // Country is already US
+ "VK_TAB",
+ TEST_ADDRESS_1.tel,
+ "VK_TAB",
+ TEST_ADDRESS_1.email,
+ "VK_TAB",
+ ];
+ if (AppConstants.platform != "win") {
+ keypresses.push("VK_TAB", "VK_RETURN");
+ } else {
+ keypresses.push("VK_RETURN");
+ }
+ 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();
+
+ is(addresses.length, 1, "only one address is in storage");
+ is(
+ Object.keys(TEST_ADDRESS_1).length,
+ 11,
+ "Sanity check number of properties"
+ );
+ for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_1)) {
+ is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+ }
+});
+
+add_task(async function test_editAddress() {
+ let addresses = await getAddresses();
+ await testDialog(
+ EDIT_ADDRESS_DIALOG_URL,
+ win => {
+ EventUtils.synthesizeKey("VK_TAB", {}, win);
+ EventUtils.synthesizeKey("VK_RIGHT", {}, 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();
+ },
+ {
+ record: addresses[0],
+ }
+ );
+ addresses = await getAddresses();
+
+ is(addresses.length, 1, "only one address is in storage");
+ is(
+ addresses[0]["given-name"],
+ TEST_ADDRESS_1["given-name"] + "test",
+ "given-name changed"
+ );
+ await removeAddresses([addresses[0].guid]);
+
+ addresses = await getAddresses();
+ 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 setStorage(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() {
+ let record = { ...TEST_ADDRESS_1 };
+ info("delete some usually required properties");
+ delete record["street-address"];
+ delete record["address-level1"];
+ delete record["address-level2"];
+ await testDialog(
+ EDIT_ADDRESS_DIALOG_URL,
+ win => {
+ is(
+ win.document.querySelectorAll(":-moz-ui-invalid").length,
+ 0,
+ "Check no fields are visually invalid"
+ );
+ EventUtils.synthesizeKey("VK_TAB", {}, win);
+ EventUtils.synthesizeKey("VK_RIGHT", {}, win);
+ EventUtils.synthesizeKey("test", {}, win);
+ is(
+ win.document.querySelector("#save").disabled,
+ false,
+ "Save button should be enabled after an edit"
+ );
+ win.document.querySelector("#cancel").click();
+ },
+ {
+ record,
+ }
+ );
+});
+
+add_task(async function test_saveAddressCA() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ // Change country to verify labels
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Canada", {}, win);
+
+ await TestUtils.waitForCondition(() => {
+ return (
+ doc.querySelector("#address-level1-container > .label-text")
+ .textContent == "Province"
+ );
+ }, "Wait for the mutation observer to change the labels");
+ is(
+ doc.querySelector("#address-level1-container > .label-text").textContent,
+ "Province",
+ "CA address-level1 label should be 'Province'"
+ );
+ is(
+ doc.querySelector("#postal-code-container > .label-text").textContent,
+ "Postal Code",
+ "CA postal-code label should be 'Postal Code'"
+ );
+ is(
+ doc.querySelector("#address-level3-container").style.display,
+ "none",
+ "CA address-level3 should be hidden"
+ );
+
+ // Input address info and verify move through form with tab keys
+ doc.querySelector("#given-name").focus();
+ let keyInputs = [
+ TEST_ADDRESS_CA_1["given-name"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["additional-name"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["family-name"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1.organization,
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["street-address"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["address-level2"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["address-level1"],
+ "VK_TAB",
+ TEST_ADDRESS_CA_1["postal-code"],
+ "VK_TAB",
+ // TEST_ADDRESS_1.country, // Country is already selected above
+ "VK_TAB",
+ TEST_ADDRESS_CA_1.tel,
+ "VK_TAB",
+ TEST_ADDRESS_CA_1.email,
+ "VK_TAB",
+ ];
+ if (AppConstants.platform != "win") {
+ keyInputs.push("VK_TAB", "VK_RETURN");
+ } else {
+ keyInputs.push("VK_RETURN");
+ }
+ keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
+ });
+ let addresses = await getAddresses();
+ for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_CA_1)) {
+ is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+ }
+ await removeAllRecords();
+});
+
+add_task(async function test_saveAddressDE() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ // Change country to verify labels
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Germany", {}, win);
+ await TestUtils.waitForCondition(() => {
+ return (
+ doc.querySelector("#postal-code-container > .label-text").textContent ==
+ "Postal Code"
+ );
+ }, "Wait for the mutation observer to change the labels");
+ is(
+ doc.querySelector("#postal-code-container > .label-text").textContent,
+ "Postal Code",
+ "DE postal-code label should be 'Postal Code'"
+ );
+ is(
+ doc.querySelector("#address-level1-container").style.display,
+ "none",
+ "DE address-level1 should be hidden"
+ );
+ is(
+ doc.querySelector("#address-level3-container").style.display,
+ "none",
+ "DE address-level3 should be hidden"
+ );
+ // Input address info and verify move through form with tab keys
+ doc.querySelector("#given-name").focus();
+ let keyInputs = [
+ TEST_ADDRESS_DE_1["given-name"],
+ "VK_TAB",
+ TEST_ADDRESS_DE_1["additional-name"],
+ "VK_TAB",
+ TEST_ADDRESS_DE_1["family-name"],
+ "VK_TAB",
+ TEST_ADDRESS_DE_1.organization,
+ "VK_TAB",
+ TEST_ADDRESS_DE_1["street-address"],
+ "VK_TAB",
+ TEST_ADDRESS_DE_1["postal-code"],
+ "VK_TAB",
+ TEST_ADDRESS_DE_1["address-level2"],
+ "VK_TAB",
+ // TEST_ADDRESS_1.country, // Country is already selected above
+ "VK_TAB",
+ TEST_ADDRESS_DE_1.tel,
+ "VK_TAB",
+ TEST_ADDRESS_DE_1.email,
+ "VK_TAB",
+ ];
+ if (AppConstants.platform != "win") {
+ keyInputs.push("VK_TAB", "VK_RETURN");
+ } else {
+ keyInputs.push("VK_RETURN");
+ }
+ keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
+ });
+ let addresses = await getAddresses();
+ for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_DE_1)) {
+ is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+ }
+ await removeAllRecords();
+});
+
+/**
+ * Test saving an address for a region from regionNames.properties but not in
+ * addressReferences.js (libaddressinput).
+ */
+add_task(async function test_saveAddress_nolibaddressinput() {
+ const TEST_ADDRESS = {
+ ...TEST_ADDRESS_IE_1,
+ ...{
+ "address-level3": undefined,
+ country: "XG",
+ },
+ };
+
+ isnot(
+ FormAutofillUtils.getCountryAddressData("XG").key,
+ "XG",
+ "Check that the region we're testing with isn't in libaddressinput"
+ );
+
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+
+ // Change country to verify labels
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Gaza Strip", {}, win);
+ await TestUtils.waitForCondition(() => {
+ return (
+ doc.querySelector("#postal-code-container > .label-text").textContent ==
+ "Postal Code"
+ );
+ }, "Wait for the mutation observer to change the labels");
+ is(
+ doc.querySelector("#postal-code-container > .label-text").textContent,
+ "Postal Code",
+ "XG postal-code label should be 'Postal Code'"
+ );
+ isnot(
+ doc.querySelector("#address-level1-container").style.display,
+ "none",
+ "XG address-level1 should be hidden"
+ );
+ is(
+ doc.querySelector("#address-level2").localName,
+ "input",
+ "XG address-level2 should be an <input>"
+ );
+ // Input address info and verify move through form with tab keys
+ doc.querySelector("#given-name").focus();
+ let keyInputs = [
+ TEST_ADDRESS["given-name"],
+ "VK_TAB",
+ TEST_ADDRESS["additional-name"],
+ "VK_TAB",
+ TEST_ADDRESS["family-name"],
+ "VK_TAB",
+ TEST_ADDRESS.organization,
+ "VK_TAB",
+ TEST_ADDRESS["street-address"],
+ "VK_TAB",
+ TEST_ADDRESS["address-level2"],
+ "VK_TAB",
+ TEST_ADDRESS["address-level1"],
+ "VK_TAB",
+ TEST_ADDRESS["postal-code"],
+ "VK_TAB",
+ // TEST_ADDRESS_1.country, // Country is already selected above
+ "VK_TAB",
+ TEST_ADDRESS.tel,
+ "VK_TAB",
+ TEST_ADDRESS.email,
+ "VK_TAB",
+ ];
+ if (AppConstants.platform != "win") {
+ keyInputs.push("VK_TAB", "VK_RETURN");
+ } else {
+ keyInputs.push("VK_RETURN");
+ }
+ keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
+ });
+ let addresses = await getAddresses();
+ for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS)) {
+ is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+ }
+ await removeAllRecords();
+});
+
+add_task(async function test_saveAddressIE() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ // Change country to verify labels
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Ireland", {}, win);
+ await TestUtils.waitForCondition(() => {
+ return (
+ doc.querySelector("#postal-code-container > .label-text").textContent ==
+ "Eircode"
+ );
+ }, "Wait for the mutation observer to change the labels");
+ is(
+ doc.querySelector("#postal-code-container > .label-text").textContent,
+ "Eircode",
+ "IE postal-code label should be 'Eircode'"
+ );
+ is(
+ doc.querySelector("#address-level1-container > .label-text").textContent,
+ "County",
+ "IE address-level1 should be 'County'"
+ );
+ is(
+ doc.querySelector("#address-level3-container > .label-text").textContent,
+ "Townland",
+ "IE address-level3 should be 'Townland'"
+ );
+
+ // Input address info and verify move through form with tab keys
+ doc.querySelector("#given-name").focus();
+ let keyInputs = [
+ TEST_ADDRESS_IE_1["given-name"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["additional-name"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["family-name"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1.organization,
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["street-address"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["address-level3"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["address-level2"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["address-level1"],
+ "VK_TAB",
+ TEST_ADDRESS_IE_1["postal-code"],
+ "VK_TAB",
+ // TEST_ADDRESS_1.country, // Country is already selected above
+ "VK_TAB",
+ TEST_ADDRESS_IE_1.tel,
+ "VK_TAB",
+ TEST_ADDRESS_IE_1.email,
+ "VK_TAB",
+ ];
+ if (AppConstants.platform != "win") {
+ keyInputs.push("VK_TAB", "VK_RETURN");
+ } else {
+ keyInputs.push("VK_RETURN");
+ }
+ keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
+ });
+
+ let addresses = await getAddresses();
+ for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_IE_1)) {
+ is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+ }
+ await removeAllRecords();
+});
+
+add_task(async function test_countryAndStateFieldLabels() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ // Change country to verify labels
+ doc.querySelector("#country").focus();
+
+ let mutableLabels = [
+ "postal-code-container",
+ "address-level1-container",
+ "address-level2-container",
+ "address-level3-container",
+ ].map(containerID =>
+ doc.getElementById(containerID).querySelector(":scope > .label-text")
+ );
+
+ for (let countryOption of doc.querySelector("#country").options) {
+ if (countryOption.value == "") {
+ info("Skipping the empty country option");
+ continue;
+ }
+
+ // Clear L10N textContent to not leave leftovers between country tests
+ for (let labelEl of mutableLabels) {
+ doc.l10n.setAttributes(labelEl, "");
+ labelEl.textContent = "";
+ }
+
+ info(`Selecting '${countryOption.label}' (${countryOption.value})`);
+ EventUtils.synthesizeKey(countryOption.label, {}, win);
+
+ let l10nResolve;
+ let l10nReady = new Promise(resolve => {
+ l10nResolve = resolve;
+ });
+ let verifyL10n = () => {
+ if (mutableLabels.every(labelEl => labelEl.textContent)) {
+ win.removeEventListener("MozAfterPaint", verifyL10n);
+ l10nResolve();
+ }
+ };
+ win.addEventListener("MozAfterPaint", verifyL10n);
+ await l10nReady;
+
+ // Check that the labels were filled
+ for (let labelEl of mutableLabels) {
+ isnot(
+ labelEl.textContent,
+ "",
+ "Ensure textContent is non-empty for: " + 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)"
+ );
+ }
+ }
+ // Dispatch a dummy key event so that <select>'s incremental search is cleared.
+ EventUtils.synthesizeKey("VK_ACCEPT", {}, win);
+ }
+
+ doc.querySelector("#cancel").click();
+ });
+});
+
+add_task(async function test_combined_name_fields() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ let givenNameField = doc.querySelector("#given-name");
+ let addtlNameField = doc.querySelector("#additional-name");
+ let familyNameField = doc.querySelector("#family-name");
+
+ function getComputedPropertyValue(field, property) {
+ return win.getComputedStyle(field).getPropertyValue(property);
+ }
+ function checkNameComputedPropertiesMatch(
+ field,
+ property,
+ value,
+ checkFn = is
+ ) {
+ checkFn(
+ getComputedPropertyValue(field, property),
+ value,
+ `Check ${field.id}'s ${property} is ${value}`
+ );
+ }
+ function checkNameFieldBorders(borderColorUnfocused, borderColorFocused) {
+ info("checking the perimeter colors");
+ checkNameComputedPropertiesMatch(
+ givenNameField,
+ "border-top-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-top-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ familyNameField,
+ "border-top-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ familyNameField,
+ "border-right-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ givenNameField,
+ "border-bottom-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-bottom-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ familyNameField,
+ "border-bottom-color",
+ borderColorFocused
+ );
+ checkNameComputedPropertiesMatch(
+ givenNameField,
+ "border-left-color",
+ borderColorFocused
+ );
+
+ info("checking the internal borders");
+ checkNameComputedPropertiesMatch(
+ givenNameField,
+ "border-right-width",
+ "0px"
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-left-width",
+ "2px"
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-left-color",
+ borderColorFocused,
+ isnot
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-right-width",
+ "2px"
+ );
+ checkNameComputedPropertiesMatch(
+ addtlNameField,
+ "border-right-color",
+ borderColorFocused,
+ isnot
+ );
+ checkNameComputedPropertiesMatch(
+ familyNameField,
+ "border-left-width",
+ "0px"
+ );
+ }
+
+ // Set these variables since the test doesn't run from a subdialog and
+ // therefore doesn't get the additional common CSS files injected.
+ let borderColor = "rgb(0, 255, 0)";
+ let borderColorFocused = "rgb(0, 0, 255)";
+ doc.body.style.setProperty("--in-content-box-border-color", borderColor);
+ doc.body.style.setProperty(
+ "--in-content-focus-outline-color",
+ borderColorFocused
+ );
+
+ givenNameField.focus();
+ checkNameFieldBorders(borderColor, borderColorFocused);
+
+ addtlNameField.focus();
+ checkNameFieldBorders(borderColor, borderColorFocused);
+
+ familyNameField.focus();
+ checkNameFieldBorders(borderColor, borderColorFocused);
+
+ info("unfocusing the name fields");
+ let cancelButton = doc.querySelector("#cancel");
+ cancelButton.focus();
+ borderColor = getComputedPropertyValue(givenNameField, "border-top-color");
+ isnot(
+ borderColor,
+ borderColorFocused,
+ "Check that the border color is different"
+ );
+ checkNameFieldBorders(borderColor, borderColor);
+
+ cancelButton.click();
+ });
+});
+
+add_task(async function test_combined_name_fields_error() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ let givenNameField = doc.querySelector("#given-name");
+ info("mark the given name field as invalid");
+ givenNameField.value = "";
+ givenNameField.focus();
+ ok(
+ givenNameField.matches(":-moz-ui-invalid"),
+ "Check field is visually invalid"
+ );
+
+ let givenNameLabel = doc.querySelector("#given-name-container .label-text");
+ // Override pointer-events so that we can use elementFromPoint to know if
+ // the label text is visible.
+ givenNameLabel.style.pointerEvents = "auto";
+ let givenNameLabelRect = givenNameLabel.getBoundingClientRect();
+ // Get the center of the label
+ let el = doc.elementFromPoint(
+ givenNameLabelRect.left + givenNameLabelRect.width / 2,
+ givenNameLabelRect.top + givenNameLabelRect.height / 2
+ );
+
+ is(
+ el,
+ givenNameLabel,
+ "Check that the label text is visible in the error state"
+ );
+ is(
+ win.getComputedStyle(givenNameField).getPropertyValue("border-top-color"),
+ "rgba(0, 0, 0, 0)",
+ "Border should be transparent so that only the error outline shows"
+ );
+ doc.querySelector("#cancel").click();
+ });
+});
+
+add_task(async function test_hiddenFieldNotSaved() {
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ doc.querySelector("#address-level2").focus();
+ EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
+ doc.querySelector("#address-level1").focus();
+ EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"], {}, win);
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Germany", {}, win);
+ doc.querySelector("#save").focus();
+ EventUtils.synthesizeKey("VK_RETURN", {}, win);
+ });
+ let addresses = await getAddresses();
+ is(addresses[0].country, "DE", "check country");
+ is(
+ addresses[0]["address-level2"],
+ TEST_ADDRESS_1["address-level2"],
+ "check address-level2"
+ );
+ is(
+ addresses[0]["address-level1"],
+ undefined,
+ "address-level1 should not be saved"
+ );
+
+ await removeAllRecords();
+});
+
+add_task(async function test_hiddenFieldRemovedWhenCountryChanged() {
+ let addresses = await getAddresses();
+ ok(!addresses.length, "no addresses at start of test");
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
+ let doc = win.document;
+ doc.querySelector("#address-level2").focus();
+ EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
+ doc.querySelector("#address-level1").focus();
+ while (
+ doc.querySelector("#address-level1").value !=
+ TEST_ADDRESS_1["address-level1"]
+ ) {
+ EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"][0], {}, win);
+ }
+ doc.querySelector("#save").focus();
+ EventUtils.synthesizeKey("VK_RETURN", {}, win);
+ });
+ addresses = await getAddresses();
+ is(addresses[0].country, "US", "check country");
+ is(
+ addresses[0]["address-level2"],
+ TEST_ADDRESS_1["address-level2"],
+ "check address-level2"
+ );
+ is(
+ addresses[0]["address-level1"],
+ TEST_ADDRESS_1["address-level1"],
+ "check address-level1"
+ );
+
+ await testDialog(
+ EDIT_ADDRESS_DIALOG_URL,
+ win => {
+ let doc = win.document;
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Germany", {}, win);
+ 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-level2"],
+ TEST_ADDRESS_1["address-level2"],
+ "check address-level2"
+ );
+ is(
+ addresses[0]["address-level1"],
+ undefined,
+ "address-level1 should be removed"
+ );
+ is(addresses[0].country, "DE", "country changed");
+ await removeAllRecords();
+});
+
+add_task(async function test_countrySpecificFieldsGetRequiredness() {
+ Region._setHomeRegion("RO", false);
+ await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+ let doc = win.document;
+ is(
+ doc.querySelector("#country").value,
+ "RO",
+ "Default country set to Romania"
+ );
+ let provinceField = doc.getElementById("address-level1");
+ ok(
+ !provinceField.required,
+ "address-level1 should not be marked as required"
+ );
+ ok(provinceField.disabled, "address-level1 should be marked as disabled");
+ is(
+ provinceField.parentNode.style.display,
+ "none",
+ "address-level1 is hidden for Romania"
+ );
+
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("United States", {}, win);
+
+ await TestUtils.waitForCondition(
+ () => {
+ provinceField = doc.getElementById("address-level1");
+ return provinceField.parentNode.style.display != "none";
+ },
+ "Wait for address-level1 to become visible",
+ 10
+ );
+
+ ok(provinceField.required, "address-level1 should be marked as required");
+ ok(
+ !provinceField.disabled,
+ "address-level1 should not be marked as disabled"
+ );
+
+ // Dispatch a dummy key event so that <select>'s incremental search is cleared.
+ EventUtils.synthesizeKey("VK_ACCEPT", {}, win);
+
+ doc.querySelector("#country").focus();
+ EventUtils.synthesizeKey("Romania", {}, win);
+
+ await TestUtils.waitForCondition(
+ () => {
+ provinceField = doc.getElementById("address-level1");
+ return provinceField.parentNode.style.display == "none";
+ },
+ "Wait for address-level1 to become hidden",
+ 10
+ );
+
+ ok(
+ provinceField.required,
+ "address-level1 will still be marked as required"
+ );
+ ok(provinceField.disabled, "address-level1 should be marked as disabled");
+
+ doc.querySelector("#cancel").click();
+ });
+});