Bug 1429180 - Option to use a new billing address when adding a new payment method. r=MattN

MozReview-Commit-ID: 5LrpUw1LdT3

--HG--
extra : rebase_source : a2266d92902800af60978011ccd34bdc7a06b7f5
This commit is contained in:
Jared Wein 2018-05-10 15:12:01 -04:00
parent d5eb061a94
commit d9f3ec17f2
13 changed files with 373 additions and 69 deletions

View File

@ -582,6 +582,11 @@ var paymentDialogWrapper = {
});
}
const pageId = collectionName == "creditCards" ?
"basic-card-page" :
"address-page";
successStateChange[pageId].guid = guid;
this.sendMessageToContent("updateState", successStateChange);
} catch (ex) {
this.sendMessageToContent("updateState", errorStateChange);

View File

@ -86,6 +86,7 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
let record = {};
let {
page,
"address-page": addressPage,
} = state;
if (this.id && page && page.id !== this.id) {
@ -101,23 +102,23 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
this.backButton.hidden = page.onboardingWizard;
this.cancelButton.hidden = !page.onboardingWizard;
if (page.addressFields) {
this.setAttribute("address-fields", page.addressFields);
if (addressPage.addressFields) {
this.setAttribute("address-fields", addressPage.addressFields);
} else {
this.removeAttribute("address-fields");
}
this.pageTitle.textContent = page.title;
this.pageTitle.textContent = addressPage.title;
this.genericErrorText.textContent = page.error;
let editing = !!page.guid;
let editing = !!addressPage.guid;
let addresses = paymentRequest.getAddresses(state);
// If an address is selected we want to edit it.
if (editing) {
record = addresses[page.guid];
record = addresses[addressPage.guid];
if (!record) {
throw new Error("Trying to edit a non-existing address: " + page.guid);
throw new Error("Trying to edit a non-existing address: " + addressPage.guid);
}
// When editing an existing record, prevent changes to persistence
this.persistCheckbox.hidden = true;
@ -146,11 +147,19 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
break;
}
case this.backButton: {
this.requestStore.setState({
let currentState = this.requestStore.getState();
const previousId = currentState.page.previousId;
let state = {
page: {
id: "payment-summary",
id: previousId || "payment-summary",
},
});
};
if (previousId) {
state[previousId] = Object.assign({}, currentState[previousId], {
preserveFieldValues: true,
});
}
this.requestStore.setState(state);
break;
}
case this.saveButton: {
@ -169,10 +178,12 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
page,
tempAddresses,
savedBasicCards,
"address-page": addressPage,
"basic-card-page": basicCardPage,
} = this.requestStore.getState();
let editing = !!page.guid;
let editing = !!addressPage.guid;
if (editing ? (page.guid in tempAddresses) : !this.persistCheckbox.checked) {
if (editing ? (addressPage.guid in tempAddresses) : !this.persistCheckbox.checked) {
record.isTemporary = true;
}
@ -183,6 +194,7 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
onboardingWizard: page.onboardingWizard,
error: this.dataset.errorGenericSave,
},
"address-page": addressPage,
},
preserveOldProperties: true,
selectedStateKey: page.selectedStateKey,
@ -192,19 +204,29 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
state.successStateChange = {
page: {
id: "basic-card-page",
onboardingWizard: true,
guid: null,
previousId: "address-page",
onboardingWizard: page.onboardingWizard,
},
};
} else {
state.successStateChange = {
page: {
id: "payment-summary",
id: page.previousId || "payment-summary",
onboardingWizard: page.onboardingWizard,
},
};
}
paymentRequest.updateAutofillRecord("addresses", record, page.guid, state);
state.successStateChange["address-page"] = addressPage;
state.successStateChange["basic-card-page"] = basicCardPage;
const previousId = page.previousId;
if (previousId) {
state.successStateChange[previousId].preserveFieldValues = true;
state.successStateChange[previousId].addressesModified = true;
}
paymentRequest.updateAutofillRecord("addresses", record, addressPage.guid, state);
}
}

View File

@ -168,22 +168,24 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
let nextState = {
page: {
id: "address-page",
selectedStateKey: this.selectedStateKey,
},
"address-page": {
addressFields: this.getAttribute("address-fields"),
selectedStateKey: this.selectedStateKey,
},
};
switch (target) {
case this.addLink: {
nextState.page.guid = null;
nextState.page.title = this.dataset.addAddressTitle;
nextState["address-page"].guid = null;
nextState["address-page"].title = this.dataset.addAddressTitle;
break;
}
case this.editLink: {
let state = this.requestStore.getState();
let selectedAddressGUID = state[this.selectedStateKey];
nextState.page.guid = selectedAddressGUID;
nextState.page.title = this.dataset.editAddressTitle;
nextState["address-page"].guid = selectedAddressGUID;
nextState["address-page"].title = this.dataset.editAddressTitle;
break;
}
default: {

View File

@ -27,6 +27,15 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
this.cancelButton.className = "cancel-button";
this.cancelButton.addEventListener("click", this);
this.addressAddLink = document.createElement("a");
this.addressAddLink.className = "add-link";
this.addressAddLink.href = "javascript:void(0)";
this.addressAddLink.addEventListener("click", this);
this.addressEditLink = document.createElement("a");
this.addressEditLink.className = "edit-link";
this.addressEditLink.href = "javascript:void(0)";
this.addressEditLink.addEventListener("click", this);
this.backButton = document.createElement("button");
this.backButton.className = "back-button";
this.backButton.addEventListener("click", this);
@ -72,6 +81,13 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
getAddressLabel: PaymentDialogUtils.getAddressLabel,
});
let fragment = document.createDocumentFragment();
fragment.append(this.addressAddLink);
fragment.append(" ");
fragment.append(this.addressEditLink);
let billingAddressRow = this.form.querySelector(".billingAddressRow");
billingAddressRow.appendChild(fragment);
this.appendChild(this.persistCheckbox);
this.appendChild(this.genericErrorText);
this.appendChild(this.cancelButton);
@ -87,6 +103,7 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
let {
page,
selectedShippingAddress,
"basic-card-page": basicCardPage,
} = state;
if (this.id && page && page.id !== this.id) {
@ -98,6 +115,8 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
this.backButton.textContent = this.dataset.backButtonLabel;
this.saveButton.textContent = this.dataset.saveButtonLabel;
this.persistCheckbox.label = this.dataset.persistCheckboxLabel;
this.addressAddLink.textContent = this.dataset.addressAddLinkLabel;
this.addressEditLink.textContent = this.dataset.addressEditLinkLabel;
// The back button is temporarily hidden(See Bug 1462461).
this.backButton.hidden = !!page.onboardingWizard;
@ -109,22 +128,22 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
this.genericErrorText.textContent = page.error;
let editing = !!page.guid;
let editing = !!basicCardPage.guid;
this.form.querySelector("#cc-number").disabled = editing;
// If a card is selected we want to edit it.
if (editing) {
this.pageTitle.textContent = this.dataset.editBasicCardTitle;
record = basicCards[page.guid];
record = basicCards[basicCardPage.guid];
if (!record) {
throw new Error("Trying to edit a non-existing card: " + page.guid);
throw new Error("Trying to edit a non-existing card: " + basicCardPage.guid);
}
// When editing an existing record, prevent changes to persistence
this.persistCheckbox.hidden = true;
} else {
this.pageTitle.textContent = this.dataset.addBasicCardTitle;
// Use a currently selected shipping address as the default billing address
if (selectedShippingAddress) {
if (!record.billingAddressGUID && selectedShippingAddress) {
record.billingAddressGUID = selectedShippingAddress;
}
// Adding a new record: default persistence to checked when in a not-private session
@ -132,7 +151,15 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
this.persistCheckbox.checked = !state.isPrivate;
}
this.formHandler.loadRecord(record, addresses);
this.formHandler.loadRecord(record, addresses, basicCardPage.preserveFieldValues);
this.form.querySelector(".billingAddressRow").hidden = false;
if (basicCardPage.addressesModified) {
let addressGuid = state["address-page"].guid;
let billingAddressSelect = this.form.querySelector("#billingAddressGUID");
billingAddressSelect.value = addressGuid;
}
}
handleEvent(event) {
@ -150,6 +177,35 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
paymentRequest.cancel();
break;
}
case this.addressAddLink:
case this.addressEditLink: {
let {
"basic-card-page": basicCardPage,
} = this.requestStore.getState();
let nextState = {
page: {
id: "address-page",
previousId: "basic-card-page",
},
"address-page": {
guid: null,
title: this.dataset.billingAddressTitleAdd,
},
"basic-card-page": {
preserveFieldValues: true,
guid: basicCardPage.guid,
},
};
let billingAddressGUID = this.form.querySelector("#billingAddressGUID");
let selectedOption = billingAddressGUID.selectedOptions.length &&
billingAddressGUID.selectedOptions[0];
if (evt.target == this.addressEditLink && selectedOption && selectedOption.value) {
nextState["address-page"].title = this.dataset.billingAddressTitleEdit;
nextState["address-page"].guid = selectedOption.value;
}
this.requestStore.setState(nextState);
break;
}
case this.backButton: {
this.requestStore.setState({
page: {
@ -170,13 +226,15 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
saveRecord() {
let record = this.formHandler.buildFormObject();
let currentState = this.requestStore.getState();
let {
page,
tempBasicCards,
} = this.requestStore.getState();
let editing = !!page.guid;
"basic-card-page": basicCardPage,
} = currentState;
let editing = !!basicCardPage.guid;
if (editing ? (page.guid in tempBasicCards) : !this.persistCheckbox.checked) {
if (editing ? (basicCardPage.guid in tempBasicCards) : !this.persistCheckbox.checked) {
record.isTemporary = true;
}
@ -190,7 +248,7 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
record["cc-number"] = record["cc-number"] || "";
}
paymentRequest.updateAutofillRecord("creditCards", record, page.guid, {
let state = {
errorStateChange: {
page: {
id: "basic-card-page",
@ -204,7 +262,14 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
id: "payment-summary",
},
},
});
};
const previousId = page.previousId;
if (previousId) {
state.successStateChange[previousId] = Object.assign({}, currentState[previousId]);
}
paymentRequest.updateAutofillRecord("creditCards", record, basicCardPage.guid, state);
}
}

View File

@ -133,17 +133,18 @@ export default class PaymentMethodPicker extends PaymentStateSubscriberMixin(HTM
page: {
id: "basic-card-page",
},
"basic-card-page": {},
};
switch (target) {
case this.addLink: {
nextState.page.guid = null;
nextState["basic-card-page"].guid = null;
break;
}
case this.editLink: {
let state = this.requestStore.getState();
let selectedPaymentCardGUID = state[this.selectedStateKey];
nextState.page.guid = selectedPaymentCardGUID;
nextState["basic-card-page"].guid = selectedPaymentCardGUID;
break;
}
default: {

View File

@ -15,10 +15,21 @@ export let requestStore = new PaymentsStore({
changesPrevented: false,
completionState: "initial",
orderDetailsShowing: false,
"basic-card-page": {
guid: null,
// preserveFieldValues: true,
},
"address-page": {
guid: null,
title: "",
},
"payment-summary": {
},
page: {
id: "payment-summary",
previousId: null,
// onboardingWizard: true,
// error: "My error",
// error: "",
},
request: {
tabId: null,

View File

@ -134,7 +134,6 @@ var paymentRequest = {
state.page = {
id: "basic-card-page",
onboardingWizard: true,
guid: null,
};
}

View File

@ -25,6 +25,8 @@
<!ENTITY deliveryAddress.editPage.title "Edit Delivery Address">
<!ENTITY pickupAddress.addPage.title "Add Pickup Address">
<!ENTITY pickupAddress.editPage.title "Edit Pickup Address">
<!ENTITY billingAddress.addPage.title "Add Billing Address">
<!ENTITY billingAddress.editPage.title "Edit Billing Address">
<!ENTITY basicCard.addPage.title "Add Credit Card">
<!ENTITY basicCard.editPage.title "Edit Credit Card">
<!ENTITY payer.addPage.title "Add Payer Contact">
@ -39,6 +41,8 @@
<!ENTITY orderDetailsLabel "Order Details">
<!ENTITY orderTotalLabel "Total">
<!ENTITY basicCardPage.error.genericSave "There was an error saving the payment card.">
<!ENTITY basicCardPage.addressAddLink.label "Add">
<!ENTITY basicCardPage.addressEditLink.label "Edit">
<!ENTITY basicCardPage.backButton.label "Back">
<!ENTITY basicCardPage.saveButton.label "Save">
<!ENTITY basicCardPage.persistCheckbox.label "Save credit card to Firefox (Security code will not be saved)">
@ -138,6 +142,10 @@
data-add-basic-card-title="&basicCard.addPage.title;"
data-edit-basic-card-title="&basicCard.editPage.title;"
data-error-generic-save="&basicCardPage.error.genericSave;"
data-address-add-link-label="&basicCardPage.addressAddLink.label;"
data-address-edit-link-label="&basicCardPage.addressEditLink.label;"
data-billing-address-title-add="&billingAddress.addPage.title;"
data-billing-address-title-edit="&billingAddress.editPage.title;"
data-back-button-label="&basicCardPage.backButton.label;"
data-save-button-label="&basicCardPage.saveButton.label;"
data-cancel-button-label="&cancelPaymentButton.label;"

View File

@ -54,15 +54,15 @@ add_task(async function test_add_link() {
addLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !state.page.guid;
return state.page.id == "address-page" && !state["address-page"].guid;
}, "Check add page state");
let title = content.document.querySelector("address-form h1");
is(title.textContent, "Add Shipping Address", "Page title should be set");
let persistInput = content.document.querySelector("address-form labelled-checkbox");
ok(!persistInput.hidden, "checkbox should be visible when adding a new address");
ok(Cu.waiveXrays(persistInput).checked, "persist checkbox should be checked by default");
let persistCheckbox = content.document.querySelector("address-form labelled-checkbox");
ok(!persistCheckbox.hidden, "checkbox should be visible when adding a new address");
ok(Cu.waiveXrays(persistCheckbox).checked, "persist checkbox should be checked by default");
info("filling fields");
for (let [key, val] of Object.entries(address)) {
@ -145,14 +145,14 @@ add_task(async function test_edit_link() {
editLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !!state.page.guid;
return state.page.id == "address-page" && !!state["address-page"].guid;
}, "Check edit page state");
let title = content.document.querySelector("address-form h1");
is(title.textContent, "Edit Shipping Address", "Page title should be set");
let persistInput = content.document.querySelector("address-form labelled-checkbox");
ok(persistInput.hidden, "checkbox should be hidden when editing an address");
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)) {
@ -230,15 +230,15 @@ add_task(async function test_add_payer_contact_name_email_link() {
addLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !state.page.guid;
return state.page.id == "address-page" && !state["address-page"].guid;
}, "Check add page state");
let title = content.document.querySelector("address-form h1");
is(title.textContent, "Add Payer Contact", "Page title should be set");
let persistInput = content.document.querySelector("address-form labelled-checkbox");
ok(!persistInput.hidden, "checkbox should be visible when adding a new address");
ok(Cu.waiveXrays(persistInput).checked, "persist checkbox should be checked by default");
let persistCheckbox = content.document.querySelector("address-form labelled-checkbox");
ok(!persistCheckbox.hidden, "checkbox should be visible when adding a new address");
ok(Cu.waiveXrays(persistCheckbox).checked, "persist checkbox should be checked by default");
info("filling fields");
for (let [key, val] of Object.entries(address)) {
@ -317,15 +317,14 @@ add_task(async function test_edit_payer_contact_name_email_phone_link() {
editLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
info("state.page.id: " + state.page.id + "; state.page.guid: " + state.page.guid);
return state.page.id == "address-page" && !!state.page.guid;
return state.page.id == "address-page" && !!state["address-page"].guid;
}, "Check edit page state");
let title = content.document.querySelector("address-form h1");
is(title.textContent, "Edit Payer Contact", "Page title should be set");
let persistInput = content.document.querySelector("address-form labelled-checkbox");
ok(persistInput.hidden, "checkbox should be hidden when editing an address");
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)) {
@ -437,9 +436,10 @@ add_task(async function test_private_persist_addresses() {
PaymentTestUtils: PTU,
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
let persistInput = content.document.querySelector("address-form labelled-checkbox");
ok(!persistInput.hidden, "checkbox should be visible when adding a new address");
ok(!Cu.waiveXrays(persistInput).checked, "persist checkbox should be unchecked by default");
let persistCheckbox = content.document.querySelector("address-form labelled-checkbox");
ok(!persistCheckbox.hidden, "checkbox should be visible when adding a new address");
ok(!Cu.waiveXrays(persistCheckbox).checked,
"persist checkbox should be unchecked by default");
info("add the temp address");
let addressToAdd = PTU.Addresses.Temp;

View File

@ -18,16 +18,21 @@ add_task(async function test_add_link() {
addLink.click();
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !state.page.guid;
return state.page.id == "basic-card-page" && !state["basic-card-page"].guid;
}, "Check add page state");
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 0 &&
Object.keys(state.savedAddresses).length == 0;
}, "Check no cards or addresses present at beginning of test");
let title = content.document.querySelector("basic-card-form h1");
is(title.textContent, "Add Credit Card", "Add title should be set");
ok(!state.isPrivate,
"isPrivate flag is not set when paymentrequest is shown from a non-private session");
let persistInput = content.document.querySelector("basic-card-form labelled-checkbox");
ok(Cu.waiveXrays(persistInput).checked, "persist checkbox should be checked by default");
let persistCheckbox = content.document.querySelector("basic-card-form labelled-checkbox");
ok(Cu.waiveXrays(persistCheckbox).checked, "persist checkbox should be checked by default");
let year = (new Date()).getFullYear();
let card = {
@ -44,11 +49,77 @@ add_task(async function test_add_link() {
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
}
let billingAddressSelect = content.document.querySelector("#billingAddressGUID");
isnot(billingAddressSelect.getBoundingClientRect().height, 0,
"The billing address selector should always be visible");
is(billingAddressSelect.childElementCount, 1,
"Only one child option should exist by default");
is(billingAddressSelect.children[0].value, "",
"The only option should be the blank/empty option");
let addressAddLink = content.document.querySelector(".billingAddressRow .add-link");
addressAddLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !state["address-page"].guid;
}, "Check address page state");
let addressTitle = content.document.querySelector("address-form h1");
is(addressTitle.textContent, "Add Billing Address",
"Address on add address page should be correct");
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 0;
}, "Check card was not added when clicking the 'add' address button");
let addressBackButton = content.document.querySelector("address-form .back-button");
addressBackButton.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 == 0;
}, "Check basic-card page, but card should not be saved and no addresses present");
is(title.textContent, "Add Credit Card", "Add title should be still be on credit card page");
for (let [key, val] of Object.entries(card)) {
let field = content.document.getElementById(key);
is(field.value, val, "Field should still have previous value entered");
ok(!field.disabled, "Fields should still be enabled for editing");
}
addressAddLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !state["address-page"].guid;
}, "Check address page state");
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;
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)");
is(billingAddressSelect.childElementCount, 2,
"Two options should exist in the billingAddressSelect");
let selectedOption =
billingAddressSelect.children[billingAddressSelect.selectedIndex];
let selectedAddressGuid = selectedOption.value;
is(selectedAddressGuid, Object.values(state.savedAddresses)[0].guid,
"The select should have the new address selected");
content.document.querySelector("basic-card-form button:last-of-type").click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 1;
}, "Check card was added");
}, "Check card was not added again");
let cardGUIDs = Object.keys(state.savedBasicCards);
is(cardGUIDs.length, 1, "Check there is one card");
@ -57,6 +128,8 @@ add_task(async function test_add_link() {
for (let [key, val] of Object.entries(card)) {
is(savedCard[key], val, "Check " + key);
}
is(savedCard.billingAddressGUID, selectedAddressGuid,
"The saved card should be associated with the billing address");
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "payment-summary";
@ -80,9 +153,14 @@ add_task(async function test_edit_link() {
editLink.click();
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !!state.page.guid;
return state.page.id == "basic-card-page" && state["basic-card-page"].guid;
}, "Check edit page state");
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 1 &&
Object.keys(state.savedAddresses).length == 1;
}, "Check card and address present at beginning of test");
let title = content.document.querySelector("basic-card-form h1");
is(title.textContent, "Edit Credit Card", "Edit title should be set");
@ -102,6 +180,90 @@ add_task(async function test_edit_link() {
}
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,
"The billing address set by the previous test should be selected by default");
info("Test clicking 'edit' on the empty option first");
billingAddressSelect.selectedIndex = 0;
let addressEditLink = content.document.querySelector(".billingAddressRow .edit-link");
addressEditLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !state["address-page"].guid;
}, "Clicking edit button when the empty option is selected will go to 'add' page (no guid)");
let addressTitle = content.document.querySelector("address-form h1");
is(addressTitle.textContent, "Add Billing Address",
"Address on add address page should be correct");
let addressBackButton = content.document.querySelector("address-form .back-button");
addressBackButton.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 we're back at basic-card page with no state changed after adding");
info("Go back to previously selected option before clicking 'edit' now");
billingAddressSelect.selectedIndex = 1;
let selectedOption = billingAddressSelect.selectedOptions.length &&
billingAddressSelect.selectedOptions[0];
ok(selectedOption && selectedOption.value, "select should have a selected option value");
addressEditLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && state["address-page"].guid;
}, "Check address page state (editing)");
is(addressTitle.textContent, "Edit Billing Address",
"Address on edit address page should be correct");
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 1;
}, "Check card was not added again when clicking the 'edit' address button");
addressBackButton.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 we're back at basic-card page with no state changed after editing");
for (let [key, val] of Object.entries(card)) {
let field = content.document.getElementById(key);
is(field.value, val, "Field should still have previous value entered");
}
selectedOption = billingAddressSelect.selectedOptions.length &&
billingAddressSelect.selectedOptions[0];
ok(selectedOption && selectedOption.value, "select should have a selected option value");
addressEditLink.click();
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && state["address-page"].guid;
}, "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";
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",
"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) => {
@ -140,14 +302,14 @@ add_task(async function test_private_persist_defaults() {
addLink.click();
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !state.page.guid;
return state.page.id == "basic-card-page" && !state["basic-card-page"].guid;
},
"Check add page state");
ok(!state.isPrivate,
"isPrivate flag is not set when paymentrequest is shown from a non-private session");
let persistInput = content.document.querySelector("basic-card-form labelled-checkbox");
ok(Cu.waiveXrays(persistInput).checked,
let persistCheckbox = content.document.querySelector("basic-card-form labelled-checkbox");
ok(Cu.waiveXrays(persistCheckbox).checked,
"checkbox is checked by default from a non-private session");
}, args);
@ -163,14 +325,14 @@ add_task(async function test_private_persist_defaults() {
addLink.click();
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !state.page.guid;
return state.page.id == "basic-card-page" && !state["basic-card-page"].guid;
},
"Check add page state");
ok(state.isPrivate,
"isPrivate flag is set when paymentrequest is shown from a private session");
let persistInput = content.document.querySelector("labelled-checkbox");
ok(!Cu.waiveXrays(persistInput).checked,
let persistCheckbox = content.document.querySelector("labelled-checkbox");
ok(!Cu.waiveXrays(persistCheckbox).checked,
"checkbox is not checked by default from a private session");
}, args, {
browser: privateWin.gBrowser,
@ -195,7 +357,7 @@ add_task(async function test_private_card_adding() {
addLink.click();
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page" && !state.page.guid;
return state.page.id == "basic-card-page" && !state["basic-card-page"].guid;
},
"Check add page state");

View File

@ -74,7 +74,9 @@ add_task(async function test_backButton() {
form.dataset.backButtonLabel = "Back";
await form.requestStore.setState({
page: {
id: "test-page",
id: "address-page",
},
"address-page": {
title: "Sample page title",
},
});
@ -138,6 +140,9 @@ add_task(async function test_saveButton() {
error: "Generic error",
onboardingWizard: undefined,
},
"address-page": {
title: "Sample page title",
},
},
guid: undefined,
messageType: "updateAutofillRecord",
@ -158,6 +163,13 @@ add_task(async function test_saveButton() {
successStateChange: {
page: {
id: "payment-summary",
onboardingWizard: undefined,
},
"address-page": {
title: "Sample page title",
},
"basic-card-page": {
guid: null,
},
},
}, "Check event details for the message to chrome");
@ -193,6 +205,8 @@ add_task(async function test_edit() {
await form.requestStore.setState({
page: {
id: "address-page",
},
"address-page": {
guid: address1.guid,
},
savedAddresses: {
@ -210,6 +224,8 @@ add_task(async function test_edit() {
await form.requestStore.setState({
page: {
id: "address-page",
},
"address-page": {
guid: minimalAddress.guid,
},
savedAddresses: {
@ -224,6 +240,7 @@ add_task(async function test_edit() {
page: {
id: "address-page",
},
"address-page": {},
});
await asyncElementRendered();
checkAddressForm(form, {});

View File

@ -69,7 +69,9 @@ add_task(async function test_backButton() {
form.dataset.addBasicCardTitle = "Sample page title 2";
await form.requestStore.setState({
page: {
id: "test-page",
id: "basic-card-page",
},
"basic-card-page": {
},
});
await form.promiseReady;
@ -244,6 +246,8 @@ add_task(async function test_edit() {
await form.requestStore.setState({
page: {
id: "basic-card-page",
},
"basic-card-page": {
guid: card1.guid,
},
savedBasicCards: {
@ -273,6 +277,8 @@ add_task(async function test_edit() {
await form.requestStore.setState({
page: {
id: "basic-card-page",
},
"basic-card-page": {
guid: minimalCard.guid,
},
savedBasicCards: {
@ -287,6 +293,9 @@ add_task(async function test_edit() {
page: {
id: "basic-card-page",
},
"basic-card-page": {
guid: null,
},
});
await asyncElementRendered();
checkCCForm(form, {});

View File

@ -197,13 +197,16 @@ class EditCreditCard extends EditAutofillForm {
this.attachEventListeners();
}
loadRecord(record, addresses) {
loadRecord(record, addresses, preserveFieldValues) {
// _record must be updated before generateYears and generateBillingAddressOptions are called.
this._record = record;
this._addresses = addresses;
this.generateYears();
this.generateBillingAddressOptions();
super.loadRecord(record);
if (!preserveFieldValues) {
// Re-generating the years will reset the selected option.
this.generateYears();
super.loadRecord(record);
}
}
generateYears() {