mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1476345 - Only enable relevant fields in address forms and update tests. r=jaws
MozReview-Commit-ID: KuPMHrF6jaM --HG-- extra : rebase_source : f37118ff94bcb90108712dcc2f6db3d0aa5c92ef
This commit is contained in:
parent
eb2bfba0ba
commit
a290cf90f3
@ -7,23 +7,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide all form fields that are not explicitly requested
|
|
||||||
* by the paymentOptions object.
|
|
||||||
*/
|
|
||||||
address-form[address-fields]:not([address-fields~='name']) #name-container,
|
|
||||||
address-form[address-fields] #organization-container,
|
|
||||||
address-form[address-fields] #street-address-container,
|
|
||||||
address-form[address-fields] #address-level2-container,
|
|
||||||
address-form[address-fields] #address-level1-container,
|
|
||||||
address-form[address-fields] #postal-code-container,
|
|
||||||
address-form[address-fields] #country-container,
|
|
||||||
address-form[address-fields]:not([address-fields~='email']) #email-container,
|
|
||||||
address-form[address-fields]:not([address-fields~='tel']) #tel-container {
|
|
||||||
/* !important is needed because autofillEditForms.js sets
|
|
||||||
inline styles on the form fields with display: flex; */
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-text:not(:empty) {
|
.error-text:not(:empty) {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #d70022;
|
background-color: #d70022;
|
||||||
|
@ -25,6 +25,8 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
|||||||
super();
|
super();
|
||||||
|
|
||||||
this.genericErrorText = document.createElement("div");
|
this.genericErrorText = document.createElement("div");
|
||||||
|
this.genericErrorText.setAttribute("aria-live", "polite");
|
||||||
|
this.genericErrorText.classList.add("page-error");
|
||||||
|
|
||||||
this.cancelButton = document.createElement("button");
|
this.cancelButton = document.createElement("button");
|
||||||
this.cancelButton.className = "cancel-button";
|
this.cancelButton.className = "cancel-button";
|
||||||
@ -129,12 +131,6 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
|||||||
this.backButton.hidden = page.onboardingWizard;
|
this.backButton.hidden = page.onboardingWizard;
|
||||||
this.cancelButton.hidden = !page.onboardingWizard;
|
this.cancelButton.hidden = !page.onboardingWizard;
|
||||||
|
|
||||||
if (addressPage.addressFields) {
|
|
||||||
this.setAttribute("address-fields", addressPage.addressFields);
|
|
||||||
} else {
|
|
||||||
this.removeAttribute("address-fields");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pageTitleHeading.textContent = addressPage.title;
|
this.pageTitleHeading.textContent = addressPage.title;
|
||||||
this.genericErrorText.textContent = page.error;
|
this.genericErrorText.textContent = page.error;
|
||||||
|
|
||||||
@ -160,6 +156,11 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
|||||||
saveAddressDefaultChecked;
|
saveAddressDefaultChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addressPage.addressFields) {
|
||||||
|
this.form.dataset.addressFields = addressPage.addressFields;
|
||||||
|
} else {
|
||||||
|
this.form.dataset.addressFields = "mailing-address tel";
|
||||||
|
}
|
||||||
this.formHandler.loadRecord(record);
|
this.formHandler.loadRecord(record);
|
||||||
|
|
||||||
// Add validation to some address fields
|
// Add validation to some address fields
|
||||||
|
@ -31,14 +31,14 @@ export default class AddressPicker extends RichPicker {
|
|||||||
|
|
||||||
get fieldNames() {
|
get fieldNames() {
|
||||||
if (this.hasAttribute("address-fields")) {
|
if (this.hasAttribute("address-fields")) {
|
||||||
let names = this.getAttribute("address-fields").split(/\s+/);
|
let names = this.getAttribute("address-fields").trim().split(/\s+/);
|
||||||
if (names.length) {
|
if (names.length) {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
"address-level1",
|
// "address-level1", // TODO: bug 1481481 - not required for some countries e.g. DE
|
||||||
"address-level2",
|
"address-level2",
|
||||||
"country",
|
"country",
|
||||||
"name",
|
"name",
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
div[required] > label > span:first-of-type::after,
|
||||||
:-moz-any(label, div)[required] > span:first-of-type::after {
|
:-moz-any(label, div)[required] > span:first-of-type::after {
|
||||||
content: attr(fieldRequiredSymbol);
|
content: attr(fieldRequiredSymbol);
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,7 @@ var PaymentTestUtils = {
|
|||||||
organization: "World Wide Web Consortium",
|
organization: "World Wide Web Consortium",
|
||||||
"street-address": "1 Pommes Frittes Place",
|
"street-address": "1 Pommes Frittes Place",
|
||||||
"address-level2": "Berlin",
|
"address-level2": "Berlin",
|
||||||
"address-level1": "BE",
|
// address-level1 isn't used in our forms for Germany
|
||||||
"postal-code": "02138",
|
"postal-code": "02138",
|
||||||
country: "DE",
|
country: "DE",
|
||||||
tel: "+16172535702",
|
tel: "+16172535702",
|
||||||
|
@ -51,14 +51,16 @@ add_task(async function test_add_link() {
|
|||||||
{ setPersistCheckedValue: true, expectPersist: true },
|
{ setPersistCheckedValue: true, expectPersist: true },
|
||||||
{ setPersistCheckedValue: false, expectPersist: false },
|
{ setPersistCheckedValue: false, expectPersist: false },
|
||||||
];
|
];
|
||||||
let newAddress = PTU.Addresses.TimBL2;
|
let newAddress = Object.assign({}, PTU.Addresses.TimBL2);
|
||||||
|
// Emails aren't part of shipping addresses
|
||||||
|
delete newAddress.email;
|
||||||
|
|
||||||
for (let options of testOptions) {
|
for (let options of testOptions) {
|
||||||
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||||
eventName: "shippingaddresschange",
|
eventName: "shippingaddresschange",
|
||||||
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||||
|
|
||||||
await manuallyAddAddress(frame, newAddress, options);
|
await manuallyAddShippingAddress(frame, newAddress, options);
|
||||||
await shippingAddressChangePromise;
|
await shippingAddressChangePromise;
|
||||||
info("got shippingaddresschange event");
|
info("got shippingaddresschange event");
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ add_task(async function test_edit_link() {
|
|||||||
isEditing: true,
|
isEditing: true,
|
||||||
expectPersist: true,
|
expectPersist: true,
|
||||||
};
|
};
|
||||||
await fillInAddressForm(frame, EXPECTED_ADDRESS, editOptions);
|
await fillInShippingAddressForm(frame, EXPECTED_ADDRESS, editOptions);
|
||||||
await verifyPersistCheckbox(frame, editOptions);
|
await verifyPersistCheckbox(frame, editOptions);
|
||||||
await submitAddressForm(frame, EXPECTED_ADDRESS, editOptions);
|
await submitAddressForm(frame, EXPECTED_ADDRESS, editOptions);
|
||||||
|
|
||||||
@ -240,7 +242,7 @@ add_task(async function test_add_payer_contact_name_email_link() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await fillInAddressForm(frame, EXPECTED_ADDRESS, addOptions);
|
await fillInPayerAddressForm(frame, EXPECTED_ADDRESS, addOptions);
|
||||||
await verifyPersistCheckbox(frame, addOptions);
|
await verifyPersistCheckbox(frame, addOptions);
|
||||||
await submitAddressForm(frame, EXPECTED_ADDRESS, addOptions);
|
await submitAddressForm(frame, EXPECTED_ADDRESS, addOptions);
|
||||||
|
|
||||||
@ -397,7 +399,9 @@ add_task(async function test_private_persist_addresses() {
|
|||||||
);
|
);
|
||||||
info("/setupPaymentDialog");
|
info("/setupPaymentDialog");
|
||||||
|
|
||||||
let addressToAdd = PTU.Addresses.Temp;
|
let addressToAdd = Object.assign({}, PTU.Addresses.Temp);
|
||||||
|
// Emails aren't part of shipping addresses
|
||||||
|
delete addressToAdd.email;
|
||||||
const addOptions = {
|
const addOptions = {
|
||||||
checkboxSelector: "#address-page .persist-checkbox",
|
checkboxSelector: "#address-page .persist-checkbox",
|
||||||
expectPersist: false,
|
expectPersist: false,
|
||||||
@ -422,7 +426,7 @@ add_task(async function test_private_persist_addresses() {
|
|||||||
is(initialAddresses.options.length, 1,
|
is(initialAddresses.options.length, 1,
|
||||||
"Got expected number of pre-filled shipping addresses");
|
"Got expected number of pre-filled shipping addresses");
|
||||||
|
|
||||||
await fillInAddressForm(frame, addressToAdd, addOptions);
|
await fillInShippingAddressForm(frame, addressToAdd, addOptions);
|
||||||
await verifyPersistCheckbox(frame, addOptions);
|
await verifyPersistCheckbox(frame, addOptions);
|
||||||
await submitAddressForm(frame, addressToAdd, addOptions);
|
await submitAddressForm(frame, addressToAdd, addOptions);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ async function add_link(aOptions = {}) {
|
|||||||
checkboxSelector: "basic-card-form .persist-checkbox",
|
checkboxSelector: "basic-card-form .persist-checkbox",
|
||||||
expectPersist: aOptions.expectDefaultCardPersist,
|
expectPersist: aOptions.expectDefaultCardPersist,
|
||||||
});
|
});
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function checkState(testArgs = {}) {
|
||||||
let {
|
let {
|
||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
@ -58,7 +58,7 @@ async function add_link(aOptions = {}) {
|
|||||||
|
|
||||||
await verifyPersistCheckbox(frame, cardOptions);
|
await verifyPersistCheckbox(frame, cardOptions);
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function checkBillingAddressPicker(testArgs = {}) {
|
||||||
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
|
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
|
||||||
ok(content.isVisible(billingAddressSelect),
|
ok(content.isVisible(billingAddressSelect),
|
||||||
"The billing address selector should always be visible");
|
"The billing address selector should always be visible");
|
||||||
@ -82,7 +82,7 @@ async function add_link(aOptions = {}) {
|
|||||||
|
|
||||||
await navigateToAddAddressPage(frame, addressOptions);
|
await navigateToAddAddressPage(frame, addressOptions);
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function checkTask(testArgs = {}) {
|
||||||
let {
|
let {
|
||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
@ -121,13 +121,13 @@ async function add_link(aOptions = {}) {
|
|||||||
|
|
||||||
await navigateToAddAddressPage(frame, addressOptions);
|
await navigateToAddAddressPage(frame, addressOptions);
|
||||||
|
|
||||||
await fillInAddressForm(frame, PTU.Addresses.TimBL2, addressOptions);
|
await fillInBillingAddressForm(frame, PTU.Addresses.TimBL2, addressOptions);
|
||||||
|
|
||||||
await verifyPersistCheckbox(frame, addressOptions);
|
await verifyPersistCheckbox(frame, addressOptions);
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function checkCardPage(testArgs = {}) {
|
||||||
let {
|
let {
|
||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
@ -168,7 +168,7 @@ async function add_link(aOptions = {}) {
|
|||||||
|
|
||||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function waitForSummaryPage(testArgs = {}) {
|
||||||
let {
|
let {
|
||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
@ -182,7 +182,7 @@ async function add_link(aOptions = {}) {
|
|||||||
securityCode: "123",
|
securityCode: "123",
|
||||||
});
|
});
|
||||||
|
|
||||||
await spawnPaymentDialogTask(frame, async (testArgs = {}) => {
|
await spawnPaymentDialogTask(frame, async function checkCardState(testArgs = {}) {
|
||||||
let {
|
let {
|
||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
@ -476,13 +476,15 @@ add_task(async function test_edit_link() {
|
|||||||
return state.page.id == "address-page" && state["address-page"].guid;
|
return state.page.id == "address-page" && state["address-page"].guid;
|
||||||
}, "Check address page state (editing)");
|
}, "Check address page state (editing)");
|
||||||
|
|
||||||
info("filling address fields");
|
info("modify some address fields");
|
||||||
for (let [key, val] of Object.entries(PTU.Addresses.TimBL)) {
|
for (let key of ["given-name", "tel", "organization", "street-address"]) {
|
||||||
let field = content.document.getElementById(key);
|
let field = content.document.getElementById(key);
|
||||||
if (!field) {
|
if (!field) {
|
||||||
ok(false, `${key} field not found`);
|
ok(false, `${key} field not found`);
|
||||||
}
|
}
|
||||||
field.value = val.slice(0, -1) + "7";
|
field.focus();
|
||||||
|
EventUtils.sendKey("BACK_SPACE", content.window);
|
||||||
|
EventUtils.sendString("7", content.window);
|
||||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ add_task(async function test_change_shipping() {
|
|||||||
is(items.length, 1, "1 additional display item");
|
is(items.length, 1, "1 additional display item");
|
||||||
is(items[0].amountCurrency, "EUR", "First display item is in Euros");
|
is(items[0].amountCurrency, "EUR", "First display item is in Euros");
|
||||||
is(items[0].amountValue, "1.00", "First display item has 1.00 value");
|
is(items[0].amountValue, "1.00", "First display item has 1.00 value");
|
||||||
|
btn.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
info("clicking pay");
|
info("clicking pay");
|
||||||
|
@ -59,16 +59,15 @@ add_task(async function test_onboarding_wizard_without_saved_addresses_and_saved
|
|||||||
let addressCancelButton = content.document.querySelector("address-form .cancel-button");
|
let addressCancelButton = content.document.querySelector("address-form .cancel-button");
|
||||||
ok(content.isVisible(addressCancelButton),
|
ok(content.isVisible(addressCancelButton),
|
||||||
"The cancel button on the address page is visible");
|
"The cancel button on the address page is visible");
|
||||||
|
});
|
||||||
|
|
||||||
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
|
await fillInShippingAddressForm(frame, PTU.Addresses.TimBL2);
|
||||||
let field = content.document.getElementById(key);
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
if (!field) {
|
|
||||||
ok(false, `${key} field not found`);
|
await spawnPaymentDialogTask(frame, async function() {
|
||||||
}
|
let {
|
||||||
field.value = val;
|
PaymentTestUtils: PTU,
|
||||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
}
|
|
||||||
content.document.querySelector("address-form .save-button").click();
|
|
||||||
|
|
||||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "basic-card-page";
|
return state.page.id == "basic-card-page";
|
||||||
@ -271,16 +270,16 @@ add_task(async function test_onboarding_wizard_without_saved_address_with_saved_
|
|||||||
info("Checking if the address page has been rendered");
|
info("Checking if the address page has been rendered");
|
||||||
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
||||||
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
|
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);
|
await fillInShippingAddressForm(frame, PTU.Addresses.TimBL2);
|
||||||
if (!field) {
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
ok(false, `${key} field not found`);
|
|
||||||
}
|
await spawnPaymentDialogTask(frame, async function checkSavedAndCancelButton() {
|
||||||
field.value = val;
|
let {
|
||||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
PaymentTestUtils: PTU,
|
||||||
}
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
content.document.querySelector("address-form .save-button").click();
|
|
||||||
|
|
||||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "payment-summary";
|
return state.page.id == "payment-summary";
|
||||||
@ -334,16 +333,15 @@ add_task(async function test_onboarding_wizard_with_requestShipping_turned_off()
|
|||||||
ok(content.isVisible(addressPageTitle), "Address page title is visible");
|
ok(content.isVisible(addressPageTitle), "Address page title is visible");
|
||||||
is(addressPageTitle.textContent, "Add Billing Address",
|
is(addressPageTitle.textContent, "Add Billing Address",
|
||||||
"Address page title is correctly shown");
|
"Address page title is correctly shown");
|
||||||
|
});
|
||||||
|
|
||||||
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
|
await fillInBillingAddressForm(frame, PTU.Addresses.TimBL2);
|
||||||
let field = content.document.getElementById(key);
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
if (!field) {
|
|
||||||
ok(false, `${key} field not found`);
|
await spawnPaymentDialogTask(frame, async function() {
|
||||||
}
|
let {
|
||||||
field.value = val;
|
PaymentTestUtils: PTU,
|
||||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
}
|
|
||||||
content.document.querySelector("address-form .save-button").click();
|
|
||||||
|
|
||||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "basic-card-page";
|
return state.page.id == "basic-card-page";
|
||||||
@ -443,16 +441,17 @@ add_task(async function test_back_button_on_basic_card_page_during_onboarding()
|
|||||||
info("Checking if the address page has been rendered");
|
info("Checking if the address page has been rendered");
|
||||||
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
||||||
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
|
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
|
||||||
|
});
|
||||||
|
|
||||||
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
|
await fillInBillingAddressForm(frame, PTU.Addresses.TimBL2);
|
||||||
let field = content.document.getElementById(key);
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.clickPrimaryButton);
|
||||||
if (!field) {
|
|
||||||
ok(false, `${key} field not found`);
|
await spawnPaymentDialogTask(frame, async function() {
|
||||||
}
|
let {
|
||||||
field.value = val;
|
PaymentTestUtils: PTU,
|
||||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
}
|
|
||||||
content.document.querySelector("address-form .save-button").click();
|
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
||||||
|
|
||||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "basic-card-page";
|
return state.page.id == "basic-card-page";
|
||||||
@ -464,7 +463,7 @@ add_task(async function test_back_button_on_basic_card_page_during_onboarding()
|
|||||||
|
|
||||||
info("Partially fill basic card form");
|
info("Partially fill basic card form");
|
||||||
let field = content.document.getElementById("cc-number");
|
let field = content.document.getElementById("cc-number");
|
||||||
field.value = PTU.BasicCards.JohnDoe["cc-number"];
|
content.fillField(field, PTU.BasicCards.JohnDoe["cc-number"]);
|
||||||
|
|
||||||
info("Clicking on the back button to edit address saved in the previous step");
|
info("Clicking on the back button to edit address saved in the previous step");
|
||||||
basicCardBackButton.click();
|
basicCardBackButton.click();
|
||||||
@ -484,7 +483,7 @@ add_task(async function test_back_button_on_basic_card_page_during_onboarding()
|
|||||||
"Given name field value is correctly loaded");
|
"Given name field value is correctly loaded");
|
||||||
|
|
||||||
info("Editing the address and saving again");
|
info("Editing the address and saving again");
|
||||||
field.value = "John";
|
content.fillField(field, "John");
|
||||||
addressSaveButton.click();
|
addressSaveButton.click();
|
||||||
|
|
||||||
info("Checking if the address was correctly edited");
|
info("Checking if the address was correctly edited");
|
||||||
|
@ -154,6 +154,20 @@ add_task(async function test_show_field_specific_error_on_addresschange() {
|
|||||||
PaymentTestUtils: PTU,
|
PaymentTestUtils: PTU,
|
||||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
|
|
||||||
|
// TODO: bug 1482808 - Clear setCustomValidity from merchant errors since
|
||||||
|
// they don't currently ever get cleared.
|
||||||
|
for (let field of content.document.querySelector("address-form form").elements) {
|
||||||
|
if (!field.validity.customError) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
field.setCustomValidity("");
|
||||||
|
todo(false, `Clearing custom validity on #${field.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cu.waiveXrays(content.document.querySelector("address-form")).updateSaveButtonState();
|
||||||
|
|
||||||
|
// End bug 1482808 TODO
|
||||||
|
|
||||||
info("saving corrections");
|
info("saving corrections");
|
||||||
content.document.querySelector("address-form .save-button").click();
|
content.document.querySelector("address-form .save-button").click();
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ function checkPaymentAddressMatchesStorageAddress(paymentAddress, storageAddress
|
|||||||
is(paymentAddress.addressLine[0], addressLines[0], "Address line 1 should match");
|
is(paymentAddress.addressLine[0], addressLines[0], "Address line 1 should match");
|
||||||
is(paymentAddress.addressLine[1], addressLines[1], "Address line 2 should match");
|
is(paymentAddress.addressLine[1], addressLines[1], "Address line 2 should match");
|
||||||
is(paymentAddress.country, storageAddress.country, "Country should match");
|
is(paymentAddress.country, storageAddress.country, "Country should match");
|
||||||
is(paymentAddress.region, storageAddress["address-level1"], "Region should match");
|
is(paymentAddress.region, storageAddress["address-level1"] || "", "Region should match");
|
||||||
is(paymentAddress.city, storageAddress["address-level2"], "City should match");
|
is(paymentAddress.city, storageAddress["address-level2"], "City should match");
|
||||||
is(paymentAddress.postalCode, storageAddress["postal-code"], "Zip code should match");
|
is(paymentAddress.postalCode, storageAddress["postal-code"], "Zip code should match");
|
||||||
is(paymentAddress.organization, storageAddress.organization, "Org should match");
|
is(paymentAddress.organization, storageAddress.organization, "Org should match");
|
||||||
@ -266,6 +266,26 @@ async function setupPaymentDialog(browser, {methodData, details, options, mercha
|
|||||||
element.getBoundingClientRect().height;
|
element.getBoundingClientRect().height;
|
||||||
content.isHidden = (element) => elementHeight(element) == 0;
|
content.isHidden = (element) => elementHeight(element) == 0;
|
||||||
content.isVisible = (element) => elementHeight(element) > 0;
|
content.isVisible = (element) => elementHeight(element) > 0;
|
||||||
|
content.fillField = async function fillField(field, value) {
|
||||||
|
// Keep in-sync with the copy in payments_common.js but with EventUtils methods called on a
|
||||||
|
// EventUtils object.
|
||||||
|
field.focus();
|
||||||
|
if (field.localName == "select") {
|
||||||
|
if (field.value == value) {
|
||||||
|
// Do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.value = value;
|
||||||
|
field.dispatchEvent(new content.window.Event("input"));
|
||||||
|
field.dispatchEvent(new content.window.Event("change"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (field.value) {
|
||||||
|
EventUtils.sendKey("BACK_SPACE", content.window);
|
||||||
|
}
|
||||||
|
EventUtils.sendString(value, content.window);
|
||||||
|
}
|
||||||
|
;
|
||||||
});
|
});
|
||||||
await injectEventUtilsInContentTask(frame);
|
await injectEventUtilsInContentTask(frame);
|
||||||
info("helper functions injected into frame");
|
info("helper functions injected into frame");
|
||||||
@ -352,7 +372,7 @@ async function selectPaymentDialogShippingAddressByCountry(frame, country) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToAddAddressPage(frame, aOptions = {
|
async function navigateToAddAddressPage(frame, aOptions = {
|
||||||
addLinkSelector: "address-picker a.add-link",
|
addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] a.add-link",
|
||||||
initialPageId: "payment-summary",
|
initialPageId: "payment-summary",
|
||||||
}) {
|
}) {
|
||||||
await spawnPaymentDialogTask(frame, async (options) => {
|
await spawnPaymentDialogTask(frame, async (options) => {
|
||||||
@ -378,24 +398,59 @@ async function navigateToAddAddressPage(frame, aOptions = {
|
|||||||
}, aOptions);
|
}, aOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fillInBillingAddressForm(frame, aAddress) {
|
||||||
|
// For now billing and shipping address forms have the same fields but that may
|
||||||
|
// change so use separarate helpers.
|
||||||
|
return fillInShippingAddressForm(frame, aAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillInShippingAddressForm(frame, aAddress, aOptions) {
|
||||||
|
let address = Object.assign({}, aAddress);
|
||||||
|
// Email isn't used on address forms, only payer/contact ones.
|
||||||
|
delete address.email;
|
||||||
|
return fillInAddressForm(frame, address, aOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillInPayerAddressForm(frame, aAddress) {
|
||||||
|
let address = Object.assign({}, aAddress);
|
||||||
|
let payerFields = ["given-name", "additional-name", "family-name", "tel", "email"];
|
||||||
|
for (let fieldName of Object.keys(address)) {
|
||||||
|
if (payerFields.includes(fieldName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delete address[fieldName];
|
||||||
|
}
|
||||||
|
return fillInAddressForm(frame, address);
|
||||||
|
}
|
||||||
|
|
||||||
async function fillInAddressForm(frame, aAddress, aOptions = {}) {
|
async function fillInAddressForm(frame, aAddress, aOptions = {}) {
|
||||||
await spawnPaymentDialogTask(frame, async (args) => {
|
await spawnPaymentDialogTask(frame, async (args) => {
|
||||||
let {address, options = {}} = args;
|
let {address, options = {}} = args;
|
||||||
|
|
||||||
|
if (typeof(address.country) != "undefined") {
|
||||||
|
// Set the country first so that the appropriate fields are visible.
|
||||||
|
let countryField = content.document.getElementById("country");
|
||||||
|
ok(!countryField.disabled, "Country Field shouldn't be disabled");
|
||||||
|
await content.fillField(countryField, address.country);
|
||||||
|
is(countryField.value, address.country, "country value is correct after fillField");
|
||||||
|
}
|
||||||
|
|
||||||
// fill the form
|
// fill the form
|
||||||
info("manuallyAddAddress: fill the form with address: " + JSON.stringify(address));
|
info("fillInAddressForm: fill the form with address: " + JSON.stringify(address));
|
||||||
for (let [key, val] of Object.entries(address)) {
|
for (let [key, val] of Object.entries(address)) {
|
||||||
let field = content.document.getElementById(key);
|
let field = content.document.getElementById(key);
|
||||||
if (!field) {
|
if (!field) {
|
||||||
ok(false, `${key} field not found`);
|
ok(false, `${key} field not found`);
|
||||||
}
|
}
|
||||||
field.value = val;
|
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
||||||
|
await content.fillField(field, val);
|
||||||
|
is(field.value, val, `${key} value is correct after fillField`);
|
||||||
}
|
}
|
||||||
let persistCheckbox = Cu.waiveXrays(
|
let persistCheckbox = Cu.waiveXrays(
|
||||||
content.document.querySelector(options.checkboxSelector));
|
content.document.querySelector("#address-page .persist-checkbox"));
|
||||||
// only touch the checked state if explicitly told to in the options
|
// only touch the checked state if explicitly told to in the options
|
||||||
if (options.hasOwnProperty("setPersistCheckedValue")) {
|
if (options.hasOwnProperty("setPersistCheckedValue")) {
|
||||||
info("fillInCardForm: Manually setting the persist checkbox checkedness to: " +
|
info("fillInAddressForm: Manually setting the persist checkbox checkedness to: " +
|
||||||
options.setPersistCheckedValue);
|
options.setPersistCheckedValue);
|
||||||
Cu.waiveXrays(persistCheckbox).checked = options.setPersistCheckedValue;
|
Cu.waiveXrays(persistCheckbox).checked = options.setPersistCheckedValue;
|
||||||
}
|
}
|
||||||
@ -455,7 +510,7 @@ async function submitAddressForm(frame, aAddress, aOptions = {}) {
|
|||||||
}, {address: aAddress, options: aOptions});
|
}, {address: aAddress, options: aOptions});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function manuallyAddAddress(frame, aAddress, aOptions = {}) {
|
async function manuallyAddShippingAddress(frame, aAddress, aOptions = {}) {
|
||||||
let options = Object.assign({
|
let options = Object.assign({
|
||||||
expectPersist: true,
|
expectPersist: true,
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
@ -463,9 +518,10 @@ async function manuallyAddAddress(frame, aAddress, aOptions = {}) {
|
|||||||
checkboxSelector: "#address-page .persist-checkbox",
|
checkboxSelector: "#address-page .persist-checkbox",
|
||||||
});
|
});
|
||||||
await navigateToAddAddressPage(frame);
|
await navigateToAddAddressPage(frame);
|
||||||
info("manuallyAddAddress, fill in address form with options: " + JSON.stringify(options));
|
info("manuallyAddShippingAddress, fill in address form with options: " + JSON.stringify(options));
|
||||||
await fillInAddressForm(frame, aAddress, options);
|
await fillInShippingAddressForm(frame, aAddress, options);
|
||||||
info("manuallyAddAddress, verifyPersistCheckbox with options: " + JSON.stringify(options));
|
info("manuallyAddShippingAddress, verifyPersistCheckbox with options: " +
|
||||||
|
JSON.stringify(options));
|
||||||
await verifyPersistCheckbox(frame, options);
|
await verifyPersistCheckbox(frame, options);
|
||||||
await submitAddressForm(frame, aAddress, options);
|
await submitAddressForm(frame, aAddress, options);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/* exported asyncElementRendered, promiseStateChange, promiseContentToChromeMessage, deepClone,
|
/* exported asyncElementRendered, promiseStateChange, promiseContentToChromeMessage, deepClone,
|
||||||
PTU, registerConsoleFilter */
|
PTU, registerConsoleFilter, fillField */
|
||||||
|
|
||||||
const PTU = SpecialPowers.Cu.import("resource://testing-common/PaymentTestUtils.jsm", {})
|
const PTU = SpecialPowers.Cu.import("resource://testing-common/PaymentTestUtils.jsm", {})
|
||||||
.PaymentTestUtils;
|
.PaymentTestUtils;
|
||||||
@ -47,6 +47,30 @@ function deepClone(obj) {
|
|||||||
return JSON.parse(JSON.stringify(obj));
|
return JSON.parse(JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} field
|
||||||
|
* @param {string} value
|
||||||
|
* @note This is async in case we need to make it async to handle focus in the future.
|
||||||
|
* @note Keep in sync with the copy in head.js
|
||||||
|
*/
|
||||||
|
async function fillField(field, value) {
|
||||||
|
field.focus();
|
||||||
|
if (field.localName == "select") {
|
||||||
|
if (field.value == value) {
|
||||||
|
// Do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.value = value;
|
||||||
|
field.dispatchEvent(new Event("input"));
|
||||||
|
field.dispatchEvent(new Event("change"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (field.value) {
|
||||||
|
sendKey("BACK_SPACE");
|
||||||
|
}
|
||||||
|
sendString(value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If filterFunction is a function which returns true given a console message
|
* If filterFunction is a function which returns true given a console message
|
||||||
* then the test won't fail from that message.
|
* then the test won't fail from that message.
|
||||||
|
@ -59,11 +59,7 @@ function checkAddressForm(customEl, expectedAddress) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendStringAndCheckValidity(element, string, isValid) {
|
function sendStringAndCheckValidity(element, string, isValid) {
|
||||||
element.focus();
|
fillField(element, string);
|
||||||
while (element.value) {
|
|
||||||
sendKey("BACK_SPACE");
|
|
||||||
}
|
|
||||||
sendString(string);
|
|
||||||
ok(element.checkValidity() == isValid,
|
ok(element.checkValidity() == isValid,
|
||||||
`${element.id} should be ${isValid ? "valid" : "invalid"} (${string})`);
|
`${element.id} should be ${isValid ? "valid" : "invalid"} (${string})`);
|
||||||
}
|
}
|
||||||
@ -115,25 +111,26 @@ add_task(async function test_saveButton() {
|
|||||||
display.appendChild(form);
|
display.appendChild(form);
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
|
|
||||||
form.form.querySelector("#given-name").focus();
|
ok(form.saveButton.disabled, "Save button initially disabled");
|
||||||
sendString("Jaws");
|
fillField(form.form.querySelector("#given-name"), "Jaws");
|
||||||
form.form.querySelector("#family-name").focus();
|
fillField(form.form.querySelector("#family-name"), "Swaj");
|
||||||
sendString("Swaj");
|
fillField(form.form.querySelector("#organization"), "Allizom");
|
||||||
form.form.querySelector("#organization").focus();
|
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
|
||||||
sendString("Allizom");
|
fillField(form.form.querySelector("#address-level2"), "Firefoxity City");
|
||||||
form.form.querySelector("#street-address").focus();
|
fillField(form.form.querySelector("#address-level1"), "CA");
|
||||||
sendString("404 Internet Super Highway");
|
fillField(form.form.querySelector("#postal-code"), "00001");
|
||||||
form.form.querySelector("#address-level2").focus();
|
fillField(form.form.querySelector("#country"), "US");
|
||||||
sendString("Firefoxity City");
|
fillField(form.form.querySelector("#email"), "test@example.com");
|
||||||
form.form.querySelector("#address-level1").focus();
|
fillField(form.form.querySelector("#tel"), "+15555551212");
|
||||||
sendString("CA");
|
|
||||||
form.form.querySelector("#postal-code").focus();
|
ok(!form.saveButton.disabled, "Save button is enabled after filling");
|
||||||
sendString("00001");
|
|
||||||
form.form.querySelector("#country option[value='US']").selected = true;
|
info("blanking the street-address");
|
||||||
form.form.querySelector("#email").focus();
|
fillField(form.form.querySelector("#street-address"), "");
|
||||||
sendString("test@example.com");
|
ok(form.saveButton.disabled, "Save button is disabled after blanking street-address");
|
||||||
form.form.querySelector("#tel").focus();
|
|
||||||
sendString("+15555551212");
|
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
|
||||||
|
ok(!form.saveButton.disabled, "Save button is enabled after re-filling street-address");
|
||||||
|
|
||||||
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
||||||
is(form.saveButton.textContent, "Add", "Check label");
|
is(form.saveButton.textContent, "Add", "Check label");
|
||||||
@ -158,7 +155,6 @@ add_task(async function test_saveButton() {
|
|||||||
"address-level1": "CA",
|
"address-level1": "CA",
|
||||||
"postal-code": "00001",
|
"postal-code": "00001",
|
||||||
"country": "US",
|
"country": "US",
|
||||||
"email": "test@example.com",
|
|
||||||
"tel": "+15555551212",
|
"tel": "+15555551212",
|
||||||
},
|
},
|
||||||
}, "Check event details for the message to chrome");
|
}, "Check event details for the message to chrome");
|
||||||
@ -206,6 +202,8 @@ add_task(async function test_edit() {
|
|||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
checkAddressForm(form, address1);
|
checkAddressForm(form, address1);
|
||||||
|
|
||||||
|
ok(!form.saveButton.disabled, "Save button should be enabled upon edit for a valid address");
|
||||||
|
|
||||||
info("test change to minimal record");
|
info("test change to minimal record");
|
||||||
let minimalAddress = {
|
let minimalAddress = {
|
||||||
"given-name": address1["given-name"],
|
"given-name": address1["given-name"],
|
||||||
@ -225,6 +223,7 @@ add_task(async function test_edit() {
|
|||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
is(form.saveButton.textContent, "Update", "Check label");
|
is(form.saveButton.textContent, "Update", "Check label");
|
||||||
checkAddressForm(form, minimalAddress);
|
checkAddressForm(form, minimalAddress);
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled if only the name is filled");
|
||||||
|
|
||||||
info("change to no selected address");
|
info("change to no selected address");
|
||||||
await form.requestStore.setState({
|
await form.requestStore.setState({
|
||||||
@ -235,6 +234,7 @@ add_task(async function test_edit() {
|
|||||||
});
|
});
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
checkAddressForm(form, {});
|
checkAddressForm(form, {});
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled for an empty form");
|
||||||
|
|
||||||
form.remove();
|
form.remove();
|
||||||
});
|
});
|
||||||
@ -245,8 +245,14 @@ add_task(async function test_restricted_address_fields() {
|
|||||||
form.dataset.errorGenericSave = "Generic error";
|
form.dataset.errorGenericSave = "Generic error";
|
||||||
await form.promiseReady;
|
await form.promiseReady;
|
||||||
display.appendChild(form);
|
display.appendChild(form);
|
||||||
|
await form.requestStore.setState({
|
||||||
|
"address-page": {
|
||||||
|
addressFields: "name email tel",
|
||||||
|
},
|
||||||
|
});
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
form.setAttribute("address-fields", "name email tel");
|
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
|
||||||
|
|
||||||
ok(!isHidden(form.form.querySelector("#given-name")),
|
ok(!isHidden(form.form.querySelector("#given-name")),
|
||||||
"given-name should be visible");
|
"given-name should be visible");
|
||||||
@ -271,7 +277,18 @@ add_task(async function test_restricted_address_fields() {
|
|||||||
ok(!isHidden(form.form.querySelector("#tel")),
|
ok(!isHidden(form.form.querySelector("#tel")),
|
||||||
"tel should be visible");
|
"tel should be visible");
|
||||||
|
|
||||||
|
fillField(form.form.querySelector("#given-name"), "John");
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
|
||||||
|
fillField(form.form.querySelector("#email"), "john@example.com");
|
||||||
|
todo(form.saveButton.disabled,
|
||||||
|
"Save button should be disabled due to empty fields - Bug 1483412");
|
||||||
|
fillField(form.form.querySelector("#tel"), "+15555555555");
|
||||||
|
ok(!form.saveButton.disabled, "Save button should be enabled with all required fields filled");
|
||||||
|
|
||||||
form.remove();
|
form.remove();
|
||||||
|
await form.requestStore.setState({
|
||||||
|
"address-page": {},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_field_validation() {
|
add_task(async function test_field_validation() {
|
||||||
@ -298,8 +315,8 @@ add_task(async function test_field_validation() {
|
|||||||
countrySelect,
|
countrySelect,
|
||||||
];
|
];
|
||||||
for (let field of requiredFields) {
|
for (let field of requiredFields) {
|
||||||
let container = field.closest("label");
|
let container = field.closest(`#${field.id}-container`);
|
||||||
ok(container.hasAttribute("required"), "Container should have required attribute");
|
ok(container.hasAttribute("required"), `#${field.id} container should have required attribute`);
|
||||||
let span = container.querySelector("span");
|
let span = container.querySelector("span");
|
||||||
is(span.getAttribute("fieldRequiredSymbol"), "*",
|
is(span.getAttribute("fieldRequiredSymbol"), "*",
|
||||||
"span should have asterisk as fieldRequiredSymbol");
|
"span should have asterisk as fieldRequiredSymbol");
|
||||||
@ -307,8 +324,9 @@ add_task(async function test_field_validation() {
|
|||||||
"Asterisk should be on " + field.id);
|
"Asterisk should be on " + field.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
countrySelect.selectedIndex = [...countrySelect.options].findIndex(o => o.value == "US");
|
ok(form.saveButton.disabled, "Save button should be disabled upon load");
|
||||||
countrySelect.dispatchEvent(new Event("change"));
|
|
||||||
|
fillField(countrySelect, "US");
|
||||||
|
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
|
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
sendStringAndCheckValidity(addressLevel1Input, "", false);
|
||||||
@ -320,8 +338,7 @@ add_task(async function test_field_validation() {
|
|||||||
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
|
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
|
||||||
sendStringAndCheckValidity(postalCodeInput, "06390-0001", true);
|
sendStringAndCheckValidity(postalCodeInput, "06390-0001", true);
|
||||||
|
|
||||||
countrySelect.selectedIndex = [...countrySelect.options].findIndex(o => o.value == "CA");
|
fillField(countrySelect, "CA");
|
||||||
countrySelect.dispatchEvent(new Event("change"));
|
|
||||||
|
|
||||||
sendStringAndCheckValidity(postalCodeInput, "00001", false);
|
sendStringAndCheckValidity(postalCodeInput, "00001", false);
|
||||||
sendStringAndCheckValidity(addressLevel1Input, "CA", true);
|
sendStringAndCheckValidity(addressLevel1Input, "CA", true);
|
||||||
@ -373,6 +390,8 @@ add_task(async function test_customValidity() {
|
|||||||
"Validation message should match for " + selector);
|
"Validation message should match for " + selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled due to validation errors");
|
||||||
|
|
||||||
checkValidationMessage("#street-address", "addressLine");
|
checkValidationMessage("#street-address", "addressLine");
|
||||||
checkValidationMessage("#address-level2", "city");
|
checkValidationMessage("#address-level2", "city");
|
||||||
checkValidationMessage("#country", "country");
|
checkValidationMessage("#country", "country");
|
||||||
@ -382,6 +401,8 @@ add_task(async function test_customValidity() {
|
|||||||
checkValidationMessage("#given-name", "recipient");
|
checkValidationMessage("#given-name", "recipient");
|
||||||
checkValidationMessage("#address-level1", "region");
|
checkValidationMessage("#address-level1", "region");
|
||||||
|
|
||||||
|
// TODO: bug 1482808 - the save button should be enabled after editing the fields
|
||||||
|
|
||||||
form.remove();
|
form.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -416,6 +437,8 @@ add_task(async function test_field_validation() {
|
|||||||
display.appendChild(form);
|
display.appendChild(form);
|
||||||
await asyncElementRendered();
|
await asyncElementRendered();
|
||||||
|
|
||||||
|
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
|
||||||
|
|
||||||
let postalCodeInput = form.form.querySelector("#postal-code");
|
let postalCodeInput = form.form.querySelector("#postal-code");
|
||||||
let addressLevel1Input = form.form.querySelector("#address-level1");
|
let addressLevel1Input = form.form.querySelector("#address-level1");
|
||||||
ok(!postalCodeInput.value, "postal-code should be empty by default");
|
ok(!postalCodeInput.value, "postal-code should be empty by default");
|
||||||
|
@ -113,20 +113,72 @@ class EditAddress extends EditAutofillForm {
|
|||||||
this.formatForm(record.country);
|
this.formatForm(record.country);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `mailing-address` is a special attribute token to indicate mailing fields + country.
|
||||||
|
*
|
||||||
|
* @param {object[]} mailingFieldsOrder - `fieldsOrder` from `getFormFormat`
|
||||||
|
* @returns {object[]} in the same structure as `mailingFieldsOrder` but including non-mail fields
|
||||||
|
*/
|
||||||
|
computeVisibleFields(mailingFieldsOrder) {
|
||||||
|
let addressFields = this._elements.form.dataset.addressFields;
|
||||||
|
if (addressFields) {
|
||||||
|
let requestedFieldClasses = addressFields.trim().split(/\s+/);
|
||||||
|
let fieldClasses = [];
|
||||||
|
if (requestedFieldClasses.includes("mailing-address")) {
|
||||||
|
fieldClasses = fieldClasses.concat(mailingFieldsOrder);
|
||||||
|
// `country` isn't part of the `mailingFieldsOrder` so add it when filling a mailing-address
|
||||||
|
requestedFieldClasses.splice(requestedFieldClasses.indexOf("mailing-address"), 1,
|
||||||
|
"country");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let fieldClassName of requestedFieldClasses) {
|
||||||
|
fieldClasses.push({
|
||||||
|
fieldId: fieldClassName,
|
||||||
|
newLine: fieldClassName == "name",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return fieldClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the default which is shown in the management interface and includes all fields.
|
||||||
|
return mailingFieldsOrder.concat([
|
||||||
|
{
|
||||||
|
fieldId: "country",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: "tel",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: "email",
|
||||||
|
newLine: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format the form based on country. The address-level1 and postal-code labels
|
* Format the form based on country. The address-level1 and postal-code labels
|
||||||
* should be specific to the given country.
|
* should be specific to the given country.
|
||||||
* @param {string} country
|
* @param {string} country
|
||||||
*/
|
*/
|
||||||
formatForm(country) {
|
formatForm(country) {
|
||||||
const {addressLevel1Label, postalCodeLabel, fieldsOrder, postalCodePattern} =
|
const {
|
||||||
this.getFormFormat(country);
|
addressLevel1Label,
|
||||||
|
postalCodeLabel,
|
||||||
|
fieldsOrder: mailingFieldsOrder,
|
||||||
|
postalCodePattern,
|
||||||
|
} = this.getFormFormat(country);
|
||||||
this._elements.addressLevel1Label.dataset.localization = addressLevel1Label;
|
this._elements.addressLevel1Label.dataset.localization = addressLevel1Label;
|
||||||
this._elements.postalCodeLabel.dataset.localization = postalCodeLabel;
|
this._elements.postalCodeLabel.dataset.localization = postalCodeLabel;
|
||||||
this.arrangeFields(fieldsOrder);
|
let fieldClasses = this.computeVisibleFields(mailingFieldsOrder);
|
||||||
|
this.arrangeFields(fieldClasses);
|
||||||
this.updatePostalCodeValidation(postalCodePattern);
|
this.updatePostalCodeValidation(postalCodePattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update address field visibility and order based on libaddressinput data.
|
||||||
|
*
|
||||||
|
* @param {object[]} fieldsOrder array of objects with `fieldId` and optional `newLine` properties
|
||||||
|
*/
|
||||||
arrangeFields(fieldsOrder) {
|
arrangeFields(fieldsOrder) {
|
||||||
let fields = [
|
let fields = [
|
||||||
"name",
|
"name",
|
||||||
@ -135,6 +187,9 @@ class EditAddress extends EditAutofillForm {
|
|||||||
"address-level2",
|
"address-level2",
|
||||||
"address-level1",
|
"address-level1",
|
||||||
"postal-code",
|
"postal-code",
|
||||||
|
"country",
|
||||||
|
"tel",
|
||||||
|
"email",
|
||||||
];
|
];
|
||||||
let inputs = [];
|
let inputs = [];
|
||||||
for (let i = 0; i < fieldsOrder.length; i++) {
|
for (let i = 0; i < fieldsOrder.length; i++) {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<div id="name-container">
|
<div id="name-container">
|
||||||
<label id="given-name-container">
|
<label id="given-name-container">
|
||||||
<span data-localization="givenName"/>
|
<span data-localization="givenName"/>
|
||||||
<input id="given-name" type="text" required="true"/>
|
<input id="given-name" type="text" required="required"/>
|
||||||
</label>
|
</label>
|
||||||
<label id="additional-name-container">
|
<label id="additional-name-container">
|
||||||
<span data-localization="additionalName"/>
|
<span data-localization="additionalName"/>
|
||||||
@ -39,36 +39,38 @@
|
|||||||
</label>
|
</label>
|
||||||
<label id="street-address-container">
|
<label id="street-address-container">
|
||||||
<span data-localization="streetAddress"/>
|
<span data-localization="streetAddress"/>
|
||||||
<textarea id="street-address" rows="3" required="true"/>
|
<textarea id="street-address" rows="3" required="required"/>
|
||||||
</label>
|
</label>
|
||||||
<label id="address-level2-container">
|
<label id="address-level2-container">
|
||||||
<span data-localization="city"/>
|
<span data-localization="city"/>
|
||||||
<input id="address-level2" type="text" required="true"/>
|
<input id="address-level2" type="text" required="required"/>
|
||||||
</label>
|
</label>
|
||||||
<label id="address-level1-container">
|
<label id="address-level1-container">
|
||||||
<span/>
|
<span/>
|
||||||
<input id="address-level1" type="text" required="true"/>
|
<input id="address-level1" type="text" required="required"/>
|
||||||
</label>
|
</label>
|
||||||
<label id="postal-code-container">
|
<label id="postal-code-container">
|
||||||
<span/>
|
<span/>
|
||||||
<input id="postal-code" type="text" required="true"/>
|
<input id="postal-code" type="text" required="required"/>
|
||||||
|
</label>
|
||||||
|
<div id="country-container">
|
||||||
|
<label id="country-label">
|
||||||
|
<span data-localization="country"/>
|
||||||
|
<select id="country" required="required">
|
||||||
|
<option/>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<p id="country-warning-message" data-localization="countryWarningMessage2"/>
|
||||||
|
</div>
|
||||||
|
<label id="tel-container">
|
||||||
|
<span data-localization="tel"/>
|
||||||
|
<input id="tel" type="tel"/>
|
||||||
|
</label>
|
||||||
|
<label id="email-container">
|
||||||
|
<span data-localization="email"/>
|
||||||
|
<input id="email" type="email" required="required"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label id="country-container">
|
|
||||||
<span data-localization="country"/>
|
|
||||||
<select id="country" required="true">
|
|
||||||
<option/>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
<p id="country-warning-message" data-localization="countryWarningMessage2"/>
|
|
||||||
<label id="email-container">
|
|
||||||
<span data-localization="email"/>
|
|
||||||
<input id="email" type="email"/>
|
|
||||||
</label>
|
|
||||||
<label id="tel-container">
|
|
||||||
<span data-localization="tel"/>
|
|
||||||
<input id="tel" type="tel"/>
|
|
||||||
</label>
|
|
||||||
</form>
|
</form>
|
||||||
<div id="controls-container">
|
<div id="controls-container">
|
||||||
<button id="cancel" data-localization="cancelBtnLabel"/>
|
<button id="cancel" data-localization="cancelBtnLabel"/>
|
||||||
|
@ -21,7 +21,7 @@ select {
|
|||||||
#additional-name-container,
|
#additional-name-container,
|
||||||
#address-level1-container,
|
#address-level1-container,
|
||||||
#postal-code-container,
|
#postal-code-container,
|
||||||
#country-container,
|
#country-label,
|
||||||
#country-warning-message,
|
#country-warning-message,
|
||||||
#family-name-container,
|
#family-name-container,
|
||||||
#organization-container,
|
#organization-container,
|
||||||
@ -36,6 +36,7 @@ select {
|
|||||||
|
|
||||||
#name-container,
|
#name-container,
|
||||||
#street-address-container,
|
#street-address-container,
|
||||||
|
#country-container,
|
||||||
#email-container {
|
#email-container {
|
||||||
flex: 0 1 100%;
|
flex: 0 1 100%;
|
||||||
}
|
}
|
||||||
|
@ -74,10 +74,10 @@ add_task(async function test_saveAddress() {
|
|||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_1.country,
|
TEST_ADDRESS_1.country,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_1.email,
|
|
||||||
"VK_TAB",
|
|
||||||
TEST_ADDRESS_1.tel,
|
TEST_ADDRESS_1.tel,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
|
TEST_ADDRESS_1.email,
|
||||||
|
"VK_TAB",
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
"VK_RETURN",
|
"VK_RETURN",
|
||||||
];
|
];
|
||||||
@ -145,10 +145,10 @@ add_task(async function test_saveAddressCA() {
|
|||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_CA_1.country,
|
TEST_ADDRESS_CA_1.country,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_CA_1.email,
|
|
||||||
"VK_TAB",
|
|
||||||
TEST_ADDRESS_CA_1.tel,
|
TEST_ADDRESS_CA_1.tel,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
|
TEST_ADDRESS_CA_1.email,
|
||||||
|
"VK_TAB",
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
"VK_RETURN",
|
"VK_RETURN",
|
||||||
];
|
];
|
||||||
@ -193,10 +193,10 @@ add_task(async function test_saveAddressDE() {
|
|||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_DE_1.country,
|
TEST_ADDRESS_DE_1.country,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
TEST_ADDRESS_DE_1.email,
|
|
||||||
"VK_TAB",
|
|
||||||
TEST_ADDRESS_DE_1.tel,
|
TEST_ADDRESS_DE_1.tel,
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
|
TEST_ADDRESS_DE_1.email,
|
||||||
|
"VK_TAB",
|
||||||
"VK_TAB",
|
"VK_TAB",
|
||||||
"VK_RETURN",
|
"VK_RETURN",
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user