forked from mirrors/gecko-dev
The browser test actually needs keyboard input + blur. The mochitest is trickier due to the select popup unfocusing the window. MANUAL PUSH: orange fix-ups CLOSED TREE
954 lines
29 KiB
JavaScript
954 lines
29 KiB
JavaScript
"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.organization,
|
|
"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.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(":user-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.focus();
|
|
EventUtils.synthesizeKey("X", {}, win);
|
|
givenNameField.value = "";
|
|
givenNameField.blur();
|
|
ok(
|
|
givenNameField.matches(":user-invalid"),
|
|
"Check field is visually invalid"
|
|
);
|
|
|
|
givenNameField.focus();
|
|
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();
|
|
});
|
|
});
|