--- a/browser/components/payments/res/containers/address-form.css
+++ b/browser/components/payments/res/containers/address-form.css
@@ -30,17 +30,18 @@ label[required] > span:first-of-type::af
.error-text:not(:empty) {
color: #fff;
background-color: #d70022;
border-radius: 2px;
/* The padding-top and padding-bottom are referenced by address-form.js */
padding: 5px 12px;
position: absolute;
- z-index: 5;
+ z-index: 1;
+ pointer-events: none;
}
body[dir="ltr"] .error-text {
left: 3px;
}
body[dir="rtl"] .error-text {
right: 3px;
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -83,48 +83,16 @@ export default class AddressForm extends
});
this.appendChild(this.persistCheckbox);
this.appendChild(this.genericErrorText);
this.appendChild(this.cancelButton);
this.appendChild(this.backButton);
this.appendChild(this.saveButton);
- // Add validation to some address fields
- let zipCodeInput = form.querySelector("#postal-code");
- let countrySelect = form.querySelector("#country");
- countrySelect.addEventListener("change", event => {
- let country = countrySelect.value;
- if (country) {
- let {addressData} = PaymentDialogUtils.getFormFormat(country);
- // Note, this doesn't handle level1, such as CA--fr
- let countryAddressData = addressData[`data/${country}`];
- zipCodeInput.setAttribute("pattern", countryAddressData.zip);
- } else {
- zipCodeInput.removeAttribute("pattern");
- }
- });
- let streetInput = form.querySelector("#street-address");
- let cityInput = form.querySelector("#address-level2");
- let stateInput = form.querySelector("#address-level1");
- let nameInputs = form.querySelectorAll("#name-container > label > input");
- let requiredInputs = [nameInputs[0], streetInput, cityInput, zipCodeInput, stateInput];
- for (let input of requiredInputs) {
- let container = input.closest(`#${input.id}-container`);
- if (container.style.display != "none") {
- container.setAttribute("required", "true");
- input.setAttribute("required", "true");
- }
-
- // Disable the Save button if any of the fields are invalid
- input.addEventListener("change", this);
- input.addEventListener("invalid", this);
- }
- this.updateSaveButtonValidity();
-
// Only call the connected super callback(s) once our markup is fully
// connected, including the shared form fetched asynchronously.
super.connectedCallback();
});
}
render(state) {
let record = {};
@@ -142,22 +110,16 @@ export default class AddressForm extends
this.cancelButton.textContent = this.dataset.cancelButtonLabel;
this.backButton.textContent = this.dataset.backButtonLabel;
this.saveButton.textContent = this.dataset.saveButtonLabel;
this.persistCheckbox.label = this.dataset.persistCheckboxLabel;
this.backButton.hidden = page.onboardingWizard;
this.cancelButton.hidden = !page.onboardingWizard;
- if (addressPage.addressFields) {
- this.setAttribute("address-fields", addressPage.addressFields);
- } else {
- this.removeAttribute("address-fields");
- }
-
this.pageTitle.textContent = addressPage.title;
this.genericErrorText.textContent = page.error;
let editing = !!addressPage.guid;
let addresses = paymentRequest.getAddresses(state);
// If an address is selected we want to edit it.
if (editing) {
@@ -170,37 +132,85 @@ export default class AddressForm extends
} else {
// Adding a new record: default persistence to checked when in a not-private session
this.persistCheckbox.hidden = false;
this.persistCheckbox.checked = !state.isPrivate;
}
this.formHandler.loadRecord(record);
+ // Add validation to some address fields. Need to do this in
+ // render since the required fields can change between renders
+ // if shippingAddressErrors or address-fields get set.
+ let zipCodeInput = this.form.querySelector("#postal-code");
+ let countrySelect = this.form.querySelector("#country");
+ countrySelect.addEventListener("change", this);
+ let streetInput = this.form.querySelector("#street-address");
+ let cityInput = this.form.querySelector("#address-level2");
+ let stateInput = this.form.querySelector("#address-level1");
+ let nameInputs = this.form.querySelectorAll("#name-container > label > input");
+ let requiredInputs = [nameInputs[0], streetInput, cityInput, zipCodeInput, stateInput];
+ for (let input of requiredInputs) {
+ let container = input.closest(`#${input.id}-container`);
+ if (container.style.display != "none") {
+ container.setAttribute("required", "true");
+ input.setAttribute("required", "true");
+ } else {
+ container.removeAttribute("required");
+ input.removeAttribute("required");
+ }
+
+ // Disable the Save button if any of the fields are invalid
+ input.addEventListener("change", this);
+ input.addEventListener("invalid", this);
+ }
+
let shippingAddressErrors = request.paymentDetails.shippingAddressErrors;
- if (!shippingAddressErrors || !Object.entries(shippingAddressErrors).length) {
- return;
- }
for (let [errorName, errorSelector] of Object.entries(this._errorFieldMap)) {
let field = document.querySelector(errorSelector);
- let errorText = shippingAddressErrors[errorName];
+ let errorText = (shippingAddressErrors && shippingAddressErrors[errorName]) || "";
if (errorText) {
field.setAttribute("shipping-address-error", errorText);
// These fields are not required by Firefox. Validation is only
// added if the merchant provided a specific error for them.
if (["organization", "phone", "country"].includes(errorName)) {
field.addEventListener("change", this);
}
} else {
field.removeAttribute("shipping-address-error");
}
this.setErrorTextForField(field, errorText);
}
+ if (addressPage.addressFields) {
+ this.setAttribute("address-fields", addressPage.addressFields);
+ // Form elements that are hidden need their 'required' attribute removed.
+ let fieldNames = [
+ "name", "email", "tel",
+ "organization", "street-address", "address-level2",
+ "address-level1", "postal-code", "country",
+ ];
+ for (let field of addressPage.addressFields.split(" ")) {
+ let index = fieldNames.indexOf(field);
+ fieldNames.splice(index, 1);
+ }
+ for (let fieldName of fieldNames) {
+ let container = document.querySelector(`#${fieldName}-container`);
+ let inputs = [...container.querySelectorAll("input, textarea, select")];
+ for (let input of inputs) {
+ input.removeAttribute("required");
+ input.setCustomValidity("");
+ }
+ }
+ } else {
+ this.removeAttribute("address-fields");
+ }
+ this.updateSaveButtonValidity();
+
// Position the error messages all at once so layout flushes only once.
let formRect = this.form.getBoundingClientRect();
let errorSpanData = [...this.form.querySelectorAll(".error-text:not(:empty)")].map(span => {
let relatedInput = span.previousElementSibling;
let relatedRect = relatedInput.getBoundingClientRect();
return {
span,
top: relatedRect.bottom,
@@ -218,16 +228,19 @@ export default class AddressForm extends
data.span.style.left = data.left + "px";
}
}
}
handleEvent(event) {
switch (event.type) {
case "change": {
+ if (event.target.id == "country") {
+ this.updateCountryDependentFields(event);
+ }
this.updateShippingAddressErrorVisibility(event);
this.updateSaveButtonValidity();
break;
}
case "click": {
this.onClick(event);
break;
}
@@ -322,16 +335,28 @@ export default class AddressForm extends
if (previousId) {
state.successStateChange[previousId] = Object.assign({}, currentState[previousId]);
state.successStateChange[previousId].preserveFieldValues = true;
}
paymentRequest.updateAutofillRecord("addresses", record, addressPage.guid, state);
}
+ updateCountryDependentFields(event) {
+ let country = event.target.value;
+ let zipCodeInput = this.form.querySelector("#postal-code");
+ if (country) {
+ let {zipPattern} = PaymentDialogUtils.getFormFormat(country);
+ // Note, this doesn't handle level1, such as CA--fr
+ zipCodeInput.setAttribute("pattern", zipPattern);
+ } else {
+ zipCodeInput.removeAttribute("pattern");
+ }
+ }
+
updateShippingAddressErrorVisibility(event) {
let field = event.target;
if (!field.validity.valueMissing) {
field.setCustomValidity("");
return;
}
let errorText = field.getAttribute("shipping-address-error") ||
field.validationMessage;
--- a/browser/components/payments/res/unprivileged-fallbacks.js
+++ b/browser/components/payments/res/unprivileged-fallbacks.js
@@ -37,21 +37,14 @@ var PaymentDialogUtils = {
"fieldsOrder": [
{fieldId: "name", newLine: true},
{fieldId: "organization", newLine: true},
{fieldId: "street-address", newLine: true},
{fieldId: "address-level2"},
{fieldId: "address-level1"},
{fieldId: "postal-code"},
],
-
// The following values come from addressReferences.js and should not be changed.
- /* eslint-disable max-len */
- "addressData": {
- "data/CA": {"lang": "en", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/CA", "languages": "en~fr", "sub_keys": "AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "require": "ACSZ", "sub_names": "Alberta~British Columbia~Manitoba~New Brunswick~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon", "sub_zips": "T~V~R~E~A~X0E|X0G|X1A~B~X0A|X0B|X0C~K|L|M|N|P~C~G|H|J|K1A~S|R8A~Y"},
- "data/CA--fr": {"lang": "fr", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "require": "ACSZ", "sub_keys": "AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "id": "data/CA--fr", "sub_names": "Alberta~Colombie-Britannique~Île-du-Prince-Édouard~Manitoba~Nouveau-Brunswick~Nouvelle-Écosse~Nunavut~Ontario~Québec~Saskatchewan~Terre-Neuve-et-Labrador~Territoires du Nord-Ouest~Yukon", "sub_zips": "T~V~C~R~E~B~X0A|X0B|X0C~K|L|M|N|P~G|H|J|K1A~S|R8A~A~X0E|X0G|X1A~Y"},
- "data/DE": {"zipex": "26133,53225", "name": "GERMANY", "zip": "\\d{5}", "fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DE", "key": "DE", "posturl": "http://www.postdirekt.de/plzserver/", "require": "ACZ"},
- "data/US": {"lang": "en", "upper": "CS", "sub_zipexs": "35000,36999~99500,99999~96799~85000,86999~71600,72999~34000,34099~09000,09999~96200,96699~90000,96199~80000,81999~06000,06999~19700,19999~20000,56999~32000,34999~30000,39901~96910,96932~96700,96899~83200,83999~60000,62999~46000,47999~50000,52999~66000,67999~40000,42799~70000,71599~03900,04999~96960,96979~20600,21999~01000,05544~48000,49999~96941,96944~55000,56799~38600,39799~63000,65999~59000,59999~68000,69999~88900,89999~03000,03899~07000,08999~87000,88499~10000,00544~27000,28999~58000,58999~96950,96952~43000,45999~73000,74999~97000,97999~96940~15000,19699~00600,00999~02800,02999~29000,29999~57000,57999~37000,38599~75000,73344~84000,84999~05000,05999~00800,00899~20100,24699~98000,99499~24700,26999~53000,54999~82000,83414", "zipex": "95014,22162-1010", "name": "UNITED STATES", "zip": "(\\d{5})(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "fmt": "%N%n%O%n%A%n%C, %S %Z", "state_name_type": "state", "id": "data/US", "languages": "en", "sub_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", "key": "US", "posturl": "https://tools.usps.com/go/ZipLookupAction!input.action", "require": "ACSZ", "sub_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", "sub_zips": "3[56]~99[5-9]~96799~8[56]~71[6-9]|72~340~09~96[2-6]~9[0-5]|96[01]~8[01]~06~19[7-9]~20[02-5]|569~3[23]|34[1-9]~3[01]|398|39901~969([1-2]\\d|3[12])~967[0-8]|9679[0-8]|968~83[2-9]~6[0-2]~4[67]~5[0-2]~6[67]~4[01]|42[0-7]~70|71[0-5]~039|04~969[67]~20[6-9]|21~01|02[0-7]|05501|05544~4[89]~9694[1-4]~55|56[0-7]~38[6-9]|39[0-7]~6[3-5]~59~6[89]~889|89~03[0-8]~0[78]~87|88[0-4]~1[0-4]|06390|00501|00544~2[78]~58~9695[0-2]~4[3-5]~7[34]~97~969(39|40)~1[5-8]|19[0-6]~00[679]~02[89]~29~57~37|38[0-5]~7[5-9]|885|73301|73344~84~05~008~201|2[23]|24[0-6]~98|99[0-4]~24[7-9]|2[56]~5[34]~82|83[01]|83414"},
- },
- /* eslint-enable */
+ /* eslint-disable-next-line max-len */
+ "zipPattern": country == "US" ? "(\\d{5})(?:[ \\-](\\d{4}))?" : "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d",
};
},
};
--- a/browser/components/payments/test/browser/browser_address_edit.js
+++ b/browser/components/payments/test/browser/browser_address_edit.js
@@ -53,16 +53,17 @@ add_task(async function test_add_link()
info("filling fields");
for (let [key, val] of Object.entries(address)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedAddresses).length == 1;
}, "Check address was added");
@@ -140,16 +141,17 @@ add_task(async function test_edit_link()
let persistCheckbox = content.document.querySelector("address-form labelled-checkbox");
ok(persistCheckbox.hidden, "checkbox should be hidden when editing an address");
info("overwriting field values");
for (let [key, val] of Object.entries(address)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
let addresses = Object.entries(state.savedAddresses);
return addresses.length == 1 &&
@@ -229,16 +231,17 @@ add_task(async function test_add_payer_c
info("filling fields");
for (let [key, val] of Object.entries(address)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
info("check that non-payer requested fields are hidden");
for (let selector of ["#organization", "#tel"]) {
let element = content.document.querySelector(selector);
ok(content.isHidden(element), selector + " should be hidden");
}
@@ -312,16 +315,17 @@ add_task(async function test_edit_payer_
let persistCheckbox = content.document.querySelector("address-form labelled-checkbox");
ok(persistCheckbox.hidden, "checkbox should be hidden when editing an address");
info("overwriting field values");
for (let [key, val] of Object.entries(address)) {
let field = content.document.getElementById(key);
field.value = val + "1";
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
info("check that non-payer requested fields are hidden");
let formElements =
content.document.querySelectorAll("address-form :-moz-any(input, select, textarea");
let allowedFields = ["given-name", "additional-name", "family-name", "email", "tel"];
for (let element of formElements) {
@@ -428,16 +432,17 @@ add_task(async function test_private_per
ok(!Cu.waiveXrays(persistCheckbox).checked,
"persist checkbox should be unchecked by default");
info("add the temp address");
let addressToAdd = PTU.Addresses.Temp;
for (let [key, val] of Object.entries(addressToAdd)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
}
content.document.querySelector("address-form button:last-of-type").click();
info("wait until we return to the summary page");
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "payment-summary";
}, "Return to summary page");
--- a/browser/components/payments/test/browser/browser_card_edit.js
+++ b/browser/components/payments/test/browser/browser_card_edit.js
@@ -35,16 +35,17 @@ add_task(async function test_add_link()
ok(Cu.waiveXrays(persistCheckbox).checked, "persist checkbox should be checked by default");
let card = Object.assign({}, PTU.BasicCards.JohnDoe);
info("filling fields");
for (let [key, val] of Object.entries(card)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
ok(content.isVisible(billingAddressSelect),
"The billing address selector should always be visible");
is(billingAddressSelect.childElementCount, 1,
"Only one child option should exist by default");
@@ -87,16 +88,17 @@ add_task(async function test_add_link()
info("filling address fields");
for (let [key, val] of Object.entries(PTU.Addresses.TimBL)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !state["basic-card-page"].guid &&
Object.keys(state.savedAddresses).length == 1;
}, "Check address was added and we're back on basic-card page (add)");
@@ -174,16 +176,17 @@ add_task(async function test_edit_link()
delete card["cc-number"];
card["cc-exp-year"]++;
card["cc-exp-month"]++;
info("overwriting field values");
for (let [key, val] of Object.entries(card)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
ok(content.document.getElementById("cc-number").disabled, "cc-number field should be disabled");
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
is(billingAddressSelect.childElementCount, 2,
"Two options should exist in the billingAddressSelect");
is(billingAddressSelect.selectedIndex, 1,
@@ -249,27 +252,28 @@ add_task(async function test_edit_link()
}, "Check address page state (editing)");
info("filling address fields");
for (let [key, val] of Object.entries(PTU.Addresses.TimBL)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
- field.value = val + "1";
+ field.value = val.slice(0, -1) + "7";
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && state["basic-card-page"].guid &&
Object.keys(state.savedAddresses).length == 1;
}, "Check still only one address and we're back on basic-card page");
- is(Object.values(state.savedAddresses)[0].tel, PTU.Addresses.TimBL.tel + "1",
+ is(Object.values(state.savedAddresses)[0].tel, PTU.Addresses.TimBL.tel.slice(0, -1) + "7",
"Check that address was edited and saved");
content.document.querySelector("basic-card-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
let cards = Object.entries(state.savedBasicCards);
return cards.length == 1 &&
cards[0][1]["cc-name"] == card["cc-name"];
@@ -368,16 +372,17 @@ add_task(async function test_private_car
let tempCardCount = Object.keys(state.tempBasicCards).length;
let card = Object.assign({}, PTU.BasicCards.JohnDoe);
info("filling fields");
for (let [key, val] of Object.entries(card)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("basic-card-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.tempBasicCards).length > tempCardCount;
},
--- a/browser/components/payments/test/browser/browser_payments_onboarding_wizard.js
+++ b/browser/components/payments/test/browser/browser_payments_onboarding_wizard.js
@@ -61,16 +61,17 @@ add_task(async function test_onboarding_
"The cancel button on the address page is visible");
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form .save-button").click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page";
}, "Basic card page is shown after the address page during on boarding");
@@ -85,16 +86,17 @@ add_task(async function test_onboarding_
PTU.DialogContentUtils.waitForState((state) => {
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
return state.selectedShippingAddress == billingAddressSelect.value;
}, "Shipping address is selected as the billing address");
for (let [key, val] of Object.entries(PTU.BasicCards.JohnDoe)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("basic-card-form .save-button").click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "payment-summary";
}, "Payment summary page is shown after the basic card page during on boarding");
@@ -267,16 +269,17 @@ add_task(async function test_onboarding_
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form .save-button").click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "payment-summary";
}, "payment-summary is now visible");
@@ -330,16 +333,17 @@ add_task(async function test_onboarding_
"Address page title is correctly shown");
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
let field = content.document.getElementById(key);
if (!field) {
ok(false, `${key} field not found`);
}
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("address-form .save-button").click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page";
// eslint-disable-next-line max-len
}, "Basic card page is shown after the billing address page during onboarding if requestShipping is turned off");
@@ -351,16 +355,17 @@ add_task(async function test_onboarding_
PTU.DialogContentUtils.waitForState((state) => {
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
return state["basic-card-page"].billingAddressGUID == billingAddressSelect.value;
}, "Billing Address is correctly shown");
for (let [key, val] of Object.entries(PTU.BasicCards.JohnDoe)) {
let field = content.document.getElementById(key);
field.value = val;
+ field.dispatchEvent(new Event("change"));
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
content.document.querySelector("basic-card-form .save-button").click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "payment-summary";
}, "payment-summary is shown after the basic card page during on boarding");
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -778,17 +778,17 @@ this.FormAutofillUtils = {
* }
*/
getFormFormat(country) {
const dataset = this.getCountryAddressData(country);
return {
"addressLevel1Label": dataset.state_name_type || "province",
"postalCodeLabel": dataset.zip_name_type || "postalCode",
"fieldsOrder": this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C, %S %Z"),
- "addressData": this._addressData,
+ "zipPattern": dataset.zip,
};
},
/**
* Localize "data-localization" or "data-localization-region" attributes.
* @param {Element} element
* @param {string} attributeName
*/
--- a/browser/extensions/formautofill/content/autofillEditForms.js
+++ b/browser/extensions/formautofill/content/autofillEditForms.js
@@ -15,16 +15,17 @@ class EditAutofillForm {
/**
* Fill the form with a record object.
* @param {object} [record = {}]
*/
loadRecord(record = {}) {
for (let field of this._elements.form.elements) {
let value = record[field.id];
field.value = typeof(value) == "undefined" ? "" : value;
+ field.dispatchEvent(new Event("change"));
}
}
/**
* Get inputs from the form.
* @returns {object}
*/
buildFormObject() {